From: Karel Zak Date: Thu, 5 Aug 2010 12:28:19 +0000 (+0200) Subject: libmount: remove unnecessary options container X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6f0c256db39247a873c1513275073f9a574c30ce;p=util-linux libmount: remove unnecessary options container It seems that we are able to be happy with option strings only. The mnt_optls stuff was over-engineering. Signed-off-by: Karel Zak --- diff --git a/shlibs/mount/src/Makefile.am b/shlibs/mount/src/Makefile.am index 4576dd0c..6e2f6204 100644 --- a/shlibs/mount/src/Makefile.am +++ b/shlibs/mount/src/Makefile.am @@ -10,7 +10,7 @@ nodist_mountinc_HEADERS = mount.h usrlib_exec_LTLIBRARIES = libmount.la libmount_la_SOURCES = mountP.h version.c utils.c test.c init.c cache.c \ - optstr.c optmap.c optent.c optls.c iter.c lock.c \ + optstr.c optmap.c iter.c lock.c \ fs.c tab.c tab_parse.c mtab.c \ $(mountinc_HEADERS) \ $(top_srcdir)/lib/at.c \ @@ -47,7 +47,7 @@ uninstall-hook: rm -f $(DESTDIR)$(libdir)/libmount.so* -tests = test_version test_cache test_optstr test_optls test_lock \ +tests = test_version test_cache test_optstr test_lock \ test_tab test_utils test_mtab tests: all $(tests) diff --git a/shlibs/mount/src/mount.h.in b/shlibs/mount/src/mount.h.in index a1944c54..329ec8f1 100644 --- a/shlibs/mount/src/mount.h.in +++ b/shlibs/mount/src/mount.h.in @@ -54,20 +54,6 @@ typedef struct _mnt_lock mnt_lock; */ typedef struct _mnt_iter mnt_iter; -/** - * mnt_optls: - * - * Mount options list (stores parsed mount options) - */ -typedef struct _mnt_optls mnt_optls; - -/** - * mnt_optent: - * - * Parsed mount option - "mnt_optls" entry - */ -typedef struct _mnt_optent mnt_optent; - /** * mnt_optmap: * @@ -191,51 +177,6 @@ enum { }; extern const struct mnt_optmap *mnt_get_builtin_optmap(int id); -/* optent.c */ -extern const struct mnt_optmap *mnt_optent_get_map(mnt_optent *op); -extern const struct mnt_optmap *mnt_optent_get_mapent(mnt_optent *op); -extern const char *mnt_optent_get_type(mnt_optent *op); -extern int mnt_optent_set_value(mnt_optent *op, const char *data); -extern int mnt_optent_has_value(mnt_optent *op); -extern int mnt_optent_require_value(mnt_optent *op); -extern int mnt_optent_is_inverted(mnt_optent *op); -extern int mnt_optent_strtoul_value(mnt_optent *op, unsigned long int *number); -extern int mnt_optent_strtol_value(mnt_optent *op, long int *number); -extern int mnt_optent_strtoull_value(mnt_optent *op, unsigned long long int *number); -extern const char *mnt_optent_get_value(mnt_optent *op); -extern int mnt_optent_strlen_value(mnt_optent *op); -extern int mnt_optent_snprintf_value(mnt_optent *op, char *str, size_t size); -extern char *mnt_optent_dup_value(mnt_optent *op); -extern const char *mnt_optent_get_name(mnt_optent *op); -extern int mnt_optent_get_mask(mnt_optent *op); -extern int mnt_optent_get_id(mnt_optent *op); -extern int mnt_optent_get_flag(mnt_optent *op, int *flags); -extern int mnt_optent_is_unknown(mnt_optent *op); -extern int mnt_optent_print_debug(mnt_optent *op, FILE *file); - -/* optls.c */ -extern mnt_optls *mnt_new_optls(void); -extern void mnt_free_optls(mnt_optls *ls); -extern int mnt_optls_add_map(mnt_optls *ls, const struct mnt_optmap *map); -extern int mnt_optls_add_builtin_map(mnt_optls *ls, int id); -extern mnt_optent *mnt_optls_add_option(mnt_optls *ls, - const char *name, const char *value); -extern int mnt_optls_parse_optstr(mnt_optls *ls, const char *optstr); -extern int mnt_optls_remove_option(mnt_optls *ls, const char *name); -extern int mnt_optls_remove_option_by_flags(mnt_optls *ls, - const struct mnt_optmap *map, const int flags); -extern int mnt_optls_remove_option_by_iflags(mnt_optls *ls, - const struct mnt_optmap *map, const int flags); -extern int mnt_optls_next_option(mnt_optls *ls, mnt_iter *itr, - const struct mnt_optmap *map, mnt_optent **option); -extern mnt_optent *mnt_optls_get_option(mnt_optls *ls, const char *name); -extern int mnt_optls_get_ids(mnt_optls *ls, const struct mnt_optmap *map); -extern int mnt_optls_create_mountflags(mnt_optls *ls); -extern char *mnt_optls_create_mountdata(mnt_optls *ls); -extern char *mnt_optls_create_mtab_optstr(mnt_optls *ls); -extern char *mnt_optls_create_userspace_optstr(mnt_optls *ls); -extern int mnt_optls_print_debug(mnt_optls *ls, FILE *file); - /* lock.c */ extern mnt_lock *mnt_new_lock(const char *lockname, pid_t id); extern void mnt_free_lock(mnt_lock *ml); diff --git a/shlibs/mount/src/mountP.h b/shlibs/mount/src/mountP.h index bc584e3e..9f00b613 100644 --- a/shlibs/mount/src/mountP.h +++ b/shlibs/mount/src/mountP.h @@ -105,32 +105,6 @@ struct _mnt_iter { } while(0) -/* - * mnt_optls entry - */ -struct _mnt_optent { - char *name; /* option name (allcocated when mapent is NULL) */ - char *value; /* option argument value */ - - int mask; /* MNT_{INVMASK,MDATA,MFLAG,NOMTAB,NOSYS} - * modifiable flags (initial value comes from map->mask) - */ - const struct mnt_optmap *mapent;/* the option description (msp entry) */ - const struct mnt_optmap *map; /* head of the map */ - - struct list_head opts; /* list of options */ -}; - -/* - * Container (list) for mount options - */ -struct _mnt_optls { - struct mnt_optmap const **maps; /* array with option maps */ - size_t nmaps; /* number of maps */ - - struct list_head opts; /* list of options */ -}; - /* * This struct represents one entry in mtab/fstab/mountinfo file. */ @@ -193,20 +167,6 @@ extern int mnt_optmap_enum_to_number(const struct mnt_optmap *mapent, extern const char *mnt_optmap_get_type(const struct mnt_optmap *mapent); extern int mnt_optmap_require_value(const struct mnt_optmap *mapent); -/* optent.c */ - -/* private option masks -- see mount.h.in for the publick masks */ -#define MNT_HASVAL (1 << 10) - -extern mnt_optent *mnt_new_optent(const char *name, size_t namesz, - const char *value, size_t valsz, - struct mnt_optmap const **maps, int nmaps); -extern void mnt_free_optent(mnt_optent *op); -extern mnt_optent *mnt_new_optent_from_optstr(char **optstr, - struct mnt_optmap const **maps, int nmaps); -extern int mnt_optent_assign_map(mnt_optent *op, - struct mnt_optmap const **maps, int nmaps); - /* fs.c */ extern int __mnt_fs_set_source(mnt_fs *fs, char *source); extern int __mnt_fs_set_fstype(mnt_fs *fs, char *fstype); diff --git a/shlibs/mount/src/optent.c b/shlibs/mount/src/optent.c deleted file mode 100644 index 4b35b2d5..00000000 --- a/shlibs/mount/src/optent.c +++ /dev/null @@ -1,735 +0,0 @@ -/* - * Copyright (C) 2010 Karel Zak - * - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - */ - -/** - * SECTION: optent - * @title: Parsed option - * @short_description: the mnt_optent keeps one parsed mount option - */ -#include -#include -#include -#include - -#include "nls.h" -#include "mountP.h" - -static int mnt_init_optent(mnt_optent *op, const char *name, size_t namelen, - struct mnt_optmap const **maps, int nmaps); -static int __mnt_optent_set_value(mnt_optent *op, const char *data, size_t len); - - -/* - * Returns a new optent. - */ -mnt_optent *mnt_new_optent( const char *name, size_t namesz, - const char *value, size_t valsz, - struct mnt_optmap const **maps, int nmaps) -{ - mnt_optent *op; - - op = calloc(1, sizeof(struct _mnt_optent)); - if (!op) - return NULL; - - INIT_LIST_HEAD(&op->opts); - - if (mnt_init_optent(op, name, namesz, maps, nmaps)) - goto err; - - if (value) { - if (__mnt_optent_set_value(op, value, valsz)) - goto err; - } else if (mnt_optent_require_value(op)) - goto err; - - return op; -err: - free(op); - return NULL; -} - -/* - * Deallocates the optent. - */ -void mnt_free_optent(mnt_optent *op) -{ - if (!op) - return; - - if (!op->mapent || op->mapent->name != op->name) - free(op->name); - - free(op->value); - - if (!list_empty(&op->opts)) - list_del(&op->opts); - - free(op); -} - -/* - * initialize or reinitialize the option entry -- note that the option - * name is set to @name and the old name is not free()ed. If the @name - * is NULL the already existing option name is used. - */ -static int mnt_init_optent(mnt_optent *op, const char *name, size_t namelen, - struct mnt_optmap const **maps, int nmaps) -{ - const struct mnt_optmap *mapent = NULL, *map = NULL; - - assert(op); - - if (!op) - return -1; - - if (!name && op->name) { - name = op->name; - namelen = strlen(name); - } - if (!name) - return -1; - - if (nmaps && maps) - map = mnt_optmap_get_entry(maps, nmaps, name, namelen, &mapent); - - if (mapent == NULL || mnt_optmap_get_type(mapent) != NULL) { - /* we allocate the name for uknown options of for options with - * "=%" argument. This is not perfect... */ - if (op->name != name) - op->name = strndup(name, namelen); - } else - op->name = (char *) mapent->name; - - op->mapent = mapent; - op->map = map; - op->mask = mapent ? mapent->mask : 0; - if (op->value) - op->mask |= MNT_HASVAL; - - if (!op->name) - return -1; /* strdup() failed */ - - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: option %s: initialized\n", op->name)); - - return 0; -} - -static int mnt_optent_check_value(mnt_optent *op, const char *data, size_t len) -{ - const char *type; - char *end = NULL; - - assert(op); - if (!op) - return -1; - - type = mnt_optent_get_type(op); - if (!type) - goto err; /* value is unexpected */ - - if (!data) { - if (mnt_optent_require_value(op)) - goto err; - } else if (!strncmp(type, "%s", 2)) { - /* string type */ - ; - } else if (*type == '{') { - /* enum type */ - if (mnt_optmap_enum_to_number(op->mapent, data, len) < 0) - goto err; - } else { - /* numbers */ - int n; /* happy gcc */ - - errno = 0; - if (!strncmp(type, "%d", 2) || !strncmp(type, "%ld", 3)) - n = strtol(data, &end, 10); - else if (!strncmp(type, "%u", 2) || !strncmp(type, "%lu", 3)) - n = strtoul(data, &end, 10); - else if (!strncmp(type, "%lld", 4)) - n = strtoll(data, &end, 10); - else if (!strncmp(type, "%llu", 4)) - n = strtoull(data, &end, 10); - else if (!strncmp(type, "%o", 2)) - n = strtoul(data, &end, 8); - else if (!strncmp(type, "%x", 2)) - n = strtoul(data, &end, 16); - - if (errno == EINVAL || errno == ERANGE || end != data + len) - goto err; - } - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: option %s (type=%s): pass check\n", - op->name, type)); - return 0; -err: - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: option %s (type=%s): failed to check value %s\n", - op->name, type, data)); - return -1; -} - -/* - * Parses the first mount option from @optstr and move @optstr pointer - * to the next option. - * - * Returns new optent (parsed option) or NULL in case of error. - */ -mnt_optent *mnt_new_optent_from_optstr(char **optstr, - struct mnt_optmap const **maps, int nmaps) -{ - char *name, *value; - size_t nsz, vsz; - - if (mnt_optstr_next_option(optstr, &name, &nsz, &value, &vsz) == 0) - return mnt_new_optent(name, nsz, value, vsz, maps, nmaps); - - return NULL; -} - -/* - * Lookups @maps and tries to found corresponding map entry for the @op option. - * If the map is found the option value is reverified. - * - * Returns 0 on success, 1 if map not found, -1 in case of error (revalidation - * failed or so). - */ -int mnt_optent_assign_map(mnt_optent *op, - struct mnt_optmap const **maps, int nmaps) -{ - char *oldval, *oldname = NULL; - const char *type; - - assert(op); - assert(op->name); - - if (!op || !op->name) - return -1; - - if (op->mapent && op->name != op->mapent->name) - oldname = op->name; /* old name is allocated */ - - op->map = op->mapent = NULL; - oldval = op->value; - - if (mnt_init_optent(op, NULL, 0, maps, nmaps)) - return -1; - - if (op->name != oldname) - free(oldname); - - if (!op->map) - return 1; /* uknown option, it's not error */ - - /* the new type */ - type = mnt_optent_get_type(op); - - if (type == NULL && oldval) - goto err; /* value is unexpected */ - if (mnt_optent_require_value(op) && !oldval) - goto err; /* value is required */ - if (oldval && mnt_optent_check_value(op, oldval, strlen(oldval)) != 0) - goto err; /* bad value */ - - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: option %s: assigned to \n", op->name)); - return 0; -err: - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: option %s: assign failed\n", op->name)); - return -1; -} - -/** - * mnt_optent_get_map: - * @op: pointer to mnt_optent instance - * - * Returns: pointer to the head of the map that is associated with the option or - * NULL (for "extra options"). - */ -const struct mnt_optmap *mnt_optent_get_map(mnt_optent *op) -{ - assert(op); - return op ? op->map : NULL; -} - -/** - * mnt_optent_get_map_entry: - * @op: pointer to mnt_optent instance - * - * Returns: pointer to the map entry that describes the option or NULL (for - * "extra options"). - */ -const struct mnt_optmap *mnt_optent_get_mapent(mnt_optent *op) -{ - assert(op); - return op ? op->mapent : NULL; -} - -/** - * mnt_optent_get_type: - * @op: mnt_optent instance - * - * Note that the @op has to be associated with any option map - * or the default "%s]" is returned. - * - * Returns: pointer to the begin of type format string or NULL. For example: - * - * "%s" --> string, required argument (definition in the map is: "foo=%s") - * "%s]" --> string, optional argument (definition in the map is: "foo[=%s]") - */ -const char *mnt_optent_get_type(mnt_optent *op) -{ - assert(op); - if (!op) - return NULL; - return op->mapent ? mnt_optmap_get_type(op->mapent) : "%s]"; -} - - - -/** - * mnt_optent_set_value: - * @op: mnt_optent instance - * @data: option argument data or NULL - * - * The function unset (zeroize) the option value if the @data pointer is NULL. - * - * Returns: 0 on success or -1 in case of error. - */ -int mnt_optent_set_value(mnt_optent *op, const char *data) -{ - return __mnt_optent_set_value(op, data, data ? strlen(data) : 0); -} - -static int __mnt_optent_set_value(mnt_optent *op, const char *data, size_t len) -{ - assert(op); - if (!op) - return -1; - - free(op->value); - op->value = NULL; - op->mask &= ~MNT_HASVAL; - - if (mnt_optent_check_value(op, data, len) != 0) - goto err; - if (data) { - op->value = strndup(data, len); - if (!op->value) - goto err; - op->mask |= MNT_HASVAL; - } - - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: option %s: set argument value: %s\n", - op->name, op->value)); - return 0; -err: - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: option %s: set argument value failed\n", - op->name)); - return -1; - -} - -/** - * mnt_optent_has_value: - * @option: pointer to mnt_optent instance - * - * Returns: 1 if the option has actually set an argument value, or 0. - */ -int mnt_optent_has_value(mnt_optent *op) -{ - return op && (op->mask & MNT_HASVAL) ? 1 : 0; -} - -/** - * mnt_optent_require_value: - * @op: pointer to mnt_optent instance - * - * Note that the @op has to be associated with any option map - * or 0 is returned. - * - * Returns: 1 if the option requires an argument (option=arg). - */ -int mnt_optent_require_value(mnt_optent *op) -{ - return op && op->mapent ? mnt_optmap_require_value(op->mapent) : 0; -} - -/** - * mnt_optent_is_inverted: - * @op: pointer to mnt_optent instance - * - * Returns: 1 if the option has MNT_INVERT mask or 0. - */ -int mnt_optent_is_inverted(mnt_optent *op) -{ - return (op && (op->mask & MNT_INVERT)); -} - -static int get_number_base(const char *type) -{ - int base = 10; /* default */ - - if (!strncmp(type, "%o", 2)) - base = 8; - else if (!strncmp(type, "%x", 16)) - base = 16; - return base; -} - -/** - * mnt_optent_strtoul_value: - * @op: pointer to mnt_optent instance - * @number: resulting number - * - * Converts an option value to number. The strtoul() base (decimal, octan or - * hex) is determined from (%u, %o or %x) option format type -- default is - * decimal (for unknown options). - * - * The whole option value has to be possible to convert to the number - * (e.g "123ABC" returns -1). - * - * This function also converts {enum0,enumN} type to number 0..N. For more - * details see info about option maps. - * - * Returns: 0 on success, -1 in case of error. - */ -int mnt_optent_strtoul_value(mnt_optent *op, unsigned long int *number) -{ - const char *type = NULL; - char *end; - size_t len; - - if (!mnt_optent_has_value(op) || !number) - goto err;; - type = mnt_optent_get_type(op); - if (!type) - goto err; - - if (*type == '{') { - int n; - - if (!op->mapent) - goto err; - n = mnt_optmap_enum_to_number(op->mapent, op->value, - strlen(op->value)); - if (n < 0) - goto err; - *number = n; - } else { - errno = 0; - *number = strtoul(op->value, &end, get_number_base(type)); - - if (errno == EINVAL || errno == ERANGE) - goto err; - len = strlen(op->value); - if (end != op->value + len) - goto err; - } - return 0; -err: - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: option %s (type=%s): strtoul failed\n", - op->name, type)); - return -1; -} - -/** - * mnt_optent_strtol_value: - * @op: pointer to mnt_optent instance - * @number: resulting number - * - * Converts an option value to number. The strtol() base (decimal, octan or - * hex) is determined from (%u, %o or %x) option format type -- default is - * decimal. - * - * The whole option value has to be possible to convert to the number - * (e.g "123ABC" returns -1). - * - * Returns: 0 on success, -1 in case of error. - */ -int mnt_optent_strtol_value(mnt_optent *op, long int *number) -{ - const char *type; - char *end; - size_t len; - - if (!mnt_optent_has_value(op) || !number) - return -1; - - type = mnt_optent_get_type(op); - if (!type) - goto err; - - errno = 0; - *number = strtol(op->value, &end, get_number_base(type)); - - if (errno == EINVAL || errno == ERANGE) - goto err; - len = strlen(op->value); - if (end != op->value + len) - goto err; - - return 0; -err: - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: option %s (type=%s): strtol failed\n", - op->name, type)); - return -1; -} - -/** - * mnt_optent_strtoull_value: - * @op: pointer to mnt_optent instance - * @number: resulting number - * - * Converts an option value to number. The strtoull() base (decimal, octan or - * hex) is determined from (%u, %o or %x) option format type -- default is - * decimal. - * - * The whole option value has to be possible to convert to the number - * (e.g "123ABC" returns -1). - * - * Returns: 0 on success, -1 in case of error. - */ -int mnt_optent_strtoull_value(mnt_optent *op, unsigned long long int *number) -{ - const char *type; - char *end; - size_t len; - - if (!mnt_optent_has_value(op) || !number) - return -1; - - type = mnt_optent_get_type(op); - if (!type) - goto err; - - errno = 0; - *number = strtoull(op->value, &end, get_number_base(type)); - - if (errno == EINVAL || errno == ERANGE) - goto err; - len = strlen(op->value); - if (end != op->value + len) - goto err; - return 0; -err: - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: option %s (type=%s): strtoull failed\n", - op->name, type)); - return -1; - -} - -/** - * mnt_optent_get_value: - * @op: pointer to mnt_optent instance - * - * See also mnt_optent_has_value(). - * - * Returns: pointer to value or NULL. - */ -const char *mnt_optent_get_value(mnt_optent *op) -{ - return op? op->value : NULL; -} - -/** - * mnt_optent_strlen_value: - * @op: pointer to mnt_optent instance - * - * Returns: length of string that is necessary to print option value or -1 in - * case of error. - */ -int mnt_optent_strlen_value(mnt_optent *op) -{ - assert(op); - - if (!op) - return -1; - if (!mnt_optent_has_value(op)) - return 0; - return strlen(op->value); -} - -/** - * mnt_optent_snprintf_value: - * @op: pointer to mnt_optent instance - * @str: resulting string - * @size: size of string - * - * Returns: number of printed characters or negative number in case of error. - */ -int mnt_optent_snprintf_value(mnt_optent *op, char *str, size_t size) -{ - assert(op); - assert(str); - - if (!op || !str || !size) - return -1; - if (!mnt_optent_has_value(op)) - return -1; - - /* TODO: use extra quotes for SELinux contexts */ - return snprintf(str, size, "%s", op->value); -} - -/** - * mnt_optent_dup_value: - * @op: pointer to mnt_optent instance - * - * Returns: duplicate a option value. - */ -char *mnt_optent_dup_value(mnt_optent *op) -{ - assert(op); - - if (mnt_optent_has_value(op)) - return strdup(op->value); - return NULL; -} - -/** - * mnt_optent_get_name: - * @op: pointer to mnt_optent instance - * - * Returns: option name or NULL in case of error. - */ -const char *mnt_optent_get_name(mnt_optent *op) -{ - assert(op); - return op ? op->name : NULL; -} - -/** - * mnt_optent_get_mask: - * @op: pointer to mnt_optent instance - * - * The initial value of the option mask is a copy from map->mask. - * Note that the mask is NOT a mountflag/ID. - * - * Returns: option mask or 0. - */ -int mnt_optent_get_mask(mnt_optent *op) -{ - assert(op); - return op ? op->mask : 0; -} - -/** - * mnt_optent_get_id: - * @op: pointer to mnt_optent instance - * - * Note that the ID is also mountflag for all options with MNT_MFLAG mask. - * - * WARNING: the ID is usually shared between "option" (e.g. exec) and - * "nooption" (e.g. noexec) -- you have to carefully check for MNT_INVERT in - * the option mask. See mnt_optent_get_flag(). - * - * Returns: option ID/mountflag or 0 for extra options (options with undefined - * options map). - */ -int mnt_optent_get_id(mnt_optent *op) -{ - assert(op); - return op && op->mapent ? op->mapent->id : 0; -} - -/** - * mnt_optent_get_flag: - * @op: pointer to mnt_optent instance - * @flags: resulting flags - * - * Adds option ID to @flags or removes the ID from @flags when the option - * is an inverted option (e.g. "norelatime") - * - * - * - * int flags = 0; - * - * while(mnt_optls_next_option(&itr, opts, map, &op) == 0) - * mnt_optent_get_flag(op, &flags); - * - * if (flags & MS_RELATIME) - * printf("relatime is set\n"); - * - * - * - * Returns: 0 on success, -1 in case of error. - */ -int mnt_optent_get_flag(mnt_optent *op, int *flags) -{ - int id; - - assert(op); - if (!op || !flags) - return -1; - - id = mnt_optent_get_id(op); - if (op->mask & MNT_INVERT) - *flags &= ~id; - else - *flags |= id; - return 0; -} - -/** - * mnt_optent_is_unknown: - * @op: pointer to mnt_optent instance - * - * The "extra options" are unknown options (undefined in any option map) - * - * Returns: 1 or 0. - */ -int mnt_optent_is_unknown(mnt_optent *op) -{ - assert(op); - return op && op->mapent ? 0 : 1; -} - -/** - * mnt_optent_print_debug: - * @file: output - * @op: pointer to mnt_optent instance - * - * Prints details about the option. - * - * Returns: 0 on success, -1 in case of error. - */ -int mnt_optent_print_debug(mnt_optent *op, FILE *file) -{ - const struct mnt_optmap *map; - const char *type; - - if (!op) - return -1; - - fprintf(file, "------ option %p (%s):\n", op, mnt_optent_get_name(op)); - - fprintf(file, "\tID=0x%x\n", mnt_optent_get_id(op)); - fprintf(file, "\tMASK=%d\n", mnt_optent_get_mask(op)); - - map = mnt_optent_get_map(op); - fprintf(file, "\tMAP=%p\n", map ? map : NULL); - - map = mnt_optent_get_mapent(op); - fprintf(file, "\tMAPENT=%s\n", map ? map->name : NULL); - - fprintf(file, "\tHAS_VALUE=%s\n", - mnt_optent_has_value(op) ? "yes" : "not"); - - type = mnt_optent_get_type(op); - fprintf(file, "\tTYPE=%s\n", type ? : ""); - fprintf(file, "\tVALUE=%s\n", op->value); - return 0; -} diff --git a/shlibs/mount/src/optls.c b/shlibs/mount/src/optls.c deleted file mode 100644 index 289f40d7..00000000 --- a/shlibs/mount/src/optls.c +++ /dev/null @@ -1,794 +0,0 @@ -/* - * Copyright (C) 2010 Karel Zak - * - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - */ - -/** - * SECTION: optls - * @title: Options container - * @short_description: high-level API for work with parsed mount options - * - * The optls container allows to work with parsed mount options and generate - * arguments for mount(2) syscall, output to mtab or analyze userspace specific - * options. - */ -#include -#include -#include -#include - -#include "nls.h" -#include "mountP.h" - -/** - * mnt_new_optls: - * - * Returns: newly allocated and initialized optls instance. The library - * uses this object as a container for mount options. - */ -mnt_optls *mnt_new_optls(void) -{ - mnt_optls *ls = calloc(1, sizeof(struct _mnt_optls)); - if (!ls) - return NULL; - INIT_LIST_HEAD(&ls->opts); - return ls; -} - -/** - * mnt_free_optls: - * @ls: pointer to mnt_optls instance. - * - * Deallocates mnt_optls and all stored options. - */ -void mnt_free_optls(mnt_optls *ls) -{ - if (!ls) - return; - while (!list_empty(&ls->opts)) { - mnt_optent *o = list_entry(ls->opts.next, mnt_optent, opts); - mnt_free_optent(o); - } - - free(ls->maps); - free(ls); -} - -/** - * mnt_optls_add_map: - * @ls: pointer to mnt_optls instance - * @map: pointer to the custom map - * - * Stores pointer to the custom options map (options description). The map has - * to be accessible all time when the libmount works with options. (The map is - * usually a static array.) - * - * All already stored unknown mount options are reverified against the new map. - * Note, it's recommented to add all maps to the @optls container before options - * parsing. - * - * Example (add new options "foo" and "bar=data"): - * - * - * - * #define MY_MS_FOO (1 << 1) - * #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 }, - * { NULL } - * }; - * - * mnt_optls_add_map(ls, myoptions); - * - * - * - * Returns: 0 on success, 1 on failed verification, or -1 in case of error. - */ -int mnt_optls_add_map(mnt_optls *ls, const struct mnt_optmap *map) -{ - mnt_optent *op; - mnt_iter itr; - - assert(ls); - assert(map || ls->maps == NULL); - - ls->maps = realloc(ls->maps, - sizeof(struct mnt_optmap *) * (ls->nmaps + 1)); - if (!ls->maps) - return -1; - - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: optls %p: add map[%zd]", ls, ls->nmaps)); - ls->maps[ls->nmaps] = map; - ls->nmaps++; - - mnt_reset_iter(&itr, MNT_ITER_FORWARD); - - while(mnt_optls_next_option(ls, &itr, NULL, &op) == 0) { - if (!mnt_optent_is_unknown(op)) - continue; - if (mnt_optent_assign_map(op, &map, 1) == -1) - return 1; - } - return 0; -} - -/** - * mnt_optls_add_builtin_map: - * @ls: pointer to mnt_optls instance - * @id: built-in map id (see mnt_get_builtin_map()) - * - * Same as mnt_optls_add_map(), but works with libmount built in maps. - * - * Returns: 0 on success or -1 in case of error. - */ -int mnt_optls_add_builtin_map(mnt_optls *ls, int id) -{ - const struct mnt_optmap *m = mnt_get_builtin_optmap(id); - - assert(ls); - assert(id); - - return m ? mnt_optls_add_map(ls, m) : -1; -} - - -/* - * Append the option to "ls" container. - */ -static void mnt_optls_add_optent(mnt_optls *ls, mnt_optent *op) -{ - assert(ls); - assert(op); - - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: opts %p: add option %s", - ls, mnt_optent_get_name(op))); - - list_add_tail(&op->opts, &ls->opts); -} - -/** - * mnt_optls_add_option: - * @ls: pointer to mnt_optls instance - * @name: option name - * @value: option value - * - * Returns: new option or NULL in case of error. - */ -mnt_optent *mnt_optls_add_option(mnt_optls *ls, - const char *name, const char *value) -{ - mnt_optent *op; - - if (!ls || !name) - return NULL; - - op = mnt_new_optent(name, strlen(name), - value, value ? strlen(value) : 0, - ls->maps, ls->nmaps); - if (op) - mnt_optls_add_optent(ls, op); - return op; -} - -/** - * mnt_optls_parse_optstr: - * @ls: pointer to mnt_optls instance. - * @optstr: zero terminated string with mount options (comma separaed list) - * - * Parses @optstr and all options from @optstr are added to the @optls. It's - * possible to call this function more than once. The new options from @optstr - * will be appended to the container. - * - * The options are accessible by mnt_optls_next_option(). - * - * If the @optls container is associated with any options map(s), all new - * options are verified according to the descriptions from the map(s). - * - * For example: - * - * mnt_optls_parse_optstr(ls, "user=snake,noexec"); - * - * is same like: - * - * mnt_optls_add_option(ls, "user", "snake"); - * mnt_optls_add_option(ls, "noexec", NULL); - * - * Returns: 0 on success or -1 in case of error. - */ -int mnt_optls_parse_optstr(mnt_optls *ls, const char *optstr) -{ - char *p = (char *) optstr; - - assert(ls); - assert(optstr); - - if (!ls || !optstr) - return -1; - - while(p && *p) { - mnt_optent *op = mnt_new_optent_from_optstr(&p, - ls->maps, ls->nmaps); - if (!op) - return -1; - mnt_optls_add_optent(ls, op); - } - return 0; -} - -/** - * mnt_optls_remove_option: - * @ls: pointer to mnt_optls instance - * @name: option name - * - * Returns: 0 on success, 1 if @name not found and -1 in case of error. - */ -int mnt_optls_remove_option(mnt_optls *ls, const char *name) -{ - struct list_head *p, *pnext; - - if (!ls || !name) - return -1; - - list_for_each_safe(p, pnext, &ls->opts) { - mnt_optent *op; - const char *n; - - if (!p) - break; - op = list_entry(p, mnt_optent, opts); - n = mnt_optent_get_name(op); - if (n && strcmp(name, n) == 0) { - mnt_free_optent(op); - return 0; - } - } - return 1; -} - - -/** - * mnt_optls_remove_option_by_flags: - * @ls: pointer to mnt_optls instance - * @map: pointer to the map with wanted options or NULL for all options - * @flags: option flags - * - * Removes options which match with @flags. The set of options could - * be restricted by @map. For exmaple: - * - * mnt_optls_remove_option_by_flags(ls, NULL, MS_NOEXEC); - * - * removes "noexec" option from "ls". - * - * Note that this function is useles for options with MNT_INVERT mask (e.g. - * "exec" is inverting MS_NOEXEC flag). - * - * See also mnt_optent_get_flag() and mnt_optls_remove_option_by_iflags(). - * - * Returns: number of removed options or -1 in case of error. - */ -int mnt_optls_remove_option_by_flags(mnt_optls *ls, - const struct mnt_optmap *map, const int flags) -{ - struct list_head *p, *pnext; - int ct = 0; - - if (!ls) - return -1; - - list_for_each_safe(p, pnext, &ls->opts) { - mnt_optent *op; - int fl = 0; - - if (!p) - break; - op = list_entry(p, mnt_optent, opts); - - if (!map || mnt_optent_get_map(op) == map) { - mnt_optent_get_flag(op, &fl); - if (fl & flags) { - mnt_free_optent(op); - ct++; - } - } - } - return ct; -} - -/** - * mnt_optls_remove_option_by_iflags: - * @ls: pointer to mnt_optls instance - * @map: pointer to the map with wanted options or NULL for all options - * @flags: option flags - * - * Removes options which inverting any id from @flags. The set of options could - * be restricted by @map. For exmaple: - * - * mnt_optls_remove_option_by_iflags(ls, NULL, MS_NOEXEC); - * - * removes "exec" option from "ls". - * - * Note that this function is useles for options without MNT_INVERT mask (e.g. - * "noexec"). - * - * See also mnt_optent_get_flag() and mnt_optls_remove_option_by_flags(). - * - * Returns: number of removed options or -1 in case of error. - */ -int mnt_optls_remove_option_by_iflags(mnt_optls *ls, - const struct mnt_optmap *map, const int flags) -{ - struct list_head *p, *pnext; - int ct = 0; - - if (!ls) - return -1; - - list_for_each_safe(p, pnext, &ls->opts) { - mnt_optent *op; - int fl = flags; - - if (!p) - break; - op = list_entry(p, mnt_optent, opts); - - if (!map || mnt_optent_get_map(op) == map) { - int id = mnt_optent_get_id(op); - - if (!(id & fl)) - continue; - - mnt_optent_get_flag(op, &fl); - - if (!(id & fl)) { - mnt_free_optent(op); - ct++; - } - } - } - return ct; -} - -/** - * mnt_optls_next_option: - * @ls: pointer to mnt_optls instance - * @itr: iterator - * @map: pointer to the map of wanted options or NULL for all options - * @option: returns pointer to the option object - * - * Example (print all options): - * - * * - * mnt_optent *option; - * mnt_optls *ls = mnt_optls_new(); - * - * mnt_optls_parse_optstr(ls, "noexec,nodev"); - * - * while(mnt_optls_next_option(ls, itr, NULL, &option)) - * printf("%s\n", mnt_optent_get_name(option))); - * - * - * - * Returns: 0 on succes, -1 in case of error or 1 at end of list. - */ -int mnt_optls_next_option(mnt_optls *ls, mnt_iter *itr, - const struct mnt_optmap *map, mnt_optent **option) -{ - assert(itr); - assert(ls); - assert(option); - - if (!itr || !ls || !option) - return -1; - - *option = NULL; - - if (!itr->head) - MNT_ITER_INIT(itr, &ls->opts); - while (itr->p != itr->head) { - MNT_ITER_ITERATE(itr, *option, struct _mnt_optent, opts); - if (map == NULL || (*option)->map == map) - return 0; - } - - return 1; -} - -/** - * mnt_optls_get_option: - * @ls: pointer to mnt_optls instance - * @name: options name - * - * Returns: the option or NULL. - */ -mnt_optent *mnt_optls_get_option(mnt_optls *ls, const char *name) -{ - mnt_optent *op; - mnt_iter itr; - - assert(ls); - assert(name); - - if (!ls || !name) - return NULL; - mnt_reset_iter(&itr, MNT_ITER_FORWARD); - - while(mnt_optls_next_option(ls, &itr, NULL, &op) == 0) { - const char *n = mnt_optent_get_name(op); - - if (n && !strcmp(n, name)) - return op; - } - return NULL; -} - -/** - * mnt_optls_get_ids: - * @ls: pointer to mnt_optls instance - * @map: pointer to the map of wanted options or NULL for all options - * - * Note that ID has to be unique in all maps when the @map is NULL. - * - * Note also that this function works with ALL options -- see also - * mnt_optls_create_mountflags() that returns MNT_MFLAG options - * (mount(2) flags) only. - * - * Returns: IDs from all options. - */ -int mnt_optls_get_ids(mnt_optls *ls, const struct mnt_optmap *map) -{ - int flags = 0; - mnt_iter itr; - mnt_optent *op; - - assert(ls); - if (!ls) - return 0; - mnt_reset_iter(&itr, MNT_ITER_FORWARD); - - while(mnt_optls_next_option(ls, &itr, map, &op) == 0) - mnt_optent_get_flag(op, &flags); - - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: opts %p: generated IDs 0x%08x", ls, flags)); - return flags; -} - -/** - * mnt_optls_create_mountflags: - * @ls: pointer to mnt_optls instance - * - * The mountflags are IDs from all MNT_MFLAG options. See "struct mnt_optmap". - * For more details about mountflags see mount(2) syscall. - * - * Returns: mount flags or 0. - */ -int mnt_optls_create_mountflags(mnt_optls *ls) -{ - int flags = 0; - mnt_iter itr; - mnt_optent *op; - - assert(ls); - if (!ls) - return 0; - mnt_reset_iter(&itr, MNT_ITER_FORWARD); - - while(mnt_optls_next_option(ls, &itr, NULL, &op) == 0) { - if (!(op->mask & MNT_MFLAG)) - continue; - mnt_optent_get_flag(op, &flags); - } - - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: opts %p: generated mountflags 0x%08x", ls, flags)); - return flags; -} - -/** - * mnt_optls_create_mountdata: - * @ls: pointer to mnt_optls instance - * - * For more details about mountdata see mount(2) syscall. - * - * Returns: newly allocated string with mount options or NULL in case of error. - */ -char *mnt_optls_create_mountdata(mnt_optls *ls) -{ - mnt_iter itr; - mnt_optent *op; - char *optstr = NULL; - - assert(ls); - if (!ls) - return NULL; - mnt_reset_iter(&itr, MNT_ITER_FORWARD); - - while(mnt_optls_next_option(ls, &itr, NULL, &op) == 0) { - if (!(op->mask & MNT_MDATA) && !mnt_optent_is_unknown(op)) - continue; - if (mnt_optstr_append_option(&optstr, - mnt_optent_get_name(op), - mnt_optent_get_value(op))) - goto err; - } - - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: opts %p: generated mountdata: %s", ls, optstr)); - return optstr; -err: - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: ls %p: generate mountdata failed", ls)); - free(optstr); - return NULL; -} - -/** - * mnt_optls_create_mtab_optstr: - * @ls: pointer to mnt_optls instance - * - * Returns: newly allocated string with mount options for mtab. - */ -char *mnt_optls_create_mtab_optstr(mnt_optls *ls) -{ - mnt_iter itr; - mnt_optent *op; - char *optstr = NULL; - - assert(ls); - if (!ls) - return NULL; - - mnt_reset_iter(&itr, MNT_ITER_FORWARD); - - while(mnt_optls_next_option(ls, &itr, NULL, &op) == 0) { - if (op->mask & MNT_NOMTAB) - continue; - if (mnt_optstr_append_option(&optstr, - mnt_optent_get_name(op), - mnt_optent_get_value(op))) - goto err; - } - - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: opts %p: generated mtab options: %s", ls, optstr)); - return optstr; -err: - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: opts %p: generate mtab optstr failed", ls)); - free(optstr); - return NULL; -} - -/** - * mnt_optls_create_userspace_optstr: - * @ls: pointer to mnt_optls instance - * - * Returns: newly allocated string with mount options that are - * userspace specific (e.g. uhelper=,loop=). - */ -char *mnt_optls_create_userspace_optstr(mnt_optls *ls) -{ - mnt_iter itr; - mnt_optent *op; - char *optstr = NULL; - - assert(ls); - if (!ls) - return NULL; - mnt_reset_iter(&itr, MNT_ITER_FORWARD); - - while(mnt_optls_next_option(ls, &itr, NULL, &op) == 0) { - if (mnt_optent_is_unknown(op)) - continue; - if (op->mask & (MNT_MDATA | MNT_MFLAG | MNT_NOMTAB)) - continue; - if (mnt_optstr_append_option(&optstr, - mnt_optent_get_name(op), - mnt_optent_get_value(op))) - goto err; - } - - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: opts %p: generated userspace-only options: %s", - ls, optstr)); - return optstr; -err: - DBG(DEBUG_OPTIONS, fprintf(stderr, - "libmount: opts %p: generate userspace optstr failed", ls)); - free(optstr); - return NULL; -} - -/** - * mnt_optls_print_debug: - * @file: output - * @ls: pointer to mnt_optls instance - * - * Prints details about options container. - * - * Returns: 0 on success or -1 in case of error. - */ -int mnt_optls_print_debug(mnt_optls *ls, FILE *file) -{ - mnt_iter itr; - mnt_optent *op; - - if (!ls) - return -1; - mnt_reset_iter(&itr, MNT_ITER_FORWARD); - - fprintf(file, "--- opts: %p\n", ls); - while(mnt_optls_next_option(ls, &itr, NULL, &op) == 0) - mnt_optent_print_debug(op, file); - - return 0; -} - -#ifdef TEST_PROGRAM -mnt_optls *mk_optls(const char *optstr) -{ - mnt_optls *ls = mnt_new_optls(); - if (!ls) - goto err; - - mnt_optls_add_builtin_map(ls, MNT_LINUX_MAP); - mnt_optls_add_builtin_map(ls, MNT_USERSPACE_MAP); - - if (mnt_optls_parse_optstr(ls, optstr) != 0) { - fprintf(stderr, "\tfailed to parse: %s\n", optstr); - goto err; - } - return ls; -err: - mnt_free_optls(ls); - return NULL; -} - -int test_parse(struct mtest *ts, int argc, char *argv[]) -{ - mnt_optls *ls = NULL; - int rc = -1; - - if (argc < 1) - goto done; - ls = mk_optls(argv[1]); - if (!ls) - goto done; - - mnt_optls_print_debug(ls, stdout); - rc = 0; -done: - mnt_free_optls(ls); - return rc; -} - -int test_flags(struct mtest *ts, int argc, char *argv[]) -{ - mnt_optls *ls = NULL; - int rc = -1; - int flags; - const struct mnt_optmap *map; - - if (argc < 1) - goto done; - ls = mk_optls(argv[1]); - if (!ls) - goto done; - - flags = mnt_optls_create_mountflags(ls); - printf("\tmount(2) flags: 0x%08x\n", flags); - - map = mnt_get_builtin_optmap(MNT_LINUX_MAP); - flags = mnt_optls_get_ids(ls, map); - printf("\tMNT_MAP_LINUX IDs: 0x%08x (map %p)\n", flags, map); - - map = mnt_get_builtin_optmap(MNT_USERSPACE_MAP); - flags = mnt_optls_get_ids(ls, map); - printf("\tMNT_USERSPACE_MAP IDs: 0x%08x (map %p)\n", flags, map); - - rc = 0; -done: - mnt_free_optls(ls); - return rc; -} - -int test_data(struct mtest *ts, int argc, char *argv[]) -{ - mnt_optls *ls = NULL; - char *optstr; - int rc = -1; - - if (argc < 1) - goto done; - ls = mk_optls(argv[1]); - if (!ls) - goto done; - - optstr = mnt_optls_create_mountdata(ls); - printf("\tmount(2) data: '%s'\n", optstr); - free(optstr); - rc = 0; -done: - mnt_free_optls(ls); - return rc; -} - -int test_mtabstr(struct mtest *ts, int argc, char *argv[]) -{ - mnt_optls *ls = NULL; - char *optstr; - int rc = -1; - - if (argc < 1) - goto done; - ls = mk_optls(argv[1]); - if (!ls) - goto done; - - optstr = mnt_optls_create_mtab_optstr(ls); - printf("\tmtab options: '%s'\n", optstr); - free(optstr); - rc = 0; -done: - mnt_free_optls(ls); - return rc; -} - -int test_reparse(struct mtest *ts, int argc, char *argv[]) -{ - const struct mnt_optmap *map; - mnt_optls *ls = NULL; - char *optstr; - int rc = -1; - - if (argc < 1) - goto done; - optstr = argv[1]; - ls = mnt_new_optls(); - if (!ls) - goto done; - - /* add description for kernel options */ - mnt_optls_add_builtin_map(ls, MNT_LINUX_MAP); - - if (mnt_optls_parse_optstr(ls, optstr) != 0) { - fprintf(stderr, "\tfailed to parse: %s\n", optstr); - goto done; - } - - fprintf(stdout, "------ parse\n"); - mnt_optls_print_debug(ls, stdout); - - /* add description for userspace options */ - map = mnt_get_builtin_optmap(MNT_USERSPACE_MAP); - mnt_optls_add_map(ls, map); - - fprintf(stdout, "------ re-parse\n"); - mnt_optls_print_debug(ls, stdout); - - rc = 0; -done: - mnt_free_optls(ls); - return rc; -} - -int main(int argc, char *argv[]) -{ - struct mtest tss[] = { - { "--parse", test_parse, " parse mount options string" }, - { "--ls-data", test_data, " parse and generate mountdata" }, - { "--ls-flags", test_flags, " parse and generate mountflags" }, - { "--ls-mtabstr",test_mtabstr," parse and generate mtab options" }, - { "--reparse", test_reparse, " test extra options reparsing" }, - { NULL } - }; - return mnt_run_test(tss, argc, argv); -} -#endif /* TEST_PROGRAM */