commit 35e3f401ab0d00d7ff06217eb8d6ac28c2895dc3
parent 14716af4723e94913dfaf4516b975db1a764b5e8
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date: Sat, 15 Mar 2014 13:26:32 +0000
Major mount(8) refactor
Diffstat:
M | mount.c | | | 196 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- |
1 file changed, 95 insertions(+), 101 deletions(-)
diff --git a/mount.c b/mount.c
@@ -15,46 +15,79 @@ struct {
const char *notopt;
unsigned long v;
} optnames[] = {
- { "remount", NULL, MS_REMOUNT },
- { "ro", "rw", MS_RDONLY },
- { "sync", "async", MS_SYNCHRONOUS },
- { "dirsync", NULL, MS_DIRSYNC },
- { "nodev", "dev", MS_NODEV },
- { "noatime", "atime", MS_NOATIME },
- { "nodiratime", "diratime", MS_NODIRATIME },
- { "noexec", "exec", MS_NOEXEC },
- { "nosuid", "suid", MS_NOSUID },
- { "mand", "nomand", MS_MANDLOCK },
- { "relatime", "norelatime", MS_RELATIME },
- { NULL, NULL, 0 }
+ { "remount", NULL, MS_REMOUNT },
+ { "ro", "rw", MS_RDONLY },
+ { "sync", "async", MS_SYNCHRONOUS },
+ { "dirsync", NULL, MS_DIRSYNC },
+ { "nodev", "dev", MS_NODEV },
+ { "noatime", "atime", MS_NOATIME },
+ { "nodiratime", "diratime", MS_NODIRATIME },
+ { "noexec", "exec", MS_NOEXEC },
+ { "nosuid", "suid", MS_NOSUID },
+ { "mand", "nomand", MS_MANDLOCK },
+ { "relatime", "norelatime", MS_RELATIME },
+ { "bind", NULL, MS_BIND },
+ { NULL, NULL, 0 }
};
-static struct option {
+static void
+parseopts(char *popts, unsigned long *flags, char *data, size_t bufsiz)
+{
+ unsigned int i, validopt;
+ size_t optlen, dlen = 0;
char *name;
- struct option *next;
-} *opthead;
+
+ data[0] = '\0';
+ for(name = strtok(popts, ","); name; name = strtok(NULL, ",")) {
+ validopt = 0;
+ for(i = 0; optnames[i].v; i++) {
+ if(optnames[i].opt && strcmp(name, optnames[i].opt) == 0) {
+ *flags |= optnames[i].v;
+ validopt = 1;
+ break;
+ }
+ if(optnames[i].notopt && strcmp(name, optnames[i].notopt) == 0) {
+ *flags &= ~optnames[i].v;
+ validopt = 1;
+ break;
+ }
+ }
+ if(!validopt) {
+ /* unknown option, pass as data option to mount() */
+ if((optlen = strlen(name))) {
+ if(dlen + optlen + 2 >= bufsiz)
+ return; /* prevent overflow */
+ if(dlen)
+ data[dlen++] = ',';
+ memcpy(&data[dlen], name, optlen);
+ dlen += optlen;
+ data[dlen] = '\0';
+ }
+ }
+ }
+}
static void
usage(void)
{
- eprintf("usage: %s [-BMRadn] [-t fstype] [-o options] [source] [target]\n",
+ eprintf("usage: %s [-BMRan] [-t fstype] [-o options] [source] [target]\n",
argv0);
}
int
main(int argc, char *argv[])
{
- int i, validopt;
- int oflag = 0, aflag = 0;
+ int aflag = 0, i;
unsigned long flags = 0;
- char *types = NULL, *arg = NULL, *p;
- const char *source;
- const char *target;
- struct stat st1, st2;
- void *data = NULL;
+ char *types = NULL, data[512];
+ char *files[] = { "/proc/mounts", "/etc/fstab", NULL };
+ size_t datasiz = sizeof(data);
+ const char *source, *target;
+ struct stat st;
struct mntent *me = NULL;
FILE *fp;
- struct option *opt, *tmp;
+
+ data[0] = '\0';
ARGBEGIN {
case 'B':
@@ -69,22 +102,8 @@ main(int argc, char *argv[])
case 'a':
aflag = 1;
break;
- case 'd':
- data = EARGF(usage());
- break;
case 'o':
- oflag = 1;
- arg = EARGF(usage());
- for (p = strtok(arg, ","); p; p = strtok(NULL, ",")) {
- opt = malloc(sizeof(*opt));
- if (!opt)
- eprintf("malloc:");
- opt->name = strdup(p);
- if (!opt->name)
- eprintf("strdup:");
- opt->next = opthead;
- opthead = opt;
- }
+ parseopts(EARGF(usage()), &flags, data, datasiz);
break;
case 't':
types = EARGF(usage());
@@ -95,85 +114,60 @@ main(int argc, char *argv[])
usage();
} ARGEND;
- if (argc < 1 && aflag == 0)
+ if(argc < 1 && aflag == 0)
usage();
- for (opt = opthead; opt; opt = opt->next) {
- validopt = 0;
- for (i = 0; optnames[i].v; i++) {
- if (optnames[i].opt) {
- if (!strcmp(opt->name,
- optnames[i].opt)) {
- flags |= optnames[i].v;
- validopt = 1;
- break;
- }
- }
- if (optnames[i].notopt) {
- if (!strcmp(opt->name,
- optnames[i].notopt)) {
- flags &= ~optnames[i].v;
- validopt = 1;
- break;
- }
- }
- }
- if (!validopt)
- break;
- }
- if (oflag && !validopt)
- eprintf("unknown option: %s\n", opt->name);
-
- if (aflag == 1)
- goto domount;
+ if(aflag == 1)
+ goto mountall;
source = argv[0];
target = argv[1];
- if (!target) {
+ if(!target) {
target = argv[0];
source = NULL;
- if (stat(target, &st1) < 0)
+ if(stat(target, &st) < 0)
eprintf("stat %s:", target);
- fp = setmntent("/proc/mounts", "r");
- if (!fp)
- eprintf("setmntent %s:", "/proc/mounts");
- while ((me = getmntent(fp))) {
- if (stat(me->mnt_dir, &st2) < 0)
- eprintf("stat %s:", me->mnt_dir);
- if (st1.st_dev == st2.st_dev &&
- st1.st_ino == st2.st_ino) {
- source = strdup(me->mnt_fsname);
- break;
+ }
+
+ for(i = 0; files[i]; i++) {
+ if((fp = setmntent(files[i], "r"))) {
+ while((me = getmntent(fp))) {
+ if(strcmp(me->mnt_dir, target) == 0 ||
+ strcmp(me->mnt_fsname, target) == 0) {
+ source = me->mnt_fsname;
+ target = me->mnt_dir;
+ if(!types)
+ types = me->mnt_type;
+ goto mountsingle;
+ }
}
+ endmntent(fp);
+ fp = NULL;
+ } else {
+ fprintf(stderr, "setmntent %s: %s\n", files[i], strerror(errno));
}
- endmntent(fp);
- if (!source)
- eprintf("can't find %s mountpoint\n", target);
}
+ if(!source)
+ eprintf("can't find %s mountpoint\n", target);
- if (mount(source, target, types, flags, data) < 0)
+mountsingle:
+ if(mount(source, target, types, flags, data) < 0)
eprintf("mount:");
-
-domount:
- if (aflag == 1) {
- fp = setmntent("/etc/fstab", "r");
- if (!fp)
- eprintf("setmntent %s:", "/etc/fstab");
- while ((me = getmntent(fp)))
- if (mount(me->mnt_fsname, me->mnt_dir, me->mnt_type,
- 0, me->mnt_opts) < 0)
- fprintf(stderr, "mount: %s\n", strerror(errno));
+ if(fp)
endmntent(fp);
- }
+ return EXIT_SUCCESS;
- opt = opthead;
- while (opt) {
- tmp = opt->next;
- free(opt->name);
- free(opt);
- opt = tmp;
+mountall:
+ if(!(fp = setmntent("/etc/fstab", "r")))
+ eprintf("setmntent %s:", "/etc/fstab");
+ while((me = getmntent(fp))) {
+ flags = 0;
+ parseopts(me->mnt_opts, &flags, data, datasiz);
+ if(mount(me->mnt_fsname, me->mnt_dir, me->mnt_type, flags, data) < 0)
+ fprintf(stderr, "mount: %s\n", strerror(errno));
}
+ endmntent(fp);
return EXIT_SUCCESS;
}