diff options
Diffstat (limited to 'sbin/mount/mount.c')
-rw-r--r-- | sbin/mount/mount.c | 169 |
1 files changed, 138 insertions, 31 deletions
diff --git a/sbin/mount/mount.c b/sbin/mount/mount.c index 87ae109..87d217f 100644 --- a/sbin/mount/mount.c +++ b/sbin/mount/mount.c @@ -42,7 +42,7 @@ static const char copyright[] = static char sccsid[] = "@(#)mount.c 8.25 (Berkeley) 5/8/95"; #endif static const char rcsid[] = - "$Id: mount.c,v 1.28 1998/07/06 07:12:38 charnier Exp $"; + "$Id: mount.c,v 1.29 1999/03/16 22:26:51 bde Exp $"; #endif /* not lint */ #include <sys/param.h> @@ -63,6 +63,10 @@ static const char rcsid[] = #include "extern.h" #include "pathnames.h" +/* `meta' options */ +#define MOUNT_META_OPTION_FSTAB "fstab" +#define MOUNT_META_OPTION_CURRENT "current" + int debug, fstab_style, verbose; char *catopt __P((char *, const char *)); @@ -72,11 +76,14 @@ int hasopt __P((const char *, const char *)); int ismounted __P((struct fstab *, struct statfs *, int)); int isremountable __P((const char *)); void mangle __P((char *, int *, const char **)); +char *update_options __P((char *, char *, int)); int mountfs __P((const char *, const char *, const char *, int, const char *, const char *)); +void remopt __P((char *, const char *)); void prmount __P((struct statfs *)); void putfsent __P((const struct statfs *)); void usage __P((void)); +char *flags2opts __P((int)); /* Map from mount options to printable formats. */ static struct opt { @@ -99,7 +106,7 @@ static struct opt { { MNT_NOCLUSTERW, "noclusterw" }, { MNT_SUIDDIR, "suiddir" }, { MNT_SOFTDEP, "soft-updates" }, - { NULL } + { 0, NULL } }; /* @@ -224,10 +231,15 @@ main(argc, argv) errx(1, "unknown special file or file system %s", *argv); - if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) + if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) { mntfromname = fs->fs_spec; - else + options = update_options(options, fs->fs_mntops, + mntbuf->f_flags); + } else { mntfromname = mntbuf->f_mntfromname; + options = update_options(options, NULL, + mntbuf->f_flags); + } rval = mountfs(mntbuf->f_fstypename, mntfromname, mntbuf->f_mntonname, init_flags, options, 0); break; @@ -524,6 +536,9 @@ catopt(s0, s1) size_t i; char *cp; + if (s1 == NULL || *s1 == '\0') + return s0; + if (s0 && *s0) { i = strlen(s0) + strlen(s1) + 1 + 1; if ((cp = malloc(i)) == NULL) @@ -548,7 +563,7 @@ mangle(options, argcp, argv) argc = *argcp; for (s = options; (p = strsep(&s, ",")) != NULL;) - if (*p != '\0') + if (*p != '\0') { if (*p == '-') { argv[argc++] = p; p = strchr(p, '='); @@ -560,10 +575,97 @@ mangle(options, argcp, argv) argv[argc++] = "-o"; argv[argc++] = p; } + } *argcp = argc; } + +char * +update_options(opts, fstab, curflags) + char *opts; + char *fstab; + int curflags; +{ + char *o, *p; + char *cur; + char *expopt, *newopt, *tmpopt; + + if (opts == NULL) + return strdup(""); + + fstab = strdup(fstab); + + /* remove meta options from list */ + remopt(fstab, MOUNT_META_OPTION_FSTAB); + remopt(fstab, MOUNT_META_OPTION_CURRENT); + cur = flags2opts(curflags); + + /* + * Expand all meta-options passed to us first. + */ + expopt = NULL; + for (p = opts; (o = strsep(&p, ",")) != NULL;) { + if (strcmp(MOUNT_META_OPTION_FSTAB, o) == 0) + expopt = catopt(expopt, fstab); + else if (strcmp(MOUNT_META_OPTION_CURRENT, o) == 0) + expopt = catopt(expopt, cur); + else + expopt = catopt(expopt, o); + } + free(fstab); + free(cur); + free(opts); + + /* + * Remove previous contradictory arguments. Given option "foo" we + * remove all the "nofoo" options. Given "nofoo" we remove "nonofoo" + * and "foo" - so we can deal with possible options like "notice". + */ + newopt = NULL; + for (p = expopt; (o = strsep(&p, ",")) != NULL;) { + if ((tmpopt = malloc( strlen(o) + 2 + 1 )) == NULL) + errx(1, "malloc failed"); + + strcpy(tmpopt, "no"); + strcat(tmpopt, o); + remopt(newopt, tmpopt); + free(tmpopt); + + if (strncmp("no", o, 2) == 0) + remopt(newopt, o+2); + + newopt = catopt(newopt, o); + } + free(expopt); + + return newopt; +} + +void +remopt(string, opt) + char *string; + const char *opt; +{ + char *o, *p, *r; + + if (string == NULL || *string == '\0' || opt == NULL || *opt == '\0') + return; + + r = string; + + for (p = string; (o = strsep(&p, ",")) != NULL;) { + if (strcmp(opt, o) != 0) { + if (*r == ',' && *o != '\0') + r++; + while ((*r++ = *o++) != '\0') + ; + *--r = ','; + } + } + *r = '\0'; +} + void usage() { @@ -580,33 +682,12 @@ putfsent(ent) const struct statfs *ent; { struct fstab *fst; - + char *opts; + + opts = flags2opts(ent->f_flags); printf("%s\t%s\t%s %s", ent->f_mntfromname, ent->f_mntonname, - ent->f_fstypename, (ent->f_flags & MNT_RDONLY) ? "ro" : "rw"); - - /* XXX should use optnames[] - put shorter names in it. */ - if (ent->f_flags & MNT_SYNCHRONOUS) - printf(",sync"); - if (ent->f_flags & MNT_NOEXEC) - printf(",noexec"); - if (ent->f_flags & MNT_NOSUID) - printf(",nosuid"); - if (ent->f_flags & MNT_NODEV) - printf(",nodev"); - if (ent->f_flags & MNT_UNION) - printf(",union"); - if (ent->f_flags & MNT_ASYNC) - printf(",async"); - if (ent->f_flags & MNT_NOATIME) - printf(",noatime"); - if (ent->f_flags & MNT_NOCLUSTERR) - printf(",noclusterr"); - if (ent->f_flags & MNT_NOCLUSTERW) - printf(",noclusterw"); - if (ent->f_flags & MNT_NOSYMFOLLOW) - printf (",nosymfollow"); - if (ent->f_flags & MNT_SUIDDIR) - printf(",suiddir"); + ent->f_fstypename, opts); + free(opts); if ((fst = getfsspec(ent->f_mntfromname))) printf("\t%u %u\n", fst->fs_freq, fst->fs_passno); @@ -617,3 +698,29 @@ putfsent(ent) else printf("\t0 0\n"); } + + +char * +flags2opts(flags) + int flags; +{ + char *res; + + res = NULL; + + res = catopt(res, (flags & MNT_RDONLY) ? "ro" : "rw"); + + if (flags & MNT_SYNCHRONOUS) res = catopt(res, "sync"); + if (flags & MNT_NOEXEC) res = catopt(res, "noexec"); + if (flags & MNT_NOSUID) res = catopt(res, "nosuid"); + if (flags & MNT_NODEV) res = catopt(res, "nodev"); + if (flags & MNT_UNION) res = catopt(res, "union"); + if (flags & MNT_ASYNC) res = catopt(res, "async"); + if (flags & MNT_NOATIME) res = catopt(res, "noatime"); + if (flags & MNT_NOCLUSTERR) res = catopt(res, "noclusterr"); + if (flags & MNT_NOCLUSTERW) res = catopt(res, "noclusterw"); + if (flags & MNT_NOSYMFOLLOW) res = catopt(res, "nosymfollow"); + if (flags & MNT_SUIDDIR) res = catopt(res, "suiddir"); + + return res; +} |