libmultipath: escape '"' chars while dumping config
authorMartin Wilck <mwilck@suse.com>
Fri, 8 Jun 2018 10:20:40 +0000 (12:20 +0200)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Thu, 21 Jun 2018 07:50:01 +0000 (09:50 +0200)
Since 044c5d6b "libmultipath: config parser: Allow '"' in strings",
double quotes can be part of string values in multipath.conf by escaping
them as double-double quotes ('""'). When dumping the configuration,
the un-escaping done during config file parsing must be reverted by replacing
'"' with '""' again.

Signed-off-by: Martin Wilck <mwilck@suse.com>
libmultipath/dict.c
tests/hwtable.c

index 0721b8a..fc107e9 100644 (file)
@@ -111,9 +111,45 @@ print_nonzero (char *buff, int len, long v)
 static int
 print_str (char *buff, int len, const char *ptr)
 {
-       if (!ptr)
+       char *p;
+       char *last;
+       const char *q;
+
+       if (!ptr || len <= 0)
                return 0;
-       return snprintf(buff, len, "\"%s\"", ptr);
+
+       q = strchr(ptr, '"');
+       if (q == NULL)
+               return snprintf(buff, len, "\"%s\"", ptr);
+
+       last = buff + len - 1;
+       p = buff;
+       if (p >= last)
+               goto out;
+       *p++ = '"';
+       if (p >= last)
+               goto out;
+       for (; q; q = strchr(ptr, '"')) {
+               if (q + 1 - ptr < last - p)
+                       p = mempcpy(p, ptr, q + 1 - ptr);
+               else {
+                       p = mempcpy(p, ptr, last - p);
+                       goto out;
+               }
+               *p++ = '"';
+               if (p >= last)
+                       goto out;
+               ptr = q + 1;
+       }
+       p += strlcpy(p, ptr, last - p);
+       if (p >= last)
+               goto out;
+       *p++ = '"';
+       *p = '\0';
+       return p - buff;
+out:
+       *p = '\0';
+       return len;
 }
 
 static int
index 7daf71e..9db7939 100644 (file)
@@ -598,18 +598,10 @@ static int setup_internal_nvme(void **state)
 /*
  * Device section with a simple entry qith double quotes ('foo:"bar"')
  */
-#if BROKEN
-static void test_quoted_hwe(void **state)
-#else
 static void test_quoted_hwe(const struct hwt_state *hwt)
-#endif
 {
        struct path *pp;
-#if BROKEN
-       struct hwt_state *hwt = CHECK_STATE(state);
 
-       _conf = LOAD_CONFIG(hwt);
-#endif
        /* foo:"bar" matches */
        pp = mock_path(vnd_foo.value, prd_baq.value);
        TEST_PROP(prio_name(&pp->prio), prio_emc.value);
@@ -625,11 +617,7 @@ static int setup_quoted_hwe(void **state)
        const struct key_value kv[] = { vnd_foo, prd_baqq, prio_emc };
 
        WRITE_ONE_DEVICE(hwt, kv);
-#if BROKEN
-       condlog(0, "%s: WARNING: skipping conf reload test", __func__);
-#else
        SET_TEST_FUNC(hwt, test_quoted_hwe);
-#endif
        return 0;
 }
 
@@ -1640,9 +1628,7 @@ static int setup_multipath_config_3(void **state)
        }
 
 define_test(string_hwe)
-#if !BROKEN
 define_test(quoted_hwe)
-#endif
 define_test(internal_nvme)
 define_test(regex_hwe)
 define_test(regex_string_hwe)
@@ -1680,11 +1666,7 @@ static int test_hwtable(void)
                cmocka_unit_test(test_sanity_globals),
                test_entry(internal_nvme),
                test_entry(string_hwe),
-#if BROKEN
-               cmocka_unit_test_setup(test_quoted_hwe, setup_quoted_hwe),
-#else
                test_entry(quoted_hwe),
-#endif
                test_entry(regex_hwe),
                test_entry(regex_string_hwe),
                test_entry(regex_string_hwe_dir),