diff --git a/sbin/umount/Makefile b/sbin/umount/Makefile index 120b3602635d..ec628cdee1a1 100644 --- a/sbin/umount/Makefile +++ b/sbin/umount/Makefile @@ -1,6 +1,13 @@ -# @(#)Makefile 8.2 (Berkeley) 2/20/94 +# @(#)Makefile 8.4 (Berkeley) 6/22/95 PROG= umount +SRCS= umount.c vfslist.c MAN8= umount.8 +MOUNT= ${.CURDIR}/../mount +CFLAGS+= -I${MOUNT} +.PATH: ${MOUNT} + +CFLAGS+= -D_NEW_VFSCONF + .include diff --git a/sbin/umount/umount.8 b/sbin/umount/umount.8 index d1d02d018a5a..a2742c5ceb0a 100644 --- a/sbin/umount/umount.8 +++ b/sbin/umount/umount.8 @@ -29,23 +29,23 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" @(#)umount.8 8.1 (Berkeley) 2/20/94 +.\" @(#)umount.8 8.2 (Berkeley) 5/8/95 .\" -.Dd February 20, 1994 +.Dd May 8, 1995 .Dt UMOUNT 8 .Os BSD 4 .Sh NAME .Nm umount -.Nd unmount file systems +.Nd unmount filesystems .Sh SYNOPSIS .Nm umount .Op Fl fv .Ar special | node .Nm umount -.Fl a +.Fl a | A .Op Fl fv .Op Fl h Ar host -.Op Fl t Ar ufs | lfs | external_type +.Op Fl t Ar type .Sh DESCRIPTION The .Nm umount @@ -54,7 +54,7 @@ calls the .Xr unmount 2 system call to remove a .Ar "special device" -or the remote node (rhost:path) from the file system tree at the point +or the remote node (rhost:path) from the filesystem tree at the point .Ar node . If either .Ar special @@ -67,23 +67,26 @@ file. The options are as follows: .Bl -tag -width indent .It Fl a -All of the file systems described in +All the filesystems described in .Xr fstab 5 are unmounted. +.It Fl A +All the currently mounted filesystems except +the root are unmounted. .It Fl f -The file system is forcibly unmounted. +The filesystem is forcibly unmounted. Active special devices continue to work, but all other files return errors if further accesses are attempted. -The root file system cannot be forcibly unmounted. +The root filesystem cannot be forcibly unmounted. .It Fl h Ar host Only filesystems mounted from the specified host will be unmounted. This option is implies the -.Fl a +.Fl A option and, unless otherwise specified with the .Fl t option, will only unmount NFS filesystems. -.It Fl t Ar "ufs \\*(Ba lfs \\*(Ba external type" +.It Fl t Ar type Is used to indicate the actions should only be taken on filesystems of the specified type. More than one type may be specified in a comma separated list. @@ -104,13 +107,13 @@ umounts all filesystems of the type and .Tn MFS . .It Fl v -Verbose, additional information is printed out as each file system +Verbose, additional information is printed out as each filesystem is unmounted. .El .Sh FILES .Bl -tag -width /etc/fstab -compact .It Pa /etc/fstab -file system table +filesystem table .El .Sh SEE ALSO .Xr unmount 2 , diff --git a/sbin/umount/umount.c b/sbin/umount/umount.c index 611bace79d8a..6c54b35b2558 100644 --- a/sbin/umount/umount.c +++ b/sbin/umount/umount.c @@ -38,7 +38,7 @@ static char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)umount.c 8.3 (Berkeley) 2/20/94"; +static char sccsid[] = "@(#)umount.c 8.8 (Berkeley) 5/8/95"; #endif /* not lint */ #include @@ -63,16 +63,16 @@ static char sccsid[] = "@(#)umount.c 8.3 (Berkeley) 2/20/94"; typedef enum { MNTON, MNTFROM } mntwhat; -int fake, fflag, vflag, *typelist; +int fake, fflag, vflag; char *nfshost; -int fsnametotype __P((char *)); -char *getmntname __P((char *, mntwhat, int *)); -void maketypelist __P((char *)); +int checkvfsname __P((const char *, char **)); +char *getmntname __P((char *, mntwhat, char **)); +char **makevfslist __P((char *)); int selected __P((int)); int namematch __P((struct hostent *)); -int umountall __P((void)); -int umountfs __P((char *)); +int umountall __P((char **)); +int umountfs __P((char *, char **)); void usage __P((void)); int xdr_dir __P((XDR *, char *)); @@ -81,14 +81,19 @@ main(argc, argv) int argc; char *argv[]; { - int all, ch, errs; + int all, ch, errs, mnts; + char **typelist = NULL; + struct statfs *mntbuf; /* Start disks transferring immediately. */ sync(); all = 0; - while ((ch = getopt(argc, argv, "aFfh:t:v")) != -1) + while ((ch = getopt(argc, argv, "AaFfh:t:v")) != -1) switch (ch) { + case 'A': + all = 2; + break; case 'a': all = 1; break; @@ -98,12 +103,14 @@ main(argc, argv) case 'f': fflag = MNT_FORCE; break; - case 'h': /* -h implies -a. */ - all = 1; + case 'h': /* -h implies -A. */ + all = 2; nfshost = optarg; break; case 't': - maketypelist(optarg); + if (typelist != NULL) + errx(1, "only one -t option may be specified."); + typelist = makevfslist(optarg); break; case 'v': vflag = 1; @@ -120,24 +127,44 @@ main(argc, argv) /* -h implies "-t nfs" if no -t flag. */ if ((nfshost != NULL) && (typelist == NULL)) - maketypelist("nfs"); + typelist = makevfslist("nfs"); - if (all) { + switch (all) { + case 2: + if ((mnts = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) { + warn("getmntinfo"); + errs = 1; + break; + } + for (errs = 0, mnts--; mnts > 0; mnts--) { + if (checkvfsname(mntbuf[mnts].f_fstypename, typelist)) + continue; + if (umountfs(mntbuf[mnts].f_mntonname, typelist) != 0) + errs = 1; + } + break; + case 1: if (setfsent() == 0) err(1, "%s", _PATH_FSTAB); - errs = umountall(); - } else + errs = umountall(typelist); + break; + case 0: for (errs = 0; *argv != NULL; ++argv) - errs += umountfs(*argv); + if (umountfs(*argv, typelist) != 0) + errs = 1; + break; + } exit(errs); } int -umountall() +umountall(typelist) + char **typelist; { struct fstab *fs; int rval, type; char *cp; + struct vfsconf vfc; while ((fs = getfsent()) != NULL) { /* Ignore the root. */ @@ -152,11 +179,11 @@ umountall() strcmp(fs->fs_type, FSTAB_RQ)) continue; /* If an unknown file system type, complain. */ - if ((type = fsnametotype(fs->fs_vfstype)) == MOUNT_NONE) { + if (getvfsbyname(fs->fs_vfstype, &vfc) < 0) { warnx("%s: unknown mount type", fs->fs_vfstype); continue; } - if (!selected(type)) + if (checkvfsname(fs->fs_vfstype, typelist)) continue; /* @@ -167,16 +194,16 @@ umountall() if ((cp = malloc((size_t)strlen(fs->fs_file) + 1)) == NULL) err(1, NULL); (void)strcpy(cp, fs->fs_file); - rval = umountall(); - return (umountfs(cp) || rval); + rval = umountall(typelist); + return (umountfs(cp, typelist) || rval); } return (0); } -/* Returns 1 on failure, 0 on success */ int -umountfs(name) +umountfs(name, typelist) char *name; + char **typelist; { enum clnt_stat clnt_stat; struct hostent *hp; @@ -184,8 +211,8 @@ umountfs(name) struct stat sb; struct timeval pertry, try; CLIENT *clp; - int so, type; - char *delimp, *hostp, *mntpt, rname[MAXPATHLEN]; + int so; + char *type, *delimp, *hostp, *mntpt, rname[MAXPATHLEN]; if (realpath(name, rname) == NULL) { /* Continue and let the system call check it... */ @@ -216,24 +243,27 @@ umountfs(name) return (1); } - if (!selected(type)) - return (0); + if (checkvfsname(type, typelist)) + return (1); + + hp = NULL; + if (!strcmp(type, "nfs")) { + if ((delimp = strchr(name, '@')) != NULL) { + hostp = delimp + 1; + *delimp = '\0'; + hp = gethostbyname(hostp); + *delimp = '@'; + } else if ((delimp = strchr(name, ':')) != NULL) { + *delimp = '\0'; + hostp = name; + hp = gethostbyname(hostp); + name = delimp + 1; + *delimp = ':'; + } + } - if ((delimp = strchr(name, '@')) != NULL && type == MOUNT_NFS) { - hostp = delimp + 1; - *delimp = '\0'; - hp = gethostbyname(hostp); - *delimp = '@'; - } else if ((delimp = strchr(name, ':')) != NULL && type == MOUNT_NFS) { - *delimp = '\0'; - hostp = name; - hp = gethostbyname(hostp); - name = delimp + 1; - *delimp = ':'; - } else - hp = NULL; if (!namematch(hp)) - return (0); + return (1); if (vflag) (void)printf("%s: unmount from %s\n", name, mntpt); @@ -278,101 +308,32 @@ char * getmntname(name, what, type) char *name; mntwhat what; - int *type; + char **type; { - struct statfs *mntbuf; - int i, mntsize; + static struct statfs *mntbuf; + static int mntsize; + int i; - if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) { + if (mntbuf == NULL && + (mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) { warn("getmntinfo"); return (NULL); } for (i = 0; i < mntsize; i++) { if ((what == MNTON) && !strcmp(mntbuf[i].f_mntfromname, name)) { if (type) - *type = mntbuf[i].f_type; + *type = mntbuf[i].f_fstypename; return (mntbuf[i].f_mntonname); } if ((what == MNTFROM) && !strcmp(mntbuf[i].f_mntonname, name)) { if (type) - *type = mntbuf[i].f_type; + *type = mntbuf[i].f_fstypename; return (mntbuf[i].f_mntfromname); } } return (NULL); } -static enum { IN_LIST, NOT_IN_LIST } which; - -int -selected(type) - int type; -{ - int *tmp_typelist; - - tmp_typelist=typelist; - /* If no type specified, it's always selected. */ - if (tmp_typelist == NULL) - return (1); - for (; *tmp_typelist != MOUNT_NONE; ++tmp_typelist) - if (type == *tmp_typelist) - return (which == IN_LIST ? 1 : 0); - return (which == IN_LIST ? 0 : 1); -} - -void -maketypelist(fslist) - char *fslist; -{ - int *av, i; - char *nextcp; - - if ((fslist == NULL) || (fslist[0] == '\0')) - errx(1, "empty type list"); - - /* - * XXX - * Note: the syntax is "noxxx,yyy" for no xxx's and - * no yyy's, not the more intuitive "noyyy,noyyy". - */ - if (fslist[0] == 'n' && fslist[1] == 'o') { - fslist += 2; - which = NOT_IN_LIST; - } else - which = IN_LIST; - - /* Count the number of types. */ - for (i = 0, nextcp = fslist; *nextcp != NULL; ++nextcp) - if (*nextcp == ',') - i++; - - /* Build an array of that many types. */ - if ((av = typelist = malloc((i + 2) * sizeof(int))) == NULL) - err(1, NULL); - for (i = 0; fslist != NULL; fslist = nextcp, ++i) { - if ((nextcp = strchr(fslist, ',')) != NULL) - *nextcp++ = '\0'; - av[i] = fsnametotype(fslist); - if (av[i] == MOUNT_NONE) - errx(1, "%s: unknown mount type", fslist); - } - /* Terminate the array. */ - av[i++] = MOUNT_NONE; -} - -int -fsnametotype(name) - char *name; -{ - static char const *namelist[] = INITMOUNTNAMES; - char const **cp; - - for (cp = namelist; *cp; ++cp) - if (strcmp(name, *cp) == 0) - return (cp - namelist); - return (MOUNT_NONE); -} - int namematch(hp) struct hostent *hp;