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