diff --git a/man/rules/meson.build b/man/rules/meson.build index 80412269c7..c702d88f74 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -241,6 +241,8 @@ manpages = [ 'sd_bus_error_free', 'sd_bus_error_get_errno', 'sd_bus_error_has_name', + 'sd_bus_error_has_names', + 'sd_bus_error_has_names_sentinel', 'sd_bus_error_is_set', 'sd_bus_error_move', 'sd_bus_error_set', diff --git a/man/sd_bus_error.xml b/man/sd_bus_error.xml index 8616f7ee43..3ce375bb2b 100644 --- a/man/sd_bus_error.xml +++ b/man/sd_bus_error.xml @@ -31,6 +31,8 @@ sd_bus_error_move sd_bus_error_is_set sd_bus_error_has_name + sd_bus_error_has_names_sentinel + sd_bus_error_has_names sd-bus error handling @@ -128,6 +130,16 @@ const sd_bus_error *e const char *name + + + int sd_bus_error_has_names_sentinel + const sd_bus_error *e + ... + + + + #define sd_bus_error_has_names(e, ...) sd_bus_error_has_names_sentinel(e, ..., NULL) + @@ -268,6 +280,12 @@ name has been set, false otherwise. + sd_bus_error_has_names_sentinel() is similar to + sd_bus_error_has_name(), but takes multiple names to check against. The list must be + terminated with NULL. sd_bus_error_has_names() + is a macro wrapper around sd_bus_error_has_names_sentinel() that adds the + NULL sentinel automatically. + sd_bus_error_free() will destroy resources held by e. The parameter itself will not be deallocated, and must be name field are non-NULL, zero otherwise. - sd_bus_error_has_name() returns a - non-zero value when e is - non-NULL and the - name field is equal to - name, zero otherwise. + sd_bus_error_has_name(), sd_bus_error_has_names(), and + sd_bus_error_has_names_sentinel() return a non-zero value when e is + non-NULL and the name field is equal to one of the given + names, zero otherwise. diff --git a/src/home/pam_systemd_home.c b/src/home/pam_systemd_home.c index 2c2c7a0819..13b164ecfc 100644 --- a/src/home/pam_systemd_home.c +++ b/src/home/pam_systemd_home.c @@ -7,6 +7,7 @@ #include "bus-common-errors.h" #include "bus-locator.h" +#include "bus-util.h" #include "errno-util.h" #include "fd-util.h" #include "home-util.h" @@ -153,8 +154,7 @@ static int acquire_user_record( r = bus_call_method(bus, bus_home_mgr, "GetUserRecordByName", &error, &reply, "s", username); if (r < 0) { - if (sd_bus_error_has_name(&error, SD_BUS_ERROR_SERVICE_UNKNOWN) || - sd_bus_error_has_name(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER)) { + if (bus_error_is_unknown_service(&error)) { pam_syslog(handle, LOG_DEBUG, "systemd-homed is not available: %s", bus_error_message(&error, r)); goto user_unknown; } diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 3168a4dcc4..e2b0d118b0 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -727,3 +727,8 @@ global: sd_event_add_time_relative; sd_event_source_set_time_relative; } LIBSYSTEMD_246; + +LIBSYSTEMD_248 { +global: + sd_bus_error_has_names_sentinel; +} LIBSYSTEMD_247; diff --git a/src/libsystemd/sd-bus/bus-error.c b/src/libsystemd/sd-bus/bus-error.c index f760f0fdd2..63f5097161 100644 --- a/src/libsystemd/sd-bus/bus-error.c +++ b/src/libsystemd/sd-bus/bus-error.c @@ -13,6 +13,7 @@ #include "errno-list.h" #include "errno-util.h" #include "string-util.h" +#include "strv.h" #include "util.h" BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = { @@ -355,11 +356,23 @@ _public_ int sd_bus_error_has_name(const sd_bus_error *e, const char *name) { return streq_ptr(e->name, name); } -_public_ int sd_bus_error_get_errno(const sd_bus_error* e) { - if (!e) +_public_ int sd_bus_error_has_names_sentinel(const sd_bus_error *e, ...) { + if (!e || !e->name) return 0; - if (!e->name) + va_list ap; + const char *p; + + va_start(ap, e); + while ((p = va_arg(ap, const char *))) + if (streq(p, e->name)) + break; + va_end(ap); + return !!p; +} + +_public_ int sd_bus_error_get_errno(const sd_bus_error* e) { + if (!e || !e->name) return 0; return bus_error_name_to_errno(e->name); diff --git a/src/libsystemd/sd-bus/test-bus-error.c b/src/libsystemd/sd-bus/test-bus-error.c index cb5d620993..52d30c85ad 100644 --- a/src/libsystemd/sd-bus/test-bus-error.c +++ b/src/libsystemd/sd-bus/test-bus-error.c @@ -22,6 +22,11 @@ static void test_error(void) { assert_se(streq(error.name, SD_BUS_ERROR_NOT_SUPPORTED)); assert_se(streq(error.message, "xxx")); assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_NOT_SUPPORTED)); + assert_se(sd_bus_error_has_names_sentinel(&error, SD_BUS_ERROR_NOT_SUPPORTED, NULL)); + assert_se(sd_bus_error_has_names(&error, SD_BUS_ERROR_NOT_SUPPORTED)); + assert_se(sd_bus_error_has_names(&error, SD_BUS_ERROR_NOT_SUPPORTED, SD_BUS_ERROR_FILE_NOT_FOUND)); + assert_se(sd_bus_error_has_names(&error, SD_BUS_ERROR_FILE_NOT_FOUND, SD_BUS_ERROR_NOT_SUPPORTED, NULL)); + assert_se(!sd_bus_error_has_names(&error, SD_BUS_ERROR_FILE_NOT_FOUND)); assert_se(sd_bus_error_get_errno(&error) == EOPNOTSUPP); assert_se(sd_bus_error_is_set(&error)); sd_bus_error_free(&error); @@ -32,6 +37,7 @@ static void test_error(void) { assert_se(error.name == NULL); assert_se(error.message == NULL); assert_se(!sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND)); + assert_se(!sd_bus_error_has_names(&error, SD_BUS_ERROR_FILE_NOT_FOUND)); assert_se(sd_bus_error_get_errno(&error) == 0); assert_se(!sd_bus_error_is_set(&error)); @@ -39,6 +45,7 @@ static void test_error(void) { assert_se(streq(error.name, SD_BUS_ERROR_FILE_NOT_FOUND)); assert_se(streq(error.message, "yyy -1")); assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND)); + assert_se(sd_bus_error_has_names(&error, SD_BUS_ERROR_FILE_NOT_FOUND)); assert_se(sd_bus_error_get_errno(&error) == ENOENT); assert_se(sd_bus_error_is_set(&error)); @@ -51,6 +58,7 @@ static void test_error(void) { assert_se(streq(error.message, second.message)); assert_se(sd_bus_error_get_errno(&second) == ENOENT); assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_NOT_FOUND)); + assert_se(sd_bus_error_has_names(&second, SD_BUS_ERROR_FILE_NOT_FOUND)); assert_se(sd_bus_error_is_set(&second)); sd_bus_error_free(&error); diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 40e9790159..d883288b25 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -4093,8 +4093,8 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c &reply, "ss", unit, "fail"); if (r < 0) { - if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) || - sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) { + if (sd_bus_error_has_names(error, BUS_ERROR_NO_SUCH_UNIT, + BUS_ERROR_LOAD_FAILED)) { *job = NULL; sd_bus_error_free(error); @@ -4129,9 +4129,9 @@ int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *ret NULL, NULL); if (r < 0) { - if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) || - sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED) || - sd_bus_error_has_name(&error, BUS_ERROR_SCOPE_NOT_RUNNING)) + if (sd_bus_error_has_names(&error, BUS_ERROR_NO_SUCH_UNIT, + BUS_ERROR_LOAD_FAILED, + BUS_ERROR_SCOPE_NOT_RUNNING)) return 0; sd_bus_error_move(ret_error, &error); @@ -4180,14 +4180,14 @@ int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *ret if (r < 0) { /* systemd might have dropped off momentarily, let's * not make this an error */ - if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || - sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) + if (sd_bus_error_has_names(&error, SD_BUS_ERROR_NO_REPLY, + SD_BUS_ERROR_DISCONNECTED)) return true; /* If the unit is already unloaded then it's not * active */ - if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) || - sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED)) + if (sd_bus_error_has_names(&error, BUS_ERROR_NO_SUCH_UNIT, + BUS_ERROR_LOAD_FAILED)) return false; sd_bus_error_move(ret_error, &error); @@ -4219,8 +4219,8 @@ int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *ret_ &reply, "s"); if (r < 0) { - if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || - sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) + if (sd_bus_error_has_names(&error, SD_BUS_ERROR_NO_REPLY, + SD_BUS_ERROR_DISCONNECTED)) return true; if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT)) diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index 467f16b72a..9efae8e19c 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -1464,8 +1464,8 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c r = bus_call_method(manager->bus, bus_systemd_mgr, "StopUnit", error, &reply, "ss", unit, "fail"); if (r < 0) { - if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) || - sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) { + if (sd_bus_error_has_names(error, BUS_ERROR_NO_SUCH_UNIT, + BUS_ERROR_LOAD_FAILED)) { if (job) *job = NULL; @@ -1526,12 +1526,12 @@ int manager_unit_is_active(Manager *manager, const char *unit) { &reply, "s"); if (r < 0) { - if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || - sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) + if (sd_bus_error_has_names(&error, SD_BUS_ERROR_NO_REPLY, + SD_BUS_ERROR_DISCONNECTED)) return true; - if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) || - sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED)) + if (sd_bus_error_has_names(&error, BUS_ERROR_NO_SUCH_UNIT, + BUS_ERROR_LOAD_FAILED)) return false; return r; @@ -1562,8 +1562,8 @@ int manager_job_is_active(Manager *manager, const char *path) { &reply, "s"); if (r < 0) { - if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || - sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) + if (sd_bus_error_has_names(&error, SD_BUS_ERROR_NO_REPLY, + SD_BUS_ERROR_DISCONNECTED)) return true; if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT)) diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 48182e61dd..2178b5799e 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -510,8 +510,8 @@ static int acquire_link_bitrates(sd_bus *bus, LinkInfo *link) { r = link_get_property(bus, link, &error, &reply, "org.freedesktop.network1.Link", "BitRates"); if (r < 0) { - bool quiet = sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_PROPERTY) || - sd_bus_error_has_name(&error, BUS_ERROR_SPEED_METER_INACTIVE); + bool quiet = sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_PROPERTY, + BUS_ERROR_SPEED_METER_INACTIVE); return log_full_errno(quiet ? LOG_DEBUG : LOG_WARNING, r, "Failed to query link bit rates: %s", bus_error_message(&error, r)); diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c index 43ab521635..a3416c83c8 100644 --- a/src/nss-resolve/nss-resolve.c +++ b/src/nss-resolve/nss-resolve.c @@ -23,12 +23,14 @@ NSS_GETHOSTBYNAME_PROTOTYPES(resolve); NSS_GETHOSTBYADDR_PROTOTYPES(resolve); static bool bus_error_shall_fallback(sd_bus_error *e) { - return sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) || - sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER) || - sd_bus_error_has_name(e, SD_BUS_ERROR_NO_REPLY) || - sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED) || - sd_bus_error_has_name(e, SD_BUS_ERROR_DISCONNECTED) || - sd_bus_error_has_name(e, SD_BUS_ERROR_TIMEOUT); + return sd_bus_error_has_names(e, + SD_BUS_ERROR_SERVICE_UNKNOWN, + SD_BUS_ERROR_NAME_HAS_NO_OWNER, + SD_BUS_ERROR_NO_REPLY, + SD_BUS_ERROR_ACCESS_DENIED, + SD_BUS_ERROR_DISCONNECTED, + SD_BUS_ERROR_TIMEOUT, + BUS_ERROR_NO_SUCH_UNIT); } static int count_addresses(sd_bus_message *m, int af, const char **canonical) { diff --git a/src/shared/bus-polkit.c b/src/shared/bus-polkit.c index 9b0a4552be..0722b1a118 100644 --- a/src/shared/bus-polkit.c +++ b/src/shared/bus-polkit.c @@ -3,6 +3,7 @@ #include "bus-internal.h" #include "bus-message.h" #include "bus-polkit.h" +#include "bus-util.h" #include "strv.h" #include "user-util.h" @@ -123,7 +124,7 @@ int bus_test_polkit( r = sd_bus_call(call->bus, request, 0, ret_error, &reply); if (r < 0) { /* Treat no PK available as access denied */ - if (sd_bus_error_has_name(ret_error, SD_BUS_ERROR_SERVICE_UNKNOWN)) { + if (bus_error_is_unknown_service(ret_error)) { sd_bus_error_free(ret_error); return -EACCES; } @@ -296,8 +297,7 @@ int bus_verify_polkit_async( e = sd_bus_message_get_error(q->reply); /* Treat no PK available as access denied */ - if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) || - sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER)) + if (bus_error_is_unknown_service(e)) return -EACCES; /* Copy error from polkit reply */ diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 77c1c62182..9a306daa03 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -14,14 +14,13 @@ #include "sd-event.h" #include "sd-id128.h" -/* #include "alloc-util.h" */ +#include "bus-common-errors.h" #include "bus-internal.h" #include "bus-label.h" #include "bus-util.h" #include "path-util.h" #include "socket-util.h" #include "stdio-util.h" -/* #include "string-util.h" */ static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { sd_event *e = userdata; @@ -153,6 +152,13 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) { return has_owner; } +bool bus_error_is_unknown_service(const sd_bus_error *error) { + return sd_bus_error_has_names(error, + SD_BUS_ERROR_SERVICE_UNKNOWN, + SD_BUS_ERROR_NAME_HAS_NO_OWNER, + BUS_ERROR_NO_SUCH_UNIT); +} + int bus_check_peercred(sd_bus *c) { struct ucred ucred; int fd, r; diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index d98e0040f3..9b86f9526e 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -28,6 +28,7 @@ typedef bool (*check_idle_t)(void *userdata); int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout, check_idle_t check_idle, void *userdata); int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error); +bool bus_error_is_unknown_service(const sd_bus_error *error); int bus_check_peercred(sd_bus *c); diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c index 7029352ca5..cf7e238ad4 100644 --- a/src/sleep/sleep.c +++ b/src/sleep/sleep.c @@ -160,11 +160,8 @@ static int lock_all_homes(void) { r = sd_bus_call(bus, m, DEFAULT_TIMEOUT_USEC, &error, NULL); if (r < 0) { - if (sd_bus_error_has_name(&error, SD_BUS_ERROR_SERVICE_UNKNOWN) || - sd_bus_error_has_name(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER)) { - log_debug("systemd-homed is not running, skipping locking of home directories."); - return 0; - } + if (bus_error_is_unknown_service(&error)) + return log_debug("systemd-homed is not running, skipping locking of home directories."); return log_error_errno(r, "Failed to lock home directories: %s", bus_error_message(&error, r)); } diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 24856572a8..5bfbc4852a 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -279,17 +279,17 @@ static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) if (!sd_bus_error_is_set(error)) return r; - if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) || - sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) || - sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) || - sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE)) + if (sd_bus_error_has_names(error, SD_BUS_ERROR_ACCESS_DENIED, + BUS_ERROR_ONLY_BY_DEPENDENCY, + BUS_ERROR_NO_ISOLATION, + BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE)) return EXIT_NOPERMISSION; if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT)) return EXIT_NOTINSTALLED; - if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) || - sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED)) + if (sd_bus_error_has_names(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, + SD_BUS_ERROR_NOT_SUPPORTED)) return EXIT_NOTIMPLEMENTED; if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) @@ -552,8 +552,8 @@ static int get_unit_list( return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, &reply); - if (r < 0 && (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD) || - sd_bus_error_has_name(&error, SD_BUS_ERROR_ACCESS_DENIED))) { + if (r < 0 && (sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_METHOD, + SD_BUS_ERROR_ACCESS_DENIED))) { /* Fallback to legacy ListUnitsFiltered method */ fallback = true; log_debug_errno(r, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error, r)); @@ -2945,9 +2945,9 @@ fail: log_error_errno(r, "Failed to %s %s: %s", job_type, name, bus_error_message(error, r)); - if (!sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) && - !sd_bus_error_has_name(error, BUS_ERROR_UNIT_MASKED) && - !sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE)) + if (!sd_bus_error_has_names(error, BUS_ERROR_NO_SUCH_UNIT, + BUS_ERROR_UNIT_MASKED, + BUS_ERROR_JOB_TYPE_NOT_APPLICABLE)) log_error("See %s logs and 'systemctl%s status%s %s' for details.", arg_scope == UNIT_FILE_SYSTEM ? "system" : "user", arg_scope == UNIT_FILE_SYSTEM ? "" : " --user", diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index d4b6befc8c..787bc71271 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -458,6 +458,8 @@ int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e); int sd_bus_error_move(sd_bus_error *dest, sd_bus_error *e); int sd_bus_error_is_set(const sd_bus_error *e); int sd_bus_error_has_name(const sd_bus_error *e, const char *name); +int sd_bus_error_has_names_sentinel(const sd_bus_error *e, ...) _sd_sentinel_; +#define sd_bus_error_has_names(e, ...) sd_bus_error_has_names_sentinel(e, __VA_ARGS__, NULL) #define SD_BUS_ERROR_MAP(_name, _code) \ { \