diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c index a866c68823..780ad56eb1 100644 --- a/src/backlight/backlight.c +++ b/src/backlight/backlight.c @@ -44,9 +44,7 @@ static int find_pci_or_platform_parent(sd_device *device, sd_device **ret) { c += strspn(c, DIGITS); if (*c == '-') { /* A connector DRM device, let's ignore all but LVDS and eDP! */ - - if (!startswith(c, "-LVDS-") && - !startswith(c, "-Embedded DisplayPort-")) + if (!STARTSWITH_SET(c, "-LVDS-", "-Embedded DisplayPort-")) return -EOPNOTSUPP; } diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 3f94602c8f..ec29a6f4c9 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -1852,9 +1852,7 @@ char *cg_escape(const char *p) { * needs free()! */ if (IN_SET(p[0], 0, '_', '.') || - streq(p, "notify_on_release") || - streq(p, "release_agent") || - streq(p, "tasks") || + STR_IN_SET(p, "notify_on_release", "release_agent", "tasks") || startswith(p, "cgroup.")) need_prefix = true; else { diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 2deb176240..eb64c886e6 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -919,8 +919,7 @@ bool valid_device_allow_pattern(const char *path) { /* Like valid_device_node_path(), but also allows full-subsystem expressions, like DeviceAllow= and DeviceDeny= * accept it */ - if (startswith(path, "block-") || - startswith(path, "char-")) + if (STARTSWITH_SET(path, "block-", "char-")) return true; return valid_device_node_path(path); diff --git a/src/basic/path-util.h b/src/basic/path-util.h index 52a93b1c3f..e2a51ff33a 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -71,13 +71,13 @@ static inline bool path_equal_ptr(const char *a, const char *b) { #define PATH_STARTSWITH_SET(p, ...) \ ({ \ - char **s; \ - bool _found = false; \ - STRV_FOREACH(s, STRV_MAKE(__VA_ARGS__)) \ - if (path_startswith(p, *s)) { \ - _found = true; \ - break; \ - } \ + const char *_p = (p); \ + char *_found = NULL, **_i; \ + STRV_FOREACH(_i, STRV_MAKE(__VA_ARGS__)) { \ + _found = path_startswith(_p, *_i); \ + if (_found) \ + break; \ + } \ _found; \ }) diff --git a/src/basic/strv.h b/src/basic/strv.h index 5f1803d87d..aa4cd4aaca 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -144,6 +144,18 @@ void strv_print(char **l); _x && strv_contains(STRV_MAKE(__VA_ARGS__), _x); \ }) +#define STARTSWITH_SET(p, ...) \ + ({ \ + const char *_p = (p); \ + char *_found = NULL, **_i; \ + STRV_FOREACH(_i, STRV_MAKE(__VA_ARGS__)) { \ + _found = startswith(_p, *_i); \ + if (_found) \ + break; \ + } \ + _found; \ + }) + #define FOREACH_STRING(x, ...) \ for (char **_l = ({ \ char **_ll = STRV_MAKE(__VA_ARGS__); \ diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 7fce84bf82..a5e4de00b0 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -1014,11 +1014,8 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) { return -ENOMEM; } } else { - if (startswith(s, "/dev/")) - p = s + 5; - else if (startswith(s, "../")) - p = s + 3; - else + p = PATH_STARTSWITH_SET(s, "/dev/", "../"); + if (!p) p = s; b = strdup(p); diff --git a/src/basic/time-util.c b/src/basic/time-util.c index 30ad83d0a7..f1f52f1beb 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -1384,9 +1384,7 @@ int get_timezone(char **tz) { if (r < 0) return r; /* returns EINVAL if not a symlink */ - e = path_startswith(t, "/usr/share/zoneinfo/"); - if (!e) - e = path_startswith(t, "../usr/share/zoneinfo/"); + e = PATH_STARTSWITH_SET(t, "/usr/share/zoneinfo/", "../usr/share/zoneinfo/"); if (!e) return -EINVAL; diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index efefdaed99..ce222e4023 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -3242,7 +3242,7 @@ int config_parse_device_allow( return 0; } - if (!startswith(resolved, "block-") && !startswith(resolved, "char-")) { + if (!STARTSWITH_SET(resolved, "block-", "char-")) { r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue); if (r < 0) diff --git a/src/core/umount.c b/src/core/umount.c index 9e6c404ab9..bd4e4e7257 100644 --- a/src/core/umount.c +++ b/src/core/umount.c @@ -29,6 +29,7 @@ #include "process-util.h" #include "signal-util.h" #include "string-util.h" +#include "strv.h" #include "umount.h" #include "util.h" #include "virt.h" diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 7da13dc207..b0b1065e2f 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -510,11 +510,9 @@ static int add_crypttab_devices(void) { continue; } - uuid = startswith(device, "UUID="); + uuid = STARTSWITH_SET(device, "UUID=", "luks-"); if (!uuid) uuid = path_startswith(device, "/dev/disk/by-uuid/"); - if (!uuid) - uuid = startswith(name, "luks-"); if (uuid) d = hashmap_get(arg_disks, uuid); diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c index 44f3450d87..c46e0acdd3 100644 --- a/src/journal-remote/journal-remote-main.c +++ b/src/journal-remote/journal-remote-main.c @@ -614,15 +614,14 @@ static int create_remoteserver( if (arg_url) { const char *url; - char *hostname, *p; + char *hostname; if (!strstr(arg_url, "/entries")) { if (endswith(arg_url, "/")) url = strjoina(arg_url, "entries"); else url = strjoina(arg_url, "/entries"); - } - else + } else url = strdupa(arg_url); log_info("Spawning curl %s...", url); @@ -630,16 +629,11 @@ static int create_remoteserver( if (fd < 0) return fd; - hostname = - startswith(arg_url, "https://") ?: - startswith(arg_url, "http://") ?: - arg_url; + hostname = STARTSWITH_SET(arg_url, "https://", "http://"); + if (!hostname) + hostname = arg_url; - hostname = strdupa(hostname); - if ((p = strchr(hostname, '/'))) - *p = '\0'; - if ((p = strchr(hostname, ':'))) - *p = '\0'; + hostname = strndupa(hostname, strcspn(hostname, "/:")); r = journal_remote_add_source(s, fd, hostname, false); if (r < 0) diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index f7b91fddde..924ea4936e 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -25,6 +25,7 @@ #include "sigbus.h" #include "signal-util.h" #include "string-util.h" +#include "strv.h" #include "util.h" #define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-upload.pem" @@ -405,10 +406,12 @@ static int setup_uploader(Uploader *u, const char *url, const char *state_file) assert(u); assert(url); - memzero(u, sizeof(Uploader)); - u->input = -1; + *u = (Uploader) { + .input = -1 + }; - if (!(host = startswith(url, "http://")) && !(host = startswith(url, "https://"))) { + host = STARTSWITH_SET(url, "http://", "https://"); + if (!host) { host = url; proto = "https://"; } diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c index 7dd9ca62d5..5ea4601ba3 100644 --- a/src/journal/journald-native.c +++ b/src/journal/journald-native.c @@ -25,6 +25,7 @@ #include "selinux-util.h" #include "socket-util.h" #include "string-util.h" +#include "strv.h" #include "unaligned.h" static bool allow_object_pid(const struct ucred *ucred) { @@ -337,11 +338,7 @@ void server_process_native_file( return; } - e = path_startswith(k, "/dev/shm/"); - if (!e) - e = path_startswith(k, "/tmp/"); - if (!e) - e = path_startswith(k, "/var/tmp/"); + e = PATH_STARTSWITH_SET(k, "/dev/shm/", "/tmp/", "/var/tmp/"); if (!e) { log_error("Received file outside of allowed directories. Refusing."); return; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index a81e0e94c7..952f67a0d9 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -1183,8 +1183,7 @@ static bool file_has_type_prefix(const char *prefix, const char *filename) { tilded = strjoina(full, "~"); atted = strjoina(prefix, "@"); - return streq(filename, full) || - streq(filename, tilded) || + return STR_IN_SET(filename, full, tilded) || startswith(filename, atted); } diff --git a/src/login/logind-core.c b/src/login/logind-core.c index 2bab2fd2f5..60831bb1c3 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -606,9 +606,8 @@ static int manager_count_external_displays(Manager *m) { return r; FOREACH_DEVICE(e, d) { + const char *status, *enabled, *dash, *nn, *subsys; sd_device *p; - const char *status, *enabled, *dash, *nn, *i, *subsys; - bool external = false; if (sd_device_get_parent(d, &p) < 0) continue; @@ -631,16 +630,10 @@ static int manager_count_external_displays(Manager *m) { continue; dash++; - FOREACH_STRING(i, "VGA-", "DVI-I-", "DVI-D-", "DVI-A-" - "Composite-", "SVIDEO-", "Component-", - "DIN-", "DP-", "HDMI-A-", "HDMI-B-", "TV-") { - - if (startswith(dash, i)) { - external = true; - break; - } - } - if (!external) + if (!STARTSWITH_SET(dash, + "VGA-", "DVI-I-", "DVI-D-", "DVI-A-" + "Composite-", "SVIDEO-", "Component-", + "DIN-", "DP-", "HDMI-A-", "HDMI-B-", "TV-")) continue; /* Ignore ports that are not enabled */ diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 47fe7d4865..c581514b29 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1427,17 +1427,10 @@ static int userns_mkdir(const char *root, const char *path, mode_t mode, uid_t u } static const char *timezone_from_path(const char *path) { - const char *z; - - z = path_startswith(path, "../usr/share/zoneinfo/"); - if (z) - return z; - - z = path_startswith(path, "/usr/share/zoneinfo/"); - if (z) - return z; - - return NULL; + return PATH_STARTSWITH_SET( + path, + "../usr/share/zoneinfo/", + "/usr/share/zoneinfo/"); } static int setup_timezone(const char *dest) { diff --git a/src/run/run.c b/src/run/run.c index 0475156a43..e9e31282b6 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -384,12 +384,13 @@ static int parse_argv(int argc, char *argv[]) { return log_oom(); with_timer = with_timer || - !!startswith(optarg, "OnActiveSec=") || - !!startswith(optarg, "OnBootSec=") || - !!startswith(optarg, "OnStartupSec=") || - !!startswith(optarg, "OnUnitActiveSec=") || - !!startswith(optarg, "OnUnitInactiveSec=") || - !!startswith(optarg, "OnCalendar="); + STARTSWITH_SET(optarg, + "OnActiveSec=", + "OnBootSec=", + "OnStartupSec=", + "OnUnitActiveSec=", + "OnUnitInactiveSec=", + "OnCalendar="); break; case ARG_PATH_PROPERTY: diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c index 1eaf653103..6f0657174c 100644 --- a/src/shared/acl-util.c +++ b/src/shared/acl-util.c @@ -219,14 +219,11 @@ int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want STRV_FOREACH(entry, split) { char *p; - p = startswith(*entry, "default:"); + p = STARTSWITH_SET(*entry, "default:", "d:"); if (!p) - p = startswith(*entry, "d:"); + p = *entry; - if (p) - r = strv_push(&d, p); - else - r = strv_push(&a, *entry); + r = strv_push(&d, p); if (r < 0) return r; } diff --git a/src/shared/web-util.c b/src/shared/web-util.c index 82221af194..edf650d200 100644 --- a/src/shared/web-util.c +++ b/src/shared/web-util.c @@ -3,6 +3,7 @@ #include #include "string-util.h" +#include "strv.h" #include "utf8.h" #include "web-util.h" @@ -13,7 +14,7 @@ bool http_etag_is_valid(const char *etag) { if (!endswith(etag, "\"")) return false; - if (!startswith(etag, "\"") && !startswith(etag, "W/\"")) + if (!STARTSWITH_SET(etag, "\"", "W/\"")) return false; return true; @@ -25,9 +26,7 @@ bool http_url_is_valid(const char *url) { if (isempty(url)) return false; - p = startswith(url, "http://"); - if (!p) - p = startswith(url, "https://"); + p = STARTSWITH_SET(url, "http://", "https://"); if (!p) return false; @@ -46,12 +45,7 @@ bool documentation_url_is_valid(const char *url) { if (http_url_is_valid(url)) return true; - p = startswith(url, "file:/"); - if (!p) - p = startswith(url, "info:"); - if (!p) - p = startswith(url, "man:"); - + p = STARTSWITH_SET(url, "file:/", "info:", "man:"); if (isempty(p)) return false; diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index fd5f598701..b5030ea494 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -506,6 +506,27 @@ static void test_empty_or_root(void) { assert_se(!empty_or_root("//yy//")); } +static void test_path_startswith_set(void) { + + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/foo/bar", "/zzz"), "")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/foo/", "/zzz"), "bar")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/foo", "/zzz"), "bar")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/", "/zzz"), "foo/bar")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "", "/zzz"), NULL)); + + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/foo/bar", "/zzz"), NULL)); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/foo/", "/zzz"), "bar2")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/foo", "/zzz"), "bar2")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/", "/zzz"), "foo/bar2")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "", "/zzz"), NULL)); + + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/foo/bar", "/zzz"), NULL)); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/foo/", "/zzz"), NULL)); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/foo", "/zzz"), NULL)); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/", "/zzz"), "foo2/bar")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "", "/zzz"), NULL)); +} + int main(int argc, char **argv) { test_setup_logging(LOG_DEBUG); @@ -525,6 +546,7 @@ int main(int argc, char **argv) { test_hidden_or_backup_file(); test_skip_dev_prefix(); test_empty_or_root(); + test_path_startswith_set(); test_systemd_installation_has_version(argv[1]); /* NULL is OK */ diff --git a/src/test/test-strv.c b/src/test/test-strv.c index 63757afdce..31ef1abb44 100644 --- a/src/test/test-strv.c +++ b/src/test/test-strv.c @@ -56,6 +56,20 @@ static void test_strptr_in_set(void) { assert_se(!STRPTR_IN_SET(NULL, NULL)); } +static void test_startswith_set(void) { + assert_se(!STARTSWITH_SET("foo", "bar", "baz", "waldo")); + assert_se(!STARTSWITH_SET("foo", "bar")); + + assert_se(STARTSWITH_SET("abc", "a", "ab", "abc")); + assert_se(STARTSWITH_SET("abc", "ax", "ab", "abc")); + assert_se(STARTSWITH_SET("abc", "ax", "abx", "abc")); + assert_se(!STARTSWITH_SET("abc", "ax", "abx", "abcx")); + + assert_se(streq_ptr(STARTSWITH_SET("foobar", "hhh", "kkk", "foo", "zzz"), "bar")); + assert_se(streq_ptr(STARTSWITH_SET("foobar", "hhh", "kkk", "", "zzz"), "foobar")); + assert_se(streq_ptr(STARTSWITH_SET("", "hhh", "kkk", "zzz", ""), "")); +} + static const char* const input_table_multiple[] = { "one", "two", @@ -847,6 +861,7 @@ int main(int argc, char *argv[]) { test_specifier_printf(); test_str_in_set(); test_strptr_in_set(); + test_startswith_set(); test_strv_foreach(); test_strv_foreach_backwards(); test_strv_foreach_pair(); diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 6eacfe811f..9c8e7f977f 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -57,6 +57,7 @@ #include "signal-util.h" #include "socket-util.h" #include "string-util.h" +#include "strv.h" #include "strxcpyx.h" #include "syslog-util.h" #include "udev-builtin.h" @@ -361,9 +362,7 @@ static int worker_lock_block_device(sd_device *dev, int *ret_fd) { if (r < 0) return log_device_debug_errno(dev, r, "Failed to get sysname: %m"); - if (startswith(val, "dm-") || - startswith(val, "md") || - startswith(val, "drbd")) + if (STARTSWITH_SET(val, "dm-", "md", "drbd")) return 0; r = sd_device_get_devtype(dev, &val);