diff --git a/src/basic/env-util.c b/src/basic/env-util.c index 99ce1a1842..09c8e7c28f 100644 --- a/src/basic/env-util.c +++ b/src/basic/env-util.c @@ -695,7 +695,7 @@ int replace_env_full( _cleanup_strv_free_ char **unset_variables = NULL, **bad_variables = NULL; const char *e, *word = format, *test_value = NULL; /* test_value is initialized to appease gcc */ _cleanup_free_ char *s = NULL; - char ***pu, ***pb, *k; + char ***pu, ***pb; size_t i, len = 0; /* len is initialized to appease gcc */ int nest = 0, r; @@ -717,33 +717,24 @@ int replace_env_full( case CURLY: if (*e == '{') { - k = strnappend(s, word, e-word-1); - if (!k) + if (!strextendn(&s, word, e-word-1)) return -ENOMEM; - free_and_replace(s, k); - word = e-1; state = VARIABLE; nest++; } else if (*e == '$') { - k = strnappend(s, word, e-word); - if (!k) + if (!strextendn(&s, word, e-word)) return -ENOMEM; - free_and_replace(s, k); - word = e+1; state = WORD; } else if (FLAGS_SET(flags, REPLACE_ENV_ALLOW_BRACELESS) && strchr(VALID_BASH_ENV_NAME_CHARS, *e)) { - k = strnappend(s, word, e-word-1); - if (!k) + if (!strextendn(&s, word, e-word-1)) return -ENOMEM; - free_and_replace(s, k); - word = e-1; state = VARIABLE_RAW; diff --git a/src/basic/string-util.c b/src/basic/string-util.c index b2919164d6..7f4be13b62 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -46,35 +46,42 @@ char* first_word(const char *s, const char *word) { return (char*) nw; } -char* strnappend(const char *s, const char *suffix, size_t b) { - size_t a; - char *r; +char* strprepend(char **x, const char *s) { + assert(x); - if (!s && !suffix) - return strdup(""); + if (isempty(s) && *x) + return *x; - if (!s) - return strndup(suffix, b); - - if (!suffix) - return strdup(s); - - assert(s); - assert(suffix); - - a = strlen(s); - if (b > SIZE_MAX - a) + char *p = strjoin(strempty(s), *x); + if (!p) return NULL; - r = new(char, a+b+1); - if (!r) - return NULL; + free_and_replace(*x, p); + return *x; +} - memcpy(r, s, a); - memcpy(r+a, suffix, b); - r[a+b] = 0; +char* strextendn(char **x, const char *s, size_t l) { + assert(x); + assert(s || l == 0); - return r; + if (l > 0) + l = strnlen(s, l); /* ignore trailing noise */ + + if (l > 0 || !*x) { + size_t q; + char *m; + + q = strlen_ptr(*x); + m = realloc(*x, q + l + 1); + if (!m) + return NULL; + + *mempcpy_typesafe(m + q, s, l) = 0; + + *x = m; + } + + return *x; } char* strstrip(char *s) { @@ -975,33 +982,6 @@ oom: return -ENOMEM; } -char* strextendn(char **x, const char *s, size_t l) { - assert(x); - assert(s || l == 0); - - if (l == SIZE_MAX) - l = strlen_ptr(s); - else if (l > 0) - l = strnlen(s, l); /* ignore trailing noise */ - - if (l > 0 || !*x) { - size_t q; - char *m; - - q = strlen_ptr(*x); - m = realloc(*x, q + l + 1); - if (!m) - return NULL; - - memcpy_safe(m + q, s, l); - m[q + l] = 0; - - *x = m; - } - - return *x; -} - char* strrep(const char *s, unsigned n) { char *r, *p; size_t l; diff --git a/src/basic/string-util.h b/src/basic/string-util.h index 1bcb1c40e3..8a5df741cc 100644 --- a/src/basic/string-util.h +++ b/src/basic/string-util.h @@ -106,7 +106,8 @@ static inline const char* empty_or_dash_to_null(const char *p) { char* first_word(const char *s, const char *word) _pure_; -char* strnappend(const char *s, const char *suffix, size_t length); +char* strprepend(char **x, const char *s); +char* strextendn(char **x, const char *s, size_t l); #define strjoin(a, ...) strextend_with_separator_internal(NULL, NULL, a, __VA_ARGS__, NULL) @@ -193,8 +194,6 @@ char* strextend_with_separator_internal(char **x, const char *separator, ...) _s #define strextend_with_separator(x, separator, ...) strextend_with_separator_internal(x, separator, __VA_ARGS__, NULL) #define strextend(x, ...) strextend_with_separator_internal(x, NULL, __VA_ARGS__, NULL) -char* strextendn(char **x, const char *s, size_t l); - int strextendf_with_separator(char **x, const char *separator, const char *format, ...) _printf_(3,4); #define strextendf(x, ...) strextendf_with_separator(x, NULL, __VA_ARGS__) diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 6fd10613d1..d109d0914f 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -600,14 +600,15 @@ static int parse_one_option(const char *option) { * - text descriptions prefixed with "%:" or "%keyring:". * - text description with no prefix. * - numeric keyring id (ignored in current patch set). */ - if (IN_SET(*val, '@', '%')) - keyring = strndup(val, sep - val); - else - /* add type prefix if missing (crypt_set_keyring_to_link() expects it) */ - keyring = strnappend("%:", val, sep - val); + keyring = strndup(val, sep - val); if (!keyring) return log_oom(); + /* add type prefix if missing (crypt_set_keyring_to_link() expects it) */ + if (!IN_SET(*keyring, '@', '%')) + if (!strprepend(&keyring, "%:")) + return log_oom(); + sep += 2; /* % is optional (and defaults to 'user') */ diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c index fbfb3990e4..1b447abda9 100644 --- a/src/test/test-string-util.c +++ b/src/test/test-string-util.c @@ -1348,6 +1348,19 @@ TEST(strextendn) { x = mfree(x); } +TEST(strprepend) { + _cleanup_free_ char *x = NULL; + + ASSERT_STREQ(strprepend(&x, NULL), ""); + x = mfree(x); + + ASSERT_STREQ(strprepend(&x, ""), ""); + + ASSERT_STREQ(strprepend(&x, "xxx"), "xxx"); + ASSERT_STREQ(strprepend(&x, "bar"), "barxxx"); + ASSERT_STREQ(strprepend(&x, "foo"), "foobarxxx"); +} + TEST(strlevenshtein) { assert_se(strlevenshtein(NULL, NULL) == 0); assert_se(strlevenshtein("", "") == 0);