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