]> err.no Git - util-linux/commitdiff
libmount: clean up mountflags usage
authorKarel Zak <kzak@redhat.com>
Fri, 24 Sep 2010 23:48:38 +0000 (01:48 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 3 Jan 2011 11:28:43 +0000 (12:28 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
shlibs/mount/src/mount.h.in
shlibs/mount/src/mount.sym
shlibs/mount/src/optmap.c
shlibs/mount/src/optstr.c

index 08ba59c8fc890e67e0d1b1d164a305f6354734ca..ac69ac55706bda634fe9c722dec27d1effd0e067 100644 (file)
@@ -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);
index b6cf39015858816d91176c20b69c887b147d376c..308abcde986b30181fe017e48e9f9023831e5122 100644 (file)
@@ -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;
index d8ec5eab76674fe4011c14b3e1520429bcae300a..d96da986ce2df460820b685f410323eea2759f01 100644 (file)
@@ -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 }
  *     };
  *   </programlisting>
  */
 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 }
 };
index 5e14c1c0ecf3f99f1eaccf9a2fd0f46a8ef9d87b..0cfcd513b623f2c74629d2d914869d5f9ebedc78 100644 (file)
@@ -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, "<optstr> <name>            remove name in optstr" },
                { "--split",  test_split,  "<optstr>                   split into FS, VFS and userspace" },
                { "--flags",  test_flags,  "<optstr>                   convert options to MS_* flags" },
+               { "--apply",  test_apply,  "--{linux,user} <optstr> <mask>    apply mask to optstr" },
                { "--fix",    test_fix,    "<optstr>                   fix uid=, gid= and context=" },
 
                { NULL }