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: }

Defined functions

fsnametotype defined in line 287; used 3 times
getmntname defined in line 204; used 5 times
main defined in line 65; never used
maketypelist defined in line 247; used 2 times
selected defined in line 234; used 3 times
umountall defined in line 116; used 3 times
umountfs defined in line 158; used 3 times
usage defined in line 300; used 3 times

Defined variables

copyright defined in line 35; never used
fake defined in line 53; used 2 times
fflag defined in line 53; used 1 times
  • in line 86
nfshost defined in line 54; never used
sccsid defined in line 39; never used
typelist defined in line 53; used 5 times
vflag defined in line 53; used 2 times
Last modified: 1996-01-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1704
Valid CSS Valid XHTML 1.0 Strict