summaryrefslogtreecommitdiffstats
path: root/shlibs
diff options
context:
space:
mode:
Diffstat (limited to 'shlibs')
-rw-r--r--shlibs/mount/src/Makefile.am6
-rw-r--r--shlibs/mount/src/mount.h.in2
-rw-r--r--shlibs/mount/src/utils.c162
3 files changed, 169 insertions, 1 deletions
diff --git a/shlibs/mount/src/Makefile.am b/shlibs/mount/src/Makefile.am
index 5d80779e0..4e17cfe11 100644
--- a/shlibs/mount/src/Makefile.am
+++ b/shlibs/mount/src/Makefile.am
@@ -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)
diff --git a/shlibs/mount/src/mount.h.in b/shlibs/mount/src/mount.h.in
index b4c9bc53a..6bea2a174 100644
--- a/shlibs/mount/src/mount.h.in
+++ b/shlibs/mount/src/mount.h.in
@@ -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);
diff --git a/shlibs/mount/src/utils.c b/shlibs/mount/src/utils.c
index fbdfadb84..fb9ffe8d5 100644
--- a/shlibs/mount/src/utils.c
+++ b/shlibs/mount/src/utils.c
@@ -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 */