core: fix dependency parsing
authorLennart Poettering <lennart@poettering.net>
Wed, 11 Nov 2015 21:53:05 +0000 (22:53 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 11 Nov 2015 21:53:05 +0000 (22:53 +0100)
3d793d29059a7ddf5282efa6b32b953c183d7a4d broke parsing of unit file
names that include backslashes, as extract_first_word() strips those.
Fix this, by introducing a new EXTRACT_RETAIN_ESCAPE flag which disables
looking at any flags, thus being compatible with the classic
FOREACH_WORD() behaviour.

src/basic/extract-word.c
src/basic/extract-word.h
src/core/load-fragment.c
src/test/test-extract-word.c

index ff6d211..fd49569 100644 (file)
@@ -128,7 +128,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
                                 } else if (c == quote) {        /* found the end quote */
                                         quote = 0;
                                         break;
-                                } else if (c == '\\') {
+                                } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
                                         backslash = true;
                                         break;
                                 } else {
@@ -146,7 +146,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
                                 else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) {
                                         quote = c;
                                         break;
-                                } else if (c == '\\') {
+                                } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
                                         backslash = true;
                                         break;
                                 } else if (strchr(separators, c)) {
index ddc1c4f..9606ab6 100644 (file)
 #include "macro.h"
 
 typedef enum ExtractFlags {
-        EXTRACT_RELAX           = 1,
-        EXTRACT_CUNESCAPE       = 2,
-        EXTRACT_CUNESCAPE_RELAX = 4,
-        EXTRACT_QUOTES          = 8,
+        EXTRACT_RELAX                    = 1,
+        EXTRACT_CUNESCAPE                = 2,
+        EXTRACT_CUNESCAPE_RELAX          = 4,
+        EXTRACT_QUOTES                   = 8,
         EXTRACT_DONT_COALESCE_SEPARATORS = 16,
+        EXTRACT_RETAIN_ESCAPE            = 32,
 } ExtractFlags;
 
 int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags);
index 79cabd2..93eeeab 100644 (file)
@@ -122,7 +122,7 @@ int config_parse_unit_deps(const char *unit,
                 _cleanup_free_ char *word = NULL, *k = NULL;
                 int r;
 
-                r = extract_first_word(&p, &word, NULL, 0);
+                r = extract_first_word(&p, &word, NULL, EXTRACT_RETAIN_ESCAPE);
                 if (r == 0)
                         break;
                 if (r == -ENOMEM)
index 09698c0..65d3a0a 100644 (file)
@@ -325,6 +325,18 @@ static void test_extract_first_word(void) {
         assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 0);
         assert_se(!t);
         assert_se(!p);
+
+        p = "foo\\xbar";
+        assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+        assert_se(streq(t, "fooxbar"));
+        free(t);
+        assert_se(p == NULL);
+
+        p = "foo\\xbar";
+        assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RETAIN_ESCAPE) > 0);
+        assert_se(streq(t, "foo\\xbar"));
+        free(t);
+        assert_se(p == NULL);
 }
 
 static void test_extract_first_word_and_warn(void) {