]> git.decadent.org.uk Git - nfs-utils.git/blob - support/export/xtab.c
Mountd should use separate lockfiles
[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, char *lockfn, 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(lockfn, "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,
70                                  _PATH_PROC_EXPORTS, 0);
71         } else if ((fd=open(_PATH_PROC_EXPORTS_ALT, O_RDONLY) >= 0)) {
72                 close(fd);
73                 return xtab_read(_PATH_PROC_EXPORTS_ALT,
74                                  _PATH_PROC_EXPORTS_ALT, 0);
75         } else
76                 return xtab_read(_PATH_XTAB, _PATH_XTABLCK, 2);
77 }
78
79 int
80 xtab_export_read(void)
81 {
82         return xtab_read(_PATH_ETAB, _PATH_ETABLCK, 1);
83 }
84
85 /*
86  * mountd now keeps an open fd for the etab at all times to make sure that the
87  * inode number changes when the xtab_export_write is done. If you change the
88  * routine below such that the files are edited in place, then you'll need to
89  * fix the auth_reload logic as well...
90  */
91 static int
92 xtab_write(char *xtab, char *xtabtmp, char *lockfn, int is_export)
93 {
94         struct exportent        xe;
95         nfs_export              *exp;
96         int                     lockid, i;
97
98         if ((lockid = xflock(lockfn, "w")) < 0) {
99                 xlog(L_ERROR, "can't lock %s for writing", xtab);
100                 return 0;
101         }
102         setexportent(xtabtmp, "w");
103
104         for (i = 0; i < MCL_MAXTYPES; i++) {
105                 for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
106                         if (is_export && !exp->m_xtabent)
107                                 continue;
108                         if (!is_export && ! exp->m_exported)
109                                 continue;
110
111                         /* write out the export entry using the FQDN */
112                         xe = exp->m_export;
113                         xe.e_hostname = exp->m_client->m_hostname;
114                         putexportent(&xe);
115                 }
116         }
117         endexportent();
118
119         cond_rename(xtabtmp, xtab);
120
121         xfunlock(lockid);
122
123         return 1;
124 }
125
126 int
127 xtab_export_write()
128 {
129         return xtab_write(_PATH_ETAB, _PATH_ETABTMP, _PATH_ETABLCK, 1);
130 }
131
132 int
133 xtab_mount_write()
134 {
135         return xtab_write(_PATH_XTAB, _PATH_XTABTMP, _PATH_XTABLCK, 0);
136 }
137
138 void
139 xtab_append(nfs_export *exp)
140 {
141         struct exportent xe;
142         int             lockid;
143
144         if ((lockid = xflock(_PATH_XTABLCK, "w")) < 0)
145                 return;
146         setexportent(_PATH_XTAB, "a");
147         xe = exp->m_export;
148         xe.e_hostname = exp->m_client->m_hostname;
149         putexportent(&xe);
150         endexportent();
151         xfunlock(lockid);
152         exp->m_xtabent = 1;
153 }
154
155 /*
156  * rename newfile onto oldfile unless
157  * they are identical
158  */
159 static void cond_rename(char *newfile, char *oldfile)
160 {
161         int nfd, ofd;
162         char nbuf[4096], obuf[4096];
163         int ncnt, ocnt;
164
165         nfd = open(newfile, 0);
166         if (nfd < 0)
167                 return;
168         ofd = open(oldfile, 0);
169         if (ofd < 0) {
170                 close(nfd);
171                 rename(newfile, oldfile);
172                 return;
173         }
174
175         do {
176                 ncnt = read(nfd, nbuf, sizeof(nbuf));
177                 if (ncnt < 0)
178                         break;
179                 ocnt = read(ofd, obuf, sizeof(obuf));
180                 if (ocnt < 0)
181                         break;
182                 if (ncnt != ocnt)
183                         break;
184                 if (ncnt == 0) {
185                         close(nfd);
186                         close(ofd);
187                         unlink(newfile);
188                         return;
189                 }
190         } while (memcmp(obuf, nbuf, ncnt) == 0);
191
192         /* some mis-match */
193         close(nfd);
194         close(ofd);
195         rename(newfile, oldfile);
196         return;
197 }