]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/rpc.umntall/rpc.umntall.c
This commit was generated by cvs2svn to compensate for changes in r55357,
[FreeBSD/FreeBSD.git] / usr.sbin / rpc.umntall / rpc.umntall.c
1 /*
2  * Copyright (c) 1999 Martin Blapp
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27
28 #ifndef lint
29 static const char rcsid[] =
30   "$FreeBSD$";
31 #endif /* not lint */
32
33 #include <sys/param.h>
34 #include <sys/ucred.h>
35 #include <sys/mount.h>
36
37 #include <rpc/rpc.h>
38 #include <nfs/rpcv2.h>
39
40 #include <err.h>
41 #include <netdb.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46
47 #include "mounttab.h"
48
49 int verbose;
50
51 static int do_umount (char *, char *);
52 static int do_umntall (char *);
53 static int is_mounted (char *, char *);
54 static void usage (void);
55 int     xdr_dir (XDR *, char *);
56
57 struct mtablist *mtabhead;
58
59 int
60 main(int argc, char **argv) {
61         int ch, keep, success, pathlen;
62         time_t expire, *now;
63         char *host, *path;
64         struct mtablist *mtab;
65
66         mtab = NULL;
67         now = NULL;
68         expire = 0;
69         host = path = '\0';
70         success = keep = verbose = 0;
71         while ((ch = getopt(argc, argv, "h:kp:ve:")) != -1)
72                 switch (ch) {
73                 case 'h':
74                         host = optarg;
75                         break;
76                 case 'e':
77                         expire = (time_t)optarg;
78                         break;
79                 case 'k':
80                         keep = 1;
81                         break;
82                 case 'p':
83                         path = optarg;
84                         break;
85                 case 'v':
86                         verbose = 1;
87                         break;
88                 case '?':
89                         usage();
90                 default:
91                 }
92         argc -= optind;
93         argv += optind;
94
95         /* Ignore SIGINT and SIGQUIT during shutdown */
96         signal(SIGINT, SIG_IGN);
97         signal(SIGQUIT, SIG_IGN);
98
99         /* Default expiretime is two days */
100         if (expire == 0)
101                 expire = 172800;
102         /*
103          * Read PATH_MOUNTTAB and check each entry
104          * and do finally the unmounts.
105          */
106         if (host == NULL && path == NULL) {
107                 if (!read_mtab(mtab)) {
108                         if (verbose)
109                                 warnx("nothing to do, remove %s",
110                                     PATH_MOUNTTAB);
111                 }
112                 for (mtab = mtabhead; mtab != NULL; mtab = mtab->mtab_next) {
113                         if (*mtab->mtab_host != '\0' ||
114                             mtab->mtab_time <= (time(now) - expire)) {
115                                 if (keep && is_mounted(mtab->mtab_host,
116                                     mtab->mtab_dirp)) {
117                                         if (verbose) {
118                                                 warnx("skipping entry %s:%s",
119                                                     mtab->mtab_host,
120                                                     mtab->mtab_dirp);
121                                         }
122                                 } else if (do_umount(mtab->mtab_host,
123                                     mtab->mtab_dirp)) {
124                                         clean_mtab(mtab->mtab_host,
125                                             mtab->mtab_dirp);
126                                 }
127                         }
128                 }
129         /* Only do a RPC UMNTALL for this specific host */
130         } else if (host != NULL && path == NULL) {
131                 if (!do_umntall(host))
132                         exit(1);
133                 else 
134                         success = 1;
135         /* Someone forgot to enter a hostname */
136         } else if (host == NULL && path != NULL)
137                 usage();
138         /* Only do a RPC UMOUNT for this specific mount */
139         else {
140                 for (pathlen = strlen(path);
141                     pathlen > 1 && path[pathlen - 1] == '/'; pathlen--)
142                         path[pathlen - 1] = '\0';
143                 if (!do_umount(host, path))
144                         exit(1);
145                 else 
146                         success = 1;
147         }
148         /* Write and unlink PATH_MOUNTTAB if necessary */
149         if (success) {
150                 if (verbose)
151                         warnx("UMOUNT RPC successfully sent to %s", host);
152                 if (read_mtab(mtab)) {
153                         mtab = mtabhead;
154                         clean_mtab(host, path);
155                 }
156         }
157         if (!write_mtab()) {
158                 free_mtab();
159                 exit(1);
160         }
161         free_mtab();
162         exit(0);
163 }
164
165 /*
166  * Send a RPC_MNT UMNTALL request to hostname.
167  * XXX This works for all mountd implementations,
168  * but produces a RPC IOERR on non FreeBSD systems.
169  */
170 int
171 do_umntall(char *hostname) {
172         enum clnt_stat clnt_stat;
173         struct hostent *hp;
174         struct sockaddr_in saddr;
175         struct timeval pertry, try;
176         int so;
177         CLIENT *clp;
178
179         if ((hp = gethostbyname(hostname)) == NULL) {
180                 warnx("gethostbyname(%s) failed", hostname);
181                 return (0);
182         }
183         memset(&saddr, 0, sizeof(saddr));
184         saddr.sin_family = AF_INET;
185         saddr.sin_port = 0;
186         memmove(&saddr.sin_addr, hp->h_addr, MIN(hp->h_length,
187             sizeof(saddr.sin_addr)));
188         pertry.tv_sec = 3;
189         pertry.tv_usec = 0;
190         so = RPC_ANYSOCK;
191         if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1,
192             pertry, &so)) == NULL) {
193                 clnt_pcreateerror("Cannot send MNT PRC");
194                 return (0);
195         }
196         clp->cl_auth = authunix_create_default();
197         try.tv_sec = 3;
198         try.tv_usec = 0;
199         clnt_stat = clnt_call(clp, RPCMNT_UMNTALL, xdr_void, (caddr_t)0,
200             xdr_void, (caddr_t)0, try);
201         if (clnt_stat != RPC_SUCCESS) {
202                 clnt_perror(clp, "Bad MNT RPC");
203                 return (0);
204         } else
205                 return (1);
206 }
207
208 /*
209  * Send a RPC_MNT UMOUNT request for dirp to hostname.
210  */
211 int
212 do_umount(char *hostname, char *dirp) {
213         enum clnt_stat clnt_stat;
214         struct hostent *hp;
215         struct sockaddr_in saddr;
216         struct timeval pertry, try;
217         CLIENT *clp;
218         int so;
219
220         if ((hp = gethostbyname(hostname)) == NULL) {
221                 warnx("gethostbyname(%s) failed", hostname);
222                 return (0);
223         }
224         memset(&saddr, 0, sizeof(saddr));
225         saddr.sin_family = AF_INET;
226         saddr.sin_port = 0;
227         memmove(&saddr.sin_addr, hp->h_addr, MIN(hp->h_length,
228             sizeof(saddr.sin_addr)));
229         pertry.tv_sec = 3;
230         pertry.tv_usec = 0;
231         so = RPC_ANYSOCK;
232         if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1,
233             pertry, &so)) == NULL) {
234                 clnt_pcreateerror("Cannot send MNT PRC");
235                 return (0);
236         }
237         clp->cl_auth = authunix_create_default();
238         try.tv_sec = 3;
239         try.tv_usec = 0;
240         clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, dirp,
241             xdr_void, (caddr_t)0, try);
242         if (clnt_stat != RPC_SUCCESS) {
243                 clnt_perror(clp, "Bad MNT RPC");
244                 return (0);
245         }
246         return (1);
247 }
248
249 /*
250  * Check if the entry is still/already mounted.
251  */
252 int
253 is_mounted(char *hostname, char *dirp) {
254         struct statfs *mntbuf;
255         char name[MNAMELEN + 1];
256         size_t bufsize, hostlen, dirlen;
257         int mntsize, i;
258
259         hostlen = strlen(hostname);
260         dirlen = strlen(dirp);
261         if ((hostlen + dirlen) >= MNAMELEN)
262                 return (0);
263         memmove(name, hostname, hostlen);
264         name[hostlen] = ':';
265         memmove(name + hostlen + 1, dirp, dirlen);
266         name[hostlen + dirlen + 1] = '\0';
267         mntsize = getfsstat(NULL, 0, MNT_NOWAIT);
268         if (mntsize <= 0)
269                 return (0);
270         bufsize = (mntsize + 1) * sizeof(struct statfs);
271         if ((mntbuf = malloc(bufsize)) == NULL)
272                 err(1, "malloc");
273         mntsize = getfsstat(mntbuf, (long)bufsize, MNT_NOWAIT);
274         for (i = mntsize - 1; i >= 0; i--) {
275                 if (strcmp(mntbuf[i].f_mntfromname, name) == 0) {
276                         free(mntbuf);
277                         return (1);
278                 }
279         }
280         free(mntbuf);
281         return (0);
282 }
283
284 /*
285  * xdr routines for mount rpc's
286  */
287 int
288 xdr_dir(XDR *xdrsp, char *dirp) {
289
290         return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
291 }
292
293 static void
294 usage() {
295
296         (void)fprintf(stderr, "%s\n",
297             "usage: rpc.umntall [-h host] [-k] [-p path] [-t expire] [-v]");
298         exit(1);
299 }