diff options
-rw-r--r-- | libmount/docs/libmount-sections.txt | 2 | ||||
-rw-r--r-- | libmount/src/optstr.c | 79 | ||||
-rw-r--r-- | libmount/src/utils.c | 92 |
3 files changed, 80 insertions, 93 deletions
diff --git a/libmount/docs/libmount-sections.txt b/libmount/docs/libmount-sections.txt index e1607ea54..78d89cae7 100644 --- a/libmount/docs/libmount-sections.txt +++ b/libmount/docs/libmount-sections.txt @@ -287,6 +287,7 @@ mnt_optstr_prepend_option mnt_optstr_remove_option mnt_optstr_set_option mnt_split_optstr +mnt_match_options </SECTION> <SECTION> @@ -377,7 +378,6 @@ mnt_get_swaps_path mnt_has_regular_mtab mnt_mangle mnt_match_fstype -mnt_match_options mnt_tag_is_valid mnt_unmangle </SECTION> diff --git a/libmount/src/optstr.c b/libmount/src/optstr.c index 9dfab67f3..2aa6e8ccb 100644 --- a/libmount/src/optstr.c +++ b/libmount/src/optstr.c @@ -20,6 +20,7 @@ #include <selinux/context.h> #endif +#include "strutils.h" #include "mountP.h" /* @@ -1079,6 +1080,84 @@ int mnt_optstr_fix_user(char **optstr) return rc; } +/** + * mnt_match_options: + * @optstr: options string + * @pattern: comma delimited list of options + * + * The "no" could be used for individual items in the @options list. The "no" + * prefix does not have a global meaning. + * + * Unlike fs type matching, nonetdev,user and nonetdev,nouser have + * DIFFERENT meanings; each option is matched explicitly as specified. + * + * The "no" prefix interpretation could be disabled by the "+" prefix, for example + * "+noauto" matches if @optstr literally contains the "noauto" string. + * + * "xxx,yyy,zzz" : "nozzz" -> False + * + * "xxx,yyy,zzz" : "xxx,noeee" -> True + * + * "bar,zzz" : "nofoo" -> True (does not contain "foo") + * + * "nofoo,bar" : "nofoo" -> True (does not contain "foo") + * + * "nofoo,bar" : "+nofoo" -> True (contains "nofoo") + * + * "bar,zzz" : "+nofoo" -> False (does not contain "nofoo") + * + * + * Returns: 1 if pattern is matching, else 0. This function also returns 0 + * if @pattern is NULL and @optstr is non-NULL. + */ +int mnt_match_options(const char *optstr, const char *pattern) +{ + char *name, *pat = (char *) pattern; + char *buf; + size_t namesz = 0, valsz = 0; + int match = 1; + + if (!pattern && !optstr) + return 1; + if (!pattern) + return 0; + + buf = malloc(strlen(pattern) + 1); + if (!buf) + return 0; + + /* walk on pattern string + */ + while (match && !mnt_optstr_next_option(&pat, &name, &namesz, NULL, &valsz)) { + char *val; + size_t sz; + int no = 0; + + if (*name == '+') + name++, namesz--; + else if ((no = (startswith(name, "no") != NULL))) + name += 2, namesz -= 2; + + xstrncpy(buf, name, namesz + 1); + + switch (mnt_optstr_get_option(optstr, buf, &val, &sz)) { + case 0: /* found */ + match = no == 0 ? 1 : 0; + break; + case 1: /* not found */ + match = no == 1 ? 1 : 0; + break; + default: /* parse error */ + match = 0; + break; + } + + } + + free(buf); + return match; +} + #ifdef TEST_PROGRAM static int test_append(struct libmnt_test *ts, int argc, char *argv[]) diff --git a/libmount/src/utils.c b/libmount/src/utils.c index 29f259ffe..7e028ee02 100644 --- a/libmount/src/utils.c +++ b/libmount/src/utils.c @@ -430,98 +430,6 @@ int mnt_match_fstype(const char *type, const char *pattern) return match_fstype(type, pattern); } - -/* Returns 1 if needle found or noneedle not found in haystack - * Otherwise returns 0 - */ -static int check_option(const char *haystack, size_t len, - const char *needle, size_t needle_len) -{ - const char *p; - int no = 0; - - if (needle_len >= 1 && *needle == '+') { - needle++; - needle_len--; - } else if (needle_len >= 2 && !strncmp(needle, "no", 2)) { - no = 1; - needle += 2; - needle_len -= 2; - } - - for (p = haystack; p && p < haystack + len; p++) { - char *sep = strchr(p, ','); - size_t plen = sep ? (size_t) (sep - p) : - len - (p - haystack); - - if (plen == needle_len && !strncmp(p, needle, plen)) - return !no; /* foo or nofoo was found */ - p += plen; - } - - return no; /* foo or nofoo was not found */ -} - -/** - * mnt_match_options: - * @optstr: options string - * @pattern: comma delimited list of options - * - * The "no" could be used for individual items in the @options list. The "no" - * prefix does not have a global meaning. - * - * Unlike fs type matching, nonetdev,user and nonetdev,nouser have - * DIFFERENT meanings; each option is matched explicitly as specified. - * - * The "no" prefix interpretation could be disabled by the "+" prefix, for example - * "+noauto" matches if @optstr literally contains the "noauto" string. - * - * "xxx,yyy,zzz" : "nozzz" -> False - * - * "xxx,yyy,zzz" : "xxx,noeee" -> True - * - * "bar,zzz" : "nofoo" -> True - * - * "nofoo,bar" : "+nofoo" -> True - * - * "bar,zzz" : "+nofoo" -> False - * - * - * Returns: 1 if pattern is matching, else 0. This function also returns 0 - * if @pattern is NULL and @optstr is non-NULL. - */ -int mnt_match_options(const char *optstr, const char *pattern) -{ - const char *p; - size_t len, optstr_len = 0; - - if (!pattern && !optstr) - return 1; - if (!pattern) - return 0; - - len = strlen(pattern); - if (optstr) - optstr_len = strlen(optstr); - - for (p = pattern; p < pattern + len; p++) { - char *sep = strchr(p, ','); - size_t plen = sep ? (size_t) (sep - p) : - len - (p - pattern); - - if (!plen) - continue; /* if two ',' appear in a row */ - - if (!check_option(optstr, optstr_len, p, plen)) - return 0; /* any match failure means failure */ - - p += plen; - } - - /* no match failures in list means success */ - return 1; -} - void mnt_free_filesystems(char **filesystems) { char **p; |