diff --git a/src/core/dbus-job.h b/src/core/dbus-job.h index a840c6dfe8..96c5b66309 100644 --- a/src/core/dbus-job.h +++ b/src/core/dbus-job.h @@ -4,7 +4,7 @@ #include "sd-bus.h" #include "unit.h" -#include "bus-util.h" +#include "bus-object.h" extern const sd_bus_vtable bus_job_vtable[]; extern const BusObjectImplementation job_object; diff --git a/src/home/homed-home-bus.h b/src/home/homed-home-bus.h index 59b2a970b8..8ac7ff9995 100644 --- a/src/home/homed-home-bus.h +++ b/src/home/homed-home-bus.h @@ -3,7 +3,7 @@ #include "sd-bus.h" -#include "bus-util.h" +#include "bus-object.h" #include "homed-home.h" int bus_home_client_is_trusted(Home *h, sd_bus_message *message); diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c index f609854925..13fd52ffd5 100644 --- a/src/libsystemd/sd-bus/bus-track.c +++ b/src/libsystemd/sd-bus/bus-track.c @@ -6,6 +6,7 @@ #include "bus-internal.h" #include "bus-track.h" #include "bus-util.h" +#include "string-util.h" struct track_item { unsigned n_ref; diff --git a/src/login/logind-dbus.h b/src/login/logind-dbus.h index 6a3ee82f1c..7707587545 100644 --- a/src/login/logind-dbus.h +++ b/src/login/logind-dbus.h @@ -3,10 +3,10 @@ #include "sd-bus.h" -#include "bus-util.h" -#include "logind.h" +#include "bus-object.h" #include "logind-session.h" #include "logind-user.h" +#include "logind.h" int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret); int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret); diff --git a/src/login/logind-seat-dbus.h b/src/login/logind-seat-dbus.h index 5fc857584e..6169cfe1ed 100644 --- a/src/login/logind-seat-dbus.h +++ b/src/login/logind-seat-dbus.h @@ -3,8 +3,8 @@ #include "sd-bus.h" +#include "bus-object.h" #include "logind-seat.h" -#include "bus-util.h" extern const BusObjectImplementation seat_object; diff --git a/src/login/logind-session-dbus.h b/src/login/logind-session-dbus.h index 6df96e06b2..97f7c413cb 100644 --- a/src/login/logind-session-dbus.h +++ b/src/login/logind-session-dbus.h @@ -3,6 +3,7 @@ #include "sd-bus.h" +#include "bus-object.h" #include "logind-session.h" extern const BusObjectImplementation session_object; diff --git a/src/machine/image-dbus.h b/src/machine/image-dbus.h index 43f5f34d20..d785c10817 100644 --- a/src/machine/image-dbus.h +++ b/src/machine/image-dbus.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -#include "bus-util.h" +#include "bus-object.h" #include "machined.h" extern const BusObjectImplementation image_object; diff --git a/src/resolve/resolved-bus.h b/src/resolve/resolved-bus.h index e69171ca70..6d6b095323 100644 --- a/src/resolve/resolved-bus.h +++ b/src/resolve/resolved-bus.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -#include "bus-util.h" +#include "bus-object.h" #include "resolved-manager.h" extern const BusObjectImplementation manager_object; diff --git a/src/resolve/resolved-dnssd-bus.h b/src/resolve/resolved-dnssd-bus.h index 8cd75642a7..403455e89f 100644 --- a/src/resolve/resolved-dnssd-bus.h +++ b/src/resolve/resolved-dnssd-bus.h @@ -2,7 +2,7 @@ #include "sd-bus.h" -#include "bus-util.h" +#include "bus-object.h" extern const BusObjectImplementation dnssd_object; diff --git a/src/shared/bus-log-control-api.h b/src/shared/bus-log-control-api.h index 3e654d7d81..64eaa540f4 100644 --- a/src/shared/bus-log-control-api.h +++ b/src/shared/bus-log-control-api.h @@ -3,7 +3,7 @@ #include "sd-bus.h" -#include "bus-util.h" +#include "bus-object.h" extern const BusObjectImplementation log_control_object; static inline int bus_log_control_api_register(sd_bus *bus) { diff --git a/src/shared/bus-object.c b/src/shared/bus-object.c new file mode 100644 index 0000000000..217d43d333 --- /dev/null +++ b/src/shared/bus-object.c @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "bus-introspect.h" +#include "bus-object.h" +#include "macro.h" +#include "string-util.h" +#include "strv.h" + +int bus_add_implementation(sd_bus *bus, const BusObjectImplementation *impl, void *userdata) { + int r; + + log_debug("Registering bus object implementation for path=%s iface=%s", impl->path, impl->interface); + + for (const sd_bus_vtable **p = impl->vtables; p && *p; p++) { + r = sd_bus_add_object_vtable(bus, NULL, + impl->path, + impl->interface, + *p, + userdata); + if (r < 0) + return log_error_errno(r, "Failed to register bus path %s with interface %s: %m", + impl->path, + impl->interface); + } + + for (const BusObjectVtablePair *p = impl->fallback_vtables; p && p->vtable; p++) { + r = sd_bus_add_fallback_vtable(bus, NULL, + impl->path, + impl->interface, + p->vtable, + p->object_find, + userdata); + if (r < 0) + return log_error_errno(r, "Failed to register bus path %s with interface %s: %m", + impl->path, + impl->interface); + } + + if (impl->node_enumerator) { + r = sd_bus_add_node_enumerator(bus, NULL, + impl->path, + impl->node_enumerator, + userdata); + if (r < 0) + return log_error_errno(r, "Failed to add node enumerator for %s: %m", + impl->path); + } + + if (impl->manager) { + r = sd_bus_add_object_manager(bus, NULL, impl->path); + if (r < 0) + return log_error_errno(r, "Failed to add object manager for %s: %m", impl->path); + } + + for (size_t i = 0; impl->children && impl->children[i]; i++) { + r = bus_add_implementation(bus, impl->children[i], userdata); + if (r < 0) + return r; + } + + return 0; +} + +static const BusObjectImplementation* find_implementation( + const char *pattern, + const BusObjectImplementation* const* bus_objects) { + + for (size_t i = 0; bus_objects && bus_objects[i]; i++) { + const BusObjectImplementation *impl = bus_objects[i]; + + if (STR_IN_SET(pattern, impl->path, impl->interface)) + return impl; + + impl = find_implementation(pattern, impl->children); + if (impl) + return impl; + } + + return NULL; +} + +static int bus_introspect_implementation( + struct introspect *intro, + const BusObjectImplementation *impl) { + int r; + + for (const sd_bus_vtable **p = impl->vtables; p && *p; p++) { + r = introspect_write_interface(intro, impl->interface, *p); + if (r < 0) + return log_error_errno(r, "Failed to write introspection data: %m"); + } + + for (const BusObjectVtablePair *p = impl->fallback_vtables; p && p->vtable; p++) { + r = introspect_write_interface(intro, impl->interface, p->vtable); + if (r < 0) + return log_error_errno(r, "Failed to write introspection data: %m"); + } + + return 0; +} + +static void list_paths( + FILE *out, + const BusObjectImplementation* const* bus_objects) { + + for (size_t i = 0; bus_objects[i]; i++) { + fprintf(out, "%s\t%s\n", bus_objects[i]->path, bus_objects[i]->interface); + if (bus_objects[i]->children) + list_paths(out, bus_objects[i]->children); + } +} + +int bus_introspect_implementations( + FILE *out, + const char *pattern, + const BusObjectImplementation* const* bus_objects) { + + const BusObjectImplementation *impl, *main_impl = NULL; + _cleanup_free_ char *s = NULL; + int r; + + if (streq(pattern, "list")) { + list_paths(out, bus_objects); + return 0; + } + + struct introspect intro = {}; + bool is_interface = sd_bus_interface_name_is_valid(pattern); + + impl = find_implementation(pattern, bus_objects); + if (!impl) + return log_error_errno(SYNTHETIC_ERRNO(ENOENT), + "%s %s not found", + is_interface ? "Interface" : "Object path", + pattern); + + /* We use trusted=false here to get all the @org.freedesktop.systemd1.Privileged annotations. */ + r = introspect_begin(&intro, false); + if (r < 0) + return log_error_errno(r, "Failed to write introspection data: %m"); + + r = introspect_write_default_interfaces(&intro, impl->manager); + if (r < 0) + return log_error_errno(r, "Failed to write introspection data: %m"); + + /* Check if there is a non-fallback path that applies to the given interface, also + * print it. This is useful in the case of units: o.fd.systemd1.Service is declared + * as a fallback vtable for o/fd/systemd1/unit, and we also want to print + * o.fd.systemd1.Unit, which is the non-fallback implementation. */ + if (impl->fallback_vtables && is_interface) + main_impl = find_implementation(impl->path, bus_objects); + + if (main_impl) + bus_introspect_implementation(&intro, main_impl); + + if (impl != main_impl) + bus_introspect_implementation(&intro, impl); + + _cleanup_set_free_ Set *nodes = NULL; + + for (size_t i = 0; impl->children && impl->children[i]; i++) { + r = set_put_strdup(&nodes, impl->children[i]->path); + if (r < 0) + return log_oom(); + } + + r = introspect_write_child_nodes(&intro, nodes, impl->path); + if (r < 0) + return r; + + r = introspect_finish(&intro, &s); + if (r < 0) + return log_error_errno(r, "Failed to write introspection data: %m"); + + fputs(s, out); + return 0; +} diff --git a/src/shared/bus-object.h b/src/shared/bus-object.h new file mode 100644 index 0000000000..8add854e59 --- /dev/null +++ b/src/shared/bus-object.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "sd-bus.h" + +typedef struct BusObjectImplementation BusObjectImplementation; + +typedef struct BusObjectVtablePair { + const sd_bus_vtable *vtable; + sd_bus_object_find_t object_find; +} BusObjectVtablePair; + +struct BusObjectImplementation { + const char *path; + const char *interface; + const sd_bus_vtable **vtables; + const BusObjectVtablePair *fallback_vtables; + sd_bus_node_enumerator_t node_enumerator; + bool manager; + const BusObjectImplementation **children; +}; + +#define BUS_VTABLES(...) ((const sd_bus_vtable* []){ __VA_ARGS__, NULL }) +#define BUS_FALLBACK_VTABLES(...) ((const BusObjectVtablePair[]) { __VA_ARGS__, {} }) +#define BUS_IMPLEMENTATIONS(...) ((const BusObjectImplementation* []) { __VA_ARGS__, NULL }) + +int bus_add_implementation(sd_bus *bus, const BusObjectImplementation *impl, void *userdata); +int bus_introspect_implementations( + FILE *out, + const char *pattern, + const BusObjectImplementation* const* bus_objects); diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index f64e200731..a43fe66888 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -16,7 +16,6 @@ #include "alloc-util.h" #include "bus-internal.h" -#include "bus-introspect.h" #include "bus-label.h" #include "bus-message.h" #include "bus-util.h" @@ -30,6 +29,7 @@ #include "rlimit-util.h" #include "socket-util.h" #include "stdio-util.h" +#include "string-util.h" #include "strv.h" #include "user-util.h" @@ -1546,173 +1546,3 @@ int bus_message_new_method_call( return sd_bus_message_new_method_call(bus, m, locator->destination, locator->path, locator->interface, member); } - -int bus_add_implementation(sd_bus *bus, const BusObjectImplementation *impl, void *userdata) { - int r; - - log_debug("Registering bus object implementation for path=%s iface=%s", impl->path, impl->interface); - - for (const sd_bus_vtable **p = impl->vtables; p && *p; p++) { - r = sd_bus_add_object_vtable(bus, NULL, - impl->path, - impl->interface, - *p, - userdata); - if (r < 0) - return log_error_errno(r, "Failed to register bus path %s with interface %s: %m", - impl->path, - impl->interface); - } - - for (const BusObjectVtablePair *p = impl->fallback_vtables; p && p->vtable; p++) { - r = sd_bus_add_fallback_vtable(bus, NULL, - impl->path, - impl->interface, - p->vtable, - p->object_find, - userdata); - if (r < 0) - return log_error_errno(r, "Failed to register bus path %s with interface %s: %m", - impl->path, - impl->interface); - } - - if (impl->node_enumerator) { - r = sd_bus_add_node_enumerator(bus, NULL, - impl->path, - impl->node_enumerator, - userdata); - if (r < 0) - return log_error_errno(r, "Failed to add node enumerator for %s: %m", - impl->path); - } - - if (impl->manager) { - r = sd_bus_add_object_manager(bus, NULL, impl->path); - if (r < 0) - return log_error_errno(r, "Failed to add object manager for %s: %m", impl->path); - } - - for (size_t i = 0; impl->children && impl->children[i]; i++) { - r = bus_add_implementation(bus, impl->children[i], userdata); - if (r < 0) - return r; - } - - return 0; -} - -static const BusObjectImplementation* find_implementation( - const char *pattern, - const BusObjectImplementation* const* bus_objects) { - - for (size_t i = 0; bus_objects && bus_objects[i]; i++) { - const BusObjectImplementation *impl = bus_objects[i]; - - if (STR_IN_SET(pattern, impl->path, impl->interface)) - return impl; - - impl = find_implementation(pattern, impl->children); - if (impl) - return impl; - } - - return NULL; -} - -static int bus_introspect_implementation( - struct introspect *intro, - const BusObjectImplementation *impl) { - int r; - - for (const sd_bus_vtable **p = impl->vtables; p && *p; p++) { - r = introspect_write_interface(intro, impl->interface, *p); - if (r < 0) - return log_error_errno(r, "Failed to write introspection data: %m"); - } - - for (const BusObjectVtablePair *p = impl->fallback_vtables; p && p->vtable; p++) { - r = introspect_write_interface(intro, impl->interface, p->vtable); - if (r < 0) - return log_error_errno(r, "Failed to write introspection data: %m"); - } - - return 0; -} - -static void list_paths( - FILE *out, - const BusObjectImplementation* const* bus_objects) { - - for (size_t i = 0; bus_objects[i]; i++) { - fprintf(out, "%s\t%s\n", bus_objects[i]->path, bus_objects[i]->interface); - if (bus_objects[i]->children) - list_paths(out, bus_objects[i]->children); - } -} - -int bus_introspect_implementations( - FILE *out, - const char *pattern, - const BusObjectImplementation* const* bus_objects) { - - const BusObjectImplementation *impl, *main_impl = NULL; - _cleanup_free_ char *s = NULL; - int r; - - if (streq(pattern, "list")) { - list_paths(out, bus_objects); - return 0; - } - - struct introspect intro = {}; - bool is_interface = sd_bus_interface_name_is_valid(pattern); - - impl = find_implementation(pattern, bus_objects); - if (!impl) - return log_error_errno(SYNTHETIC_ERRNO(ENOENT), - "%s %s not found", - is_interface ? "Interface" : "Object path", - pattern); - - /* We use trusted=false here to get all the @org.freedesktop.systemd1.Privileged annotations. */ - r = introspect_begin(&intro, false); - if (r < 0) - return log_error_errno(r, "Failed to write introspection data: %m"); - - r = introspect_write_default_interfaces(&intro, impl->manager); - if (r < 0) - return log_error_errno(r, "Failed to write introspection data: %m"); - - /* Check if there is a non-fallback path that applies to the given interface, also - * print it. This is useful in the case of units: o.fd.systemd1.Service is declared - * as a fallback vtable for o/fd/systemd1/unit, and we also want to print - * o.fd.systemd1.Unit, which is the non-fallback implementation. */ - if (impl->fallback_vtables && is_interface) - main_impl = find_implementation(impl->path, bus_objects); - - if (main_impl) - bus_introspect_implementation(&intro, main_impl); - - if (impl != main_impl) - bus_introspect_implementation(&intro, impl); - - _cleanup_set_free_ Set *nodes = NULL; - - for (size_t i = 0; impl->children && impl->children[i]; i++) { - r = set_put_strdup(&nodes, impl->children[i]->path); - if (r < 0) - return log_oom(); - } - - r = introspect_write_child_nodes(&intro, nodes, impl->path); - if (r < 0) - return r; - - r = introspect_finish(&intro, &s); - if (r < 0) - return log_error_errno(r, "Failed to write introspection data: %m"); - - fputs(s, out); - return 0; -} diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index ef14217e93..1d44cd7676 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -23,26 +23,6 @@ typedef enum BusTransport { _BUS_TRANSPORT_INVALID = -1 } BusTransport; -typedef struct BusObjectImplementation BusObjectImplementation; - -typedef struct BusObjectVtablePair { - const sd_bus_vtable *vtable; - sd_bus_object_find_t object_find; -} BusObjectVtablePair; - -struct BusObjectImplementation { - const char *path; - const char *interface; - const sd_bus_vtable **vtables; - const BusObjectVtablePair *fallback_vtables; - sd_bus_node_enumerator_t node_enumerator; - bool manager; - const BusObjectImplementation **children; -}; - -#define BUS_VTABLES(...) ((const sd_bus_vtable* []){ __VA_ARGS__, NULL }) -#define BUS_FALLBACK_VTABLES(...) ((const BusObjectVtablePair[]) { __VA_ARGS__, {} }) -#define BUS_IMPLEMENTATIONS(...) ((const BusObjectImplementation* []) { __VA_ARGS__, NULL }) typedef int (*bus_property_set_t) (sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata); @@ -215,9 +195,3 @@ int bus_set_property(sd_bus *bus, const BusLocator *locator, const char *member, int bus_match_signal(sd_bus *bus, sd_bus_slot **ret, const BusLocator *locator, const char *member, sd_bus_message_handler_t callback, void *userdata); int bus_match_signal_async(sd_bus *bus, sd_bus_slot **ret, const BusLocator *locator, const char *member, sd_bus_message_handler_t callback, sd_bus_message_handler_t install_callback, void *userdata); int bus_message_new_method_call(sd_bus *bus, sd_bus_message **m, const BusLocator *locator, const char *member); - -int bus_add_implementation(sd_bus *bus, const BusObjectImplementation *impl, void *userdata); -int bus_introspect_implementations( - FILE *out, - const char *pattern, - const BusObjectImplementation* const* bus_objects); diff --git a/src/shared/meson.build b/src/shared/meson.build index e3aee57ac8..30ece1f193 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -31,6 +31,8 @@ shared_sources = files(''' bus-locator.h bus-log-control-api.c bus-log-control-api.h + bus-object.c + bus-object.h bus-polkit.c bus-polkit.h bus-unit-procs.c diff --git a/src/shared/service-util.h b/src/shared/service-util.h index 76bff61d58..928c5961e7 100644 --- a/src/shared/service-util.h +++ b/src/shared/service-util.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -#include "bus-util.h" +#include "bus-object.h" int service_parse_argv( const char *service,