990113e14bf471da86269867a8b4b4ef4fb7528b
[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                         xe.e_hostname = exp->m_client->m_hostname;
112                         putexportent(&xe);
113                 }
114         }
115         endexportent();
116
117         cond_rename(xtabtmp, xtab);
118
119         xfunlock(lockid);
120
121         return 1;
122 }
123
124 int
125 xtab_export_write()
126 {
127         return xtab_write(_PATH_ETAB, _PATH_ETABTMP, 1);
128 }
129
130 int
131 xtab_mount_write()
132 {
133         return xtab_write(_PATH_XTAB, _PATH_XTABTMP, 0);
134 }
135
136 void
137 xtab_append(nfs_export *exp)
138 {
139         struct exportent xe;
140         int             lockid;
141
142         if ((lockid = xflock(_PATH_XTAB, "w")) < 0)
143                 return;
144         setexportent(_PATH_XTAB, "a");
145         xe = exp->m_export;
146         xe.e_hostname = exp->m_client->m_hostname;
147         putexportent(&xe);
148         endexportent();
149         xfunlock(lockid);
150         exp->m_xtabent = 1;
151 }
152
153 /*
154  * rename newfile onto oldfile unless
155  * they are identical
156  */
157 static void cond_rename(char *newfile, char *oldfile)
158 {
159         int nfd, ofd;
160         char nbuf[4096], obuf[4096];
161         int ncnt, ocnt;
162
163         nfd = open(newfile, 0);
164         if (nfd < 0)
165                 return;
166         ofd = open(oldfile, 0);
167         if (ofd < 0) {
168                 close(nfd);
169                 rename(newfile, oldfile);
170                 return;
171         }
172
173         do {
174                 ncnt = read(nfd, nbuf, sizeof(nbuf));
175                 if (ncnt < 0)
176                         break;
177                 ocnt = read(ofd, obuf, sizeof(obuf));
178                 if (ocnt < 0)
179                         break;
180                 if (ncnt != ocnt)
181                         break;
182                 if (ncnt == 0) {
183                         close(nfd);
184                         close(ofd);
185                         unlink(newfile);
186                         return;
187                 }
188         } while (memcmp(obuf, nbuf, ncnt) == 0);
189
190         /* some mis-match */
191         close(nfd);
192         close(ofd);
193         rename(newfile, oldfile);
194         return;
195 }