1: /*- 2: * Copyright (c) 1980, 1989, 1993 3: * The Regents of the University of California. 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: #if !defined(lint) && defined(DOSCCS) 35: static char copyright[] = 36: "@(#) Copyright (c) 1980, 1989, 1993\n\ 37: The Regents of the University of California. All rights reserved.\n"; 38: 39: static char sccsid[] = "@(#)umount.c 8.3.1 (2.11BSD) 1996/1/16"; 40: #endif /* not lint */ 41: 42: #include <sys/param.h> 43: #include <sys/stat.h> 44: #include <sys/mount.h> 45: #include <fstab.h> 46: #include <stdio.h> 47: #include <stdlib.h> 48: #include <string.h> 49: #include <unistd.h> 50: 51: typedef enum { MNTON, MNTFROM } mntwhat; 52: 53: int fake, fflag, vflag, *typelist; 54: char *nfshost; 55: 56: int fsnametotype(); 57: char *getmntname(); 58: void maketypelist(); 59: int selected(); 60: int namematch(); 61: int umountall(); 62: int umountfs(); 63: void usage(); 64: 65: int 66: main(argc, argv) 67: int argc; 68: register char *argv[]; 69: { 70: int all, ch, errs; 71: 72: /* Start disks transferring immediately. */ 73: sync(); 74: 75: all = 0; 76: while ((ch = getopt(argc, argv, "aFft:v")) != EOF) 77: switch (ch) { 78: case 'a': 79: all = 1; 80: break; 81: case 'F': 82: fake = 1; 83: break; 84: case 'f': 85: #ifdef notnow 86: fflag = MNT_FORCE; 87: #endif 88: break; 89: case 't': 90: maketypelist(optarg); 91: break; 92: case 'v': 93: vflag = 1; 94: break; 95: default: 96: usage(); 97: /* NOTREACHED */ 98: } 99: argc -= optind; 100: argv += optind; 101: 102: if (argc == 0 && !all || argc != 0 && all) 103: usage(); 104: 105: if (all) { 106: if (setfsent() == 0) 107: err(1, "%s", _PATH_FSTAB); 108: errs = umountall(); 109: } else 110: for (errs = 0; *argv != NULL; ++argv) 111: if (umountfs(*argv) == 0) 112: errs = 1; 113: exit(errs); 114: } 115: 116: int 117: umountall() 118: { 119: register struct fstab *fs; 120: int rval, type; 121: register char *cp; 122: 123: while ((fs = getfsent()) != NULL) { 124: /* Ignore the root. */ 125: if (strcmp(fs->fs_file, "/") == 0) 126: continue; 127: /* 128: * !!! 129: * Historic practice: ignore unknown FSTAB_* fields. 130: */ 131: if (strcmp(fs->fs_type, FSTAB_RW) && 132: strcmp(fs->fs_type, FSTAB_RO) && 133: strcmp(fs->fs_type, FSTAB_RQ)) 134: continue; 135: /* If an unknown file system type, complain. */ 136: if ((type = fsnametotype(fs->fs_vfstype)) == MOUNT_NONE) { 137: warnx("%s: unknown mount type", fs->fs_vfstype); 138: continue; 139: } 140: if (!selected(type)) 141: continue; 142: 143: /* 144: * We want to unmount the file systems in the reverse order 145: * that they were mounted. So, we save off the file name 146: * in some allocated memory, and then call recursively. 147: */ 148: cp = (char *)malloc((size_t)strlen(fs->fs_file) + 1); 149: if (cp == NULL) 150: err(1, NULL); 151: (void)strcpy(cp, fs->fs_file); 152: rval = umountall(); 153: return (umountfs(cp) || rval); 154: } 155: return (0); 156: } 157: 158: int 159: umountfs(name) 160: char *name; 161: { 162: struct stat sb; 163: int type; 164: register char *mntpt; 165: 166: if (stat(name, &sb) < 0) { 167: if (((mntpt = getmntname(name, MNTFROM, &type)) == NULL) && 168: ((mntpt = getmntname(name, MNTON, &type)) == NULL)) { 169: warnx("%s: not currently mounted", name); 170: return (1); 171: } 172: } else if ((sb.st_mode & S_IFMT) == S_IFBLK) { 173: if ((mntpt = getmntname(name, MNTON, &type)) == NULL) { 174: warnx("%s: not currently mounted", name); 175: return (1); 176: } 177: } else if ((sb.st_mode & S_IFMT) == S_IFDIR) { 178: mntpt = name; 179: if ((name = getmntname(mntpt, MNTFROM, &type)) == NULL) { 180: warnx("%s: not currently mounted", mntpt); 181: return (1); 182: } 183: } else { 184: warnx("%s: not a directory or special device", name); 185: return (1); 186: } 187: 188: if (!selected(type)) 189: return (0); 190: 191: if (vflag) 192: (void)printf("%s: unmount from %s\n", name, mntpt); 193: if (fake) 194: return (0); 195: 196: if (umount(name) < 0) { 197: warn("%s on %s", name, mntpt); 198: return (1); 199: } 200: 201: return (0); 202: } 203: 204: char * 205: getmntname(name, what, type) 206: char *name; 207: mntwhat what; 208: int *type; 209: { 210: struct statfs *mntbuf; 211: register int i, mntsize; 212: 213: if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) { 214: warn("getmntinfo"); 215: return (NULL); 216: } 217: for (i = 0; i < mntsize; i++) { 218: if ((what == MNTON) && !strcmp(mntbuf[i].f_mntfromname, name)) { 219: if (type) 220: *type = mntbuf[i].f_type; 221: return (mntbuf[i].f_mntonname); 222: } 223: if ((what == MNTFROM) && !strcmp(mntbuf[i].f_mntonname, name)) { 224: if (type) 225: *type = mntbuf[i].f_type; 226: return (mntbuf[i].f_mntfromname); 227: } 228: } 229: return (NULL); 230: } 231: 232: static enum { IN_LIST, NOT_IN_LIST } which; 233: 234: int 235: selected(type) 236: int type; 237: { 238: /* If no type specified, it's always selected. */ 239: if (typelist == NULL) 240: return (1); 241: for (; *typelist != MOUNT_NONE; ++typelist) 242: if (type == *typelist) 243: return (which == IN_LIST ? 1 : 0); 244: return (which == IN_LIST ? 0 : 1); 245: } 246: 247: void 248: maketypelist(fslist) 249: register char *fslist; 250: { 251: register int *av, i; 252: char *nextcp; 253: 254: if ((fslist == NULL) || (fslist[0] == '\0')) 255: errx(1, "empty type list"); 256: 257: /* 258: * XXX 259: * Note: the syntax is "noxxx,yyy" for no xxx's and 260: * no yyy's, not the more intuitive "noyyy,noyyy". 261: */ 262: if (fslist[0] == 'n' && fslist[1] == 'o') { 263: fslist += 2; 264: which = NOT_IN_LIST; 265: } else 266: which = IN_LIST; 267: 268: /* Count the number of types. */ 269: for (i = 0, nextcp = fslist; *nextcp != NULL; ++nextcp) 270: if (*nextcp == ',') 271: i++; 272: 273: /* Build an array of that many types. */ 274: if ((av = typelist = (int *)malloc((i + 2) * sizeof(int))) == NULL) 275: err(1, NULL); 276: for (i = 0; fslist != NULL; fslist = nextcp, ++i) { 277: if ((nextcp = strchr(fslist, ',')) != NULL) 278: *nextcp++ = '\0'; 279: av[i] = fsnametotype(fslist); 280: if (av[i] == MOUNT_NONE) 281: errx(1, "%s: unknown mount type", fslist); 282: } 283: /* Terminate the array. */ 284: av[i++] = MOUNT_NONE; 285: } 286: 287: int 288: fsnametotype(name) 289: char *name; 290: { 291: static char *namelist[] = INITMOUNTNAMES; 292: register char **cp; 293: 294: for (cp = namelist; *cp; ++cp) 295: if (strcmp(name, *cp) == 0) 296: return (cp - namelist); 297: return (MOUNT_NONE); 298: } 299: 300: void 301: usage() 302: { 303: (void)fprintf(stderr, 304: "usage: %s\n %s\n", 305: "umount [-fv] [-t fstypelist] special | node", 306: "umount -a[fv] [-t fstypelist]"); 307: exit(1); 308: }