summaryrefslogtreecommitdiffstats
path: root/src/basic/unit-name.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/basic/unit-name.c68
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;