umount.c revision 1.1 1 /*-
2 * Copyright (c) 1980, 1989 The Regents of the University of California.
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 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 char copyright[] =
36 "@(#) Copyright (c) 1980, 1989 The Regents of the University of California.\n\
37 All rights reserved.\n";
38 #endif /* not lint */
39
40 #ifndef lint
41 static char sccsid[] = "@(#)umount.c 5.16 (Berkeley) 6/3/91";
42 #endif /* not lint */
43
44 #include <sys/param.h>
45 #include <sys/stat.h>
46 #include <sys/mount.h>
47
48 #ifdef NFS
49 #include <sys/time.h>
50 #include <sys/socket.h>
51 #include <sys/socketvar.h>
52 #include <netdb.h>
53 #include <rpc/rpc.h>
54 #include <rpc/pmap_clnt.h>
55 #include <rpc/pmap_prot.h>
56 #include <nfs/rpcv2.h>
57 #endif
58
59 #include <fstab.h>
60 #include <stdio.h>
61 #include <string.h>
62
63 #ifdef NFS
64 int xdr_dir();
65 char *nfshost;
66 #endif
67
68 int vflag, all, errs, fake;
69 int fflag = MNT_NOFORCE;
70 char *getmntname();
71
72 #define MNTON 1
73 #define MNTFROM 2
74 #define MNTTYPE 3
75
76 int *typelist, *maketypelist();
77
78 main(argc, argv)
79 int argc;
80 char **argv;
81 {
82 extern char *optarg;
83 extern int optind;
84 int ch;
85
86 sync();
87 while ((ch = getopt(argc, argv, "afFh:t:v")) != EOF)
88 switch((char)ch) {
89 case 'v':
90 vflag++;
91 break;
92 case 'f':
93 fflag = MNT_FORCE;
94 break;
95 case 'F':
96 fake++;
97 break;
98 case 'a':
99 all++;
100 break;
101 case 't':
102 typelist = maketypelist(optarg);
103 break;
104 #ifdef NFS
105 case 'h':
106 /* -h flag implies -a, and "-t nfs" if no -t flag */
107 nfshost = optarg;
108 all++;
109 if (typelist == NULL)
110 typelist = maketypelist("nfs");
111 break;
112 #endif /* NFS */
113 case '?':
114 default:
115 usage();
116 /* NOTREACHED */
117 }
118 argc -= optind;
119 argv += optind;
120
121 if (argc == 0 && !all)
122 usage();
123 if (all) {
124 if (argc > 0)
125 usage();
126 if (setfsent() == 0)
127 perror(FSTAB), exit(1);
128 umountall(typelist);
129 exit(0);
130 } else
131 setfsent();
132 while (argc > 0) {
133 if (umountfs(*argv++, 0) == 0)
134 errs++;
135 argc--;
136 }
137 exit(errs);
138 }
139
140 usage()
141 {
142 fprintf(stderr,
143 "%s\n%s\n",
144 "Usage: umount [-fv] special | node",
145 #ifndef NFS
146 " or umount -a[fv] [-t fstypelist]"
147 #else
148 " or umount -a[fv] [-h host] [-t fstypelist]"
149 #endif
150 );
151 exit(1);
152 }
153
154 umountall(typelist)
155 char **typelist;
156 {
157 register struct fstab *fs;
158 struct fstab *allocfsent();
159
160 if ((fs = getfsent()) == (struct fstab *)0)
161 return;
162 fs = allocfsent(fs);
163 umountall(typelist);
164 if (strcmp(fs->fs_file, "/") == 0) {
165 freefsent(fs);
166 return;
167 }
168 if (strcmp(fs->fs_type, FSTAB_RW) &&
169 strcmp(fs->fs_type, FSTAB_RO) &&
170 strcmp(fs->fs_type, FSTAB_RQ)) {
171 freefsent(fs);
172 return;
173 }
174 (void) umountfs(fs->fs_file, typelist);
175 freefsent(fs);
176 }
177
178 struct fstab *
179 allocfsent(fs)
180 register struct fstab *fs;
181 {
182 register struct fstab *new;
183 register char *cp;
184
185 new = (struct fstab *)malloc((unsigned)sizeof (*fs));
186 cp = (char *)malloc((unsigned)strlen(fs->fs_file) + 1);
187 strcpy(cp, fs->fs_file);
188 new->fs_file = cp;
189 cp = (char *)malloc((unsigned)strlen(fs->fs_type) + 1);
190 strcpy(cp, fs->fs_type);
191 new->fs_type = cp;
192 cp = (char *)malloc((unsigned)strlen(fs->fs_spec) + 1);
193 strcpy(cp, fs->fs_spec);
194 new->fs_spec = cp;
195 new->fs_passno = fs->fs_passno;
196 new->fs_freq = fs->fs_freq;
197 return (new);
198 }
199
200 freefsent(fs)
201 register struct fstab *fs;
202 {
203
204 if (fs->fs_file)
205 free(fs->fs_file);
206 if (fs->fs_spec)
207 free(fs->fs_spec);
208 if (fs->fs_type)
209 free(fs->fs_type);
210 free((char *)fs);
211 }
212
213 umountfs(name, typelist)
214 char *name;
215 int *typelist;
216 {
217 char *mntpt;
218 struct stat stbuf;
219 int type;
220 #ifdef NFS
221 register CLIENT *clp;
222 struct hostent *hp = 0;
223 struct sockaddr_in saddr;
224 struct timeval pertry, try;
225 enum clnt_stat clnt_stat;
226 int so = RPC_ANYSOCK;
227 char *hostp, *delimp;
228 #endif /* NFS */
229
230 if (stat(name, &stbuf) < 0) {
231 if (getmntname(name, MNTFROM, &type) != 0)
232 mntpt = name;
233 else if ((mntpt = getmntname(name, MNTON, &type)) == 0) {
234 fprintf(stderr, "%s: not currently mounted\n", name);
235 return (0);
236 }
237 } else if ((stbuf.st_mode & S_IFMT) == S_IFBLK) {
238 if ((mntpt = getmntname(name, MNTON, &type)) == 0) {
239 fprintf(stderr, "%s: not currently mounted\n", name);
240 return (0);
241 }
242 } else if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
243 mntpt = name;
244 if (getmntname(mntpt, MNTFROM, &type) == 0) {
245 fprintf(stderr, "%s: not currently mounted\n", name);
246 return (0);
247 }
248 } else {
249 fprintf(stderr, "%s: not a directory or special device\n",
250 name);
251 return (0);
252 }
253
254 if (badtype(type, typelist))
255 return(1);
256 #ifdef NFS
257 if ((delimp = index(name, '@')) != NULL) {
258 hostp = delimp + 1;
259 *delimp = '\0';
260 hp = gethostbyname(hostp);
261 *delimp = '@';
262 } else if ((delimp = index(name, ':')) != NULL) {
263 *delimp = '\0';
264 hostp = name;
265 hp = gethostbyname(hostp);
266 name = delimp+1;
267 *delimp = ':';
268 }
269
270 if (!namematch(hp, nfshost))
271 return(1);
272 #endif /* NFS */
273 if (!fake && unmount(mntpt, fflag) < 0) {
274 perror(mntpt);
275 return (0);
276 }
277 if (vflag)
278 fprintf(stderr, "%s: Unmounted from %s\n", name, mntpt);
279
280 #ifdef NFS
281 if (!fake && hp != NULL && (fflag & MNT_FORCE) == 0) {
282 *delimp = '\0';
283 bcopy(hp->h_addr,(caddr_t)&saddr.sin_addr,hp->h_length);
284 saddr.sin_family = AF_INET;
285 saddr.sin_port = 0;
286 pertry.tv_sec = 3;
287 pertry.tv_usec = 0;
288 if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1,
289 pertry, &so)) == NULL) {
290 clnt_pcreateerror("Cannot MNT PRC");
291 return (1);
292 }
293 clp->cl_auth = authunix_create_default();
294 try.tv_sec = 20;
295 try.tv_usec = 0;
296 clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, name,
297 xdr_void, (caddr_t)0, try);
298 if (clnt_stat != RPC_SUCCESS) {
299 clnt_perror(clp, "Bad MNT RPC");
300 return (1);
301 }
302 auth_destroy(clp->cl_auth);
303 clnt_destroy(clp);
304 }
305 #endif /* NFS */
306 return (1);
307 }
308
309 char *
310 getmntname(name, what, type)
311 char *name;
312 int what;
313 int *type;
314 {
315 int mntsize, i;
316 struct statfs *mntbuf;
317
318 if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) {
319 perror("umount");
320 return (0);
321 }
322 for (i = 0; i < mntsize; i++) {
323 if (what == MNTON && !strcmp(mntbuf[i].f_mntfromname, name)) {
324 if (type)
325 *type = mntbuf[i].f_type;
326 return (mntbuf[i].f_mntonname);
327 }
328 if (what == MNTFROM && !strcmp(mntbuf[i].f_mntonname, name)) {
329 if (type)
330 *type = mntbuf[i].f_type;
331 return (mntbuf[i].f_mntfromname);
332 }
333 }
334 return (0);
335 }
336
337 static int skipvfs;
338
339 badtype(type, typelist)
340 int type;
341 int *typelist;
342 {
343 if (typelist == 0)
344 return(0);
345 while (*typelist) {
346 if (type == *typelist)
347 return(skipvfs);
348 typelist++;
349 }
350 return(!skipvfs);
351 }
352
353 int *
354 maketypelist(fslist)
355 char *fslist;
356 {
357 register char *nextcp;
358 register int *av, i;
359
360 if (fslist == NULL)
361 return(NULL);
362 if (fslist[0] == 'n' && fslist[1] == 'o') {
363 fslist += 2;
364 skipvfs = 1;
365 } else
366 skipvfs = 0;
367 for (i = 0, nextcp = fslist; *nextcp; nextcp++)
368 if (*nextcp == ',')
369 i++;
370 av = (int *)malloc((i+2) * sizeof(int));
371 if (av == NULL)
372 return(NULL);
373 for (i = 0; fslist; fslist = nextcp) {
374 if (nextcp = index(fslist, ','))
375 *nextcp++ = '\0';
376 if (strcmp(fslist, "ufs") == 0)
377 av[i++] = MOUNT_UFS;
378 else if (strcmp(fslist, "nfs") == 0)
379 av[i++] = MOUNT_NFS;
380 else if (strcmp(fslist, "mfs") == 0)
381 av[i++] = MOUNT_MFS;
382 else if (strcmp(fslist, "msdos") == 0)
383 av[i++] = MOUNT_MSDOS;
384 else if (strcmp(fslist, "isofs") == 0)
385 av[i++] = MOUNT_ISOFS;
386 }
387 av[i++] = 0;
388 return(av);
389 }
390
391 #ifdef NFS
392 namematch(hp, nfshost)
393 struct hostent *hp;
394 char *nfshost;
395 {
396 register char *cp;
397 register char **np;
398
399 if (hp == NULL || nfshost == NULL)
400 return(1);
401 if (strcasecmp(nfshost, hp->h_name) == 0)
402 return(1);
403 if (cp = index(hp->h_name, '.')) {
404 *cp = '\0';
405 if (strcasecmp(nfshost, hp->h_name) == 0)
406 return(1);
407 }
408 for (np = hp->h_aliases; *np; np++) {
409 if (strcasecmp(nfshost, *np) == 0)
410 return(1);
411 if (cp = index(*np, '.')) {
412 *cp = '\0';
413 if (strcasecmp(nfshost, *np) == 0)
414 return(1);
415 }
416 }
417 return(0);
418 }
419
420 /*
421 * xdr routines for mount rpc's
422 */
423 xdr_dir(xdrsp, dirp)
424 XDR *xdrsp;
425 char *dirp;
426 {
427 return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
428 }
429 #endif /* NFS */
430