diff options
-rw-r--r-- | libmount/docs/libmount-sections.txt | 1 | ||||
-rw-r--r-- | libmount/src/libmount.h.in | 2 | ||||
-rw-r--r-- | libmount/src/libmount.sym | 19 | ||||
-rw-r--r-- | libmount/src/optstr.c | 61 |
4 files changed, 74 insertions, 9 deletions
diff --git a/libmount/docs/libmount-sections.txt b/libmount/docs/libmount-sections.txt index dc6aeabf5..e0f899471 100644 --- a/libmount/docs/libmount-sections.txt +++ b/libmount/docs/libmount-sections.txt @@ -250,6 +250,7 @@ MNT_NOHLPS <FILE>optstr</FILE> mnt_optstr_append_option mnt_optstr_apply_flags +mnt_optstr_deduplicate_option mnt_optstr_get_flags mnt_optstr_get_option mnt_optstr_get_options diff --git a/libmount/src/libmount.h.in b/libmount/src/libmount.h.in index 326588fec..43646ac8a 100644 --- a/libmount/src/libmount.h.in +++ b/libmount/src/libmount.h.in @@ -183,6 +183,7 @@ extern int mnt_optstr_get_option(const char *optstr, const char *name, extern int mnt_optstr_set_option(char **optstr, const char *name, const char *value); extern int mnt_optstr_remove_option(char **optstr, const char *name); +extern int mnt_optstr_deduplicate_option(char **optstr, const char *name); extern int mnt_split_optstr(const char *optstr, char **user, char **vfs, char **fs, @@ -196,6 +197,7 @@ extern int mnt_optstr_get_flags(const char *optstr, unsigned long *flags, extern int mnt_optstr_apply_flags(char **optstr, unsigned long flags, const struct libmnt_optmap *map); + /* iter.c */ enum { diff --git a/libmount/src/libmount.sym b/libmount/src/libmount.sym index 260642d4d..9e0f2c45d 100644 --- a/libmount/src/libmount.sym +++ b/libmount/src/libmount.sym @@ -228,22 +228,23 @@ global: MOUNT_2.22 { global: - mnt_fs_streq_target; - mnt_fs_streq_srcpath; - mnt_context_tab_applied; + mnt_context_disable_swapmatch; mnt_context_get_options; mnt_context_is_loopdel; mnt_context_is_nocanonicalize; mnt_context_is_nohelpers; - mnt_table_find_devno; - mnt_table_parse_swaps; - mnt_get_mountpoint; - mnt_get_swaps_path; + mnt_context_is_swapmatch; + mnt_context_tab_applied; mnt_fs_get_priority; mnt_fs_get_size; mnt_fs_get_swaptype; mnt_fs_get_tid; mnt_fs_get_usedsize; - mnt_context_is_swapmatch; - mnt_context_disable_swapmatch; + mnt_fs_streq_srcpath; + mnt_fs_streq_target; + mnt_get_mountpoint; + mnt_get_swaps_path; + mnt_optstr_deduplicate_option; + mnt_table_find_devno; + mnt_table_parse_swaps; } MOUNT_2.21; diff --git a/libmount/src/optstr.c b/libmount/src/optstr.c index 08c12150e..16d6d13a2 100644 --- a/libmount/src/optstr.c +++ b/libmount/src/optstr.c @@ -290,6 +290,48 @@ int mnt_optstr_get_option(const char *optstr, const char *name, return rc; } +/** + * mnt_optstr_deduplicate_option: + * @optstr: string with comma separated list of options + * @name: requested option name + * + * Removes all instances of @name except the last one. + * + * Returns: 0 on success, 1 when not found the @name or negative number in case + * of error. + */ +int mnt_optstr_deduplicate_option(char **optstr, const char *name) +{ + int rc; + char *begin = NULL, *end = NULL, *opt = *optstr; + + do { + struct libmnt_optloc ol; + + mnt_init_optloc(&ol); + + rc = mnt_optstr_locate_option(opt, name, &ol); + if (!rc) { + if (begin) { + /* remove previous instance */ + size_t shift = strlen(*optstr); + + mnt_optstr_remove_option_at(optstr, begin, end); + + /* now all offset are not valied anymore - recount */ + shift -= strlen(*optstr); + ol.begin -= shift; + ol.end -= shift; + } + begin = ol.begin; + end = ol.end; + opt = end && *end ? end + 1 : NULL; + } + } while (rc == 0 && opt && *opt); + + return rc < 0 ? rc : begin ? 0 : 1; +} + /* * The result never starts or ends with comma or contains two commas * (e.g. ",aaa,bbb" or "aaa,,bbb" or "aaa,") @@ -1187,6 +1229,24 @@ int test_remove(struct libmnt_test *ts, int argc, char *argv[]) return rc; } +int test_dedup(struct libmnt_test *ts, int argc, char *argv[]) +{ + const char *name; + char *optstr; + int rc; + + if (argc < 3) + return -EINVAL; + optstr = strdup(argv[1]); + name = argv[2]; + + rc = mnt_optstr_deduplicate_option(&optstr, name); + if (!rc) + printf("result: >%s<\n", optstr); + free(optstr); + return rc; +} + int test_fix(struct libmnt_test *ts, int argc, char *argv[]) { char *optstr; @@ -1230,6 +1290,7 @@ int main(int argc, char *argv[]) { "--set", test_set, "<optstr> <name> [<value>] (un)set value" }, { "--get", test_get, "<optstr> <name> search name in optstr" }, { "--remove", test_remove, "<optstr> <name> remove name in optstr" }, + { "--dedup", test_dedup, "<optstr> <name> deduplicate 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" }, |