]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: reimplement mnt_match_options()
authorKarel Zak <kzak@redhat.com>
Tue, 20 Dec 2016 14:31:33 +0000 (15:31 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 20 Dec 2016 14:35:50 +0000 (15:35 +0100)
Let's use optstr.c functions to parse pattern and options strings.
It's more robust that the old original mount(8) code and it supports
quotes in the options strings.

Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/docs/libmount-sections.txt
libmount/src/optstr.c
libmount/src/utils.c

index e1607ea54d9539f805d449682e8070809d0da750..78d89cae7a65174f6dcb13be5c1d6dde6bbaec9f 100644 (file)
@@ -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>
index 9dfab67f33e4817cfb6dad3fe3d12b2be3cc3d3c..2aa6e8ccb2eed02ce135bd54b3599ae04d13f1ef 100644 (file)
@@ -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[])
index 29f259ffefdd6e99c29ad358baa2b136bac4d2bd..7e028ee021203b716b66c28718d4c062ddaccbea 100644 (file)
@@ -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;