From 66b8b8cd774978f1c885464a51ca1492e6459f2d Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Sat, 25 Sep 2010 01:48:38 +0200 Subject: [PATCH] libmount: clean up mountflags usage Signed-off-by: Karel Zak --- shlibs/mount/src/mount.h.in | 10 ++- shlibs/mount/src/mount.sym | 2 + shlibs/mount/src/optmap.c | 72 ++++++++--------- shlibs/mount/src/optstr.c | 150 ++++++++++++++++++++++++++++++++---- 4 files changed, 178 insertions(+), 56 deletions(-) diff --git a/shlibs/mount/src/mount.h.in b/shlibs/mount/src/mount.h.in index 08ba59c8..ac69ac55 100644 --- a/shlibs/mount/src/mount.h.in +++ b/shlibs/mount/src/mount.h.in @@ -69,10 +69,8 @@ struct mnt_optmap /* * mount options map masks */ -#define MNT_MFLAG (1 << 1) /* use the mask as mount(2) flag */ -#define MNT_MDATA (1 << 2) /* use the option as mount(2) data */ -#define MNT_INVERT (1 << 3) /* invert the mountflag */ -#define MNT_NOMTAB (1 << 4) /* skip in the mtab option string */ +#define MNT_INVERT (1 << 1) /* invert the mountflag */ +#define MNT_NOMTAB (1 << 2) /* skip in the mtab option string */ /** * mnt_fs: @@ -169,8 +167,12 @@ extern int mnt_split_optstr(const char *optstr, char **user, char **vfs, char **fs, int ifnore_user, int ignore_vfs); +extern int mnt_optstr_get_flags(const char *optstr, unsigned long *flags, + const struct mnt_optmap *map); extern int mnt_optstr_get_mountflags(const char *optstr, unsigned long *flags); extern int mnt_optstr_get_userspace_mountflags(const char *optstr, unsigned long *flags); +extern int mnt_optstr_apply_flags(char **optstr, unsigned long flags, + const struct mnt_optmap *map); extern int mnt_optstr_fix_gid(char **optstr, char *value, size_t valsz, char **next); extern int mnt_optstr_fix_uid(char **optstr, char *value, size_t valsz, char **next); diff --git a/shlibs/mount/src/mount.sym b/shlibs/mount/src/mount.sym index b6cf3901..308abcde 100644 --- a/shlibs/mount/src/mount.sym +++ b/shlibs/mount/src/mount.sym @@ -82,6 +82,8 @@ global: mnt_optstr_fix_gid; mnt_optstr_fix_selinux; mnt_optstr_fix_uid; + mnt_optstr_apply_flags; + mnt_optstr_get_flags; mnt_parse_version_string; mnt_reset_iter; mnt_resolve_path; diff --git a/shlibs/mount/src/optmap.c b/shlibs/mount/src/optmap.c index d8ec5eab..d96da986 100644 --- a/shlibs/mount/src/optmap.c +++ b/shlibs/mount/src/optmap.c @@ -26,7 +26,7 @@ * * @id: (in the map unique identifier or a mountflags, e.g MS_RDONLY) * - * @mask: (MNT_INVERT, MNT_MDATA, MNT_MFLAG, MNT_NOMTAB) + * @mask: (MNT_INVERT, MNT_NOMTAB) * * The option argument type is defined by: * @@ -56,9 +56,9 @@ * #define MY_MS_BAR (1 << 2) * * mnt_optmap myoptions[] = { - * { "foo", MY_MS_FOO, MNT_MFLAG }, - * { "nofoo", MY_MS_FOO, MNT_MFLAG | MNT_INVERT }, - * { "bar=%s",MY_MS_BAR, MNT_MDATA }, + * { "foo", MY_MS_FOO }, + * { "nofoo", MY_MS_FOO | MNT_INVERT }, + * { "bar=%s",MY_MS_BAR }, * { NULL } * }; * @@ -86,53 +86,53 @@ */ static const struct mnt_optmap linux_flags_map[] = { - { "ro", MS_RDONLY, MNT_MFLAG }, /* read-only */ - { "rw", MS_RDONLY, MNT_MFLAG | MNT_INVERT }, /* read-write */ - { "exec", MS_NOEXEC, MNT_MFLAG | MNT_INVERT }, /* permit execution of binaries */ - { "noexec", MS_NOEXEC, MNT_MFLAG }, /* don't execute binaries */ - { "suid", MS_NOSUID, MNT_MFLAG | MNT_INVERT }, /* honor suid executables */ - { "nosuid", MS_NOSUID, MNT_MFLAG }, /* don't honor suid executables */ - { "dev", MS_NODEV, MNT_MFLAG | MNT_INVERT }, /* interpret device files */ - { "nodev", MS_NODEV, MNT_MFLAG }, /* don't interpret devices */ - - { "sync", MS_SYNCHRONOUS, MNT_MFLAG }, /* synchronous I/O */ - { "async", MS_SYNCHRONOUS, MNT_MFLAG | MNT_INVERT }, /* asynchronous I/O */ - - { "dirsync", MS_DIRSYNC, MNT_MFLAG }, /* synchronous directory modifications */ - { "remount", MS_REMOUNT, MNT_MFLAG }, /* Alter flags of mounted FS */ - { "bind", MS_BIND, MNT_MFLAG }, /* Remount part of tree elsewhere */ - { "rbind", MS_BIND|MS_REC, MNT_MFLAG }, /* Idem, plus mounted subtrees */ + { "ro", MS_RDONLY }, /* read-only */ + { "rw", MS_RDONLY, MNT_INVERT }, /* read-write */ + { "exec", MS_NOEXEC, MNT_INVERT }, /* permit execution of binaries */ + { "noexec", MS_NOEXEC }, /* don't execute binaries */ + { "suid", MS_NOSUID, MNT_INVERT }, /* honor suid executables */ + { "nosuid", MS_NOSUID }, /* don't honor suid executables */ + { "dev", MS_NODEV, MNT_INVERT }, /* interpret device files */ + { "nodev", MS_NODEV }, /* don't interpret devices */ + + { "sync", MS_SYNCHRONOUS }, /* synchronous I/O */ + { "async", MS_SYNCHRONOUS, MNT_INVERT },/* asynchronous I/O */ + + { "dirsync", MS_DIRSYNC }, /* synchronous directory modifications */ + { "remount", MS_REMOUNT }, /* Alter flags of mounted FS */ + { "bind", MS_BIND }, /* Remount part of tree elsewhere */ + { "rbind", MS_BIND | MS_REC }, /* Idem, plus mounted subtrees */ #ifdef MS_NOSUB - { "sub", MS_NOSUB, MNT_MFLAG | MNT_INVERT }, /* allow submounts */ - { "nosub", MS_NOSUB, MNT_MFLAG }, /* don't allow submounts */ + { "sub", MS_NOSUB, MNT_INVERT }, /* allow submounts */ + { "nosub", MS_NOSUB }, /* don't allow submounts */ #endif #ifdef MS_SILENT - { "quiet", MS_SILENT, MNT_MFLAG }, /* be quiet */ - { "loud", MS_SILENT, MNT_MFLAG | MNT_INVERT }, /* print out messages. */ + { "quiet", MS_SILENT }, /* be quiet */ + { "loud", MS_SILENT, MNT_INVERT }, /* print out messages. */ #endif #ifdef MS_MANDLOCK - { "mand", MS_MANDLOCK, MNT_MFLAG }, /* Allow mandatory locks on this FS */ - { "nomand", MS_MANDLOCK, MNT_MFLAG | MNT_INVERT },/* Forbid mandatory locks on this FS */ + { "mand", MS_MANDLOCK }, /* Allow mandatory locks on this FS */ + { "nomand", MS_MANDLOCK, MNT_INVERT }, /* Forbid mandatory locks on this FS */ #endif #ifdef MS_NOATIME - { "atime", MS_NOATIME, MNT_MFLAG | MNT_INVERT }, /* Update access time */ - { "noatime", MS_NOATIME, MNT_MFLAG }, /* Do not update access time */ + { "atime", MS_NOATIME, MNT_INVERT }, /* Update access time */ + { "noatime", MS_NOATIME }, /* Do not update access time */ #endif #ifdef MS_I_VERSION - { "iversion", MS_I_VERSION, MNT_MFLAG }, /* Update inode I_version time */ - { "noiversion", MS_I_VERSION, MNT_MFLAG | MNT_INVERT}, /* Don't update inode I_version time */ + { "iversion", MS_I_VERSION }, /* Update inode I_version time */ + { "noiversion", MS_I_VERSION, MNT_INVERT},/* Don't update inode I_version time */ #endif #ifdef MS_NODIRATIME - { "diratime", MS_NODIRATIME, MNT_MFLAG | MNT_INVERT }, /* Update dir access times */ - { "nodiratime", MS_NODIRATIME, MNT_MFLAG }, /* Do not update dir access times */ + { "diratime", MS_NODIRATIME, MNT_INVERT }, /* Update dir access times */ + { "nodiratime", MS_NODIRATIME }, /* Do not update dir access times */ #endif #ifdef MS_RELATIME - { "relatime", MS_RELATIME, MNT_MFLAG }, /* Update access times relative to mtime/ctime */ - { "norelatime", MS_RELATIME, MNT_MFLAG | MNT_INVERT }, /* Update access time without regard to mtime/ctime */ + { "relatime", MS_RELATIME }, /* Update access times relative to mtime/ctime */ + { "norelatime", MS_RELATIME, MNT_INVERT }, /* Update access time without regard to mtime/ctime */ #endif #ifdef MS_STRICTATIME - { "strictatime", MS_STRICTATIME, MNT_MFLAG }, /* Strict atime semantics */ - { "nostrictatime", MS_STRICTATIME, MNT_MFLAG | MNT_INVERT }, /* kernel default atime */ + { "strictatime", MS_STRICTATIME }, /* Strict atime semantics */ + { "nostrictatime", MS_STRICTATIME, MNT_INVERT }, /* kernel default atime */ #endif { NULL, 0, 0 } }; diff --git a/shlibs/mount/src/optstr.c b/shlibs/mount/src/optstr.c index 5e14c1c0..0cfcd513 100644 --- a/shlibs/mount/src/optstr.c +++ b/shlibs/mount/src/optstr.c @@ -504,8 +504,26 @@ int mnt_split_optstr(const char *optstr, char **user, char **vfs, char **fs, return 0; } -static int mnt_optstr_get_flags(const char *optstr, const struct mnt_optmap *map, - unsigned long *flags, int mask_fltr) +/** + * mnt_optstr_get_flags: + * @optstr: string with comma separated list of options + * @flags: returns mount flags + * + * Returns in @flags IDs of options from @optstr as defined in the @map. + * + * For example: + * + * "bind,exec,foo,bar" --returns-> MS_BIND + * + * "bind,noexec,foo,bar" --returns-> MS_BIND|MS_NOEXEC + * + * Note that @flags are not zeroized by this function. + * + * Returns: 0 on success or negative number in case of error + */ + +int mnt_optstr_get_flags(const char *optstr, unsigned long *flags, + const struct mnt_optmap *map) { struct mnt_optmap const *maps[1]; char *name, *str = (char *) optstr; @@ -522,9 +540,6 @@ static int mnt_optstr_get_flags(const char *optstr, const struct mnt_optmap *map const struct mnt_optmap *ent; if (mnt_optmap_get_entry(maps, 1, name, namesz, &ent)) { - - if (mask_fltr && !(ent->mask & mask_fltr)) - continue; if (ent->mask & MNT_INVERT) *flags &= ~ent->id; else @@ -540,9 +555,8 @@ static int mnt_optstr_get_flags(const char *optstr, const struct mnt_optmap *map * @optstr: string with comma separated list of options * @flags: returns mount flags * - * The mountflags are IDs from all MNT_MFLAG options from MNT_LINUX_MAP options - * map. See "struct mnt_optmap". For more details about mountflags see - * mount(2) syscall. + * For more details about mountflags see mount(2) syscall. The flags are + * generated according to MNT_LINUX_MAP. * * For example: * @@ -556,10 +570,8 @@ static int mnt_optstr_get_flags(const char *optstr, const struct mnt_optmap *map */ int mnt_optstr_get_mountflags(const char *optstr, unsigned long *flags) { - return mnt_optstr_get_flags(optstr, - mnt_get_builtin_optmap(MNT_LINUX_MAP), - flags, - MNT_MFLAG); + return mnt_optstr_get_flags(optstr, flags, + mnt_get_builtin_optmap(MNT_LINUX_MAP)); } /** @@ -580,10 +592,85 @@ int mnt_optstr_get_mountflags(const char *optstr, unsigned long *flags) */ int mnt_optstr_get_userspace_mountflags(const char *optstr, unsigned long *flags) { - return mnt_optstr_get_flags(optstr, - mnt_get_builtin_optmap(MNT_USERSPACE_MAP), - flags, - 0); + return mnt_optstr_get_flags(optstr, flags, + mnt_get_builtin_optmap(MNT_USERSPACE_MAP)); +} + +/** + * mnt_optstr_apply_flags: + * @optstr: string with comma separated list of options + * @flags: returns mount flags + * @map: options map + * + * Removes/adds options to the @optstr according to flags. For example: + * + * MS_NOATIME and "foo,bar,noexec" --returns-> "foo,bar,noatime" + * + * Returns: 0 on success or negative number in case of error. + */ +int mnt_optstr_apply_flags(char **optstr, unsigned long flags, + const struct mnt_optmap *map) +{ + struct mnt_optmap const *maps[1]; + char *name, *next, *val; + size_t namesz = 0, valsz = 0; + unsigned long fl; + int rc = 0; + + assert(optstr); + + if (!optstr || !map) + return -EINVAL; + + maps[0] = map; + next = *optstr; + fl = flags; + + /* scan @optstr and remove options that are missing in the @flags */ + while(!mnt_optstr_next_option(&next, &name, &namesz, &val, &valsz)) { + const struct mnt_optmap *ent; + + if (mnt_optmap_get_entry(maps, 1, name, namesz, &ent)) { + + /* remove unwanted option */ + if ((ent->mask & MNT_INVERT) || !(fl & ent->id)) { + char *end = val ? val + valsz : name + namesz; + next = name; + rc = mnt_optstr_remove_option_at(optstr, name, end); + if (rc) + return rc; + } + if (!(ent->mask & MNT_INVERT)) + fl &= ~ent->id; + } + } + + /* add missing options */ + if (fl) { + const struct mnt_optmap *ent; + char *p; + + for (ent = map; ent && ent->name; ent++) { + if ((ent->mask & MNT_INVERT) || !(fl & ent->id)) + continue; + + /* don't add options which require values (e.g. offset=%d) */ + p = strchr(ent->name, '='); + if (p && p > ent->name && *(p - 1) != '[') + continue; + + /* prepare name for value with optional value (e.g. loop[=%s]) */ + if (p) { + p = strndup(ent->name, p - ent->name); + if (!p) + return -ENOMEM; + mnt_optstr_append_option(optstr, p, NULL); + free(p); + } else + mnt_optstr_append_option(optstr, ent->name, NULL); + } + } + return rc; } /** @@ -855,6 +942,36 @@ int test_flags(struct mtest *ts, int argc, char *argv[]) return rc; } +int test_apply(struct mtest *ts, int argc, char *argv[]) +{ + char *optstr; + int rc, map; + unsigned long flags; + + if (argc < 4) + return -EINVAL; + + if (!strcmp(argv[1], "--user")) + map = MNT_USERSPACE_MAP; + else if (!strcmp(argv[1], "--linux")) + map = MNT_LINUX_MAP; + else { + fprintf(stderr, "unknown option '%s'\n", argv[1]); + return -EINVAL; + } + + optstr = strdup(argv[2]); + flags = strtoul(argv[3], NULL, 16); + + printf("flags: 0x%08lx\n", flags); + + rc = mnt_optstr_apply_flags(&optstr, flags, mnt_get_builtin_optmap(map)); + printf("optstr: %s\n", optstr); + + free(optstr); + return rc; +} + int test_set(struct mtest *ts, int argc, char *argv[]) { const char *value = NULL, *name; @@ -965,6 +1082,7 @@ int main(int argc, char *argv[]) { "--remove", test_remove, " remove name in optstr" }, { "--split", test_split, " split into FS, VFS and userspace" }, { "--flags", test_flags, " convert options to MS_* flags" }, + { "--apply", test_apply, "--{linux,user} apply mask to optstr" }, { "--fix", test_fix, " fix uid=, gid= and context=" }, { NULL } -- 2.39.5