Merge from Lite2.

- use new getvfsbyname() interface.
- new -A option, like -a except only mounted file systems are unmounted.

All non-cosmetic FreeBSD changes in umount.c, except ignoring of
realpath() failures, went away because they are done better in Lite2.
realpath() failures must be ignored so that non-pathnames like
"<above>:/foo" and "host:/bar" get as far as mount(2).

Reviewed by:	dfr
This commit is contained in:
Bruce Evans 1997-06-16 11:20:05 +00:00
parent 71706cc1fd
commit d499a0ef65
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=26683
3 changed files with 104 additions and 133 deletions

View File

@ -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 <bsd.prog.mk>

View File

@ -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 ,

View File

@ -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 <sys/param.h>
@ -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;