diff --git a/src/basic/string-util.c b/src/basic/string-util.c index 6fb4134ae9..be2613ca9e 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -278,6 +278,9 @@ char *strjoin_real(const char *x, ...) { char *strstrip(char *s) { char *e; + if (!s) + return NULL; + /* Drops trailing whitespace. Modifies the string in * place. Returns pointer to first non-space character */ @@ -295,7 +298,13 @@ char *strstrip(char *s) { char *delete_chars(char *s, const char *bad) { char *f, *t; - /* Drops all whitespace, regardless where in the string */ + /* Drops all specified bad characters, regardless where in the string */ + + if (!s) + return NULL; + + if (!bad) + bad = WHITESPACE; for (f = s, t = s; *f; f++) { if (strchr(bad, *f)) @@ -309,6 +318,26 @@ char *delete_chars(char *s, const char *bad) { return s; } +char *delete_trailing_chars(char *s, const char *bad) { + char *p, *c = s; + + /* Drops all specified bad characters, at the end of the string */ + + if (!s) + return NULL; + + if (!bad) + bad = WHITESPACE; + + for (p = s; *p; p++) + if (!strchr(bad, *p)) + c = p + 1; + + *c = 0; + + return s; +} + char *truncate_nl(char *s) { assert(s); diff --git a/src/basic/string-util.h b/src/basic/string-util.h index 4c94b182c1..d2040ebd12 100644 --- a/src/basic/string-util.h +++ b/src/basic/string-util.h @@ -133,8 +133,20 @@ char *strjoin_real(const char *x, ...) _sentinel_; char *strstrip(char *s); char *delete_chars(char *s, const char *bad); +char *delete_trailing_chars(char *s, const char *bad); char *truncate_nl(char *s); +static inline char *skip_leading_chars(const char *s, const char *bad) { + + if (!s) + return NULL; + + if (!bad) + bad = WHITESPACE; + + return (char*) s + strspn(s, bad); +} + char ascii_tolower(char x); char *ascii_strlower(char *s); char *ascii_strlower_n(char *s, size_t n); diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c index ba9928375e..27ce432197 100644 --- a/src/basic/unit-name.c +++ b/src/basic/unit-name.c @@ -382,19 +382,14 @@ int unit_name_path_escape(const char *f, char **ret) { if (STR_IN_SET(p, "/", "")) s = strdup("-"); else { - char *e; - if (!path_is_safe(p)) return -EINVAL; /* Truncate trailing slashes */ - e = endswith(p, "/"); - if (e) - *e = 0; + delete_trailing_chars(p, "/"); /* Truncate leading slashes */ - if (p[0] == '/') - p++; + p = skip_leading_chars(p, "/"); s = unit_name_escape(p); } diff --git a/src/core/cgroup.c b/src/core/cgroup.c index b717837c72..d81d10a2df 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -1944,11 +1944,9 @@ int manager_setup_cgroup(Manager *m) { if (e) *e = 0; - /* And make sure to store away the root value without trailing - * slash, even for the root dir, so that we can easily prepend - * it everywhere. */ - while ((e = endswith(m->cgroup_root, "/"))) - *e = 0; + /* And make sure to store away the root value without trailing slash, even for the root dir, so that we can + * easily prepend it everywhere. */ + delete_trailing_chars(m->cgroup_root, "/"); /* 2. Show data */ r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, NULL, &path); diff --git a/src/libudev/libudev-private.h b/src/libudev/libudev-private.h index 52c5075110..818da8465e 100644 --- a/src/libudev/libudev-private.h +++ b/src/libudev/libudev-private.h @@ -138,7 +138,6 @@ int udev_queue_export_device_finished(struct udev_queue_export *udev_queue_expor #define UDEV_ALLOWED_CHARS_INPUT "/ $%?," int util_log_priority(const char *priority); size_t util_path_encode(const char *src, char *dest, size_t size); -void util_remove_trailing_chars(char *path, char c); int util_replace_whitespace(const char *str, char *to, size_t len); int util_replace_chars(char *str, const char *white); unsigned int util_string_hash32(const char *key); diff --git a/src/libudev/libudev-util.c b/src/libudev/libudev-util.c index 1d73d8f090..ae809d85e1 100644 --- a/src/libudev/libudev-util.c +++ b/src/libudev/libudev-util.c @@ -150,17 +150,6 @@ size_t util_path_encode(const char *src, char *dest, size_t size) return j; } -void util_remove_trailing_chars(char *path, char c) -{ - size_t len; - - if (path == NULL) - return; - len = strlen(path); - while (len > 0 && path[len-1] == c) - path[--len] = '\0'; -} - /* * Copy from 'str' to 'to', while removing all leading and trailing whitespace, * and replacing each run of consecutive whitespace with a single underscore. diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c index 604701ff7a..5d97080d2c 100644 --- a/src/test/test-string-util.c +++ b/src/test/test-string-util.c @@ -288,11 +288,47 @@ static void test_endswith_no_case(void) { } static void test_delete_chars(void) { - char *r; - char input[] = " hello, waldo. abc"; + char *s, input[] = " hello, waldo. abc"; - r = delete_chars(input, WHITESPACE); - assert_se(streq(r, "hello,waldo.abc")); + s = delete_chars(input, WHITESPACE); + assert_se(streq(s, "hello,waldo.abc")); + assert_se(s == input); +} + +static void test_delete_trailing_chars(void) { + + char *s, + input1[] = " \n \r k \n \r ", + input2[] = "kkkkthiskkkiskkkaktestkkk", + input3[] = "abcdef"; + + s = delete_trailing_chars(input1, WHITESPACE); + assert_se(streq(s, " \n \r k")); + assert_se(s == input1); + + s = delete_trailing_chars(input2, "kt"); + assert_se(streq(s, "kkkkthiskkkiskkkaktes")); + assert_se(s == input2); + + s = delete_trailing_chars(input3, WHITESPACE); + assert_se(streq(s, "abcdef")); + assert_se(s == input3); + + s = delete_trailing_chars(input3, "fe"); + assert_se(streq(s, "abcd")); + assert_se(s == input3); +} + +static void test_skip_leading_chars(void) { + char input1[] = " \n \r k \n \r ", + input2[] = "kkkkthiskkkiskkkaktestkkk", + input3[] = "abcdef"; + + assert_se(streq(skip_leading_chars(input1, WHITESPACE), "k \n \r ")); + assert_se(streq(skip_leading_chars(input2, "k"), "thiskkkiskkkaktestkkk")); + assert_se(streq(skip_leading_chars(input2, "tk"), "hiskkkiskkkaktestkkk")); + assert_se(streq(skip_leading_chars(input3, WHITESPACE), "abcdef")); + assert_se(streq(skip_leading_chars(input3, "bcaef"), "def")); } static void test_in_charset(void) { @@ -361,6 +397,8 @@ int main(int argc, char *argv[]) { test_endswith(); test_endswith_no_case(); test_delete_chars(); + test_delete_trailing_chars(); + test_skip_leading_chars(); test_in_charset(); test_split_pair(); test_first_word(); diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 9aaec72baf..b061210c7c 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -1967,7 +1967,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules, } else { int count; - util_remove_trailing_chars(result, '\n'); + delete_trailing_chars(result, "\n"); if (IN_SET(esc, ESCAPE_UNSET, ESCAPE_REPLACE)) { count = util_replace_chars(result, UDEV_ALLOWED_CHARS_INPUT); if (count > 0) diff --git a/src/udev/udevadm-test-builtin.c b/src/udev/udevadm-test-builtin.c index b5662be5c2..3bcd09061a 100644 --- a/src/udev/udevadm-test-builtin.c +++ b/src/udev/udevadm-test-builtin.c @@ -85,7 +85,7 @@ static int adm_builtin(struct udev *udev, int argc, char *argv[]) { strscpyl(filename, sizeof(filename), "/sys", syspath, NULL); else strscpy(filename, sizeof(filename), syspath); - util_remove_trailing_chars(filename, '/'); + delete_trailing_chars(filename, "/"); dev = udev_device_new_from_syspath(udev, filename); if (dev == NULL) { diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c index e8ffe2f309..b180e24369 100644 --- a/src/udev/udevadm-test.c +++ b/src/udev/udevadm-test.c @@ -116,7 +116,7 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) { strscpyl(filename, sizeof(filename), "/sys", syspath, NULL); else strscpy(filename, sizeof(filename), syspath); - util_remove_trailing_chars(filename, '/'); + delete_trailing_chars(filename, "/"); dev = udev_device_new_from_synthetic_event(udev, filename, action); if (dev == NULL) {