2005-08-26 Kevin Coffman <kwc@citi.umich.edu>
[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 #include "config.h"
10
11 #include <sys/fcntl.h>
12 #include <unistd.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include "xmalloc.h"
16 #include "nfslib.h"
17 #include "exportfs.h"
18 #include "xio.h"
19 #include "xlog.h"
20
21 static void cond_rename(char *newfile, char *oldfile);
22
23 static int
24 xtab_read(char *xtab, int is_export)
25 {
26     /* is_export == 0  => reading /proc/fs/nfs/exports - we know these things are exported to kernel
27      * is_export == 1  => reading /var/lib/nfs/etab - these things are allowed to be exported
28      * is_export == 2  => reading /var/lib/nfs/xtab - these things might be known to kernel
29      */
30         struct exportent        *xp;
31         nfs_export              *exp;
32         int                     lockid;
33
34         if ((lockid = xflock(xtab, "r")) < 0)
35                 return 0;
36         setexportent(xtab, "r");
37         while ((xp = getexportent(is_export==0, 0)) != NULL) {
38                 if (!(exp = export_lookup(xp->e_hostname, xp->e_path, is_export != 1)) &&
39                     !(exp = export_create(xp, is_export!=1))) {
40                         continue;
41                 }
42                 switch (is_export) {
43                 case 0:
44                         exp->m_exported = 1;
45                         break;
46                 case 1:
47                         exp->m_xtabent = 1;
48                         exp->m_mayexport = 1;
49                         break;
50                 case 2:
51                         exp->m_exported = -1;/* may be exported */
52                         break;
53                 }
54         }
55         endexportent();
56         xfunlock(lockid);
57
58         return 0;
59 }
60
61 int
62 xtab_mount_read(void)
63 {
64         int fd;
65         if ((fd=open(_PATH_PROC_EXPORTS, O_RDONLY))>=0) {
66                 close(fd);
67                 return xtab_read(_PATH_PROC_EXPORTS, 0);
68         } else if ((fd=open(_PATH_PROC_EXPORTS_ALT, O_RDONLY) >= 0)) {
69                 close(fd);
70                 return xtab_read(_PATH_PROC_EXPORTS_ALT, 0);
71         } else
72                 return xtab_read(_PATH_XTAB, 2);
73 }
74
75 int
76 xtab_export_read(void)
77 {
78         return xtab_read(_PATH_ETAB, 1);
79 }
80
81 static int
82 xtab_write(char *xtab, char *xtabtmp, int is_export)
83 {
84         struct exportent        xe;
85         nfs_export              *exp;
86         int                     lockid, i;
87
88         if ((lockid = xflock(xtab, "w")) < 0) {
89                 xlog(L_ERROR, "can't lock %s for writing", xtab);
90                 return 0;
91         }
92         setexportent(xtabtmp, "w");
93
94         for (i = 0; i < MCL_MAXTYPES; i++) {
95                 for (exp = exportlist[i]; exp; exp = exp->m_next) {
96                         if (is_export && !exp->m_xtabent)
97                                 continue;
98                         if (!is_export && ! exp->m_exported)
99                                 continue;
100
101                         /* write out the export entry using the FQDN */
102                         xe = exp->m_export;
103                         strncpy(xe.e_hostname,
104                                 exp->m_client->m_hostname,
105                                 sizeof (xe.e_hostname) - 1);
106                         xe.e_hostname[sizeof (xe.e_hostname) - 1] = '\0';
107                         putexportent(&xe);
108                 }
109         }
110         endexportent();
111
112         cond_rename(xtabtmp, xtab);
113
114         xfunlock(lockid);
115
116         return 1;
117 }
118
119 int
120 xtab_export_write()
121 {
122         return xtab_write(_PATH_ETAB, _PATH_ETABTMP, 1);
123 }
124
125 int
126 xtab_mount_write()
127 {
128         return xtab_write(_PATH_XTAB, _PATH_XTABTMP, 0);
129 }
130
131 void
132 xtab_append(nfs_export *exp)
133 {
134         struct exportent xe;
135         int             lockid;
136
137         if ((lockid = xflock(_PATH_XTAB, "w")) < 0)
138                 return;
139         setexportent(_PATH_XTAB, "a");
140         xe = exp->m_export;
141         strncpy(xe.e_hostname, exp->m_client->m_hostname,
142                sizeof (xe.e_hostname) - 1);
143         xe.e_hostname[sizeof (xe.e_hostname) - 1] = '\0';
144         putexportent(&xe);
145         endexportent();
146         xfunlock(lockid);
147         exp->m_xtabent = 1;
148 }
149
150 /*
151  * rename newfile onto oldfile unless
152  * they are identical 
153  */
154 static void cond_rename(char *newfile, char *oldfile)
155 {
156         int nfd, ofd;
157         char nbuf[4096], obuf[4096];
158         int ncnt, ocnt;
159
160         nfd = open(newfile, 0);
161         if (nfd < 0)
162                 return;
163         ofd = open(oldfile, 0);
164         if (ofd < 0) {
165                 close(nfd);
166                 rename(newfile, oldfile);
167                 return;
168         }
169
170         do {
171                 ncnt = read(nfd, nbuf, sizeof(nbuf));
172                 if (ncnt < 0)
173                         break;
174                 ocnt = read(ofd, obuf, sizeof(obuf));
175                 if (ocnt < 0)
176                         break;
177                 if (ncnt != ocnt)
178                         break;
179                 if (ncnt == 0) {
180                         close(nfd);
181                         close(ofd);
182                         unlink(newfile);
183                         return;
184                 }
185         } while (memcmp(obuf, nbuf, ncnt) == 0);
186
187         /* some mis-match */
188         close(nfd);
189         close(ofd);
190         rename(newfile, oldfile);
191         return;
192 }