*
* @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:
*
* #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 }
};
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;
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
* @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:
*
*/
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));
}
/**
*/
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;
}
/**
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;
{ "--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 }