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