summaryrefslogtreecommitdiffstats
path: root/usr/utils/mount_opts.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/utils/mount_opts.c')
-rw-r--r--usr/utils/mount_opts.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/usr/utils/mount_opts.c b/usr/utils/mount_opts.c
new file mode 100644
index 0000000..bb26c7d
--- /dev/null
+++ b/usr/utils/mount_opts.c
@@ -0,0 +1,102 @@
+/*
+ * by rmk
+ *
+ * Decode mount options.
+ */
+#include <sys/mount.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mount_opts.h"
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+
+static const struct mount_opts options[] = {
+ /* name mask set noset */
+ {"async", MS_SYNCHRONOUS, 0, MS_SYNCHRONOUS},
+ {"atime", MS_NOATIME, 0, MS_NOATIME},
+ {"bind", MS_TYPE, MS_BIND, 0,},
+ {"dev", MS_NODEV, 0, MS_NODEV},
+ {"diratime", MS_NODIRATIME, 0, MS_NODIRATIME},
+ {"dirsync", MS_DIRSYNC, MS_DIRSYNC, 0},
+ {"exec", MS_NOEXEC, 0, MS_NOEXEC},
+ {"move", MS_TYPE, MS_MOVE, 0},
+ {"nodev", MS_NODEV, MS_NODEV, 0},
+ {"noexec", MS_NOEXEC, MS_NOEXEC, 0},
+ {"nosuid", MS_NOSUID, MS_NOSUID, 0},
+ {"recurse", MS_REC, MS_REC, 0},
+ {"remount", MS_TYPE, MS_REMOUNT, 0},
+ {"ro", MS_RDONLY, MS_RDONLY, 0},
+ {"rw", MS_RDONLY, 0, MS_RDONLY},
+ {"suid", MS_NOSUID, 0, MS_NOSUID},
+ {"sync", MS_SYNCHRONOUS, MS_SYNCHRONOUS, 0},
+ {"verbose", MS_VERBOSE, MS_VERBOSE, 0},
+};
+
+static void add_extra_option(struct extra_opts *extra, char *s)
+{
+ int len = strlen(s);
+ int newlen = extra->used_size + len;
+
+ if (extra->str)
+ len++; /* +1 for ',' */
+
+ if (newlen >= extra->alloc_size) {
+ char *new;
+
+ new = realloc(extra->str, newlen + 1); /* +1 for NUL */
+ if (!new)
+ return;
+
+ extra->str = new;
+ extra->end = extra->str + extra->used_size;
+ extra->alloc_size = newlen;
+ }
+
+ if (extra->used_size) {
+ *extra->end = ',';
+ extra->end++;
+ }
+ strcpy(extra->end, s);
+ extra->used_size += len;
+
+}
+
+unsigned long
+parse_mount_options(char *arg, unsigned long rwflag, struct extra_opts *extra)
+{
+ char *s;
+
+ while ((s = strsep(&arg, ",")) != NULL) {
+ char *opt = s;
+ unsigned int i;
+ int res, no = s[0] == 'n' && s[1] == 'o';
+
+ if (no)
+ s += 2;
+
+ for (i = 0, res = 1; i < ARRAY_SIZE(options); i++) {
+ res = strcmp(s, options[i].str);
+
+ if (res == 0) {
+ rwflag &= ~options[i].rwmask;
+ if (no)
+ rwflag |= options[i].rwnoset;
+ else
+ rwflag |= options[i].rwset;
+ }
+ if (res <= 0)
+ break;
+ }
+
+ if (res != 0 && s[0]) {
+ if (!strcmp(opt, "defaults"))
+ rwflag &= ~(MS_RDONLY|MS_NOSUID|MS_NODEV|
+ MS_NOEXEC|MS_SYNCHRONOUS);
+ else
+ add_extra_option(extra, opt);
+ }
+ }
+
+ return rwflag;
+}