Fixes to make unexporting and exporting with wildcards
[nfs-utils.git] / support / export / export.c
1 /*
2  * support/export/export.c
3  *
4  * Maintain list of exported file systems.
5  *
6  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7  */
8
9 #include "config.h"
10
11 #include <string.h>
12 #include <sys/types.h>
13 #include <sys/param.h>
14 #include <netinet/in.h>
15 #include <stdlib.h>
16 #include "xmalloc.h"
17 #include "nfslib.h"
18 #include "exportfs.h"
19
20 nfs_export      *exportlist[MCL_MAXTYPES] = { NULL, };
21
22 static void     export_init(nfs_export *exp, nfs_client *clp,
23                                         struct exportent *nep);
24 static int      export_check(nfs_export *, struct hostent *, char *);
25 static nfs_export *
26                 export_allowed_internal(struct hostent *hp, char *path);
27
28 int
29 export_read(char *fname)
30 {
31         struct exportent        *eep;
32         nfs_export              *exp;
33
34         setexportent(fname, "r");
35         while ((eep = getexportent(0,1)) != NULL) {
36           exp = export_lookup(eep->e_hostname, eep->e_path, 0);
37           if (!exp)
38             export_create(eep,0);
39           else {
40             if (exp->m_export.e_flags != eep->e_flags) {
41               xlog(L_ERROR, "incompatible duplicated export entries:");
42               xlog(L_ERROR, "\t%s:%s (0x%x) [IGNORED]", eep->e_hostname,
43                    eep->e_path, eep->e_flags);
44               xlog(L_ERROR, "\t%s:%s (0x%x)", exp->m_export.e_hostname,
45                    exp->m_export.e_path, exp->m_export.e_flags);
46             }
47             else {
48               xlog(L_ERROR, "duplicated export entries:");
49               xlog(L_ERROR, "\t%s:%s", eep->e_hostname, eep->e_path);
50               xlog(L_ERROR, "\t%s:%s", exp->m_export.e_hostname,
51                    exp->m_export.e_path);
52             }
53           }
54         }
55         endexportent();
56
57         return 0;
58 }
59
60 /*
61  * Create an in-core export struct from an export entry.
62  */
63 nfs_export *
64 export_create(struct exportent *xep, int canonical)
65 {
66         nfs_client      *clp;
67         nfs_export      *exp;
68
69         if (!(clp = client_lookup(xep->e_hostname, canonical))) {
70                 /* bad export entry; complaint already logged */
71                 return NULL;
72         }
73         exp = (nfs_export *) xmalloc(sizeof(*exp));
74         export_init(exp, clp, xep);
75         export_add(exp);
76
77         return exp;
78 }
79
80 static void
81 export_init(nfs_export *exp, nfs_client *clp, struct exportent *nep)
82 {
83         struct exportent        *e = &exp->m_export;
84
85         dupexportent(e, nep);
86
87         exp->m_exported = 0;
88         exp->m_xtabent = 0;
89         exp->m_mayexport = 0;
90         exp->m_changed = 0;
91         exp->m_client = clp;
92         clp->m_count++;
93 }
94
95 /*
96  * Duplicate exports data. The in-core export struct retains the
97  * original hostname from /etc/exports, while the in-core client struct
98  * gets the newly found FQDN.
99  */
100 nfs_export *
101 export_dup(nfs_export *exp, struct hostent *hp)
102 {
103         nfs_export              *new;
104         nfs_client              *clp;
105
106         new = (nfs_export *) xmalloc(sizeof(*new));
107         memcpy(new, exp, sizeof(*new));
108         dupexportent(&new->m_export, &exp->m_export);
109         clp = client_dup(exp->m_client, hp);
110         clp->m_count++;
111         new->m_client = clp;
112         new->m_mayexport = exp->m_mayexport;
113         new->m_exported = 0;
114         new->m_xtabent = 0;
115         new->m_changed = 0;
116         export_add(new);
117
118         return new;
119 }
120
121 void
122 export_add(nfs_export *exp)
123 {
124         nfs_export      **epp;
125         int             type = exp->m_client->m_type;
126         int             slen = strlen(exp->m_export.e_path);
127
128         if (type < 0 || type >= MCL_MAXTYPES)
129                 xlog(L_FATAL, "unknown client type in export_add");
130
131         epp = exportlist + type;
132         while (*epp && slen < strlen((*epp)->m_export.e_path))
133                 epp = &((*epp)->m_next);
134         exp->m_next = *epp;
135         *epp = exp;
136 }
137
138 nfs_export *
139 export_find(struct hostent *hp, char *path)
140 {
141         nfs_export      *exp;
142         int             i;
143
144         for (i = 0; i < MCL_MAXTYPES; i++) {
145                 for (exp = exportlist[i]; exp; exp = exp->m_next) {
146                         if (!export_check(exp, hp, path))
147                                 continue;
148                         if (exp->m_client->m_type == MCL_FQDN)
149                                 return exp;
150                         return export_dup(exp, hp);
151                 }
152         }
153
154         return NULL;
155 }
156
157 static nfs_export *
158 export_allowed_internal (struct hostent *hp, char *path)
159 {
160         nfs_export      *exp;
161         int             i;
162
163         for (i = 0; i < MCL_MAXTYPES; i++) {
164                 for (exp = exportlist[i]; exp; exp = exp->m_next) {
165                         if (!exp->m_mayexport ||
166                             !export_check(exp, hp, path))
167                                 continue;
168                         return exp;
169                 }
170         }
171
172         return NULL;
173 }
174
175 nfs_export *
176 export_allowed(struct hostent *hp, char *path)
177 {
178         nfs_export              *exp;
179         char                    epath[MAXPATHLEN+1];
180         char                    *p = NULL;
181
182         if (path [0] != '/') return NULL;
183
184         strncpy(epath, path, sizeof (epath) - 1);
185         epath[sizeof (epath) - 1] = '\0';
186
187         /* Try the longest matching exported pathname. */
188         while (1) {
189                 exp = export_allowed_internal (hp, epath);
190                 if (exp)
191                         return exp;
192                 /* We have to treat the root, "/", specially. */
193                 if (p == &epath[1]) break;
194                 p = strrchr(epath, '/');
195                 if (p == epath) p++;
196                 *p = '\0';
197         }
198
199         return NULL;
200 }
201
202 nfs_export *
203 export_lookup(char *hname, char *path, int canonical)
204 {
205         nfs_client      *clp;
206         nfs_export      *exp;
207
208         if (!(clp = client_lookup(hname, canonical)))
209                 return NULL;
210         for (exp = exportlist[clp->m_type]; exp; exp = exp->m_next)
211                 if (exp->m_client == clp && !strcmp(exp->m_export.e_path, path))
212                         return exp;
213         return NULL;
214 }
215
216 static int
217 export_check(nfs_export *exp, struct hostent *hp, char *path)
218 {
219         if (strcmp(path, exp->m_export.e_path))
220                 return 0;
221
222         return client_check(exp->m_client, hp);
223 }
224
225 void
226 export_freeall(void)
227 {
228         nfs_export      *exp, *nxt;
229         int             i;
230
231         for (i = 0; i < MCL_MAXTYPES; i++) {
232                 for (exp = exportlist[i]; exp; exp = nxt) {
233                         nxt = exp->m_next;
234                         client_release(exp->m_client);
235                         if (exp->m_export.e_squids)
236                                 xfree(exp->m_export.e_squids);
237                         if (exp->m_export.e_sqgids)
238                                 xfree(exp->m_export.e_sqgids);
239                         if (exp->m_export.e_mountpoint)
240                                 free(exp->m_export.e_mountpoint);
241                         xfree(exp);
242                 }
243                 exportlist[i] = NULL;
244         }
245         client_freeall();
246 }
247
248 void
249 export_reset(nfs_export *exp)
250 {
251         if (!exp)
252                 return;
253
254         /* Restore m_path. */
255         strncpy(exp->m_export.m_path, exp->m_export.e_path,
256                 sizeof (exp->m_export.m_path) - 1);
257         exp->m_export.m_path[sizeof (exp->m_export.m_path) - 1] = '\0';
258 }