diff options
author | Karel Zak | 2010-01-11 13:33:06 +0100 |
---|---|---|
committer | Karel Zak | 2010-06-03 15:20:10 +0200 |
commit | 078edb2d6e4188963938b7be076db5382f6f802b (patch) | |
tree | 5770e1758274c47120ed57f278d7a9b9433904cb /shlibs/mount/src/optmap.c | |
parent | libmount: add list routines and generic iterator (diff) | |
download | kernel-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.c | 289 |
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; +} |