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