X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/c65344794559547655ccbdcb1eac06066ad52af1..1e45f70ebd9c9229879f7237db81e8e9b92dab00:/usr/src/sbin/mount/mount.c?ds=inline diff --git a/usr/src/sbin/mount/mount.c b/usr/src/sbin/mount/mount.c index d0c4b38505..c4a003dd1c 100644 --- a/usr/src/sbin/mount/mount.c +++ b/usr/src/sbin/mount/mount.c @@ -1,30 +1,30 @@ /* - * Copyright (c) 1980 Regents of the University of California. - * All rights reserved. The Berkeley software License Agreement - * specifies the terms and conditions for redistribution. + * Copyright (c) 1980, 1989 The Regents of the University of California. + * All rights reserved. + * + * %sccs.include.redist.c% */ #ifndef lint char copyright[] = -"@(#) Copyright (c) 1980 Regents of the University of California.\n\ +"@(#) Copyright (c) 1980, 1989 The Regents of the University of California.\n\ All rights reserved.\n"; -#endif not lint +#endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)mount.c 5.11 (Berkeley) %G%"; -#endif not lint +static char sccsid[] = "@(#)mount.c 5.39 (Berkeley) %G%"; +#endif /* not lint */ #include "pathnames.h" #include #include #include +#include #include #include #include -#include -#include -#include -#include +#include +#include #include #ifdef NFS #include @@ -38,20 +38,25 @@ static char sccsid[] = "@(#)mount.c 5.11 (Berkeley) %G%"; #include #endif +#define DEFAULT_ROOTUID -2 + #define BADTYPE(type) \ (strcmp(type, FSTAB_RO) && strcmp(type, FSTAB_RW) && \ strcmp(type, FSTAB_RQ)) #define SETTYPE(type) \ (!strcmp(type, FSTAB_RW) || !strcmp(type, FSTAB_RQ)) -static int fake, verbose, mnttype; -char **envp; +int fake, verbose, updateflg, mnttype; +char *mntname, **envp; +char **vfslist, **makevfslist(); #ifdef NFS int xdr_dir(), xdr_fh(); char *getnfsargs(); -struct nfs_args nfsargs = { - (struct sockaddr_in *)0, +struct nfs_args nfsdefargs = { + (struct sockaddr *)0, + SOCK_DGRAM, + 0, (nfsv2fh_t *)0, 0, NFS_WSIZE, @@ -65,7 +70,8 @@ struct nfhret { u_long stat; nfsv2fh_t nfh; }; -int retrycnt = 10000; +#define DEF_RETRY 10000 +int retrycnt; #define BGRND 1 #define ISBGRND 2 int opflags = 0; @@ -79,17 +85,18 @@ main(argc, argv, arge) extern char *optarg; extern int optind; register struct fstab *fs; - register int cnt; - int all, ch, rval, sfake, i; + int all, ch, rval, flags, ret, pid, i; long mntsize; - struct statfs statfsbuf, *mntbuf; + struct statfs *mntbuf, *getmntpt(); char *type, *options = NULL; + FILE *pidfile; envp = arge; all = 0; type = NULL; mnttype = MOUNT_UFS; - while ((ch = getopt(argc, argv, "afrwvt:o:")) != EOF) + mntname = "ufs"; + while ((ch = getopt(argc, argv, "afrwuvt:o:")) != EOF) switch((char)ch) { case 'a': all = 1; @@ -100,6 +107,9 @@ main(argc, argv, arge) case 'r': type = FSTAB_RO; break; + case 'u': + updateflg = MNT_UPDATE; + break; case 'v': verbose = 1; break; @@ -110,19 +120,9 @@ main(argc, argv, arge) options = optarg; break; case 't': - if (!strcmp(optarg, "ufs")) { - mnttype = MOUNT_UFS; - break; - } - if (!strcmp(optarg, "nfs")) { - mnttype = MOUNT_NFS; - break; - } - if (!strcmp(optarg, "mfs")) { - mnttype = MOUNT_MFS; - break; - } - /* fall through */ + vfslist = makevfslist(optarg); + mnttype = getmnttype(optarg); + break; case '?': default: usage(); @@ -135,14 +135,19 @@ main(argc, argv, arge) if (all) { rval = 0; - for (sfake = fake; fs = getfsent(); fake = sfake) { + while (fs = getfsent()) { if (BADTYPE(fs->fs_type)) continue; + if (badvfsname(fs->fs_vfstype, vfslist)) + continue; /* `/' is special, it's always mounted */ if (!strcmp(fs->fs_file, "/")) - fake = 1; - rval |= mountfs(fs->fs_spec, fs->fs_file, - type ? type : fs->fs_type, options, fs->fs_mntops); + flags = MNT_UPDATE; + else + flags = updateflg; + mnttype = getmnttype(fs->fs_vfstype); + rval |= mountfs(fs->fs_spec, fs->fs_file, flags, + type, options, fs->fs_mntops); } exit(rval); } @@ -150,40 +155,35 @@ main(argc, argv, arge) if (argc == 0) { if (verbose || fake || type) usage(); - if ((mntsize = getfsstat(0, 0)) < 0) { - perror("mount"); + if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) { + fprintf(stderr, + "mount: cannot get mount information\n"); exit(1); } - mntbuf = 0; - do { - if (mntbuf) - free(mntbuf); - i = (mntsize + 1) * sizeof(struct statfs); - if ((mntbuf = (struct statfs *)malloc(i)) == 0) { - fprintf(stderr, - "no space for mount table buffer\n"); - exit(1); - } - if ((mntsize = getfsstat(mntbuf, i)) < 0) { - perror("mount"); - exit(1); - } - } while (i == mntsize * sizeof(struct statfs)); for (i = 0; i < mntsize; i++) { - if (mntbuf[i].f_flags & M_RDONLY) - type = "ro"; - else - type = "rw"; + if (badvfstype(mntbuf[i].f_type, vfslist)) + continue; prmount(mntbuf[i].f_mntfromname, mntbuf[i].f_mntonname, - type); + mntbuf[i].f_flags); } exit(0); } - if (all) - usage(); - - if (argc == 1) { + if (argc == 1 && updateflg) { + if ((mntbuf = getmntpt(*argv)) == NULL) { + fprintf(stderr, + "mount: unknown special file or file system %s.\n", + *argv); + exit(1); + } + mnttype = mntbuf->f_type; + if (!strcmp(mntbuf->f_mntfromname, "root_device")) { + fs = getfsfile("/"); + strcpy(mntbuf->f_mntfromname, fs->fs_spec); + } + ret = mountfs(mntbuf->f_mntfromname, mntbuf->f_mntonname, + updateflg, type, options, (char *)NULL); + } else if (argc == 1) { if (!(fs = getfsfile(*argv)) && !(fs = getfsspec(*argv))) { fprintf(stderr, "mount: unknown special file or file system %s.\n", @@ -195,165 +195,294 @@ main(argc, argv, arge) "mount: %s has unknown file system type.\n", *argv); exit(1); } - exit(mountfs(fs->fs_spec, fs->fs_file, - type ? type : fs->fs_type, options, fs->fs_mntops)); - } - - if (argc != 2) + mnttype = getmnttype(fs->fs_vfstype); + ret = mountfs(fs->fs_spec, fs->fs_file, updateflg, + type, options, fs->fs_mntops); + } else if (argc != 2) { usage(); - - exit(mountfs(argv[0], argv[1], type ? type : "rw", options, NULL)); + ret = 1; + } else { + /* + * If -t flag has not been specified, and spec + * contains either a ':' or a '@' then assume that + * an NFS filesystem is being specified ala Sun. + */ + if (vfslist == (char **)0 && + (index(argv[0], ':') || index(argv[0], '@'))) + mnttype = MOUNT_NFS; + ret = mountfs(argv[0], argv[1], updateflg, type, options, + (char *)NULL); + } + if ((pidfile = fopen(_PATH_MOUNTDPID, "r")) != NULL) { + pid = 0; + fscanf(pidfile, "%d", &pid); + fclose(pidfile); + if (pid > 0) + kill(pid, SIGHUP); + } + exit (ret); } -mountfs(spec, name, type, options, mntopts) +mountfs(spec, name, flags, type, options, mntopts) char *spec, *name, *type, *options, *mntopts; + int flags; { extern int errno; - register int cnt; - int flags, argc, status, i; + union wait status; + pid_t pid; + int argc, i; struct ufs_args args; + struct nfs_args nfsargs; char *argp, *argv[50]; - - if (!fake) { - flags = 0; - if (!strcmp(type, FSTAB_RO)) - flags |= M_RDONLY; - switch (mnttype) { - case MOUNT_UFS: - if (options) - getufsopts(options, &flags); - if (mntopts) - getufsopts(mntopts, &flags); - args.fspec = spec; - argp = (caddr_t)&args; - break; + char execname[MAXPATHLEN + 1], flagval[12]; + + nfsargs = nfsdefargs; + if (mntopts) + getstdopts(mntopts, &flags); + if (options) + getstdopts(options, &flags); + if (type) + getstdopts(type, &flags); + switch (mnttype) { + case MOUNT_UFS: + if (mntopts) + getufsopts(mntopts, &flags); + if (options) + getufsopts(options, &flags); + args.fspec = spec; + args.exroot = DEFAULT_ROOTUID; + if (flags & MNT_RDONLY) + args.exflags = MNT_EXRDONLY; + else + args.exflags = 0; + argp = (caddr_t)&args; + break; #ifdef NFS - case MOUNT_NFS: - if (options) - getnfsopts(options, &nfsargs, &opflags, - &retrycnt); - if (mntopts) - getnfsopts(mntopts, &nfsargs, &opflags, - &retrycnt); - if (argp = getnfsargs(spec, name, type)) - break; - return (1); + case MOUNT_NFS: + retrycnt = DEF_RETRY; + if (mntopts) + getnfsopts(mntopts, &nfsargs, &opflags, &retrycnt); + if (options) + getnfsopts(options, &nfsargs, &opflags, &retrycnt); + if (argp = getnfsargs(spec, &nfsargs)) + break; + return (1); #endif /* NFS */ -#ifdef MFS - case MOUNT_MFS: - argv[0] = "memfs"; - argc = 1; - if (options) - argc += getmfsopts(options, &argv[argc]); - if (mntopts) - argc += getmfsopts(mntopts, &argv[argc]); - argv[argc++] = spec; - argv[argc++] = name; - if (i = vfork()) { - if (i == -1) { - perror("mount: vfork for memfs"); - return (1); - } - if (waitpid(i, &status, 0) != -1 && - WIFEXITED(status) && - WEXITSTATUS(status) != 0) - return (WEXITSTATUS(status)); - spec = "memfs"; - goto out; + case MOUNT_MFS: + default: + argv[0] = mntname; + argc = 1; + if (flags) { + argv[argc++] = "-F"; + sprintf(flagval, "%d", flags); + argv[argc++] = flagval; + } + if (mntopts) + argc += getexecopts(mntopts, &argv[argc]); + if (options) + argc += getexecopts(options, &argv[argc]); + argv[argc++] = spec; + argv[argc++] = name; + argv[argc++] = NULL; + sprintf(execname, "%s/mount_%s", _PATH_EXECDIR, mntname); + if (verbose) { + (void)printf("exec: %s", execname); + for (i = 1; i < argc - 1; i++) + (void)printf(" %s", argv[i]); + (void)printf("\n"); + } + if (fake) + break; + if (pid = vfork()) { + if (pid == -1) { + perror("mount: vfork starting file system"); + return (1); } - execve(_PATH_MEMFS, argv, envp); - perror(_PATH_MEMFS); - exit (1); -#endif /* MFS */ + if (waitpid(pid, &status, 0) != -1 && + WIFEXITED(status) && + WEXITSTATUS(status) != 0) + return (WEXITSTATUS(status)); + spec = mntname; + goto out; + } + execve(execname, argv, envp); + fprintf(stderr, "mount: cannot exec %s for %s: ", + execname, name); + perror((char *)NULL); + exit (1); + /* NOTREACHED */ - default: - if (opflags & ISBGRND) - exit(1); - fprintf(stderr, "%d: unknown mount type\n", mnttype); + } + if (!fake && mount(mnttype, name, flags, argp)) { + if (opflags & ISBGRND) exit(1); - /* NOTREACHED */ - - }; - if (mount(mnttype, name, flags, argp)) { - if (opflags & ISBGRND) - exit(1); - fprintf(stderr, "%s on %s: ", spec, name); - switch (errno) { - case EMFILE: - fprintf(stderr, "Mount table full\n"); - break; - case EINVAL: + fprintf(stderr, "%s on %s: ", spec, name); + switch (errno) { + case EMFILE: + fprintf(stderr, "Mount table full\n"); + break; + case EINVAL: + if (flags & MNT_UPDATE) + fprintf(stderr, "Specified device does %s\n", + "not match mounted device"); + else fprintf(stderr, "Bogus super block\n"); - break; - default: - perror((char *)NULL); - break; - } - return(1); + break; + case EOPNOTSUPP: + fprintf(stderr, "Operation not supported\n"); + break; + default: + perror((char *)NULL); + break; } + return(1); } out: if (verbose) - prmount(spec, name, type); + prmount(spec, name, flags); if (opflags & ISBGRND) - exit(); - else - return(0); + exit(1); + return(0); } static -prmount(spec, name, type) - char *spec, *name, *type; +prmount(spec, name, flags) + char *spec, *name; + register short flags; { - register char *root; + register int first; if (opflags & ISBGRND) return; - /* - * trim trailing /'s and find last component of name - */ - for (root = index(spec, '\0'); *--root == '/';) - /* void */; - *++root = '\0'; - if (root = rindex(spec, '/')) - spec = root + 1; - printf("%s on %s", spec, name); - if (!strcmp(type, FSTAB_RO)) - printf("\t(read-only)"); - else if (!strcmp(type, FSTAB_RQ)) - printf("\t(with quotas)"); - printf("\n"); + (void)printf("%s on %s", spec, name); + if (!(flags & MNT_VISFLAGMASK)) { + (void)printf("\n"); + return; + } + first = 0; +#define PR(msg) (void)printf("%s%s", !first++ ? " (" : ", ", msg) + if (flags & MNT_RDONLY) + PR("read-only"); + if (flags & MNT_NOEXEC) + PR("noexec"); + if (flags & MNT_NOSUID) + PR("nosuid"); + if (flags & MNT_NODEV) + PR("nodev"); + if (flags & MNT_SYNCHRONOUS) + PR("synchronous"); + if (flags & MNT_QUOTA) + PR("with quotas"); + if (flags & MNT_LOCAL) + PR("local"); + if (flags & MNT_EXPORTED) + if (flags & MNT_EXRDONLY) + PR("NFS exported read-only"); + else + PR("NFS exported"); + (void)printf(")\n"); +} + +getmnttype(fstype) + char *fstype; +{ + + mntname = fstype; + if (!strcmp(fstype, "ufs")) + return (MOUNT_UFS); + if (!strcmp(fstype, "nfs")) + return (MOUNT_NFS); + if (!strcmp(fstype, "mfs")) + return (MOUNT_MFS); + return (0); } -static usage() { - fprintf(stderr, "usage: mount [-afrw]\nor mount [-frw] special | node\nor mount [-frw] special node\n"); + + fprintf(stderr, "usage:\n mount %s %s\n mount %s\n mount %s\n", + "[ -frwu ] [ -t nfs | ufs | external_type ]", + "[ -o options ] special node", + "[ -afrwu ] [ -t nfs | ufs | external_type ]", + "[ -frwu ] special | node"); exit(1); } -getufsopts(options, flagp) +getstdopts(options, flagp) char *options; - long *flagp; + int *flagp; { + register char *opt; + int negative; + char optbuf[BUFSIZ]; + + (void)strcpy(optbuf, options); + for (opt = strtok(optbuf, ","); opt; opt = strtok((char *)NULL, ",")) { + if (opt[0] == 'n' && opt[1] == 'o') { + negative++; + opt += 2; + } else { + negative = 0; + } + if (!negative && !strcasecmp(opt, FSTAB_RO)) { + *flagp |= MNT_RDONLY; + continue; + } + if (!negative && !strcasecmp(opt, FSTAB_RW)) { + *flagp &= ~MNT_RDONLY; + continue; + } + if (!strcasecmp(opt, "exec")) { + if (negative) + *flagp |= MNT_NOEXEC; + else + *flagp &= ~MNT_NOEXEC; + continue; + } + if (!strcasecmp(opt, "suid")) { + if (negative) + *flagp |= MNT_NOSUID; + else + *flagp &= ~MNT_NOSUID; + continue; + } + if (!strcasecmp(opt, "dev")) { + if (negative) + *flagp |= MNT_NODEV; + else + *flagp &= ~MNT_NODEV; + continue; + } + if (!strcasecmp(opt, "synchronous")) { + if (!negative) + *flagp |= MNT_SYNCHRONOUS; + else + *flagp &= ~MNT_SYNCHRONOUS; + continue; + } + } +} +/* ARGSUSED */ +getufsopts(options, flagp) + char *options; + int *flagp; +{ return; } -#ifdef MFS -getmfsopts(options, argv) +getexecopts(options, argv) char *options; char **argv; { register int argc = 0; register char *opt; - char *strtok(); - for (opt = strtok(options, ","); opt; opt = strtok(NULL, ",")) { + for (opt = strtok(options, ","); opt; opt = strtok((char *)NULL, ",")) { if (opt[0] != '-') continue; argv[argc++] = opt; @@ -364,7 +493,85 @@ getmfsopts(options, argv) } return (argc); } -#endif /* MFS */ + +struct statfs * +getmntpt(name) + char *name; +{ + long mntsize; + register long i; + struct statfs *mntbuf; + + mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); + for (i = 0; i < mntsize; i++) { + if (!strcmp(mntbuf[i].f_mntfromname, name) || + !strcmp(mntbuf[i].f_mntonname, name)) + return (&mntbuf[i]); + } + return ((struct statfs *)0); +} + +static int skipvfs; + +badvfstype(vfstype, vfslist) + short vfstype; + char **vfslist; +{ + + if (vfslist == 0) + return(0); + while (*vfslist) { + if (vfstype == getmnttype(*vfslist)) + return(skipvfs); + vfslist++; + } + return (!skipvfs); +} + +badvfsname(vfsname, vfslist) + char *vfsname; + char **vfslist; +{ + + if (vfslist == 0) + return(0); + while (*vfslist) { + if (strcmp(vfsname, *vfslist) == 0) + return(skipvfs); + vfslist++; + } + return (!skipvfs); +} + +char ** +makevfslist(fslist) + char *fslist; +{ + register char **av, *nextcp; + register int i; + + if (fslist == NULL) + return (NULL); + if (fslist[0] == 'n' && fslist[1] == 'o') { + fslist += 2; + skipvfs = 1; + } + for (i = 0, nextcp = fslist; *nextcp; nextcp++) + if (*nextcp == ',') + i++; + av = (char **)malloc((size_t)(i+2) * sizeof(char *)); + if (av == NULL) + return (NULL); + nextcp = fslist; + i = 0; + av[i++] = nextcp; + while (nextcp = index(nextcp, ',')) { + *nextcp++ = '\0'; + av[i++] = nextcp; + } + av[i++] = 0; + return (av); +} #ifdef NFS /* @@ -396,9 +603,25 @@ getnfsopts(optarg, nfsargsp, opflagsp, retrycntp) if (!strcmp(cp, "bg")) { *opflagsp |= BGRND; } else if (!strcmp(cp, "soft")) { + if (nfsargsp->flags & NFSMNT_SPONGY) { + fprintf(stderr, + "Options soft, spongy mutually exclusive\n"); + exit(1); + } nfsargsp->flags |= NFSMNT_SOFT; + } else if (!strcmp(cp, "spongy")) { + if (nfsargsp->flags & NFSMNT_SOFT) { + fprintf(stderr, + "Options soft, spongy mutually exclusive\n"); + exit(1); + } + nfsargsp->flags |= NFSMNT_SPONGY; } else if (!strcmp(cp, "intr")) { nfsargsp->flags |= NFSMNT_INT; + } else if (!strcmp(cp, "tcp")) { + nfsargsp->sotype = SOCK_STREAM; + } else if (!strcmp(cp, "noconn")) { + nfsargsp->flags |= NFSMNT_NOCONN; } else if (!strcmp(cp, "retry") && num > 0) { *retrycntp = num; } else if (!strcmp(cp, "rsize") && num > 0) { @@ -416,22 +639,30 @@ getnfsopts(optarg, nfsargsp, opflagsp, retrycntp) } cp = nextcp; } + if (nfsargsp->sotype == SOCK_DGRAM) { + if (nfsargsp->rsize > NFS_MAXDGRAMDATA) + nfsargsp->rsize = NFS_MAXDGRAMDATA; + if (nfsargsp->wsize > NFS_MAXDGRAMDATA) + nfsargsp->wsize = NFS_MAXDGRAMDATA; + } } char * -getnfsargs(spec) +getnfsargs(spec, nfsargsp) char *spec; + struct nfs_args *nfsargsp; { + extern int errno; register CLIENT *clp; struct hostent *hp; - struct sockaddr_in saddr; + static struct sockaddr_in saddr; struct timeval pertry, try; enum clnt_stat clnt_stat; int so = RPC_ANYSOCK; char *hostp, *delimp; u_short tport; - struct nfhret nfhret; - char nam[MNAMELEN + 1]; + static struct nfhret nfhret; + static char nam[MNAMELEN + 1]; strncpy(nam, spec, MNAMELEN); nam[MNAMELEN] = '\0'; @@ -497,15 +728,16 @@ getnfsargs(spec) if (nfhret.stat) { if (opflags & ISBGRND) exit(1); - fprintf(stderr, "Can't access %s, errno=%d\n", spec, - nfhret.stat); + fprintf(stderr, "Can't access %s: ", spec); + errno = nfhret.stat; + perror((char *)NULL); return (0); } saddr.sin_port = htons(tport); - nfsargs.addr = &saddr; - nfsargs.fh = &nfhret.nfh; - nfsargs.hostname = nam; - return ((caddr_t)&nfsargs); + nfsargsp->addr = (struct sockaddr *) &saddr; + nfsargsp->fh = &nfhret.nfh; + nfsargsp->hostname = nam; + return ((caddr_t)nfsargsp); } /*