From 7b82d95f8d867958be648cc0027bf36d3f558e41 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Mar 2023 18:02:32 +0100 Subject: [PATCH 1/3] string-util: add new helper for finding line starting with specific string in a text buffer We have implemented this manually a couple of times, and always wrong. Hence let's implement this correctly for once and use everywhere. --- src/basic/string-util.c | 23 +++++++++++++++++++++++ src/basic/string-util.h | 2 ++ src/test/test-string-util.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/src/basic/string-util.c b/src/basic/string-util.c index ad8c9863bd..cc2f8ecdab 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -1260,3 +1260,26 @@ char *strdupcspn(const char *a, const char *reject) { return strndup(a, strcspn(a, reject)); } + +char *find_line_startswith(const char *haystack, const char *needle) { + char *p; + + assert(haystack); + assert(needle); + + /* Finds the first line in 'haystack' that starts with the specified string. Returns a pointer to the + * first character after it */ + + p = strstr(haystack, needle); + if (!p) + return NULL; + + if (p > haystack) + while (p[-1] != '\n') { + p = strstr(p + 1, needle); + if (!p) + return NULL; + } + + return p + strlen(needle); +} diff --git a/src/basic/string-util.h b/src/basic/string-util.h index e0a47a21a9..1755b3275a 100644 --- a/src/basic/string-util.h +++ b/src/basic/string-util.h @@ -253,3 +253,5 @@ size_t strspn_from_end(const char *str, const char *accept); char *strdupspn(const char *a, const char *accept); char *strdupcspn(const char *a, const char *reject); + +char *find_line_startswith(const char *haystack, const char *needle); diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c index b3ff7d65c1..9eb048adfa 100644 --- a/src/test/test-string-util.c +++ b/src/test/test-string-util.c @@ -1218,4 +1218,33 @@ TEST(make_cstring) { TEST_MAKE_CSTRING_ONE(test8, -EINVAL, MAKE_CSTRING_REQUIRE_TRAILING_NUL, NULL); } +TEST(find_line_startswith) { + static const char text[] = + "foobar\n" + "this is a test\n" + "foobar: waldo\n" + "more\n" + "\n" + "piff\n" + "foobarfoobar\n" + "iff\n"; + static const char emptystring[] = ""; + + assert_se(find_line_startswith(text, "") == text); + assert_se(find_line_startswith(text, "f") == text+1); + assert_se(find_line_startswith(text, "foobar") == text+6); + assert_se(!find_line_startswith(text, "foobarx")); + assert_se(!find_line_startswith(text, "oobar")); + assert_se(find_line_startswith(text, "t") == text + 8); + assert_se(find_line_startswith(text, "th") == text + 9); + assert_se(find_line_startswith(text, "this") == text + 11); + assert_se(find_line_startswith(text, "foobarf") == text + 54); + assert_se(find_line_startswith(text, "more\n") == text + 41); + assert_se(find_line_startswith(text, "\n") == text + 42); + assert_se(find_line_startswith(text, "iff") == text + 63); + + assert_se(find_line_startswith(emptystring, "") == emptystring); + assert_se(!find_line_startswith(emptystring, "x")); +} + DEFINE_TEST_MAIN(LOG_DEBUG); From 50ed5cbf5f305d331a2f72a389cb39c9e670286c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Mar 2023 18:25:13 +0100 Subject: [PATCH 2/3] tree-wide: port various places to find_line_startswith() --- src/basic/mountpoint-util.c | 11 +++-------- src/basic/process-util.c | 11 +++-------- src/import/importd.c | 11 +++-------- src/shared/logs-show.c | 11 +++-------- 4 files changed, 12 insertions(+), 32 deletions(-) diff --git a/src/basic/mountpoint-util.c b/src/basic/mountpoint-util.c index ad22894a59..751d5a35ce 100644 --- a/src/basic/mountpoint-util.c +++ b/src/basic/mountpoint-util.c @@ -125,14 +125,9 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *ret_mn if (r < 0) return r; - p = startswith(fdinfo, "mnt_id:"); - if (!p) { - p = strstr(fdinfo, "\nmnt_id:"); - if (!p) /* The mnt_id field is a relatively new addition */ - return -EOPNOTSUPP; - - p += 8; - } + p = find_line_startswith(fdinfo, "mnt_id:"); + if (!p) /* The mnt_id field is a relatively new addition */ + return -EOPNOTSUPP; p += strspn(p, WHITESPACE); p[strcspn(p, WHITESPACE)] = 0; diff --git a/src/basic/process-util.c b/src/basic/process-util.c index cf2dca1dc4..c891f74be8 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -1453,14 +1453,9 @@ int pidfd_get_pid(int fd, pid_t *ret) { if (r < 0) return r; - p = startswith(fdinfo, "Pid:"); - if (!p) { - p = strstr(fdinfo, "\nPid:"); - if (!p) - return -ENOTTY; /* not a pidfd? */ - - p += 5; - } + p = find_line_startswith(fdinfo, "Pid:"); + if (!p) + return -ENOTTY; /* not a pidfd? */ p += strspn(p, WHITESPACE); p[strcspn(p, WHITESPACE)] = 0; diff --git a/src/import/importd.c b/src/import/importd.c index ed757019cf..4675aa5a61 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -590,14 +590,9 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void buf[n] = 0; - p = startswith(buf, "X_IMPORT_PROGRESS="); - if (!p) { - p = strstr(buf, "\nX_IMPORT_PROGRESS="); - if (!p) - return 0; - - p += 19; - } + p = find_line_startswith(buf, "X_IMPORT_PROGRESS="); + if (!p) + return 0; e = strchrnul(p, '\n'); *e = 0; diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 6ed9a6890f..d372e096c4 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -93,14 +93,9 @@ static int url_from_catalog(sd_journal *j, char **ret) { if (r < 0) return log_error_errno(r, "Failed to find catalog entry: %m"); - weblink = startswith(t, "Documentation:"); - if (!weblink) { - weblink = strstr(t + 1, "\nDocumentation:"); - if (!weblink) - goto notfound; - - weblink += 15; - } + weblink = find_line_startswith(t, "Documentation:"); + if (!weblink) + goto notfound; /* Skip whitespace to value */ weblink += strspn(weblink, " \t"); From 90f5f3552c89d2cf7b8e09dc072860da9859062a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Mar 2023 18:27:03 +0100 Subject: [PATCH 3/3] import: use truncate_nl() where appropriate --- src/import/importd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/import/importd.c b/src/import/importd.c index 4675aa5a61..a58587beb2 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -554,9 +554,9 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void }; struct ucred *ucred; Manager *m = userdata; - char *p, *e; Transfer *t; ssize_t n; + char *p; int r; n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); @@ -594,8 +594,7 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void if (!p) return 0; - e = strchrnul(p, '\n'); - *e = 0; + truncate_nl(p); r = parse_percent(p); if (r < 0) {