summaryrefslogtreecommitdiffstats
path: root/shlibs/mount/src/optmap.c
diff options
context:
space:
mode:
authorKarel Zak2010-01-11 13:33:06 +0100
committerKarel Zak2010-06-03 15:20:10 +0200
commit078edb2d6e4188963938b7be076db5382f6f802b (patch)
tree5770e1758274c47120ed57f278d7a9b9433904cb /shlibs/mount/src/optmap.c
parentlibmount: add list routines and generic iterator (diff)
downloadkernel-qcow2-util-linux-078edb2d6e4188963938b7be076db5382f6f802b.tar.gz
kernel-qcow2-util-linux-078edb2d6e4188963938b7be076db5382f6f802b.tar.xz
kernel-qcow2-util-linux-078edb2d6e4188963938b7be076db5382f6f802b.zip
libmount: add optls (options container)
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'shlibs/mount/src/optmap.c')
-rw-r--r--shlibs/mount/src/optmap.c289
1 files changed, 289 insertions, 0 deletions
diff --git a/shlibs/mount/src/optmap.c b/shlibs/mount/src/optmap.c
new file mode 100644
index 000000000..873c545ce
--- /dev/null
+++ b/shlibs/mount/src/optmap.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ *
+ * Option-maps
+ * -----------
+ * The mount(2) linux syscall uses two arguments for mount options:
+ *
+ * 1) mountflags (see MS_* macros in linux/fs.h)
+ * 2) mountdata (usully a comma separated string of options)
+ *
+ * The libmount uses options-map(s) to describe mount options. The number of
+ * maps is unlimited. The libmount options parser could be easily extended
+ * (e.g. by mnt_optls_add_map()) to work with new options.
+ *
+ * The option description (map entry) includes:
+ *
+ * - option name and argument type (e.g. "loop[=%s]")
+ * - option ID (in the map unique identifier or a mountflags, e.g MS_RDONLY)
+ * - mask (MNT_INVERT, MNT_MDATA, MNT_MFLAG, MNT_NOMTAB)
+ *
+ * The option argument type is defined by:
+ *
+ * "=<type>" -- required argument
+ * "[=<type>]" -- optional argument
+ *
+ * where the <type> is sscanf() format string or
+ *
+ * {item0,item1,...} -- enum (mnt_option_get_number() converts the value
+ * to 0..N number)
+ *
+ * The options argument format is used for parsing only. The library internally
+ * stores the option argument as a string. The conversion to the data type is
+ * on-demant by mnt_option_get_value_*() functions.
+ *
+ * The library checks options argument according to <type> format for simple
+ * formats only:
+ *
+ * %s, %d, %ld, %lld, %u, %lu, %llu, %x, %o and {enum}
+ *
+ * The libmount defines two basic built-in options maps:
+ *
+ * - MNT_LINUX_MAP -- fs-independent kernel mount options (usually MS_* flags)
+ * - MNT_USERSPACE_MAP -- userspace specific mount options (e.g. "user", "loop")
+ *
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "nls.h"
+#include "mountP.h"
+
+/*
+ * fs-independent mount flags (built-in MNT_LINUX_MAP)
+ */
+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 */
+#ifdef MS_NOSUB
+ { "sub", MS_NOSUB, MNT_MFLAG | MNT_INVERT }, /* allow submounts */
+ { "nosub", MS_NOSUB, MNT_MFLAG }, /* 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. */
+#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 */
+#endif
+#ifdef MS_NOATIME
+ { "atime", MS_NOATIME, MNT_MFLAG | MNT_INVERT }, /* Update access time */
+ { "noatime", MS_NOATIME, MNT_MFLAG }, /* 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 */
+#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 */
+#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 */
+#endif
+#ifdef MS_STRICTATIME
+ { "strictatime", MS_STRICTATIME, MNT_MFLAG }, /* Strict atime semantics */
+ { "nostrictatime", MS_STRICTATIME, MNT_MFLAG | MNT_INVERT }, /* kernel default atime */
+#endif
+ { NULL, 0, 0 }
+};
+
+/*
+ * userspace mount option (built-in MNT_USERSPACE_MAP)
+ */
+static const struct mnt_optmap userspace_opts_map[] =
+{
+ { "defaults", MNT_MS_DFLTS, MNT_NOMTAB }, /* default options */
+
+ { "auto", MNT_MS_NOAUTO, MNT_INVERT | MNT_NOMTAB }, /* Can be mounted using -a */
+ { "noauto", MNT_MS_NOAUTO, MNT_NOMTAB }, /* Can only be mounted explicitly */
+
+ { "user[=%s]", MNT_MS_USER }, /* Allow ordinary user to mount (mtab) */
+ { "nouser", MNT_MS_USER, MNT_INVERT | MNT_NOMTAB }, /* Forbid ordinary user to mount */
+
+ { "users", MNT_MS_USERS, MNT_NOMTAB }, /* Allow ordinary users to mount */
+ { "nousers", MNT_MS_USERS, MNT_INVERT | MNT_NOMTAB }, /* Forbid ordinary users to mount */
+
+ { "owner", MNT_MS_OWNER, MNT_NOMTAB }, /* Let the owner of the device mount */
+ { "noowner", MNT_MS_OWNER, MNT_INVERT | MNT_NOMTAB }, /* Device owner has no special privs */
+
+ { "group", MNT_MS_GROUP, MNT_NOMTAB }, /* Let the group of the device mount */
+ { "nogroup", MNT_MS_GROUP, MNT_INVERT | MNT_NOMTAB }, /* Device group has no special privs */
+
+ { "_netdev", MNT_MS_NETDEV }, /* Device requires network */
+
+ { "comment=%s", MNT_MS_COMMENT, MNT_NOMTAB }, /* fstab comment only */
+
+ { "loop[=%s]", MNT_MS_LOOP }, /* use the loop device */
+
+ { "nofail", MNT_MS_NOFAIL, MNT_NOMTAB }, /* Do not fail if ENOENT on dev */
+
+ { NULL, 0, 0 }
+};
+
+/**
+ * mnt_get_builtin_map:
+ * @id: map id -- MNT_LINUX_MAP or MNT_USERSPACE_MAP
+ *
+ * MNT_LINUX_MAP - Linux kernel fs-independent mount options
+ * (usually MS_* flags, see linux/fs.h)
+ *
+ * MNT_USERSPACE_MAP - userpace mount(8) specific mount options
+ * (e.g user=, _netdev, ...)
+ *
+ * Returns internal (static) libmount map.
+ */
+const struct mnt_optmap *mnt_get_builtin_optmap(int id)
+{
+ assert(id);
+
+ if (id == MNT_LINUX_MAP)
+ return linux_flags_map;
+ else if (id == MNT_USERSPACE_MAP)
+ return userspace_opts_map;
+ return NULL;
+}
+
+/*
+ * Lookups for the @name in @maps and returns a map and in @mapent
+ * returns the map entry
+ */
+const struct mnt_optmap *mnt_optmap_get_entry(
+ struct mnt_optmap const **maps,
+ int nmaps,
+ const char *name,
+ size_t namelen,
+ const struct mnt_optmap **mapent)
+{
+ int i;
+
+ assert(maps);
+ assert(nmaps);
+ assert(name);
+ assert(namelen);
+ assert(mapent);
+
+ *mapent = NULL;
+
+ for (i = 0; i < nmaps; i++) {
+ const struct mnt_optmap *map = maps[i];
+ const struct mnt_optmap *ent;
+ const char *p;
+
+ for (ent = map; ent && ent->name; ent++) {
+ if (strncmp(ent->name, name, namelen))
+ continue;
+ p = ent->name + namelen;
+ if (*p == '\0' || *p == '=' || *p == '[') {
+ *mapent = ent;
+ return map;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+/*
+ * Converts @rawdata to number according to enum definition in the @mapent.
+ */
+int mnt_optmap_enum_to_number(const struct mnt_optmap *mapent,
+ const char *rawdata, size_t len)
+{
+ const char *p, *end = NULL, *begin = NULL;
+ int n = -1;
+
+ if (!rawdata || !*rawdata || !mapent || !len)
+ return -1;
+
+ p = strrchr(mapent->name, '=');
+ if (!p || *(p + 1) == '{')
+ return -1; /* value unexpected or not "enum" */
+ p += 2;
+ if (!*p || *(p + 1) == '}')
+ return -1; /* hmm... option <type> is "={" or "={}" */
+
+ /* we cannot use strstr(), @rawdata is not terminated */
+ for (; p && *p; p++) {
+ if (!begin)
+ begin = p; /* begin of the item */
+ if (*p == ',')
+ end = p; /* terminate the item */
+ if (*(p + 1) == '}')
+ end = p + 1; /* end of enum definition */
+ if (!begin || !end)
+ continue;
+ if (end <= begin)
+ return -1;
+ n++;
+ if (len == end - begin && strncasecmp(begin, rawdata, len) == 0)
+ return n;
+ p = end;
+ }
+
+ return -1;
+}
+
+/*
+ * Returns data type defined in the @mapent.
+ */
+const char *mnt_optmap_get_type(const struct mnt_optmap *mapent)
+{
+ char *type;
+
+ assert(mapent);
+ assert(mapent->name);
+
+ type = strrchr(mapent->name, '=');
+ if (!type)
+ return NULL; /* value is unexpected */
+ if (type == mapent->name)
+ return NULL; /* wrong format of type definition */
+ type++;
+ if (*type != '%' && *type != '{')
+ return NULL; /* wrong format of type definition */
+ return type ? : NULL;
+}
+
+/*
+ * Does the option (that is described by @mntent) require any value? (e.g.
+ * uid=<foo>)
+ */
+int mnt_optmap_require_value(const struct mnt_optmap *mapent)
+{
+ char *type;
+
+ assert(mapent);
+ assert(mapent->name);
+
+ type = strchr(mapent->name, '=');
+ if (!type)
+ return 0; /* value is unexpected */
+ if (type == mapent->name)
+ return 0; /* wrong format of type definition */
+ if (*(type - 1) == '[')
+ return 0; /* optional */
+ return 1;
+}