shared: split out BusObjectImplementor APIs

Just some refactoring, no code changes
This commit is contained in:
Lennart Poettering 2020-06-28 15:37:47 +02:00
parent 7aee1e7304
commit c664cf5607
16 changed files with 226 additions and 207 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -3,6 +3,7 @@
#include "sd-bus.h"
#include "bus-object.h"
#include "logind-session.h"
extern const BusObjectImplementation session_object;

View File

@ -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;

View File

@ -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;

View File

@ -2,7 +2,7 @@
#include "sd-bus.h"
#include "bus-util.h"
#include "bus-object.h"
extern const BusObjectImplementation dnssd_object;

View File

@ -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) {

177
src/shared/bus-object.c Normal file
View File

@ -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;
}

34
src/shared/bus-object.h Normal file
View File

@ -0,0 +1,34 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <stdbool.h>
#include <stdio.h>
#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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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,