From 8d80f275303385eb9e2452f97f9c11be5c196862 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 11 Dec 2020 08:34:13 +0900 Subject: [PATCH] sd-device: make TAGS= property prefixed and suffixed with ":" The commit 6f3ac0d51766b0b9101676cefe5c4ba81feba436 drops the prefix and suffix in TAGS= property. But there exists several rules that have like `TAGS=="*:tag:*"`. So, the property must be always prefixed and suffixed with ":". Fixes #17930. --- src/basic/hashmap.c | 25 ++++++++--- src/basic/set.h | 2 +- src/libsystemd/sd-device/sd-device.c | 6 +-- src/test/test-set.c | 67 +++++++++++++++++++--------- test/units/testsuite-55.sh | 44 +++++++----------- 5 files changed, 87 insertions(+), 57 deletions(-) diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index e38e580530..cdc6847edf 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -1977,23 +1977,33 @@ IteratedCache* iterated_cache_free(IteratedCache *cache) { return mfree(cache); } -int set_strjoin(Set *s, const char *separator, char **ret) { +int set_strjoin(Set *s, const char *separator, bool wrap_with_separator, char **ret) { size_t separator_len, allocated = 0, len = 0; _cleanup_free_ char *str = NULL; const char *value; - bool first = true; + bool first; assert(ret); + if (set_isempty(s)) { + *ret = NULL; + return 0; + } + separator_len = strlen_ptr(separator); + if (separator_len == 0) + wrap_with_separator = false; + + first = !wrap_with_separator; + SET_FOREACH(value, s) { size_t l = strlen_ptr(value); if (l == 0) continue; - if (!GREEDY_REALLOC(str, allocated, len + l + (first ? 0 : separator_len) + 1)) + if (!GREEDY_REALLOC(str, allocated, len + l + (first ? 0 : separator_len) + (wrap_with_separator ? separator_len : 0) + 1)) return -ENOMEM; if (separator_len > 0 && !first) { @@ -2005,8 +2015,13 @@ int set_strjoin(Set *s, const char *separator, char **ret) { len += l; first = false; } - if (str) - str[len] = '\0'; + + if (wrap_with_separator) { + memcpy(str + len, separator, separator_len); + len += separator_len; + } + + str[len] = '\0'; *ret = TAKE_PTR(str); return 0; diff --git a/src/basic/set.h b/src/basic/set.h index 2b06c39cbe..57ff713039 100644 --- a/src/basic/set.h +++ b/src/basic/set.h @@ -151,4 +151,4 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free); #define _cleanup_set_free_ _cleanup_(set_freep) #define _cleanup_set_free_free_ _cleanup_(set_free_freep) -int set_strjoin(Set *s, const char *separator, char **ret); +int set_strjoin(Set *s, const char *separator, bool wrap_with_separator, char **ret); diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index 005801e1a6..d1aa3282bf 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -1534,7 +1534,7 @@ int device_properties_prepare(sd_device *device) { if (device->property_devlinks_outdated) { _cleanup_free_ char *devlinks = NULL; - r = set_strjoin(device->devlinks, " ", &devlinks); + r = set_strjoin(device->devlinks, " ", false, &devlinks); if (r < 0) return r; @@ -1550,7 +1550,7 @@ int device_properties_prepare(sd_device *device) { if (device->property_tags_outdated) { _cleanup_free_ char *tags = NULL; - r = set_strjoin(device->all_tags, ":", &tags); + r = set_strjoin(device->all_tags, ":", true, &tags); if (r < 0) return r; @@ -1561,7 +1561,7 @@ int device_properties_prepare(sd_device *device) { } tags = mfree(tags); - r = set_strjoin(device->current_tags, ":", &tags); + r = set_strjoin(device->current_tags, ":", true, &tags); if (r < 0) return r; diff --git a/src/test/test-set.c b/src/test/test-set.c index 8979408242..b4d07b2078 100644 --- a/src/test/test-set.c +++ b/src/test/test-set.c @@ -154,50 +154,77 @@ static void test_set_strjoin(void) { _cleanup_set_free_ Set *m = NULL; _cleanup_free_ char *joined = NULL; - assert_se(set_strjoin(m, NULL, &joined) >= 0); + /* Empty set */ + assert_se(set_strjoin(m, NULL, false, &joined) >= 0); assert_se(!joined); - assert_se(set_strjoin(m, "", &joined) >= 0); + assert_se(set_strjoin(m, "", false, &joined) >= 0); assert_se(!joined); - assert_se(set_strjoin(m, " ", &joined) >= 0); + assert_se(set_strjoin(m, " ", false, &joined) >= 0); assert_se(!joined); - assert_se(set_strjoin(m, "xxx", &joined) >= 0); + assert_se(set_strjoin(m, "xxx", false, &joined) >= 0); + assert_se(!joined); + assert_se(set_strjoin(m, NULL, true, &joined) >= 0); + assert_se(!joined); + assert_se(set_strjoin(m, "", true, &joined) >= 0); + assert_se(!joined); + assert_se(set_strjoin(m, " ", true, &joined) >= 0); + assert_se(!joined); + assert_se(set_strjoin(m, "xxx", true, &joined) >= 0); assert_se(!joined); + /* Single entry */ assert_se(set_put_strdup(&m, "aaa") == 1); - - assert_se(set_strjoin(m, NULL, &joined) >= 0); + assert_se(set_strjoin(m, NULL, false, &joined) >= 0); assert_se(streq(joined, "aaa")); - joined = mfree(joined); - assert_se(set_strjoin(m, "", &joined) >= 0); + assert_se(set_strjoin(m, "", false, &joined) >= 0); assert_se(streq(joined, "aaa")); - joined = mfree(joined); - assert_se(set_strjoin(m, " ", &joined) >= 0); + assert_se(set_strjoin(m, " ", false, &joined) >= 0); assert_se(streq(joined, "aaa")); - joined = mfree(joined); - assert_se(set_strjoin(m, "xxx", &joined) >= 0); + assert_se(set_strjoin(m, "xxx", false, &joined) >= 0); assert_se(streq(joined, "aaa")); + joined = mfree(joined); + assert_se(set_strjoin(m, NULL, true, &joined) >= 0); + assert_se(streq(joined, "aaa")); + joined = mfree(joined); + assert_se(set_strjoin(m, "", true, &joined) >= 0); + assert_se(streq(joined, "aaa")); + joined = mfree(joined); + assert_se(set_strjoin(m, " ", true, &joined) >= 0); + assert_se(streq(joined, " aaa ")); + joined = mfree(joined); + assert_se(set_strjoin(m, "xxx", true, &joined) >= 0); + assert_se(streq(joined, "xxxaaaxxx")); + /* Two entries */ assert_se(set_put_strdup(&m, "bbb") == 1); assert_se(set_put_strdup(&m, "aaa") == 0); - joined = mfree(joined); - assert_se(set_strjoin(m, NULL, &joined) >= 0); + assert_se(set_strjoin(m, NULL, false, &joined) >= 0); assert_se(STR_IN_SET(joined, "aaabbb", "bbbaaa")); - joined = mfree(joined); - assert_se(set_strjoin(m, "", &joined) >= 0); + assert_se(set_strjoin(m, "", false, &joined) >= 0); assert_se(STR_IN_SET(joined, "aaabbb", "bbbaaa")); - joined = mfree(joined); - assert_se(set_strjoin(m, " ", &joined) >= 0); + assert_se(set_strjoin(m, " ", false, &joined) >= 0); assert_se(STR_IN_SET(joined, "aaa bbb", "bbb aaa")); - joined = mfree(joined); - assert_se(set_strjoin(m, "xxx", &joined) >= 0); + assert_se(set_strjoin(m, "xxx", false, &joined) >= 0); assert_se(STR_IN_SET(joined, "aaaxxxbbb", "bbbxxxaaa")); + joined = mfree(joined); + assert_se(set_strjoin(m, NULL, true, &joined) >= 0); + assert_se(STR_IN_SET(joined, "aaabbb", "bbbaaa")); + joined = mfree(joined); + assert_se(set_strjoin(m, "", true, &joined) >= 0); + assert_se(STR_IN_SET(joined, "aaabbb", "bbbaaa")); + joined = mfree(joined); + assert_se(set_strjoin(m, " ", true, &joined) >= 0); + assert_se(STR_IN_SET(joined, " aaa bbb ", " bbb aaa ")); + joined = mfree(joined); + assert_se(set_strjoin(m, "xxx", true, &joined) >= 0); + assert_se(STR_IN_SET(joined, "xxxaaaxxxbbbxxx", "xxxbbbxxxaaaxxx")); } int main(int argc, const char *argv[]) { diff --git a/test/units/testsuite-55.sh b/test/units/testsuite-55.sh index 19f5683f57..ffceefb6a5 100755 --- a/test/units/testsuite-55.sh +++ b/test/units/testsuite-55.sh @@ -2,26 +2,14 @@ set -ex set -o pipefail -function has_tag_internal() { - udevadm info /dev/null | sed -n '/E: '$1'=/ {s/E: '$1'=/:/; s/$/:/; p}' | grep -q ":$2:" -} - -function has_tag() { - has_tag_internal TAGS $1 -} - -function has_current_tag() { - has_tag_internal CURRENT_TAGS $1 -} - mkdir -p /run/udev/rules.d/ ! test -f /run/udev/tags/added/c1:3 && ! test -f /run/udev/tags/changed/c1:3 && - ! has_tag added && - ! has_current_tag added && - ! has_tag changed && - ! has_current_tag changed + udevadm info /dev/null | grep -q -v 'E: TAGS=.*:added:.*' && + udevadm info /dev/null | grep -q -v 'E: CURRENT_TAGS=.*:added:.*' && + udevadm info /dev/null | grep -q -v 'E: TAGS=.*:changed:.*' && + udevadm info /dev/null | grep -q -v 'E: CURRENT_TAGS=.*:changed:.*' cat > /run/udev/rules.d/50-testsuite.rules <