]> git.decadent.org.uk Git - nfs-utils.git/blob - support/export/xtab.c
nfs-utils: have mountd hold open etab file to force inode number to change
[nfs-utils.git] / support / export / xtab.c
1 /*
2  * support/export/xtab.c
3  *
4  * Interface to the xtab file.
5  *
6  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7  */
8
9 #ifdef HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include <sys/fcntl.h>
14 #include <unistd.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include "xmalloc.h"
18 #include "nfslib.h"
19 #include "exportfs.h"
20 #include "xio.h"
21 #include "xlog.h"
22
23 static void cond_rename(char *newfile, char *oldfile);
24
25 static int
26 xtab_read(char *xtab, int is_export)
27 {
28     /* is_export == 0  => reading /proc/fs/nfs/exports - we know these things are exported to kernel
29      * is_export == 1  => reading /var/lib/nfs/etab - these things are allowed to be exported
30      * is_export == 2  => reading /var/lib/nfs/xtab - these things might be known to kernel
31      */
32         struct exportent        *xp;
33         nfs_export              *exp;
34         int                     lockid;
35
36         if ((lockid = xflock(xtab, "r")) < 0)
37                 return 0;
38         setexportent(xtab, "r");
39         while ((xp = getexportent(is_export==0, 0)) != NULL) {
40                 if (!(exp = export_lookup(xp->e_hostname, xp->e_path, is_export != 1)) &&
41                     !(exp = export_create(xp, is_export!=1))) {
42                         continue;
43                 }
44                 switch (is_export) {
45                 case 0:
46                         exp->m_exported = 1;
47                         break;
48                 case 1:
49                         exp->m_xtabent = 1;
50                         exp->m_mayexport = 1;
51                         break;
52                 case 2:
53                         exp->m_exported = -1;/* may be exported */
54                         break;
55                 }
56         }
57         endexportent();
58         xfunlock(lockid);
59
60         return 0;
61 }
62
63 int
64 xtab_mount_read(void)
65 {
66         int fd;
67         if ((fd=open(_PATH_PROC_EXPORTS, O_RDONLY))>=0) {
68                 close(fd);
69                 return xtab_read(_PATH_PROC_EXPORTS, 0);
70         } else if ((fd=open(_PATH_PROC_EXPORTS_ALT, O_RDONLY) >= 0)) {
71                 close(fd);
72                 return xtab_read(_PATH_PROC_EXPORTS_ALT, 0);
73         } else
74                 return xtab_read(_PATH_XTAB, 2);
75 }
76
77 int
78 xtab_export_read(void)
79 {
80         return xtab_read(_PATH_ETAB, 1);
81 }
82
83 /*
84  * mountd now keeps an open fd for the etab at all times to make sure that the
85  * inode number changes when the xtab_export_write is done. If you change the
86  * routine below such that the files are edited in place, then you'll need to
87  * fix the auth_reload logic as well...
88  */
89 static int
90 xtab_write(char *xtab, char *xtabtmp, int is_export)
91 {
92         struct exportent        xe;
93         nfs_export              *exp;
94         int                     lockid, i;
95
96         if ((lockid = xflock(xtab, "w")) < 0) {
97                 xlog(L_ERROR, "can't lock %s for writing", xtab);
98                 return 0;
99         }
100         setexportent(xtabtmp, "w");
101
102         for (i = 0; i < MCL_MAXTYPES; i++) {
103                 for (exp = exportlist[i]; exp; exp = exp->m_next) {
104                         if (is_export && !exp->m_xtabent)
105                                 continue;
106                         if (!is_export && ! exp->m_exported)
107                                 continue;
108
109                         /* write out the export entry using the FQDN */
110                         xe = exp->m_export;
111                         strncpy(xe.e_hostname,
112                                 exp->m_client->m_hostname,
113                                 sizeof (xe.e_hostname) - 1);
114                         xe.e_hostname[sizeof (xe.e_hostname) - 1] = '\0';
115                         putexportent(&xe);
116                 }
117         }
118         endexportent();
119
120         cond_rename(xtabtmp, xtab);
121
122         xfunlock(lockid);
123
124         return 1;
125 }
126
127 int
128 xtab_export_write()
129 {
130         return xtab_write(_PATH_ETAB, _PATH_ETABTMP, 1);
131 }
132
133 int
134 xtab_mount_write()
135 {
136         return xtab_write(_PATH_XTAB, _PATH_XTABTMP, 0);
137 }
138
139 void
140 xtab_append(nfs_export *exp)
141 {
142         struct exportent xe;
143         int             lockid;
144
145         if ((lockid = xflock(_PATH_XTAB, "w")) < 0)
146                 return;
147         setexportent(_PATH_XTAB, "a");
148         xe = exp->m_export;
149         strncpy(xe.e_hostname, exp->m_client->m_hostname,
150                sizeof (xe.e_hostname) - 1);
151         xe.e_hostname[sizeof (xe.e_hostname) - 1] = '\0';
152         putexportent(&xe);
153         endexportent();
154         xfunlock(lockid);
155         exp->m_xtabent = 1;
156 }
157
158 /*
159  * rename newfile onto oldfile unless
160  * they are identical
161  */
162 static void cond_rename(char *newfile, char *oldfile)
163 {
164         int nfd, ofd;
165         char nbuf[4096], obuf[4096];
166         int ncnt, ocnt;
167
168         nfd = open(newfile, 0);
169         if (nfd < 0)
170                 return;
171         ofd = open(oldfile, 0);
172         if (ofd < 0) {
173                 close(nfd);
174                 rename(newfile, oldfile);
175                 return;
176         }
177
178         do {
179                 ncnt = read(nfd, nbuf, sizeof(nbuf));
180                 if (ncnt < 0)
181                         break;
182                 ocnt = read(ofd, obuf, sizeof(obuf));
183                 if (ocnt < 0)
184                         break;
185                 if (ncnt != ocnt)
186                         break;
187                 if (ncnt == 0) {
188                         close(nfd);
189                         close(ofd);
190                         unlink(newfile);
191                         return;
192                 }
193         } while (memcmp(obuf, nbuf, ncnt) == 0);
194
195         /* some mis-match */
196         close(nfd);
197         close(ofd);
198         rename(newfile, oldfile);
199         return;
200 }