From 6b783209a8b441996d9b130e2b8b3a8cce278c6f Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Fri, 6 Sep 2024 23:03:06 -0500 Subject: [PATCH 1/4] tree-wide: basename -> path_extract_filename --- src/analyze/analyze-verify-util.c | 11 +- src/core/load-dropin.c | 24 +++-- src/libsystemd/sd-bus/test-bus-watch-bind.c | 5 +- src/network/netdev/netdev.c | 8 +- src/network/networkd-network.c | 7 +- src/shared/unit-file.c | 18 ++-- src/systemctl/systemctl-show.c | 10 +- src/systemctl/systemctl-sysv-compat.c | 8 +- src/test/test-fileio.c | 67 +++++------- src/test/test-install-root.c | 6 +- src/test/test-install.c | 109 +++++++------------- src/test/test-mountpoint-util.c | 7 +- src/test/test-parse-argument.c | 6 +- src/test/test-path-util.c | 37 ++++--- src/udev/net/link-config.c | 8 +- 15 files changed, 173 insertions(+), 158 deletions(-) diff --git a/src/analyze/analyze-verify-util.c b/src/analyze/analyze-verify-util.c index 781b941d11..6c668222bd 100644 --- a/src/analyze/analyze-verify-util.c +++ b/src/analyze/analyze-verify-util.c @@ -361,9 +361,16 @@ int verify_units( * its direct dependencies. Hence, search for any of the filenames in the set and if found, * return a non-zero process exit status. */ if (recursive_errors == RECURSIVE_ERRORS_ONE) - STRV_FOREACH(filename, filenames) - if (set_contains(s, basename(*filename))) + STRV_FOREACH(filename, filenames) { + _cleanup_free_ char *unit_file = NULL; + + r = path_extract_filename(*filename, &unit_file); + if (r < 0) + return log_error_errno(r, "Failed to extract file name from '%s': %m", *filename); + + if (set_contains(s, unit_file)) return -ENOTRECOVERABLE; + } return 0; } diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c index a295d7f343..c9d7b9338e 100644 --- a/src/core/load-dropin.c +++ b/src/core/load-dropin.c @@ -7,6 +7,7 @@ #include "load-fragment.h" #include "log.h" #include "manager.h" +#include "path-util.h" #include "stat-util.h" #include "strv.h" #include "unit.h" @@ -37,10 +38,7 @@ static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suff return r; STRV_FOREACH(p, paths) { - _cleanup_free_ char *target = NULL; - const char *entry; - - entry = basename(*p); + _cleanup_free_ char *target = NULL, *target_file = NULL, *entry = NULL; if (null_or_empty_path(*p) > 0) { /* an error usually means an invalid symlink, which is not a mask */ @@ -61,6 +59,13 @@ static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suff continue; } + r = path_extract_filename(*p, &entry); + if (r < 0) { + log_unit_warning_errno(u, r, "Failed to extract file name of %s dependency dropin %s, ignoring: %m", + unit_dependency_to_string(dependency), *p); + continue; + } + if (!unit_name_is_valid(entry, UNIT_NAME_ANY)) { log_unit_warning(u, "%s dependency dropin %s is not a valid unit name, ignoring.", unit_dependency_to_string(dependency), *p); @@ -73,12 +78,19 @@ static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suff continue; } + r = path_extract_filename(target, &target_file); + if (r < 0) { + log_unit_warning_errno(u, r, "Failed to extract file name for dropin target %s, ignoring: %m", + target); + continue; + } + /* We don't treat this as an error, especially because we didn't check this for a * long time. Nevertheless, we warn, because such mismatch can be mighty confusing. */ - r = unit_symlink_name_compatible(entry, basename(target), u->instance); + r = unit_symlink_name_compatible(entry, target_file, u->instance); if (r < 0) { log_unit_warning_errno(u, r, "Can't check if names %s and %s are compatible, ignoring: %m", - entry, basename(target)); + entry, target_file); continue; } if (r == 0) diff --git a/src/libsystemd/sd-bus/test-bus-watch-bind.c b/src/libsystemd/sd-bus/test-bus-watch-bind.c index c6c072440e..ff4a2b1fce 100644 --- a/src/libsystemd/sd-bus/test-bus-watch-bind.c +++ b/src/libsystemd/sd-bus/test-bus-watch-bind.c @@ -44,7 +44,7 @@ static const sd_bus_vtable vtable[] = { }; static void* thread_server(void *p) { - _cleanup_free_ char *suffixed = NULL, *suffixed2 = NULL, *d = NULL; + _cleanup_free_ char *suffixed = NULL, *suffixed_basename = NULL, *suffixed2 = NULL, *d = NULL; _cleanup_close_ int fd = -EBADF; union sockaddr_union u; const char *path = p; @@ -67,7 +67,8 @@ static void* thread_server(void *p) { assert_se(symlink(suffixed2, d) >= 0); usleep_safe(100 * USEC_PER_MSEC); - assert_se(symlink(basename(suffixed), suffixed2) >= 0); + assert_se(path_extract_filename(suffixed, &suffixed_basename) >= 0); + assert_se(symlink(suffixed_basename, suffixed2) >= 0); usleep_safe(100 * USEC_PER_MSEC); socklen_t sa_len; diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index b99f3d31e3..d3e29c0c33 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -34,6 +34,7 @@ #include "networkd-sriov.h" #include "networkd-state-file.h" #include "nlmon.h" +#include "path-util.h" #include "stat-util.h" #include "string-table.h" #include "string-util.h" @@ -1000,6 +1001,7 @@ static int netdev_request_to_create(NetDev *netdev) { int netdev_load_one(Manager *manager, const char *filename, NetDev **ret) { _cleanup_(netdev_unrefp) NetDev *netdev_raw = NULL, *netdev = NULL; + _cleanup_free_ char *file_basename = NULL; const char *dropin_dirname; int r; @@ -1023,7 +1025,11 @@ int netdev_load_one(Manager *manager, const char *filename, NetDev **ret) { .state = _NETDEV_STATE_INVALID, /* an invalid state means done() of the implementation won't be called on destruction */ }; - dropin_dirname = strjoina(basename(filename), ".d"); + r = path_extract_filename(filename, &file_basename); + if (r < 0) + return log_warning_errno(r, "Failed to extract file name of '%s': %m", filename); + + dropin_dirname = strjoina(file_basename, ".d"); r = config_parse_many( STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname, /* root = */ NULL, NETDEV_COMMON_SECTIONS NETDEV_OTHER_SECTIONS, diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index c9805509cc..69fa1983da 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -28,6 +28,7 @@ #include "networkd-routing-policy-rule.h" #include "ordered-set.h" #include "parse-util.h" +#include "path-util.h" #include "qdisc.h" #include "radv-internal.h" #include "set.h" @@ -341,9 +342,9 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi if (!fname) return log_oom(); - name = strdup(basename(filename)); - if (!name) - return log_oom(); + r = path_extract_filename(filename, &name); + if (r < 0) + return log_warning_errno(r, "Failed to extract file name of \"%s\": %m", filename); d = strrchr(name, '.'); if (!d) diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c index 2833b5be68..b0d46d388a 100644 --- a/src/shared/unit-file.c +++ b/src/shared/unit-file.c @@ -572,17 +572,21 @@ int unit_file_build_name_map( /* Let's also put the names in the reverse db. */ const char *dummy, *src; HASHMAP_FOREACH_KEY(dummy, src, ids) { - _cleanup_free_ char *inst = NULL, *dst_inst = NULL; - const char *dst; + _cleanup_free_ char *inst = NULL, *dst = NULL; + const char *dst_path; - r = unit_ids_map_get(ids, src, &dst); + r = unit_ids_map_get(ids, src, &dst_path); if (r < 0) continue; - if (null_or_empty_path(dst) != 0) + if (null_or_empty_path(dst_path) != 0) continue; - dst = basename(dst); + r = path_extract_filename(dst_path, &dst); + if (r < 0) { + log_debug_errno(r, "Failed to extract file name from %s, ignoring: %m", dst_path); + continue; + } /* If we have an symlink from an instance name to a template name, it is an alias just for * this specific instance, foo@id.service ↔ template@id.service. */ @@ -591,6 +595,8 @@ int unit_file_build_name_map( if (t < 0) return log_error_errno(t, "Failed to extract instance part from %s: %m", src); if (t == UNIT_NAME_INSTANCE) { + _cleanup_free_ char *dst_inst = NULL; + r = unit_name_replace_instance(dst, inst, &dst_inst); if (r < 0) { /* This might happen e.g. if the combined length is too large. @@ -600,7 +606,7 @@ int unit_file_build_name_map( continue; } - dst = dst_inst; + free_and_replace(dst, dst_inst); } } diff --git a/src/systemctl/systemctl-show.c b/src/systemctl/systemctl-show.c index 207107c6a3..f6eeeb29c9 100644 --- a/src/systemctl/systemctl-show.c +++ b/src/systemctl/systemctl-show.c @@ -410,7 +410,7 @@ static void print_status_info( bool last = false; STRV_FOREACH(dropin, i->dropin_paths) { - _cleanup_free_ char *dropin_formatted = NULL; + _cleanup_free_ char *dropin_formatted = NULL, *dropin_basename = NULL; const char *df; if (!dir || last) { @@ -432,7 +432,13 @@ static void print_status_info( last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir)); - if (terminal_urlify_path(*dropin, basename(*dropin), &dropin_formatted) >= 0) + r = path_extract_filename(*dropin, &dropin_basename); + if (r < 0) { + log_error_errno(r, "Failed to extract file name of '%s': %m", *dropin); + break; + } + + if (terminal_urlify_path(*dropin, dropin_basename, &dropin_formatted) >= 0) df = dropin_formatted; else df = *dropin; diff --git a/src/systemctl/systemctl-sysv-compat.c b/src/systemctl/systemctl-sysv-compat.c index a872e94d8d..60e62d82d7 100644 --- a/src/systemctl/systemctl-sysv-compat.c +++ b/src/systemctl/systemctl-sysv-compat.c @@ -150,7 +150,7 @@ int enable_sysv_units(const char *verb, char **args) { NULL, }; - _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL, *v = NULL; + _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL, *v = NULL, *b = NULL; bool found_native = false, found_sysv; const char *name; unsigned c = 1; @@ -205,8 +205,12 @@ int enable_sysv_units(const char *verb, char **args) { if (!v) return log_oom(); + j = path_extract_filename(p, &b); + if (j < 0) + return log_error_errno(j, "Failed to extract file name from '%s': %m", p); + argv[c++] = v; - argv[c++] = basename(p); + argv[c++] = b; argv[c] = NULL; l = strv_join((char**)argv, " "); diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c index 744fb49427..aa68155fe6 100644 --- a/src/test/test-fileio.c +++ b/src/test/test-fileio.c @@ -534,7 +534,7 @@ TEST(search_and_fopen) { }; char name[] = "/tmp/test-search_and_fopen.XXXXXX"; _cleanup_fclose_ FILE *f = NULL; - _cleanup_free_ char *p = NULL; + _cleanup_free_ char *p = NULL, *bn = NULL; _cleanup_close_ int fd = -EBADF; const char *e; int r; @@ -543,59 +543,48 @@ TEST(search_and_fopen) { assert_se(fd >= 0); fd = safe_close(fd); - r = search_and_fopen(basename(name), "re", NULL, (const char**) dirs, &f, &p); - assert_se(r >= 0); + ASSERT_OK(path_extract_filename(name, &bn)); + ASSERT_OK(search_and_fopen(bn, "re", NULL, (const char**) dirs, &f, &p)); assert_se(e = path_startswith(p, "/tmp/")); - ASSERT_STREQ(basename(name), e); + ASSERT_STREQ(bn, e); f = safe_fclose(f); p = mfree(p); - r = search_and_fopen(basename(name), NULL, NULL, (const char**) dirs, NULL, &p); - assert_se(r >= 0); + ASSERT_OK(search_and_fopen(bn, NULL, NULL, (const char**) dirs, NULL, &p)); assert_se(e = path_startswith(p, "/tmp/")); - ASSERT_STREQ(basename(name), e); + ASSERT_STREQ(bn, e); p = mfree(p); - r = search_and_fopen(name, "re", NULL, (const char**) dirs, &f, &p); - assert_se(r >= 0); + ASSERT_OK(search_and_fopen(name, "re", NULL, (const char**) dirs, &f, &p)); assert_se(path_equal(name, p)); f = safe_fclose(f); p = mfree(p); - r = search_and_fopen(name, NULL, NULL, (const char**) dirs, NULL, &p); - assert_se(r >= 0); + ASSERT_OK(search_and_fopen(name, NULL, NULL, (const char**) dirs, NULL, &p)); assert_se(path_equal(name, p)); p = mfree(p); - r = search_and_fopen(basename(name), "re", "/", (const char**) dirs, &f, &p); - assert_se(r >= 0); + ASSERT_OK(search_and_fopen(bn, "re", "/", (const char**) dirs, &f, &p)); assert_se(e = path_startswith(p, "/tmp/")); - ASSERT_STREQ(basename(name), e); + ASSERT_STREQ(bn, e); f = safe_fclose(f); p = mfree(p); - r = search_and_fopen(basename(name), NULL, "/", (const char**) dirs, NULL, &p); - assert_se(r >= 0); + ASSERT_OK(search_and_fopen(bn, NULL, "/", (const char**) dirs, NULL, &p)); assert_se(e = path_startswith(p, "/tmp/")); - ASSERT_STREQ(basename(name), e); + ASSERT_STREQ(bn, e); p = mfree(p); - r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "re", NULL, (const char**) dirs, &f, &p); - assert_se(r == -ENOENT); - r = search_and_fopen("/a/file/which/does/not/exist/i/guess", NULL, NULL, (const char**) dirs, NULL, &p); - assert_se(r == -ENOENT); - r = search_and_fopen("afilewhichdoesnotexistiguess", "re", NULL, (const char**) dirs, &f, &p); - assert_se(r == -ENOENT); - r = search_and_fopen("afilewhichdoesnotexistiguess", NULL, NULL, (const char**) dirs, NULL, &p); - assert_se(r == -ENOENT); + ASSERT_ERROR(search_and_fopen("/a/file/which/does/not/exist/i/guess", "re", NULL, (const char**) dirs, &f, &p), ENOENT); + ASSERT_ERROR(search_and_fopen("/a/file/which/does/not/exist/i/guess", NULL, NULL, (const char**) dirs, NULL, &p), ENOENT); + ASSERT_ERROR(search_and_fopen("afilewhichdoesnotexistiguess", "re", NULL, (const char**) dirs, &f, &p), ENOENT); + ASSERT_ERROR(search_and_fopen("afilewhichdoesnotexistiguess", NULL, NULL, (const char**) dirs, NULL, &p), ENOENT); r = unlink(name); assert_se(r == 0); - r = search_and_fopen(basename(name), "re", NULL, (const char**) dirs, &f, &p); - assert_se(r == -ENOENT); - r = search_and_fopen(basename(name), NULL, NULL, (const char**) dirs, NULL, &p); - assert_se(r == -ENOENT); + ASSERT_ERROR(search_and_fopen(bn, "re", NULL, (const char**) dirs, &f, &p), ENOENT); + ASSERT_ERROR(search_and_fopen(bn, NULL, NULL, (const char**) dirs, NULL, &p), ENOENT); } TEST(search_and_fopen_nulstr) { @@ -605,7 +594,7 @@ TEST(search_and_fopen_nulstr) { _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-search_and_fopen.XXXXXX"; _cleanup_fclose_ FILE *f = NULL; - _cleanup_free_ char *p = NULL; + _cleanup_free_ char *p = NULL, *bn = NULL; _cleanup_close_ int fd = -EBADF; const char *e; int r; @@ -614,29 +603,25 @@ TEST(search_and_fopen_nulstr) { assert_se(fd >= 0); fd = safe_close(fd); - r = search_and_fopen_nulstr(basename(name), "re", NULL, dirs, &f, &p); - assert_se(r >= 0); + ASSERT_OK(path_extract_filename(name, &bn)); + ASSERT_OK(search_and_fopen_nulstr(bn, "re", NULL, dirs, &f, &p)); assert_se(e = path_startswith(p, "/tmp/")); - ASSERT_STREQ(basename(name), e); + ASSERT_STREQ(bn, e); f = safe_fclose(f); p = mfree(p); - r = search_and_fopen_nulstr(name, "re", NULL, dirs, &f, &p); - assert_se(r >= 0); + ASSERT_OK(search_and_fopen_nulstr(name, "re", NULL, dirs, &f, &p)); assert_se(path_equal(name, p)); f = safe_fclose(f); p = mfree(p); - r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "re", NULL, dirs, &f, &p); - assert_se(r == -ENOENT); - r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "re", NULL, dirs, &f, &p); - assert_se(r == -ENOENT); + ASSERT_ERROR(search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "re", NULL, dirs, &f, &p), ENOENT); + ASSERT_ERROR(search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "re", NULL, dirs, &f, &p), ENOENT); r = unlink(name); assert_se(r == 0); - r = search_and_fopen_nulstr(basename(name), "re", NULL, dirs, &f, &p); - assert_se(r == -ENOENT); + ASSERT_ERROR(search_and_fopen_nulstr(bn, "re", NULL, dirs, &f, &p), ENOENT); } TEST(writing_tmpfile) { diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c index 2f38694a05..a17198b935 100644 --- a/src/test/test-install-root.c +++ b/src/test/test-install-root.c @@ -7,6 +7,7 @@ #include "hashmap.h" #include "install.h" #include "mkdir.h" +#include "path-util.h" #include "rm-rf.h" #include "special.h" #include "string-util.h" @@ -706,7 +707,10 @@ TEST(preset_and_list) { q = strjoina(root, "/usr/lib/systemd/system/preset-no.service"); HASHMAP_FOREACH(fl, h) { - assert_se(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, basename(fl->path), &state) >= 0); + _cleanup_free_ char *unit_filename = NULL; + + ASSERT_OK(path_extract_filename(fl->path, &unit_filename)); + ASSERT_OK(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, unit_filename, &state)); assert_se(fl->state == state); if (streq(fl->path, p)) { diff --git a/src/test/test-install.c b/src/test/test-install.c index 45704064b2..9c6e9cba06 100644 --- a/src/test/test-install.c +++ b/src/test/test-install.c @@ -5,6 +5,7 @@ #include "hashmap.h" #include "install.h" +#include "path-util.h" #include "tests.h" static void dump_changes(InstallChange *c, unsigned n) { @@ -25,7 +26,9 @@ int main(int argc, char* argv[]) { UnitFileList *p; int r; const char *const files[] = { "avahi-daemon.service", NULL }; + const char *files_name = "avahi-daemon.service"; const char *const files2[] = { "/home/lennart/test.service", NULL }; + const char *files2_name = "test.service"; InstallChange *changes = NULL; size_t n_changes = 0; UnitFileState state = 0; @@ -36,8 +39,10 @@ int main(int argc, char* argv[]) { HASHMAP_FOREACH(p, h) { UnitFileState s = _UNIT_FILE_STATE_INVALID; + _cleanup_free_ char *unit_filename = NULL; - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, basename(p->path), &s); + ASSERT_OK(path_extract_filename(p->path, &unit_filename)); + r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, unit_filename, &s); assert_se((r < 0 && p->state == UNIT_FILE_BAD) || (p->state == s)); @@ -49,220 +54,186 @@ int main(int argc, char* argv[]) { log_info("/*** enable **/"); - r = unit_file_enable(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_enable(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes)); log_info("/*** enable2 **/"); - r = unit_file_enable(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_enable(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes)); dump_changes(changes, n_changes); install_changes_free(changes, n_changes); - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files[0], &state); - assert_se(r >= 0); + ASSERT_OK(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files[0], &state)); assert_se(state == UNIT_FILE_ENABLED); log_info("/*** disable ***/"); changes = NULL; n_changes = 0; - r = unit_file_disable(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_disable(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes)); dump_changes(changes, n_changes); install_changes_free(changes, n_changes); - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files[0], &state); - assert_se(r >= 0); + ASSERT_OK(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files[0], &state)); assert_se(state == UNIT_FILE_DISABLED); log_info("/*** mask ***/"); changes = NULL; n_changes = 0; - r = unit_file_mask(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_mask(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes)); log_info("/*** mask2 ***/"); - r = unit_file_mask(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_mask(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes)); dump_changes(changes, n_changes); install_changes_free(changes, n_changes); - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files[0], &state); - assert_se(r >= 0); + ASSERT_OK(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files[0], &state)); assert_se(state == UNIT_FILE_MASKED); log_info("/*** unmask ***/"); changes = NULL; n_changes = 0; - r = unit_file_unmask(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_unmask(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes)); log_info("/*** unmask2 ***/"); - r = unit_file_unmask(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_unmask(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes)); dump_changes(changes, n_changes); install_changes_free(changes, n_changes); - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files[0], &state); - assert_se(r >= 0); + ASSERT_OK(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files[0], &state)); assert_se(state == UNIT_FILE_DISABLED); log_info("/*** mask ***/"); changes = NULL; n_changes = 0; - r = unit_file_mask(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_mask(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes)); dump_changes(changes, n_changes); install_changes_free(changes, n_changes); - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files[0], &state); - assert_se(r >= 0); + ASSERT_OK(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files[0], &state)); assert_se(state == UNIT_FILE_MASKED); log_info("/*** disable ***/"); changes = NULL; n_changes = 0; - r = unit_file_disable(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_disable(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes)); log_info("/*** disable2 ***/"); - r = unit_file_disable(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_disable(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes)); dump_changes(changes, n_changes); install_changes_free(changes, n_changes); - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files[0], &state); - assert_se(r >= 0); + ASSERT_OK(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files[0], &state)); assert_se(state == UNIT_FILE_MASKED); log_info("/*** umask ***/"); changes = NULL; n_changes = 0; - r = unit_file_unmask(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_unmask(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes)); dump_changes(changes, n_changes); install_changes_free(changes, n_changes); - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files[0], &state); - assert_se(r >= 0); + ASSERT_OK(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files[0], &state)); assert_se(state == UNIT_FILE_DISABLED); log_info("/*** enable files2 ***/"); changes = NULL; n_changes = 0; - r = unit_file_enable(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_enable(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes)); dump_changes(changes, n_changes); install_changes_free(changes, n_changes); - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, basename(files2[0]), &state); - assert_se(r >= 0); + ASSERT_OK(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files2_name, &state)); assert_se(state == UNIT_FILE_ENABLED); log_info("/*** disable files2 ***/"); changes = NULL; n_changes = 0; - r = unit_file_disable(RUNTIME_SCOPE_SYSTEM, 0, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_disable(RUNTIME_SCOPE_SYSTEM, 0, NULL, STRV_MAKE(files2_name), &changes, &n_changes)); dump_changes(changes, n_changes); install_changes_free(changes, n_changes); - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, basename(files2[0]), &state); - assert_se(r < 0); + ASSERT_FAIL(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files2_name, &state)); log_info("/*** link files2 ***/"); changes = NULL; n_changes = 0; - r = unit_file_link(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_link(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes)); dump_changes(changes, n_changes); install_changes_free(changes, n_changes); - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, basename(files2[0]), &state); - assert_se(r >= 0); + ASSERT_OK(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files2_name, &state)); assert_se(state == UNIT_FILE_LINKED); log_info("/*** disable files2 ***/"); changes = NULL; n_changes = 0; - r = unit_file_disable(RUNTIME_SCOPE_SYSTEM, 0, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_disable(RUNTIME_SCOPE_SYSTEM, 0, NULL, STRV_MAKE(files2_name), &changes, &n_changes)); dump_changes(changes, n_changes); install_changes_free(changes, n_changes); - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, basename(files2[0]), &state); - assert_se(r < 0); + ASSERT_FAIL(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files2_name, &state)); log_info("/*** link files2 ***/"); changes = NULL; n_changes = 0; - r = unit_file_link(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_link(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes)); dump_changes(changes, n_changes); install_changes_free(changes, n_changes); - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, basename(files2[0]), &state); - assert_se(r >= 0); + ASSERT_OK(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files2_name, &state)); assert_se(state == UNIT_FILE_LINKED); log_info("/*** reenable files2 ***/"); changes = NULL; n_changes = 0; - r = unit_file_reenable(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_reenable(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes)); dump_changes(changes, n_changes); install_changes_free(changes, n_changes); - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, basename(files2[0]), &state); - assert_se(r >= 0); + ASSERT_OK(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files2_name, &state)); assert_se(state == UNIT_FILE_ENABLED); log_info("/*** disable files2 ***/"); changes = NULL; n_changes = 0; - r = unit_file_disable(RUNTIME_SCOPE_SYSTEM, 0, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_disable(RUNTIME_SCOPE_SYSTEM, 0, NULL, STRV_MAKE(files2_name), &changes, &n_changes)); dump_changes(changes, n_changes); install_changes_free(changes, n_changes); - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, basename(files2[0]), &state); - assert_se(r < 0); + ASSERT_FAIL(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files2_name, &state)); log_info("/*** preset files ***/"); changes = NULL; n_changes = 0; - r = unit_file_preset(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, UNIT_FILE_PRESET_FULL, &changes, &n_changes); - assert_se(r >= 0); + ASSERT_OK(unit_file_preset(RUNTIME_SCOPE_SYSTEM, 0, NULL, (char**) files, UNIT_FILE_PRESET_FULL, &changes, &n_changes)); dump_changes(changes, n_changes); install_changes_free(changes, n_changes); - r = unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, basename(files[0]), &state); - assert_se(r >= 0); + ASSERT_OK(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, NULL, files_name, &state)); assert_se(state == UNIT_FILE_ENABLED); return 0; diff --git a/src/test/test-mountpoint-util.c b/src/test/test-mountpoint-util.c index ee2d21825a..ceb59ce455 100644 --- a/src/test/test-mountpoint-util.c +++ b/src/test/test-mountpoint-util.c @@ -274,7 +274,7 @@ TEST(path_is_mount_point) { TEST(is_mount_point_at) { _cleanup_(rm_rf_physical_and_freep) char *tmpdir = NULL; - _cleanup_free_ char *pwd = NULL; + _cleanup_free_ char *pwd = NULL, *tmpdir_basename = NULL; _cleanup_close_ int fd = -EBADF; int r; @@ -299,8 +299,9 @@ TEST(is_mount_point_at) { assert_se(fd >= 0); assert_se(mkdtemp_malloc("/tmp/not-mounted-XXXXXX", &tmpdir) >= 0); - assert_se(is_mount_point_at(fd, basename(tmpdir), 0) == 0); - assert_se(is_mount_point_at(fd, strjoina(basename(tmpdir), "/"), 0) == 0); + ASSERT_OK(path_extract_filename(tmpdir, &tmpdir_basename)); + ASSERT_OK_ZERO(is_mount_point_at(fd, tmpdir_basename, 0)); + ASSERT_OK_ZERO(is_mount_point_at(fd, strjoina(tmpdir_basename, "/"), 0)); safe_close(fd); fd = open("/proc", O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY); diff --git a/src/test/test-parse-argument.c b/src/test/test-parse-argument.c index d3d88cf0d1..843179b666 100644 --- a/src/test/test-parse-argument.c +++ b/src/test/test-parse-argument.c @@ -5,6 +5,7 @@ #include "sd-json.h" #include "parse-argument.h" +#include "path-util.h" #include "stdio-util.h" #include "tests.h" @@ -19,10 +20,11 @@ TEST(parse_json_argument) { } TEST(parse_path_argument) { - _cleanup_free_ char *path = NULL; + _cleanup_free_ char *path = NULL, *file = NULL; assert_se(parse_path_argument("help", false, &path) == 0); - ASSERT_STREQ(basename(path), "help"); + ASSERT_OK(path_extract_filename(path, &file)); + ASSERT_STREQ(file, "help"); assert_se(parse_path_argument("/", false, &path) == 0); ASSERT_STREQ(path, "/"); diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 5928b2520d..ea025cb135 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -26,11 +26,6 @@ TEST(path) { assert_se( path_is_absolute("/")); assert_se(!path_is_absolute("./")); - ASSERT_STREQ(basename("./aa/bb/../file.da."), "file.da."); - ASSERT_STREQ(basename("/aa///.file"), ".file"); - ASSERT_STREQ(basename("/aa///file..."), "file..."); - ASSERT_STREQ(basename("file.../"), ""); - assert_se( PATH_IN_SET("/bin", "/", "/bin", "/foo")); assert_se( PATH_IN_SET("/bin", "/bin")); assert_se( PATH_IN_SET("/bin", "/foo/bar", "/bin")); @@ -372,20 +367,24 @@ TEST(path_equal_root) { } TEST(find_executable_full) { - char *p; - char* test_file_name; + char *p, *bp; + _cleanup_free_ char *test_file_name = NULL; _cleanup_close_ int fd = -EBADF; char fn[] = "/tmp/test-XXXXXX"; assert_se(find_executable_full("sh", NULL, NULL, true, &p, NULL) == 0); puts(p); - ASSERT_STREQ(basename(p), "sh"); + ASSERT_OK(path_extract_filename(p, &bp)); + ASSERT_STREQ(bp, "sh"); free(p); + free(bp); assert_se(find_executable_full("sh", NULL, NULL, false, &p, NULL) == 0); puts(p); - ASSERT_STREQ(basename(p), "sh"); + ASSERT_OK(path_extract_filename(p, &bp)); + ASSERT_STREQ(bp, "sh"); free(p); + free(bp); _cleanup_free_ char *oldpath = NULL; p = getenv("PATH"); @@ -396,21 +395,25 @@ TEST(find_executable_full) { assert_se(find_executable_full("sh", NULL, NULL, true, &p, NULL) == 0); puts(p); - ASSERT_STREQ(basename(p), "sh"); + ASSERT_OK(path_extract_filename(p, &bp)); + ASSERT_STREQ(bp, "sh"); free(p); + free(bp); assert_se(find_executable_full("sh", NULL, NULL, false, &p, NULL) == 0); puts(p); - ASSERT_STREQ(basename(p), "sh"); + ASSERT_OK(path_extract_filename(p, &bp)); + ASSERT_STREQ(bp, "sh"); free(p); + free(bp); if (oldpath) - assert_se(setenv("PATH", oldpath, true) >= 0); + ASSERT_OK_ERRNO(setenv("PATH", oldpath, true)); - assert_se((fd = mkostemp_safe(fn)) >= 0); - assert_se(fchmod(fd, 0755) >= 0); + ASSERT_OK(fd = mkostemp_safe(fn)); + ASSERT_OK_ERRNO(fchmod(fd, 0755)); - test_file_name = basename(fn); + ASSERT_OK(path_extract_filename(fn, &test_file_name)); assert_se(find_executable_full(test_file_name, NULL, STRV_MAKE("/doesnotexist", "/tmp", "/bin"), false, &p, NULL) == 0); puts(p); @@ -423,6 +426,7 @@ TEST(find_executable_full) { TEST(find_executable) { char *p; + _cleanup_free_ char *bp = NULL; assert_se(find_executable("/bin/sh", &p) == 0); puts(p); @@ -447,7 +451,8 @@ TEST(find_executable) { assert_se(find_executable("touch", &p) == 0); assert_se(path_is_absolute(p)); - ASSERT_STREQ(basename(p), "touch"); + ASSERT_OK(path_extract_filename(p, &bp)); + ASSERT_STREQ(bp, "touch"); free(p); assert_se(find_executable("xxxx-xxxx", &p) == -ENOENT); diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 7437c9561f..831575666d 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -230,7 +230,7 @@ static int link_adjust_wol_options(LinkConfig *config) { int link_load_one(LinkConfigContext *ctx, const char *filename) { _cleanup_(link_config_freep) LinkConfig *config = NULL; _cleanup_hashmap_free_ Hashmap *stats_by_path = NULL; - _cleanup_free_ char *name = NULL; + _cleanup_free_ char *name = NULL, *file_basename = NULL; const char *dropin_dirname; int r; @@ -276,7 +276,11 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) { FOREACH_ELEMENT(feature, config->features) *feature = -1; - dropin_dirname = strjoina(basename(filename), ".d"); + r = path_extract_filename(filename, &file_basename); + if (r < 0) + return log_error_errno(r, "Failed to extract file name of '%s': %m", filename); + + dropin_dirname = strjoina(file_basename, ".d"); r = config_parse_many( STRV_MAKE_CONST(filename), NETWORK_DIRS, From 59829bb37a44a01c4394301fd65478037e6b01d8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 6 Jun 2025 18:53:16 +0900 Subject: [PATCH 2/4] delta: rework how enumerate files --- src/delta/delta.c | 105 ++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 56 deletions(-) diff --git a/src/delta/delta.c b/src/delta/delta.c index 337472f276..694f3f1fe6 100644 --- a/src/delta/delta.c +++ b/src/delta/delta.c @@ -186,11 +186,43 @@ DEFINE_PRIVATE_HASH_OPS_FULL( char, string_hash_func, string_compare_func, free, OrderedHashmap, ordered_hashmap_free); +static int path_put(OrderedHashmap **h, const char *dir_path, const char *filename, bool override) { + int r; + + assert(h); + assert(dir_path); + assert(filename); + + if (override) { + _unused_ _cleanup_free_ char *old = NULL; + free(ordered_hashmap_remove2(*h, filename, (void**) &old)); + } else if (ordered_hashmap_contains(*h, filename)) + return 0; + + _cleanup_free_ char *p = path_join(dir_path, filename); + if (!p) + return -ENOMEM; + + _cleanup_free_ char *f = strdup(filename); + if (!f) + return -ENOMEM; + + r = ordered_hashmap_ensure_put(h, &path_hash_ops_free_free, f, p); + if (r < 0) + return r; + assert(r > 0); + + TAKE_PTR(f); + TAKE_PTR(p); + return 1; +} + static int enumerate_dir_d( OrderedHashmap **top, OrderedHashmap **bottom, OrderedHashmap **drops, - const char *toppath, const char *drop) { + const char *toppath, + const char *drop) { _cleanup_free_ char *unit = NULL; _cleanup_free_ char *path = NULL; @@ -222,41 +254,23 @@ static int enumerate_dir_d( strv_sort(list); STRV_FOREACH(file, list) { - OrderedHashmap *h; - char *p; - char *d; if (!endswith(*file, ".conf")) continue; - p = path_join(path, *file); - if (!p) - return -ENOMEM; - d = p + strlen(toppath) + 1; - - log_debug("Adding at top: %s %s %s", d, glyph(GLYPH_ARROW_RIGHT), p); - r = ordered_hashmap_ensure_put(top, &string_hash_ops_value_free, d, p); - if (r >= 0) { - p = strdup(p); - if (!p) - return -ENOMEM; - d = p + strlen(toppath) + 1; - } else if (r != -EEXIST) { - free(p); + log_debug("Adding at top: %s %s %s/%s", *file, glyph(GLYPH_ARROW_RIGHT), path, *file); + r = path_put(top, path, *file, /* override = */ false); + if (r < 0) return r; - } - log_debug("Adding at bottom: %s %s %s", d, glyph(GLYPH_ARROW_RIGHT), p); - free(ordered_hashmap_remove(*bottom, d)); - r = ordered_hashmap_ensure_put(bottom, &string_hash_ops_value_free, d, p); - if (r < 0) { - free(p); + log_debug("Adding at bottom: %s %s %s/%s", *file, glyph(GLYPH_ARROW_RIGHT), path, *file); + r = path_put(bottom, path, *file, /* override = */ true); + if (r < 0) return r; - } - h = ordered_hashmap_get(*drops, unit); + OrderedHashmap *h = ordered_hashmap_get(*drops, unit); if (!h) { - h = ordered_hashmap_new(&string_hash_ops_value_free); + h = ordered_hashmap_new(&path_hash_ops_free_free); if (!h) return -ENOMEM; r = ordered_hashmap_ensure_put(drops, &drop_hash_ops, unit, h); @@ -269,18 +283,9 @@ static int enumerate_dir_d( return -ENOMEM; } - p = strdup(p); - if (!p) - return -ENOMEM; - - log_debug("Adding to drops: %s %s %s %s %s", - unit, glyph(GLYPH_ARROW_RIGHT), basename(p), glyph(GLYPH_ARROW_RIGHT), p); - r = ordered_hashmap_put(h, basename(p), p); - if (r < 0) { - free(p); - if (r != -EEXIST) - return r; - } + log_debug("Adding to drops: %s %s %s %s %s/%s", + unit, glyph(GLYPH_ARROW_RIGHT), *file, glyph(GLYPH_ARROW_RIGHT), path, *file); + r = path_put(&h, path, *file, /* override = */ false); } return 0; } @@ -344,27 +349,15 @@ static int enumerate_dir( } STRV_FOREACH(t, files) { - _cleanup_free_ char *p = NULL; - - p = path_join(path, *t); - if (!p) - return -ENOMEM; - - log_debug("Adding at top: %s %s %s", basename(p), glyph(GLYPH_ARROW_RIGHT), p); - r = ordered_hashmap_ensure_put(top, &string_hash_ops_value_free, basename(p), p); - if (r >= 0) { - p = strdup(p); - if (!p) - return -ENOMEM; - } else if (r != -EEXIST) + log_debug("Adding at top: %s %s %s/%s", *t, glyph(GLYPH_ARROW_RIGHT), path, *t); + r = path_put(top, path, *t, /* override = */ false); + if (r < 0) return r; - log_debug("Adding at bottom: %s %s %s", basename(p), glyph(GLYPH_ARROW_RIGHT), p); - free(ordered_hashmap_remove(*bottom, basename(p))); - r = ordered_hashmap_ensure_put(bottom, &string_hash_ops_value_free, basename(p), p); + log_debug("Adding at bottom: %s %s %s/%s", *t, glyph(GLYPH_ARROW_RIGHT), path, *t); + r = path_put(bottom, path, *t, /* override = */ true); if (r < 0) return r; - p = NULL; } return 0; From 44875628ff4982cf5bebbc06fea60e7e87a586c2 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 6 Jun 2025 19:00:15 +0900 Subject: [PATCH 3/4] systemctl: replace basename() with path_extract_filename() --- src/systemctl/systemctl-list-unit-files.c | 42 +++++++++++++++++------ 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/systemctl/systemctl-list-unit-files.c b/src/systemctl/systemctl-list-unit-files.c index bd42fb7a30..5759cf6367 100644 --- a/src/systemctl/systemctl-list-unit-files.c +++ b/src/systemctl/systemctl-list-unit-files.c @@ -12,6 +12,7 @@ #include "format-table.h" #include "hashmap.h" #include "install.h" +#include "path-util.h" #include "sort-util.h" #include "string-util.h" #include "strv.h" @@ -21,25 +22,43 @@ static int compare_unit_file_list(const UnitFileList *a, const UnitFileList *b) { const char *d1, *d2; + int r, s; + + assert(a); + assert(a->path); + assert(b); + assert(b->path); d1 = strrchr(a->path, '.'); d2 = strrchr(b->path, '.'); if (d1 && d2) { - int r; - r = strcasecmp(d1, d2); if (r != 0) return r; } - return strcasecmp(basename(a->path), basename(b->path)); + _cleanup_free_ char *f1 = NULL, *f2 = NULL; + r = path_extract_filename(a->path, &f1); + s = path_extract_filename(b->path, &f2); + if (r < 0 || s < 0) + return CMP(r, s); + + return strcasecmp(f1, f2); } -static bool output_show_unit_file(const UnitFileList *u, char **states, char **patterns) { - assert(u); +static int output_show_unit_file(const UnitFileList *u, char **states, char **patterns) { + int r; - if (!strv_fnmatch_or_empty(patterns, basename(u->path), FNM_NOESCAPE)) + assert(u); + assert(u->path); + + _cleanup_free_ char *id = NULL; + r = path_extract_filename(u->path, &id); + if (r < 0) + return log_debug_errno(r, "Failed to extract unit name from path %s: %m", u->path); + + if (!strv_fnmatch_or_empty(patterns, id, FNM_NOESCAPE)) return false; if (!strv_isempty(arg_types)) { @@ -91,7 +110,7 @@ static int output_unit_file_list(const UnitFileList *units, unsigned c) { table_set_ersatz_string(table, TABLE_ERSATZ_DASH); FOREACH_ARRAY(u, units, c) { - const char *on_underline = NULL, *on_unit_color = NULL, *id; + const char *on_underline = NULL, *on_unit_color = NULL; bool underline; underline = u + 1 < units + c && @@ -113,7 +132,10 @@ static int output_unit_file_list(const UnitFileList *units, unsigned c) { else on_unit_color = on_underline; - id = basename(u->path); + _cleanup_free_ char *id = NULL; + r = path_extract_filename(u->path, &id); + if (r < 0) + return log_error_errno(r, "Failed to extract unit name from path %s: %m", u->path); r = table_add_many(table, TABLE_STRING, id, @@ -173,7 +195,7 @@ int verb_list_unit_files(int argc, char *argv[], void *userdata) { UnitFileList *u; HASHMAP_FOREACH(u, h) { - if (!output_show_unit_file(u, NULL, NULL)) + if (output_show_unit_file(u, NULL, NULL) <= 0) continue; units[c++] = *u; @@ -246,7 +268,7 @@ int verb_list_unit_files(int argc, char *argv[], void *userdata) { if (output_show_unit_file(&units[c], fallback ? arg_states : NULL, - fallback ? strv_skip(argv, 1) : NULL)) + fallback ? strv_skip(argv, 1) : NULL) > 0) c++; } if (r < 0) From b1bfa60254423034b3508c19742c388b122ae6ef Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 6 Jun 2025 19:09:49 +0900 Subject: [PATCH 4/4] TODO: drop completed entry --- TODO | 2 -- 1 file changed, 2 deletions(-) diff --git a/TODO b/TODO index 5878234e3e..e959bf5d22 100644 --- a/TODO +++ b/TODO @@ -66,8 +66,6 @@ Janitorial Clean-ups: * rework mount.c and swap.c to follow proper state enumeration/deserialization semantics, like we do for device.c now -* get rid of basename() and replace by path_extract_filename() - * Replace our fstype_is_network() with a call to libmount's mnt_fstype_is_netfs()? Having two lists is not nice, but maybe it's now worth making a dependency on libmount for something so trivial.