121156Sdist /* 239322Smckusick * Copyright (c) 1980, 1989 The Regents of the University of California. 339322Smckusick * All rights reserved. 439322Smckusick * 542702Sbostic * %sccs.include.redist.c% 621156Sdist */ 721156Sdist 810811Ssam #ifndef lint 921156Sdist char copyright[] = 1039322Smckusick "@(#) Copyright (c) 1980, 1989 The Regents of the University of California.\n\ 1121156Sdist All rights reserved.\n"; 1239322Smckusick #endif /* not lint */ 131057Sbill 1421156Sdist #ifndef lint 15*52182Smckusick static char sccsid[] = "@(#)mount.c 5.48 (Berkeley) 01/13/92"; 1639322Smckusick #endif /* not lint */ 1721156Sdist 1812808Ssam #include <sys/param.h> 1935339Sbostic #include <sys/file.h> 2038445Smckusick #include <sys/time.h> 2139133Smckusick #include <sys/wait.h> 2245524Sbostic #include <sys/errno.h> 2345524Sbostic #include <sys/signal.h> 2452110Smckusick #include <sys/ucred.h> 2538445Smckusick #include <sys/mount.h> 2645524Sbostic #include <fstab.h> 2745524Sbostic #include <string.h> 2845524Sbostic #include <stdio.h> 2945524Sbostic #include <stdlib.h> 3045524Sbostic #include "pathnames.h" 311057Sbill 3240369Smckusick #define DEFAULT_ROOTUID -2 3340369Smckusick 3435339Sbostic #define BADTYPE(type) \ 3535339Sbostic (strcmp(type, FSTAB_RO) && strcmp(type, FSTAB_RW) && \ 3635339Sbostic strcmp(type, FSTAB_RQ)) 3735339Sbostic #define SETTYPE(type) \ 3835339Sbostic (!strcmp(type, FSTAB_RW) || !strcmp(type, FSTAB_RQ)) 391057Sbill 4039333Smckusick int fake, verbose, updateflg, mnttype; 4139322Smckusick char *mntname, **envp; 4240051Smckusick char **vfslist, **makevfslist(); 4346708Sbostic static void prmount(); 4439131Smckusick 4539131Smckusick main(argc, argv, arge) 465073Sroot int argc; 475073Sroot char **argv; 4839131Smckusick char **arge; 491057Sbill { 5035339Sbostic extern char *optarg; 5135339Sbostic extern int optind; 5235339Sbostic register struct fstab *fs; 5340496Smckusick int all, ch, rval, flags, ret, pid, i; 5438632Smckusick long mntsize; 5539465Smckusick struct statfs *mntbuf, *getmntpt(); 5639131Smckusick char *type, *options = NULL; 5740496Smckusick FILE *pidfile; 581057Sbill 5939131Smckusick envp = arge; 6035339Sbostic all = 0; 6135339Sbostic type = NULL; 6238445Smckusick mnttype = MOUNT_UFS; 6339322Smckusick mntname = "ufs"; 6439333Smckusick while ((ch = getopt(argc, argv, "afrwuvt:o:")) != EOF) 6535339Sbostic switch((char)ch) { 6635339Sbostic case 'a': 6735339Sbostic all = 1; 6835339Sbostic break; 6935339Sbostic case 'f': 7035339Sbostic fake = 1; 7135339Sbostic break; 7235339Sbostic case 'r': 7312808Ssam type = FSTAB_RO; 7435339Sbostic break; 7539333Smckusick case 'u': 7641403Smckusick updateflg = MNT_UPDATE; 7739333Smckusick break; 7835339Sbostic case 'v': 7935339Sbostic verbose = 1; 8035339Sbostic break; 8135339Sbostic case 'w': 8235339Sbostic type = FSTAB_RW; 8335339Sbostic break; 8439131Smckusick case 'o': 8539131Smckusick options = optarg; 8639131Smckusick break; 8738445Smckusick case 't': 8840051Smckusick vfslist = makevfslist(optarg); 8939322Smckusick mnttype = getmnttype(optarg); 9039322Smckusick break; 9135339Sbostic case '?': 9235339Sbostic default: 9335339Sbostic usage(); 9439131Smckusick /* NOTREACHED */ 955073Sroot } 9635339Sbostic argc -= optind; 9735339Sbostic argv += optind; 9835339Sbostic 9935339Sbostic /* NOSTRICT */ 10035339Sbostic 1014460Sroot if (all) { 10235369Sbostic rval = 0; 10339333Smckusick while (fs = getfsent()) { 10435372Sbostic if (BADTYPE(fs->fs_type)) 10535372Sbostic continue; 10640844Smckusick if (badvfsname(fs->fs_vfstype, vfslist)) 10740051Smckusick continue; 10835372Sbostic /* `/' is special, it's always mounted */ 10935372Sbostic if (!strcmp(fs->fs_file, "/")) 11041403Smckusick flags = MNT_UPDATE; 11139333Smckusick else 11239333Smckusick flags = updateflg; 11339333Smckusick mnttype = getmnttype(fs->fs_vfstype); 11439333Smckusick rval |= mountfs(fs->fs_spec, fs->fs_file, flags, 11539333Smckusick type, options, fs->fs_mntops); 11635372Sbostic } 11735341Sbostic exit(rval); 11835339Sbostic } 1195073Sroot 12035339Sbostic if (argc == 0) { 12135339Sbostic if (verbose || fake || type) 12235339Sbostic usage(); 12340337Smckusick if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) { 12445689Smckusick (void) fprintf(stderr, 12539319Smckusick "mount: cannot get mount information\n"); 12638632Smckusick exit(1); 12738632Smckusick } 12840844Smckusick for (i = 0; i < mntsize; i++) { 12940844Smckusick if (badvfstype(mntbuf[i].f_type, vfslist)) 13040844Smckusick continue; 13138632Smckusick prmount(mntbuf[i].f_mntfromname, mntbuf[i].f_mntonname, 13239316Smckusick mntbuf[i].f_flags); 13340844Smckusick } 1344460Sroot exit(0); 1351057Sbill } 13612808Ssam 13739465Smckusick if (argc == 1 && updateflg) { 13839465Smckusick if ((mntbuf = getmntpt(*argv)) == NULL) { 13945689Smckusick (void) fprintf(stderr, 14039465Smckusick "mount: unknown special file or file system %s.\n", 14139465Smckusick *argv); 14239465Smckusick exit(1); 14339465Smckusick } 14439465Smckusick mnttype = mntbuf->f_type; 14540124Smckusick if (!strcmp(mntbuf->f_mntfromname, "root_device")) { 14640124Smckusick fs = getfsfile("/"); 14740124Smckusick strcpy(mntbuf->f_mntfromname, fs->fs_spec); 14840124Smckusick } 14940496Smckusick ret = mountfs(mntbuf->f_mntfromname, mntbuf->f_mntonname, 15042253Sbostic updateflg, type, options, (char *)NULL); 15140496Smckusick } else if (argc == 1) { 15235339Sbostic if (!(fs = getfsfile(*argv)) && !(fs = getfsspec(*argv))) { 15345689Smckusick (void) fprintf(stderr, 15435339Sbostic "mount: unknown special file or file system %s.\n", 15535339Sbostic *argv); 15635339Sbostic exit(1); 15735339Sbostic } 15835339Sbostic if (BADTYPE(fs->fs_type)) { 15945689Smckusick (void) fprintf(stderr, 16035339Sbostic "mount: %s has unknown file system type.\n", *argv); 16135339Sbostic exit(1); 16235339Sbostic } 16339333Smckusick mnttype = getmnttype(fs->fs_vfstype); 16440496Smckusick ret = mountfs(fs->fs_spec, fs->fs_file, updateflg, 16540496Smckusick type, options, fs->fs_mntops); 16640496Smckusick } else if (argc != 2) { 16740496Smckusick usage(); 16840496Smckusick ret = 1; 16940496Smckusick } else { 17042857Smckusick /* 17142857Smckusick * If -t flag has not been specified, and spec 17242857Smckusick * contains either a ':' or a '@' then assume that 17342857Smckusick * an NFS filesystem is being specified ala Sun. 17442857Smckusick */ 17542857Smckusick if (vfslist == (char **)0 && 176*52182Smckusick (index(argv[0], ':') || index(argv[0], '@'))) { 17742857Smckusick mnttype = MOUNT_NFS; 178*52182Smckusick mntname = "nfs"; 179*52182Smckusick } 18042253Sbostic ret = mountfs(argv[0], argv[1], updateflg, type, options, 18142253Sbostic (char *)NULL); 18212808Ssam } 18340496Smckusick if ((pidfile = fopen(_PATH_MOUNTDPID, "r")) != NULL) { 18440496Smckusick pid = 0; 18540496Smckusick fscanf(pidfile, "%d", &pid); 18640496Smckusick fclose(pidfile); 18740496Smckusick if (pid > 0) 18840496Smckusick kill(pid, SIGHUP); 18940496Smckusick } 19040496Smckusick exit (ret); 19112808Ssam } 19212808Ssam 19339333Smckusick mountfs(spec, name, flags, type, options, mntopts) 19439131Smckusick char *spec, *name, *type, *options, *mntopts; 19539333Smckusick int flags; 19612808Ssam { 19742253Sbostic union wait status; 19842253Sbostic pid_t pid; 19942253Sbostic int argc, i; 20038070Smckusick struct ufs_args args; 20139131Smckusick char *argp, *argv[50]; 20239322Smckusick char execname[MAXPATHLEN + 1], flagval[12]; 2031057Sbill 20439333Smckusick if (mntopts) 20539333Smckusick getstdopts(mntopts, &flags); 20639316Smckusick if (options) 20739316Smckusick getstdopts(options, &flags); 20839333Smckusick if (type) 20939333Smckusick getstdopts(type, &flags); 21039316Smckusick switch (mnttype) { 21152097Sbostic case MOUNT_LFS: 21239316Smckusick case MOUNT_UFS: 21339333Smckusick if (mntopts) 21439333Smckusick getufsopts(mntopts, &flags); 21539316Smckusick if (options) 21639316Smckusick getufsopts(options, &flags); 21739316Smckusick args.fspec = spec; 21840369Smckusick args.exroot = DEFAULT_ROOTUID; 21941403Smckusick if (flags & MNT_RDONLY) 22041403Smckusick args.exflags = MNT_EXRDONLY; 22140496Smckusick else 22240496Smckusick args.exflags = 0; 22339316Smckusick argp = (caddr_t)&args; 22439316Smckusick break; 22538632Smckusick 22652110Smckusick case MOUNT_MFS: 22739316Smckusick case MOUNT_NFS: 22839322Smckusick default: 22939322Smckusick argv[0] = mntname; 23039329Smckusick argc = 1; 23139322Smckusick if (flags) { 23239322Smckusick argv[argc++] = "-F"; 23339322Smckusick sprintf(flagval, "%d", flags); 23439322Smckusick argv[argc++] = flagval; 23539322Smckusick } 23639333Smckusick if (mntopts) 23739333Smckusick argc += getexecopts(mntopts, &argv[argc]); 23839329Smckusick if (options) 23939329Smckusick argc += getexecopts(options, &argv[argc]); 24039316Smckusick argv[argc++] = spec; 24139316Smckusick argv[argc++] = name; 24239521Smckusick argv[argc++] = NULL; 24339603Smckusick sprintf(execname, "%s/mount_%s", _PATH_EXECDIR, mntname); 24439316Smckusick if (verbose) { 24542253Sbostic (void)printf("exec: %s", execname); 24642253Sbostic for (i = 1; i < argc - 1; i++) 24742253Sbostic (void)printf(" %s", argv[i]); 24842253Sbostic (void)printf("\n"); 24939316Smckusick } 25039316Smckusick if (fake) 25139316Smckusick break; 25242253Sbostic if (pid = vfork()) { 25342253Sbostic if (pid == -1) { 25439322Smckusick perror("mount: vfork starting file system"); 25539316Smckusick return (1); 25639131Smckusick } 25746708Sbostic if (waitpid(pid, (int *)&status, 0) != -1 && 25839316Smckusick WIFEXITED(status) && 25939316Smckusick WEXITSTATUS(status) != 0) 26039316Smckusick return (WEXITSTATUS(status)); 26139322Smckusick spec = mntname; 26239316Smckusick goto out; 26339316Smckusick } 26439322Smckusick execve(execname, argv, envp); 26545689Smckusick (void) fprintf(stderr, "mount: cannot exec %s for %s: ", 26639603Smckusick execname, name); 26742253Sbostic perror((char *)NULL); 26839316Smckusick exit (1); 26939316Smckusick /* NOTREACHED */ 27038632Smckusick 27139316Smckusick } 27239316Smckusick if (!fake && mount(mnttype, name, flags, argp)) { 27345689Smckusick (void) fprintf(stderr, "%s on %s: ", spec, name); 27439316Smckusick switch (errno) { 27539316Smckusick case EMFILE: 27645689Smckusick (void) fprintf(stderr, "Mount table full\n"); 27739316Smckusick break; 27839316Smckusick case EINVAL: 27941403Smckusick if (flags & MNT_UPDATE) 28045689Smckusick (void) fprintf(stderr, "Specified device %s\n", 28145689Smckusick "does not match mounted device"); 28245569Skarels else if (mnttype == MOUNT_UFS) 28345689Smckusick (void) fprintf(stderr, "Bogus super block\n"); 28439333Smckusick else 28545569Skarels perror((char *)NULL); 28639316Smckusick break; 28739316Smckusick default: 28839316Smckusick perror((char *)NULL); 28939316Smckusick break; 2904460Sroot } 29139316Smckusick return(1); 2924460Sroot } 29335339Sbostic 29439131Smckusick out: 29512808Ssam if (verbose) 29639316Smckusick prmount(spec, name, flags); 29735339Sbostic 29842253Sbostic return(0); 2991057Sbill } 30035339Sbostic 30146708Sbostic static void 30239316Smckusick prmount(spec, name, flags) 30339316Smckusick char *spec, *name; 30442253Sbostic register short flags; 30535339Sbostic { 30642253Sbostic register int first; 30738632Smckusick 30842253Sbostic (void)printf("%s on %s", spec, name); 30942253Sbostic if (!(flags & MNT_VISFLAGMASK)) { 31042253Sbostic (void)printf("\n"); 31142253Sbostic return; 31242253Sbostic } 31342253Sbostic first = 0; 31442253Sbostic #define PR(msg) (void)printf("%s%s", !first++ ? " (" : ", ", msg) 31541403Smckusick if (flags & MNT_RDONLY) 31642253Sbostic PR("read-only"); 31741403Smckusick if (flags & MNT_NOEXEC) 31842253Sbostic PR("noexec"); 31941403Smckusick if (flags & MNT_NOSUID) 32042253Sbostic PR("nosuid"); 32141403Smckusick if (flags & MNT_NODEV) 32242253Sbostic PR("nodev"); 32341403Smckusick if (flags & MNT_SYNCHRONOUS) 32442253Sbostic PR("synchronous"); 32541403Smckusick if (flags & MNT_QUOTA) 32642253Sbostic PR("with quotas"); 32741403Smckusick if (flags & MNT_LOCAL) 32842253Sbostic PR("local"); 32941403Smckusick if (flags & MNT_EXPORTED) 33052110Smckusick PR("NFS exported"); 33142253Sbostic (void)printf(")\n"); 33235339Sbostic } 33335339Sbostic 33439133Smckusick getmnttype(fstype) 33539133Smckusick char *fstype; 33639133Smckusick { 33739133Smckusick 33839322Smckusick mntname = fstype; 33939133Smckusick if (!strcmp(fstype, "ufs")) 34039133Smckusick return (MOUNT_UFS); 34139133Smckusick if (!strcmp(fstype, "nfs")) 34239133Smckusick return (MOUNT_NFS); 34339133Smckusick if (!strcmp(fstype, "mfs")) 34439133Smckusick return (MOUNT_MFS); 34552097Sbostic if (!strcmp(fstype, "lfs")) 34652097Sbostic return (MOUNT_LFS); 34739133Smckusick return (0); 34839133Smckusick } 34939133Smckusick 35038632Smckusick usage() 35135339Sbostic { 35240871Smckusick 35345689Smckusick (void) fprintf(stderr, 35445689Smckusick "usage:\n mount %s %s\n mount %s\n mount %s\n", 35552110Smckusick "[ -frwu ] [ -t ufs | external_type ]", 35640871Smckusick "[ -o options ] special node", 35752110Smckusick "[ -afrwu ] [ -t ufs | external_type ]", 35840871Smckusick "[ -frwu ] special | node"); 35935339Sbostic exit(1); 36035339Sbostic } 36135339Sbostic 36239316Smckusick getstdopts(options, flagp) 36339316Smckusick char *options; 36442253Sbostic int *flagp; 36539316Smckusick { 36639316Smckusick register char *opt; 36739316Smckusick int negative; 36842253Sbostic char optbuf[BUFSIZ]; 36939316Smckusick 37042253Sbostic (void)strcpy(optbuf, options); 37142253Sbostic for (opt = strtok(optbuf, ","); opt; opt = strtok((char *)NULL, ",")) { 37239316Smckusick if (opt[0] == 'n' && opt[1] == 'o') { 37339316Smckusick negative++; 37439316Smckusick opt += 2; 37539316Smckusick } else { 37639316Smckusick negative = 0; 37739316Smckusick } 37839333Smckusick if (!negative && !strcasecmp(opt, FSTAB_RO)) { 37941403Smckusick *flagp |= MNT_RDONLY; 38039333Smckusick continue; 38139333Smckusick } 38239333Smckusick if (!negative && !strcasecmp(opt, FSTAB_RW)) { 38341403Smckusick *flagp &= ~MNT_RDONLY; 38439333Smckusick continue; 38539333Smckusick } 38639316Smckusick if (!strcasecmp(opt, "exec")) { 38739316Smckusick if (negative) 38841403Smckusick *flagp |= MNT_NOEXEC; 38939333Smckusick else 39041403Smckusick *flagp &= ~MNT_NOEXEC; 39139316Smckusick continue; 39239316Smckusick } 39339316Smckusick if (!strcasecmp(opt, "suid")) { 39439316Smckusick if (negative) 39541403Smckusick *flagp |= MNT_NOSUID; 39639333Smckusick else 39741403Smckusick *flagp &= ~MNT_NOSUID; 39839316Smckusick continue; 39939316Smckusick } 40039316Smckusick if (!strcasecmp(opt, "dev")) { 40139316Smckusick if (negative) 40241403Smckusick *flagp |= MNT_NODEV; 40339333Smckusick else 40441403Smckusick *flagp &= ~MNT_NODEV; 40539316Smckusick continue; 40639316Smckusick } 40739316Smckusick if (!strcasecmp(opt, "synchronous")) { 40839316Smckusick if (!negative) 40941403Smckusick *flagp |= MNT_SYNCHRONOUS; 41039333Smckusick else 41141403Smckusick *flagp &= ~MNT_SYNCHRONOUS; 41239316Smckusick continue; 41339316Smckusick } 41439316Smckusick } 41539316Smckusick } 41639316Smckusick 41742253Sbostic /* ARGSUSED */ 41839131Smckusick getufsopts(options, flagp) 41939131Smckusick char *options; 42042253Sbostic int *flagp; 42139131Smckusick { 42239131Smckusick return; 42339131Smckusick } 42439131Smckusick 42539329Smckusick getexecopts(options, argv) 42639131Smckusick char *options; 42739131Smckusick char **argv; 42839131Smckusick { 42939131Smckusick register int argc = 0; 43039131Smckusick register char *opt; 43139131Smckusick 43242253Sbostic for (opt = strtok(options, ","); opt; opt = strtok((char *)NULL, ",")) { 43339131Smckusick if (opt[0] != '-') 43439131Smckusick continue; 43539131Smckusick argv[argc++] = opt; 43639131Smckusick if (opt[2] == '\0' || opt[2] != '=') 43739131Smckusick continue; 43839131Smckusick opt[2] = '\0'; 43939131Smckusick argv[argc++] = &opt[3]; 44039131Smckusick } 44139131Smckusick return (argc); 44239131Smckusick } 44339131Smckusick 44439465Smckusick struct statfs * 44539465Smckusick getmntpt(name) 44639465Smckusick char *name; 44739465Smckusick { 44839465Smckusick long mntsize; 44939465Smckusick register long i; 45039465Smckusick struct statfs *mntbuf; 45139465Smckusick 45240337Smckusick mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 45339465Smckusick for (i = 0; i < mntsize; i++) { 45439465Smckusick if (!strcmp(mntbuf[i].f_mntfromname, name) || 45539465Smckusick !strcmp(mntbuf[i].f_mntonname, name)) 45639465Smckusick return (&mntbuf[i]); 45739465Smckusick } 45839465Smckusick return ((struct statfs *)0); 45939465Smckusick } 46039465Smckusick 46140051Smckusick static int skipvfs; 46240051Smckusick 46340051Smckusick badvfstype(vfstype, vfslist) 46442253Sbostic short vfstype; 46540051Smckusick char **vfslist; 46640051Smckusick { 46740051Smckusick 46840051Smckusick if (vfslist == 0) 46940051Smckusick return(0); 47040051Smckusick while (*vfslist) { 47140844Smckusick if (vfstype == getmnttype(*vfslist)) 47240051Smckusick return(skipvfs); 47340051Smckusick vfslist++; 47440051Smckusick } 47540051Smckusick return (!skipvfs); 47640051Smckusick } 47740051Smckusick 47840844Smckusick badvfsname(vfsname, vfslist) 47940844Smckusick char *vfsname; 48040844Smckusick char **vfslist; 48140844Smckusick { 48240844Smckusick 48340844Smckusick if (vfslist == 0) 48440844Smckusick return(0); 48540844Smckusick while (*vfslist) { 48640844Smckusick if (strcmp(vfsname, *vfslist) == 0) 48740844Smckusick return(skipvfs); 48840844Smckusick vfslist++; 48940844Smckusick } 49040844Smckusick return (!skipvfs); 49140844Smckusick } 49240844Smckusick 49340051Smckusick char ** 49440051Smckusick makevfslist(fslist) 49540051Smckusick char *fslist; 49640051Smckusick { 49740051Smckusick register char **av, *nextcp; 49840051Smckusick register int i; 49940051Smckusick 50040051Smckusick if (fslist == NULL) 50140051Smckusick return (NULL); 50240051Smckusick if (fslist[0] == 'n' && fslist[1] == 'o') { 50340051Smckusick fslist += 2; 50440051Smckusick skipvfs = 1; 50540051Smckusick } 50640051Smckusick for (i = 0, nextcp = fslist; *nextcp; nextcp++) 50740051Smckusick if (*nextcp == ',') 50840051Smckusick i++; 50942253Sbostic av = (char **)malloc((size_t)(i+2) * sizeof(char *)); 51040051Smckusick if (av == NULL) 51140051Smckusick return (NULL); 51240051Smckusick nextcp = fslist; 51340051Smckusick i = 0; 51440051Smckusick av[i++] = nextcp; 51540051Smckusick while (nextcp = index(nextcp, ',')) { 51640051Smckusick *nextcp++ = '\0'; 51740051Smckusick av[i++] = nextcp; 51840051Smckusick } 51940051Smckusick av[i++] = 0; 52040051Smckusick return (av); 52140051Smckusick } 522