]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/unit-name: introduce unit_name_replace_instance_full
authorMike Yuan <me@yhndnzj.com>
Thu, 8 Feb 2024 10:31:37 +0000 (18:31 +0800)
committerMike Yuan <me@yhndnzj.com>
Fri, 9 Feb 2024 08:17:59 +0000 (16:17 +0800)
that optionally accepts a globbed instance

src/basic/unit-name.c
src/basic/unit-name.h

index 8bf28ba749c343385bbc7bd8979d87089c88f102..06ed9054d0bed310a2ee470ebf705bb7bfa1f8a0 100644 (file)
@@ -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);
index d22d824fbe2c47e9791689e691279fc87dcd3816..fa7295e250e76f6204c6be921c21bfbb43caa1ff 100644 (file)
@@ -40,7 +40,14 @@ int unit_name_unescape(const char *f, char **ret);
 int unit_name_path_escape(const char *f, char **ret);
 int unit_name_path_unescape(const char *f, char **ret);
 
-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);
+static inline int unit_name_replace_instance(const char *original, const char *instance, char **ret) {
+        return unit_name_replace_instance_full(original, instance, false, ret);
+}
 
 int unit_name_template(const char *f, char **ret);