]> err.no Git - util-linux/commitdiff
libmount: add mnt_match_{fstype,options} functions
authorKarel Zak <kzak@redhat.com>
Tue, 23 Feb 2010 14:04:52 +0000 (15:04 +0100)
committerKarel Zak <kzak@redhat.com>
Thu, 3 Jun 2010 13:20:11 +0000 (15:20 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
shlibs/mount/src/Makefile.am
shlibs/mount/src/mount.h.in
shlibs/mount/src/utils.c

index 5d80779e022c44bc4dcfdeaf1a6e1bb4327ef81a..4e17cfe11ac5e6d541241b6013bf55885440c64e 100644 (file)
@@ -43,7 +43,7 @@ uninstall-hook:
 
 # tests
 noinst_PROGRAMS = test_version test_cache test_optstr test_optls test_lock \
-                 test_tab
+                 test_tab test_utils
 tests_cppflags = $(AM_CPPFLAGS) -DTEST_PROGRAM
 tests_ldadd = .libs/libmount.a $(ul_libblkid_la)
 
@@ -70,3 +70,7 @@ test_lock_LDADD = $(tests_ldadd)
 test_tab_SOURCES = tab_parse.c tab.c
 test_tab_CPPFLAGS = $(tests_cppflags)
 test_tab_LDADD = $(tests_ldadd)
+
+test_utils_SOURCES = utils.c
+test_utils_CPPFLAGS = $(tests_cppflags)
+test_utils_LDADD = $(tests_ldadd)
index b4c9bc53abcaea60572ca427f5bac84b1806cb46..6bea2a174b2db0bedb3a35d3477b9fa127d0129a 100644 (file)
@@ -111,6 +111,8 @@ extern int mnt_get_library_version(const char **ver_string);
 extern int mnt_fstype_is_netfs(const char *type);
 extern int mnt_fstype_is_pseudofs(const char *type);
 extern int mnt_open_device(const char *devname, int flags);
+extern int mnt_match_fstype(const char *type, const char *pattern);
+extern int mnt_match_options(const char *optstr, const char *pattern);
 
 /* cache.c */
 extern mnt_cache *mnt_new_cache(void);
index fbdfadb8494eb2b86194f2eb333ca6ee56ea2e58..fb9ffe8d59a4861f77e43065f7c861387c5b3a6e 100644 (file)
@@ -128,6 +128,135 @@ int mnt_fstype_is_netfs(const char *type)
        return 0;
 }
 
+/**
+ * mnt_match_fstype:
+ * @type: filesystem type
+ * @pattern: filesystem name or comma delimitted list of names
+ *
+ * The @pattern list of filesystem can be prefixed with a global
+ * "no" prefix to invert matching of the whole list. The "no" could
+ * also used for individual items in the @pattern list.
+ *
+ * "nofoo,bar" has the same meaning as "nofoo,nobar"
+ *
+ * "bar" : "nofoo,bar"         -> False   (global "no" prefix)
+ * "bar" : "foo,bar"           -> True
+ * "bar" : "foo,nobar"         -> False
+ *
+ * Returns: 1 if type is matching, else 0. This function also returns
+ *          0 if @pattern is NULL and @type is non-NULL.
+ */
+int mnt_match_fstype(const char *type, const char *pattern)
+{
+       int no = 0;             /* negated types list */
+       int len;
+       const char *p;
+
+       if (!pattern && !type)
+               return 1;
+       if (!pattern)
+               return 0;
+
+       if (!strncmp(pattern, "no", 2)) {
+               no = 1;
+               pattern += 2;
+       }
+
+       /* Does type occur in types, separated by commas? */
+       len = strlen(type);
+       p = pattern;
+       while(1) {
+               if (!strncmp(p, "no", 2) && !strncmp(p+2, type, len) &&
+                   (p[len+2] == 0 || p[len+2] == ','))
+                       return 0;
+               if (strncmp(p, type, len) == 0 && (p[len] == 0 || p[len] == ','))
+                       return !no;
+               p = strchr(p,',');
+               if (!p)
+                       break;
+               p++;
+       }
+       return no;
+}
+
+
+/* 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 >= 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 ? sep - p : len - (p - haystack);
+
+               if (plen == needle_len) {
+                       if (!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 delimitted list of options
+ *
+ * The "no" could used for individual items in the @options list. The "no"
+ * prefix does not have a global meanning.
+ *
+ * Unlike fs type matching, nonetdev,user and nonetdev,nouser have
+ * DIFFERENT meanings; each option is matched explicitly as specified.
+ *
+ * xxx,yyy,zzz : nozzz         -> False
+ * xxx,yyy,zzz : xxx,noeee     -> True
+ *
+ * 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 ? 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;
+}
+
 /*
  * Reallocates its first arg @s - typical use: s = mnt_strconcat3(s,t,u);
  * Returns reallocated @s ion succes or NULL in case of error.
@@ -206,3 +335,36 @@ char *mnt_get_username(const uid_t uid)
        free(buf);
        return username;
 }
+
+#ifdef TEST_PROGRAM
+int test_match_fstype(struct mtest *ts, int argc, char *argv[])
+{
+       char *type = argv[1];
+       char *pattern = argv[2];
+
+       printf("%s\n", mnt_match_fstype(type, pattern) ? "MATCH" : "NOT-MATCH");
+       return 0;
+}
+
+int test_match_options(struct mtest *ts, int argc, char *argv[])
+{
+       char *optstr = argv[1];
+       char *pattern = argv[2];
+
+       printf("%s\n", mnt_match_options(optstr, pattern) ? "MATCH" : "NOT-MATCH");
+       return 0;
+}
+
+
+int main(int argc, char *argv[])
+{
+       struct mtest tss[] = {
+       { "--match-fstype",  test_match_fstype,    "<type> <pattern>     FS types matching" },
+       { "--match-options", test_match_options,   "<options> <pattern>  options matching" },
+       { NULL }
+       };
+
+       return mnt_run_test(tss, argc, argv);
+}
+
+#endif /* TEST_PROGRAM */