summaryrefslogtreecommitdiffstats
path: root/src/basic/unit-name.c
diff options
context:
space:
mode:
authorMike Yuan <me@yhndnzj.com>2024-02-08 11:31:37 +0100
committerMike Yuan <me@yhndnzj.com>2024-02-09 09:17:59 +0100
commit8749b09390959232f847aceee4efe76f45bf4174 (patch)
tree55aba942fee935643546da15d3e1024177604bfd /src/basic/unit-name.c
parentsystemctl-util: some modernizations (diff)
downloadsystemd-8749b09390959232f847aceee4efe76f45bf4174.tar.xz
systemd-8749b09390959232f847aceee4efe76f45bf4174.zip
basic/unit-name: introduce unit_name_replace_instance_full
that optionally accepts a globbed instance
Diffstat (limited to 'src/basic/unit-name.c')
-rw-r--r--src/basic/unit-name.c41
1 files changed, 26 insertions, 15 deletions
diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c
index 8bf28ba749..06ed9054d0 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);