Deleted Added
full compact
rpc.umntall.c (80123) rpc.umntall.c (80146)
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
29static const char rcsid[] =
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
29static const char rcsid[] =
30 "$FreeBSD: head/usr.sbin/rpc.umntall/rpc.umntall.c 80123 2001-07-22 01:25:25Z iedowse $";
30 "$FreeBSD: head/usr.sbin/rpc.umntall/rpc.umntall.c 80146 2001-07-22 12:17:51Z iedowse $";
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
49int verbose;
50
51static int do_umount (char *, char *);
52static int do_umntall (char *);
53static int is_mounted (char *, char *);
54static void usage (void);
55int xdr_dir (XDR *, char *);
56
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
49int verbose;
50
51static int do_umount (char *, char *);
52static int do_umntall (char *);
53static int is_mounted (char *, char *);
54static void usage (void);
55int xdr_dir (XDR *, char *);
56
57struct mtablist *mtabhead;
58
59int
60main(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 expire = 0;
67 host = path = NULL;
68 success = keep = verbose = 0;
69 while ((ch = getopt(argc, argv, "h:kp:ve:")) != -1)
70 switch (ch) {
71 case 'h':
72 host = optarg;
73 break;
74 case 'e':
75 expire = atoi(optarg);
76 break;
77 case 'k':
78 keep = 1;
79 break;
80 case 'p':
81 path = optarg;
82 break;
83 case 'v':
84 verbose = 1;
85 break;
86 case '?':
87 usage();
88 default:
89 }
90 argc -= optind;
91 argv += optind;
92
93 /* Ignore SIGINT and SIGQUIT during shutdown */
94 signal(SIGINT, SIG_IGN);
95 signal(SIGQUIT, SIG_IGN);
96
97 /* Default expiretime is one day */
98 if (expire == 0)
99 expire = 86400;
100 time(&now);
101
102 /* Read PATH_MOUNTTAB. */
57int
58main(int argc, char **argv) {
59 int ch, keep, success, pathlen;
60 time_t expire, now;
61 char *host, *path;
62 struct mtablist *mtab;
63
64 expire = 0;
65 host = path = NULL;
66 success = keep = verbose = 0;
67 while ((ch = getopt(argc, argv, "h:kp:ve:")) != -1)
68 switch (ch) {
69 case 'h':
70 host = optarg;
71 break;
72 case 'e':
73 expire = atoi(optarg);
74 break;
75 case 'k':
76 keep = 1;
77 break;
78 case 'p':
79 path = optarg;
80 break;
81 case 'v':
82 verbose = 1;
83 break;
84 case '?':
85 usage();
86 default:
87 }
88 argc -= optind;
89 argv += optind;
90
91 /* Ignore SIGINT and SIGQUIT during shutdown */
92 signal(SIGINT, SIG_IGN);
93 signal(SIGQUIT, SIG_IGN);
94
95 /* Default expiretime is one day */
96 if (expire == 0)
97 expire = 86400;
98 time(&now);
99
100 /* Read PATH_MOUNTTAB. */
103 if (!read_mtab(NULL)) {
101 if (!read_mtab()) {
104 if (verbose)
105 warnx("no mounttab entries (%s does not exist)",
106 PATH_MOUNTTAB);
107 mtabhead = NULL;
108 }
109
110 if (host == NULL && path == NULL) {
111 /* Check each entry and do any necessary unmount RPCs. */
112 for (mtab = mtabhead; mtab != NULL; mtab = mtab->mtab_next) {
113 if (*mtab->mtab_host == '\0')
114 continue;
115 if (mtab->mtab_time + expire < now) {
116 /* Clear expired entry. */
117 if (verbose)
118 warnx("remove expired entry %s:%s",
119 mtab->mtab_host, mtab->mtab_dirp);
120 bzero(mtab->mtab_host,
121 sizeof(mtab->mtab_host));
122 continue;
123 }
124 if (keep && is_mounted(mtab->mtab_host,
125 mtab->mtab_dirp)) {
126 if (verbose)
127 warnx("skip entry %s:%s",
128 mtab->mtab_host, mtab->mtab_dirp);
129 continue;
130 }
131 if (do_umount(mtab->mtab_host, mtab->mtab_dirp)) {
132 if (verbose)
133 warnx("umount RPC for %s:%s succeeded",
134 mtab->mtab_host, mtab->mtab_dirp);
135 /* Remove all entries for this host + path. */
102 if (verbose)
103 warnx("no mounttab entries (%s does not exist)",
104 PATH_MOUNTTAB);
105 mtabhead = NULL;
106 }
107
108 if (host == NULL && path == NULL) {
109 /* Check each entry and do any necessary unmount RPCs. */
110 for (mtab = mtabhead; mtab != NULL; mtab = mtab->mtab_next) {
111 if (*mtab->mtab_host == '\0')
112 continue;
113 if (mtab->mtab_time + expire < now) {
114 /* Clear expired entry. */
115 if (verbose)
116 warnx("remove expired entry %s:%s",
117 mtab->mtab_host, mtab->mtab_dirp);
118 bzero(mtab->mtab_host,
119 sizeof(mtab->mtab_host));
120 continue;
121 }
122 if (keep && is_mounted(mtab->mtab_host,
123 mtab->mtab_dirp)) {
124 if (verbose)
125 warnx("skip entry %s:%s",
126 mtab->mtab_host, mtab->mtab_dirp);
127 continue;
128 }
129 if (do_umount(mtab->mtab_host, mtab->mtab_dirp)) {
130 if (verbose)
131 warnx("umount RPC for %s:%s succeeded",
132 mtab->mtab_host, mtab->mtab_dirp);
133 /* Remove all entries for this host + path. */
136 clean_mtab(mtab->mtab_host, mtab->mtab_dirp);
134 clean_mtab(mtab->mtab_host, mtab->mtab_dirp,
135 verbose);
137 }
138 }
139 success = 1;
140 } else {
141 if (host == NULL && path != NULL)
142 /* Missing hostname. */
143 usage();
144 if (path == NULL) {
145 /* Do a RPC UMNTALL for this specific host */
146 success = do_umntall(host);
147 if (verbose && success)
148 warnx("umntall RPC for %s succeeded", host);
149 } else {
150 /* Do a RPC UMNTALL for this specific mount */
151 for (pathlen = strlen(path);
152 pathlen > 1 && path[pathlen - 1] == '/'; pathlen--)
153 path[pathlen - 1] = '\0';
154 success = do_umount(host, path);
155 if (verbose && success)
156 warnx("umount RPC for %s:%s succeeded", host,
157 path);
158 }
159 /* If successful, remove any corresponding mounttab entries. */
160 if (success)
136 }
137 }
138 success = 1;
139 } else {
140 if (host == NULL && path != NULL)
141 /* Missing hostname. */
142 usage();
143 if (path == NULL) {
144 /* Do a RPC UMNTALL for this specific host */
145 success = do_umntall(host);
146 if (verbose && success)
147 warnx("umntall RPC for %s succeeded", host);
148 } else {
149 /* Do a RPC UMNTALL for this specific mount */
150 for (pathlen = strlen(path);
151 pathlen > 1 && path[pathlen - 1] == '/'; pathlen--)
152 path[pathlen - 1] = '\0';
153 success = do_umount(host, path);
154 if (verbose && success)
155 warnx("umount RPC for %s:%s succeeded", host,
156 path);
157 }
158 /* If successful, remove any corresponding mounttab entries. */
159 if (success)
161 clean_mtab(host, path);
160 clean_mtab(host, path, verbose);
162 }
163 /* Write and unlink PATH_MOUNTTAB if necessary */
164 if (success)
161 }
162 /* Write and unlink PATH_MOUNTTAB if necessary */
163 if (success)
165 success = write_mtab();
164 success = write_mtab(verbose);
166 free_mtab();
167 exit (success ? 0 : 1);
168}
169
170/*
171 * Send a RPC_MNT UMNTALL request to hostname.
172 * XXX This works for all mountd implementations,
173 * but produces a RPC IOERR on non FreeBSD systems.
174 */
175int
176do_umntall(char *hostname) {
177 enum clnt_stat clnt_stat;
178 struct timeval try;
179 CLIENT *clp;
180
181 clp = clnt_create(hostname, RPCPROG_MNT, RPCMNT_VER1, "udp");
182 if (clp == NULL) {
183 warnx("%s: %s", hostname, clnt_spcreateerror("RPCPROG_MNT"));
184 return (1);
185 }
186 clp->cl_auth = authunix_create_default();
187 try.tv_sec = 3;
188 try.tv_usec = 0;
189 clnt_stat = clnt_call(clp, RPCMNT_UMNTALL, xdr_void, (caddr_t)0,
190 xdr_void, (caddr_t)0, try);
191 clnt_destroy(clp);
192 if (clnt_stat != RPC_SUCCESS) {
193 warnx("%s: %s", hostname, clnt_sperror(clp, "RPCMNT_UMNTALL"));
194 return (0);
195 } else
196 return (1);
197}
198
199/*
200 * Send a RPC_MNT UMOUNT request for dirp to hostname.
201 */
202int
203do_umount(char *hostname, char *dirp) {
204 enum clnt_stat clnt_stat;
205 struct timeval try;
206 CLIENT *clp;
207
208 clp = clnt_create(hostname, RPCPROG_MNT, RPCMNT_VER1, "udp");
209 if (clp == NULL) {
210 warnx("%s: %s", hostname, clnt_spcreateerror("RPCPROG_MNT"));
211 return (1);
212 }
213 clp->cl_auth = authsys_create_default();
214 try.tv_sec = 3;
215 try.tv_usec = 0;
216 clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, dirp,
217 xdr_void, (caddr_t)0, try);
218 clnt_destroy(clp);
219 if (clnt_stat != RPC_SUCCESS) {
220 warnx("%s: %s", hostname, clnt_sperror(clp, "RPCMNT_UMOUNT"));
221 return (0);
222 }
223 return (1);
224}
225
226/*
227 * Check if the entry is still/already mounted.
228 */
229int
230is_mounted(char *hostname, char *dirp) {
231 struct statfs *mntbuf;
232 char name[MNAMELEN + 1];
233 size_t bufsize;
234 int mntsize, i;
235
236 if (strlen(hostname) + strlen(dirp) >= MNAMELEN)
237 return (0);
238 snprintf(name, sizeof(name), "%s:%s", hostname, dirp);
239 mntsize = getfsstat(NULL, 0, MNT_NOWAIT);
240 if (mntsize <= 0)
241 return (0);
242 bufsize = (mntsize + 1) * sizeof(struct statfs);
243 if ((mntbuf = malloc(bufsize)) == NULL)
244 err(1, "malloc");
245 mntsize = getfsstat(mntbuf, (long)bufsize, MNT_NOWAIT);
246 for (i = mntsize - 1; i >= 0; i--) {
247 if (strcmp(mntbuf[i].f_mntfromname, name) == 0) {
248 free(mntbuf);
249 return (1);
250 }
251 }
252 free(mntbuf);
253 return (0);
254}
255
256/*
257 * xdr routines for mount rpc's
258 */
259int
260xdr_dir(XDR *xdrsp, char *dirp) {
261 return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
262}
263
264static void
265usage() {
266 (void)fprintf(stderr, "%s\n",
267 "usage: rpc.umntall [-kv] [-e expire] [-h host] [-p path]");
268 exit(1);
269}
165 free_mtab();
166 exit (success ? 0 : 1);
167}
168
169/*
170 * Send a RPC_MNT UMNTALL request to hostname.
171 * XXX This works for all mountd implementations,
172 * but produces a RPC IOERR on non FreeBSD systems.
173 */
174int
175do_umntall(char *hostname) {
176 enum clnt_stat clnt_stat;
177 struct timeval try;
178 CLIENT *clp;
179
180 clp = clnt_create(hostname, RPCPROG_MNT, RPCMNT_VER1, "udp");
181 if (clp == NULL) {
182 warnx("%s: %s", hostname, clnt_spcreateerror("RPCPROG_MNT"));
183 return (1);
184 }
185 clp->cl_auth = authunix_create_default();
186 try.tv_sec = 3;
187 try.tv_usec = 0;
188 clnt_stat = clnt_call(clp, RPCMNT_UMNTALL, xdr_void, (caddr_t)0,
189 xdr_void, (caddr_t)0, try);
190 clnt_destroy(clp);
191 if (clnt_stat != RPC_SUCCESS) {
192 warnx("%s: %s", hostname, clnt_sperror(clp, "RPCMNT_UMNTALL"));
193 return (0);
194 } else
195 return (1);
196}
197
198/*
199 * Send a RPC_MNT UMOUNT request for dirp to hostname.
200 */
201int
202do_umount(char *hostname, char *dirp) {
203 enum clnt_stat clnt_stat;
204 struct timeval try;
205 CLIENT *clp;
206
207 clp = clnt_create(hostname, RPCPROG_MNT, RPCMNT_VER1, "udp");
208 if (clp == NULL) {
209 warnx("%s: %s", hostname, clnt_spcreateerror("RPCPROG_MNT"));
210 return (1);
211 }
212 clp->cl_auth = authsys_create_default();
213 try.tv_sec = 3;
214 try.tv_usec = 0;
215 clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, dirp,
216 xdr_void, (caddr_t)0, try);
217 clnt_destroy(clp);
218 if (clnt_stat != RPC_SUCCESS) {
219 warnx("%s: %s", hostname, clnt_sperror(clp, "RPCMNT_UMOUNT"));
220 return (0);
221 }
222 return (1);
223}
224
225/*
226 * Check if the entry is still/already mounted.
227 */
228int
229is_mounted(char *hostname, char *dirp) {
230 struct statfs *mntbuf;
231 char name[MNAMELEN + 1];
232 size_t bufsize;
233 int mntsize, i;
234
235 if (strlen(hostname) + strlen(dirp) >= MNAMELEN)
236 return (0);
237 snprintf(name, sizeof(name), "%s:%s", hostname, dirp);
238 mntsize = getfsstat(NULL, 0, MNT_NOWAIT);
239 if (mntsize <= 0)
240 return (0);
241 bufsize = (mntsize + 1) * sizeof(struct statfs);
242 if ((mntbuf = malloc(bufsize)) == NULL)
243 err(1, "malloc");
244 mntsize = getfsstat(mntbuf, (long)bufsize, MNT_NOWAIT);
245 for (i = mntsize - 1; i >= 0; i--) {
246 if (strcmp(mntbuf[i].f_mntfromname, name) == 0) {
247 free(mntbuf);
248 return (1);
249 }
250 }
251 free(mntbuf);
252 return (0);
253}
254
255/*
256 * xdr routines for mount rpc's
257 */
258int
259xdr_dir(XDR *xdrsp, char *dirp) {
260 return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
261}
262
263static void
264usage() {
265 (void)fprintf(stderr, "%s\n",
266 "usage: rpc.umntall [-kv] [-e expire] [-h host] [-p path]");
267 exit(1);
268}