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