diff options
Diffstat (limited to 'src/basic/unit-name.c')
-rw-r--r-- | src/basic/unit-name.c | 68 |
1 files changed, 34 insertions, 34 deletions
diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c index 8bf28ba..4e2f77c 100644 --- a/src/basic/unit-name.c +++ b/src/basic/unit-name.c @@ -454,34 +454,45 @@ int unit_name_path_unescape(const char *f, char **ret) { return 0; } -int unit_name_replace_instance(const char *f, const char *i, char **ret) { +int unit_name_replace_instance_full( + const char *original, + const char *instance, + bool accept_glob, + char **ret) { + _cleanup_free_ char *s = NULL; - const char *p, *e; - size_t a, b; + const char *prefix, *suffix; + size_t pl; - assert(f); - assert(i); + assert(original); + assert(instance); assert(ret); - if (!unit_name_is_valid(f, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) + if (!unit_name_is_valid(original, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) return -EINVAL; - if (!unit_instance_is_valid(i)) + if (!unit_instance_is_valid(instance) && !(accept_glob && in_charset(instance, VALID_CHARS_GLOB))) return -EINVAL; - assert_se(p = strchr(f, '@')); - assert_se(e = strrchr(f, '.')); + prefix = ASSERT_PTR(strchr(original, '@')); + suffix = ASSERT_PTR(strrchr(original, '.')); + assert(prefix < suffix); - a = p - f; - b = strlen(i); + pl = prefix - original + 1; /* include '@' */ - s = new(char, a + 1 + b + strlen(e) + 1); + s = new(char, pl + strlen(instance) + strlen(suffix) + 1); if (!s) return -ENOMEM; - strcpy(mempcpy(mempcpy(s, f, a + 1), i, b), e); +#if HAS_FEATURE_MEMORY_SANITIZER + /* MSan doesn't like stpncpy... See also https://github.com/google/sanitizers/issues/926 */ + memzero(s, pl + strlen(instance) + strlen(suffix) + 1); +#endif - /* Make sure the resulting name still is valid, i.e. didn't grow too large */ - if (!unit_name_is_valid(s, UNIT_NAME_INSTANCE)) + strcpy(stpcpy(stpncpy(s, original, pl), instance), suffix); + + /* Make sure the resulting name still is valid, i.e. didn't grow too large. Globs will be expanded + * by clients when used, so the check is pointless. */ + if (!accept_glob && !unit_name_is_valid(s, UNIT_NAME_INSTANCE)) return -EINVAL; *ret = TAKE_PTR(s); @@ -782,19 +793,10 @@ int unit_name_mangle_with_suffix( return 1; good: - s = strdup(name); - if (!s) - return -ENOMEM; - - *ret = TAKE_PTR(s); - return 0; + return strdup_to(ret, name); } int slice_build_parent_slice(const char *slice, char **ret) { - _cleanup_free_ char *s = NULL; - char *dash; - int r; - assert(slice); assert(ret); @@ -806,18 +808,16 @@ int slice_build_parent_slice(const char *slice, char **ret) { return 0; } - s = strdup(slice); + _cleanup_free_ char *s = strdup(slice); if (!s) return -ENOMEM; - dash = strrchr(s, '-'); - if (dash) - strcpy(dash, ".slice"); - else { - r = free_and_strdup(&s, SPECIAL_ROOT_SLICE); - if (r < 0) - return r; - } + char *dash = strrchr(s, '-'); + if (!dash) + return strdup_to_full(ret, SPECIAL_ROOT_SLICE); + + /* We know that s ended with .slice before truncation, so we have enough space. */ + strcpy(dash, ".slice"); *ret = TAKE_PTR(s); return 1; |