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.
} 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 {
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)) {
#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);
_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)
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) {