From: Lennart Poettering Date: Fri, 14 Apr 2023 10:48:14 +0000 (+0200) Subject: string-util: add strstrafter() X-Git-Tag: v254-rc1~717 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d791013ff529cbbb74d4cc5f1455f172befab1e6;p=thirdparty%2Fsystemd.git string-util: add strstrafter() strstrafter() is like strstr() but returns a pointer to the first character *after* the found substring, not on the substring itself. Quite often this is what we actually want. Inspired by #27267 I think it makes sense to add a helper for this, to avoid the potentially fragile manual pointer increment afterwards. --- diff --git a/src/basic/mountpoint-util.c b/src/basic/mountpoint-util.c index 751d5a35ce0..027e64c498c 100644 --- a/src/basic/mountpoint-util.c +++ b/src/basic/mountpoint-util.c @@ -559,12 +559,12 @@ int dev_is_devtmpfs(void) { if (mid != mount_id) continue; - e = strstr(line, " - "); + e = strstrafter(line, " - "); if (!e) continue; /* accept any name that starts with the currently expected type */ - if (startswith(e + 3, "devtmpfs")) + if (startswith(e, "devtmpfs")) return true; } diff --git a/src/basic/string-util.h b/src/basic/string-util.h index 1755b3275ad..75483924af0 100644 --- a/src/basic/string-util.h +++ b/src/basic/string-util.h @@ -29,6 +29,18 @@ static inline char* strstr_ptr(const char *haystack, const char *needle) { return strstr(haystack, needle); } +static inline char *strstrafter(const char *haystack, const char *needle) { + char *p; + + /* Returns NULL if not found, or pointer to first character after needle if found */ + + p = strstr_ptr(haystack, needle); + if (!p) + return NULL; + + return p + strlen(needle); +} + static inline const char* strnull(const char *s) { return s ?: "(null)"; } diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c index 0bd2c89eb6e..f3f59e2ac3f 100644 --- a/src/libsystemd/sd-device/device-enumerator.c +++ b/src/libsystemd/sd-device/device-enumerator.c @@ -281,11 +281,10 @@ static int sound_device_compare(const char *devpath_a, const char *devpath_b) { * kernel makes this guarantee when creating those devices, and hence we should too when * enumerating them. */ - sound_a = strstr(devpath_a, "/sound/card"); + sound_a = strstrafter(devpath_a, "/sound/card"); if (!sound_a) return 0; - sound_a += STRLEN("/sound/card"); sound_a = strchr(devpath_a, '/'); if (!sound_a) return 0; diff --git a/src/shared/bus-get-properties.c b/src/shared/bus-get-properties.c index 3d0887e6df7..53e5d6b99f1 100644 --- a/src/shared/bus-get-properties.c +++ b/src/shared/bus-get-properties.c @@ -149,9 +149,9 @@ int bus_property_get_rlimit( s = is_soft ? strndupa_safe(property, is_soft - property) : property; /* Skip over any prefix, such as "Default" */ - assert_se(p = strstr(s, "Limit")); + assert_se(p = strstrafter(s, "Limit")); - z = rlimit_from_string(p + 5); + z = rlimit_from_string(p); assert(z >= 0); (void) getrlimit(z, &buf); diff --git a/src/shared/edit-util.c b/src/shared/edit-util.c index 9fd74973aa2..96ad7213433 100644 --- a/src/shared/edit-util.c +++ b/src/shared/edit-util.c @@ -300,10 +300,8 @@ static int strip_edit_temp_file(EditFile *e) { assert(e->context->marker_end); - contents_start = strstr(old_contents, e->context->marker_start); - if (contents_start) - contents_start += strlen(e->context->marker_start); - else + contents_start = strstrafter(old_contents, e->context->marker_start); + if (!contents_start) contents_start = old_contents; contents_end = strstr(contents_start, e->context->marker_end); diff --git a/src/shared/xml.c b/src/shared/xml.c index df381d85b8b..3b1fb41fef7 100644 --- a/src/shared/xml.c +++ b/src/shared/xml.c @@ -87,26 +87,26 @@ int xml_tokenize(const char **p, char **name, void **state, unsigned *line) { if (startswith(b, "!--")) { /* A comment */ - e = strstr(b + 3, "-->"); + e = strstrafter(b + 3, "-->"); if (!e) return -EINVAL; - inc_lines(line, b, e + 3 - b); + inc_lines(line, b, e - b); - c = e + 3; + c = e; continue; } if (*b == '?') { /* Processing instruction */ - e = strstr(b + 1, "?>"); + e = strstrafter(b + 1, "?>"); if (!e) return -EINVAL; - inc_lines(line, b, e + 2 - b); + inc_lines(line, b, e - b); - c = e + 2; + c = e; continue; } diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c index 9eb048adfa0..65052c627d7 100644 --- a/src/test/test-string-util.c +++ b/src/test/test-string-util.c @@ -1247,4 +1247,21 @@ TEST(find_line_startswith) { assert_se(!find_line_startswith(emptystring, "x")); } +TEST(strstrafter) { + static const char buffer[] = "abcdefghijklmnopqrstuvwxyz"; + + assert_se(!strstrafter(NULL, NULL)); + assert_se(!strstrafter("", NULL)); + assert_se(!strstrafter(NULL, "")); + assert_se(streq_ptr(strstrafter("", ""), "")); + + assert_se(strstrafter(buffer, "a") == buffer + 1); + assert_se(strstrafter(buffer, "") == buffer); + assert_se(strstrafter(buffer, "ab") == buffer + 2); + assert_se(strstrafter(buffer, "cde") == buffer + 5); + assert_se(strstrafter(buffer, "xyz") == strchr(buffer, 0)); + assert_se(strstrafter(buffer, buffer) == strchr(buffer, 0)); + assert_se(!strstrafter(buffer, "-")); +} + DEFINE_TEST_MAIN(LOG_DEBUG);