]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/mountd/rmtab.c
typo
[nfs-utils.git] / utils / mountd / rmtab.c
1 /*
2  * utils/mountd/rmtab.c
3  *
4  * Manage the rmtab file for mountd.
5  *
6  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7  */
8
9 #include "config.h"
10
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <unistd.h>
14 #include <netinet/in.h>
15 #include <arpa/inet.h>
16 #include <netdb.h>
17 #include "xmalloc.h"
18 #include "misc.h"
19 #include "exportfs.h"
20 #include "xio.h"
21 #include "mountd.h"
22
23 #include <limits.h> /* PATH_MAX */
24
25 /* If new path is a link do not destroy it but place the
26  * file where the link points.
27  */
28
29 static int 
30 slink_safe_rename(const char * oldpath, const char * newpath)
31 {
32         int r;
33         struct stat s;
34         char slink_path[PATH_MAX];
35         const char *real_newpath = newpath;
36
37         if ((lstat(newpath, &s) == 0) && S_ISLNK(s.st_mode)) {
38                 /* New path is a symbolic link, do not destroy but follow */
39                 if ((r = readlink(newpath, slink_path, PATH_MAX - 1)) == -1)
40                         return -1;
41                 slink_path[r] = '\0';
42                 real_newpath = slink_path;
43         }
44
45         return rename(oldpath, real_newpath);
46 }
47
48 void
49 mountlist_add(nfs_export *exp, const char *path)
50 {
51         struct rmtabent xe;
52         struct rmtabent *rep;
53         int             lockid;
54         long            pos;
55
56         if ((lockid = xflock(_PATH_RMTAB, "a")) < 0)
57                 return;
58         setrmtabent("r+");
59         while ((rep = getrmtabent(1, &pos)) != NULL) {
60                 if (strcmp (rep->r_client,
61                             exp->m_client->m_hostname) == 0
62                     && strcmp(rep->r_path, path) == 0) {
63                         rep->r_count++;
64                         putrmtabent(rep, &pos);
65                         endrmtabent();
66                         xfunlock(lockid);
67                         return;
68                 }
69         }
70         endrmtabent();
71         strncpy(xe.r_client, exp->m_client->m_hostname,
72                 sizeof (xe.r_client) - 1);
73         xe.r_client [sizeof (xe.r_client) - 1] = '\0';
74         strncpy(xe.r_path, path, sizeof (xe.r_path) - 1);
75         xe.r_path [sizeof (xe.r_path) - 1] = '\0';
76         xe.r_count = 1;
77         if (setrmtabent("a")) {
78                 putrmtabent(&xe, NULL);
79                 endrmtabent();
80         }
81         xfunlock(lockid);
82 }
83
84 void
85 mountlist_del(nfs_export *exp, const char *path)
86 {
87         struct rmtabent *rep;
88         FILE            *fp;
89         char            *hname = exp->m_client->m_hostname;
90         int             lockid;
91         int             match;
92
93         if ((lockid = xflock(_PATH_RMTAB, "w")) < 0)
94                 return;
95         if (!setrmtabent("r")) {
96                 xfunlock(lockid);
97                 return;
98         }
99         if (!(fp = fsetrmtabent(_PATH_RMTABTMP, "w"))) {
100                 endrmtabent();
101                 xfunlock(lockid);
102                 return;
103         }
104         while ((rep = getrmtabent(1, NULL)) != NULL) {
105                 match = !strcmp (rep->r_client, hname)
106                         && !strcmp(rep->r_path, path);
107                 if (match)
108                         rep->r_count--;
109                 if (!match || rep->r_count)
110                         fputrmtabent(fp, rep, NULL);
111         }
112         if (slink_safe_rename(_PATH_RMTABTMP, _PATH_RMTAB) < 0) {
113                 xlog(L_ERROR, "couldn't rename %s to %s",
114                                 _PATH_RMTABTMP, _PATH_RMTAB);
115         }
116         endrmtabent();  /* close & unlink */
117         fendrmtabent(fp);
118         xfunlock(lockid);
119 }
120
121 void
122 mountlist_del_all(struct sockaddr_in *sin)
123 {
124         struct in_addr  addr = sin->sin_addr;
125         struct hostent  *hp;
126         struct rmtabent *rep;
127         nfs_export      *exp;
128         FILE            *fp;
129         int             lockid;
130
131         if ((lockid = xflock(_PATH_RMTAB, "w")) < 0)
132                 return;
133         if (!(hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET))) {
134                 xlog(L_ERROR, "can't get hostname of %s", inet_ntoa(addr));
135                 xfunlock(lockid);
136                 return;
137         }
138         else
139                 hp = hostent_dup (hp);
140
141         if (!setrmtabent("r")) {
142                 xfunlock(lockid);
143                 free (hp);
144                 return;
145         }
146         if (!(fp = fsetrmtabent(_PATH_RMTABTMP, "w"))) {
147                 endrmtabent();
148                 xfunlock(lockid);
149                 free (hp);
150                 return;
151         }
152         while ((rep = getrmtabent(1, NULL)) != NULL) {
153                 if (strcmp(rep->r_client, hp->h_name) == 0 &&
154                     (exp = auth_authenticate("umountall", sin, rep->r_path))) {
155                         export_reset(exp);
156                         continue;
157                 }
158                 fputrmtabent(fp, rep, NULL);
159         }
160         if (slink_safe_rename(_PATH_RMTABTMP, _PATH_RMTAB) < 0) {
161                 xlog(L_ERROR, "couldn't rename %s to %s",
162                                 _PATH_RMTABTMP, _PATH_RMTAB);
163         }
164         endrmtabent();  /* close & unlink */
165         fendrmtabent(fp);
166         xfunlock(lockid);
167         free (hp);
168 }
169
170 mountlist
171 mountlist_list(void)
172 {
173         static mountlist        mlist = NULL;
174         static time_t           last_mtime = 0;
175         mountlist               m;
176         struct rmtabent         *rep;
177         struct stat             stb;
178         int                     lockid;
179
180         if ((lockid = xflock(_PATH_RMTAB, "r")) < 0)
181                 return NULL;
182         if (stat(_PATH_RMTAB, &stb) < 0) {
183                 xlog(L_ERROR, "can't stat %s", _PATH_RMTAB);
184                 return NULL;
185         }
186         if (stb.st_mtime != last_mtime) {
187                 while (mlist) {
188                         mlist = (m = mlist)->ml_next;
189                         xfree(m->ml_hostname);
190                         xfree(m->ml_directory);
191                         xfree(m);
192                 }
193                 last_mtime = stb.st_mtime;
194
195                 setrmtabent("r");
196                 while ((rep = getrmtabent(1, NULL)) != NULL) {
197                         m = (mountlist) xmalloc(sizeof(*m));
198                         m->ml_hostname = xstrdup(rep->r_client);
199                         m->ml_directory = xstrdup(rep->r_path);
200                         m->ml_next = mlist;
201                         mlist = m;
202                 }
203                 endrmtabent();
204         }
205         xfunlock(lockid);
206
207         return mlist;
208 }