From: Luca Boccassi Date: Thu, 17 Jun 2021 12:12:57 +0000 (+0100) Subject: basic/extract-word: add EXTRACT_RETAIN_SEPARATORS flag X-Git-Tag: v249-rc2~13^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=70b6ee6110375222b6d102812d38e3e2bd19970f;p=thirdparty%2Fsystemd.git basic/extract-word: add EXTRACT_RETAIN_SEPARATORS flag Makes the helpers avoid skipping over the separator(s) in the input string --- diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c index 0c440db691c..9f9bb0c7910 100644 --- a/src/basic/extract-word.c +++ b/src/basic/extract-word.c @@ -51,7 +51,8 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra goto finish_force_terminate; else if (strchr(separators, c)) { if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) { - (*p)++; + if (!(flags & EXTRACT_RETAIN_SEPARATORS)) + (*p)++; goto finish_force_next; } } else { @@ -153,16 +154,18 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra break; } else if (strchr(separators, c)) { if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) { - (*p)++; + if (!(flags & EXTRACT_RETAIN_SEPARATORS)) + (*p)++; goto finish_force_next; } - /* Skip additional coalesced separators. */ - for (;; (*p)++, c = **p) { - if (c == 0) - goto finish_force_terminate; - if (!strchr(separators, c)) - break; - } + if (!(flags & EXTRACT_RETAIN_SEPARATORS)) + /* Skip additional coalesced separators. */ + for (;; (*p)++, c = **p) { + if (c == 0) + goto finish_force_terminate; + if (!strchr(separators, c)) + break; + } goto finish; } diff --git a/src/basic/extract-word.h b/src/basic/extract-word.h index f415872fac9..c82ad761efe 100644 --- a/src/basic/extract-word.h +++ b/src/basic/extract-word.h @@ -12,6 +12,7 @@ typedef enum ExtractFlags { EXTRACT_UNQUOTE = 1 << 5, /* Ignore separators in quoting with "" and '', and remove the quotes. */ EXTRACT_DONT_COALESCE_SEPARATORS = 1 << 6, /* Don't treat multiple adjacent separators as one */ EXTRACT_RETAIN_ESCAPE = 1 << 7, /* Treat escape character '\' as any other character without special meaning */ + EXTRACT_RETAIN_SEPARATORS = 1 << 8, /* Do not advance the original string pointer past the separator(s) */ /* Note that if no flags are specified, escaped escape characters will be silently stripped. */ } ExtractFlags; diff --git a/src/test/test-extract-word.c b/src/test/test-extract-word.c index a392ec75880..8cf0b63a4c7 100644 --- a/src/test/test-extract-word.c +++ b/src/test/test-extract-word.c @@ -482,6 +482,58 @@ static void test_extract_first_word(void) { assert_se(extract_first_word(&p, &t, ",", EXTRACT_UNQUOTE) > 0); assert_se(streq(t, "context=system_u:object_r:svirt_sandbox_file_t:s0:c0,c1")); free(t); + + p = "a:b"; + assert_se(extract_first_word(&p, &t, ":", EXTRACT_RETAIN_SEPARATORS) == 1); + assert_se(streq(t, "a")); + assert_se(streq(p, ":b")); + free(t); + assert_se(extract_first_word(&p, &t, ":", EXTRACT_RETAIN_SEPARATORS) == 1); + assert_se(streq(t, "b")); + free(t); + + p = "a>:b"; + assert_se(extract_first_word(&p, &t, ">:", EXTRACT_RETAIN_SEPARATORS) == 1); + assert_se(streq(t, "a")); + assert_se(streq(p, ">:b")); + free(t); + assert_se(extract_first_word(&p, &t, ">:", EXTRACT_RETAIN_SEPARATORS) == 1); + assert_se(streq(t, "b")); + free(t); + + p = "a>:b"; + assert_se(extract_first_word(&p, &t, ">:", EXTRACT_RETAIN_SEPARATORS|EXTRACT_DONT_COALESCE_SEPARATORS) == 1); + assert_se(streq(t, "a")); + assert_se(streq(p, ">:b")); + free(t); + assert_se(extract_first_word(&p, &t, ">:", EXTRACT_RETAIN_SEPARATORS|EXTRACT_DONT_COALESCE_SEPARATORS) == 1); + assert_se(streq(t, "")); + assert_se(streq(p, ">:b")); + free(t); + + p = "a\\:b"; + assert_se(extract_first_word(&p, &t, ":", EXTRACT_RETAIN_SEPARATORS|EXTRACT_RETAIN_ESCAPE) == 1); + assert_se(streq(t, "a\\")); + assert_se(streq(p, ":b")); + free(t); + + p = "a\\:b"; + assert_se(extract_first_word(&p, &t, ":", EXTRACT_RETAIN_SEPARATORS) == 1); + assert_se(streq(t, "a:b")); + assert_se(!p); + free(t); + + p = "a\\:b"; + assert_se(extract_first_word(&p, &t, ":", EXTRACT_RETAIN_SEPARATORS|EXTRACT_UNESCAPE_SEPARATORS) == 1); + assert_se(streq(t, "a:b")); + assert_se(!p); + free(t); + + p = "a\\:a:b"; + assert_se(extract_first_word(&p, &t, ":", EXTRACT_RETAIN_SEPARATORS|EXTRACT_UNESCAPE_SEPARATORS) == 1); + assert_se(streq(t, "a:a")); + assert_se(streq(p, ":b")); + free(t); } static void test_extract_first_word_and_warn(void) {