From: Jo-Philipp Wich Date: Fri, 16 Aug 2013 10:22:34 +0000 (+0200) Subject: block: add support for generic mount options X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=e2625200c27c9e3a36d90cd0b38b56486886182f;p=oweals%2Fubox.git block: add support for generic mount options Not all mount options are to be passed directly to the filesystem driver, some of them are generic VFS flags that must be passed as bitfield to the mount() syscall. Add a new option parsing implementation that properly divides the user sepcified mount options into flags and fs specific arguments. --- diff --git a/block.c b/block.c index 4397e1e..ff35ba7 100644 --- a/block.c +++ b/block.c @@ -47,6 +47,7 @@ struct mount { char *target; char *path; char *options; + uint32_t flags; char *uuid; char *label; char *device; @@ -130,6 +131,46 @@ static const struct uci_blob_param_list swap_attr_list = { .params = swap_policy, }; +struct mount_flag { + const char *name; + int32_t flag; +}; + +#ifndef MS_DIRSYNC +# define MS_DIRSYNC (1 << 7) +#endif + +#ifndef MS_RELATIME +# define MS_RELATIME (1 << 21) +#endif + +#ifndef MS_STRICTATIME +# define MS_STRICTATIME (1 << 24) +#endif + +static const struct mount_flag mount_flags[] = { + { "sync", MS_SYNCHRONOUS }, + { "async", ~MS_SYNCHRONOUS }, + { "dirsync", MS_DIRSYNC }, + { "mand", MS_MANDLOCK }, + { "nomand", ~MS_MANDLOCK }, + { "atime", ~MS_NOATIME }, + { "noatime", MS_NOATIME }, + { "dev", ~MS_NODEV }, + { "nodev", MS_NODEV }, + { "diratime", ~MS_NODIRATIME }, + { "nodiratime", MS_NODIRATIME }, + { "exec", ~MS_NOEXEC }, + { "noexec", MS_NOEXEC }, + { "suid", ~MS_NOSUID }, + { "nosuid", MS_NOSUID }, + { "rw", ~MS_RDONLY }, + { "ro", MS_RDONLY }, + { "relatime", MS_RELATIME }, + { "norelatime", ~MS_RELATIME }, + { "strictatime", MS_STRICTATIME }, +}; + static char *blobmsg_get_strdup(struct blob_attr *attr) { if (!attr) @@ -146,6 +187,52 @@ static char *blobmsg_get_basename(struct blob_attr *attr) return strdup(basename(blobmsg_get_string(attr))); } +static void parse_mount_options(struct mount *m, char *optstr) +{ + int i; + bool is_flag; + char *p, *opts, *last; + + m->flags = 0; + m->options = NULL; + + if (!optstr || !*optstr) + return; + + m->options = opts = calloc(1, strlen(optstr) + 1); + + if (!m->options) + return; + + p = last = optstr; + + do { + p = strchr(p, ','); + + if (p) + *p++ = 0; + + for (i = 0, is_flag = false; i < ARRAY_SIZE(mount_flags); i++) { + if (!strcmp(last, mount_flags[i].name)) { + if (mount_flags[i].flag < 0) + m->flags &= (uint32_t)mount_flags[i].flag; + else + m->flags |= (uint32_t)mount_flags[i].flag; + is_flag = true; + break; + } + } + + if (!is_flag) + opts += sprintf(opts, "%s%s", (opts > m->options) ? "," : "", last); + + last = p; + + } while (p); + + free(optstr); +} + static int mount_add(struct uci_section *s) { struct blob_attr *tb[__MOUNT_MAX] = { 0 }; @@ -166,8 +253,10 @@ static int mount_add(struct uci_section *s) m->uuid = blobmsg_get_strdup(tb[MOUNT_UUID]); m->label = blobmsg_get_strdup(tb[MOUNT_LABEL]); m->target = blobmsg_get_strdup(tb[MOUNT_TARGET]); - m->options = blobmsg_get_strdup(tb[MOUNT_OPTIONS]); m->device = blobmsg_get_basename(tb[MOUNT_DEVICE]); + + parse_mount_options(m, blobmsg_get_strdup(tb[MOUNT_OPTIONS])); + m->overlay = m->extroot = 0; if (m->target && !strcmp(m->target, "/")) m->extroot = 1; @@ -525,7 +614,8 @@ static int mount_device(struct blkid_struct_probe *pr, int hotplug) if (check_fs) check_filesystem(pr); - err = mount(pr->dev, target, pr->id->name, 0, (m->options) ? (m->options) : ("")); + err = mount(pr->dev, target, pr->id->name, m->flags, + (m->options) ? (m->options) : ("")); if (err) fprintf(stderr, "mounting %s (%s) as %s failed (%d) - %s\n", pr->dev, pr->id->name, target, err, strerror(err));