]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/bus-object.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "bus-introspect.h"
4 #include "bus-object.h"
6 #include "string-util.h"
9 int bus_add_implementation(sd_bus
*bus
, const BusObjectImplementation
*impl
, void *userdata
) {
12 log_debug("Registering bus object implementation for path=%s iface=%s", impl
->path
, impl
->interface
);
14 for (const sd_bus_vtable
**p
= impl
->vtables
; p
&& *p
; p
++) {
15 r
= sd_bus_add_object_vtable(bus
, NULL
,
21 return log_error_errno(r
, "Failed to register bus path %s with interface %s: %m",
26 for (const BusObjectVtablePair
*p
= impl
->fallback_vtables
; p
&& p
->vtable
; p
++) {
27 r
= sd_bus_add_fallback_vtable(bus
, NULL
,
34 return log_error_errno(r
, "Failed to register bus path %s with interface %s: %m",
39 if (impl
->node_enumerator
) {
40 r
= sd_bus_add_node_enumerator(bus
, NULL
,
42 impl
->node_enumerator
,
45 return log_error_errno(r
, "Failed to add node enumerator for %s: %m",
50 r
= sd_bus_add_object_manager(bus
, NULL
, impl
->path
);
52 return log_error_errno(r
, "Failed to add object manager for %s: %m", impl
->path
);
55 for (size_t i
= 0; impl
->children
&& impl
->children
[i
]; i
++) {
56 r
= bus_add_implementation(bus
, impl
->children
[i
], userdata
);
64 static const BusObjectImplementation
* find_implementation(
66 const BusObjectImplementation
* const* bus_objects
) {
68 for (size_t i
= 0; bus_objects
&& bus_objects
[i
]; i
++) {
69 const BusObjectImplementation
*impl
= bus_objects
[i
];
71 if (STR_IN_SET(pattern
, impl
->path
, impl
->interface
))
74 impl
= find_implementation(pattern
, impl
->children
);
82 static int bus_introspect_implementation(
83 struct introspect
*intro
,
84 const BusObjectImplementation
*impl
) {
87 for (const sd_bus_vtable
**p
= impl
->vtables
; p
&& *p
; p
++) {
88 r
= introspect_write_interface(intro
, impl
->interface
, *p
);
90 return log_error_errno(r
, "Failed to write introspection data: %m");
93 for (const BusObjectVtablePair
*p
= impl
->fallback_vtables
; p
&& p
->vtable
; p
++) {
94 r
= introspect_write_interface(intro
, impl
->interface
, p
->vtable
);
96 return log_error_errno(r
, "Failed to write introspection data: %m");
102 static void list_paths(
104 const BusObjectImplementation
* const* bus_objects
) {
106 for (size_t i
= 0; bus_objects
[i
]; i
++) {
107 fprintf(out
, "%s\t%s\n", bus_objects
[i
]->path
, bus_objects
[i
]->interface
);
108 if (bus_objects
[i
]->children
)
109 list_paths(out
, bus_objects
[i
]->children
);
113 int bus_introspect_implementations(
116 const BusObjectImplementation
* const* bus_objects
) {
118 const BusObjectImplementation
*impl
, *main_impl
= NULL
;
119 _cleanup_free_
char *s
= NULL
;
122 if (streq(pattern
, "list")) {
123 list_paths(out
, bus_objects
);
127 struct introspect intro
= {};
128 bool is_interface
= sd_bus_interface_name_is_valid(pattern
);
130 impl
= find_implementation(pattern
, bus_objects
);
132 return log_error_errno(SYNTHETIC_ERRNO(ENOENT
),
134 is_interface
? "Interface" : "Object path",
137 /* We use trusted=false here to get all the @org.freedesktop.systemd1.Privileged annotations. */
138 r
= introspect_begin(&intro
, false);
140 return log_error_errno(r
, "Failed to write introspection data: %m");
142 r
= introspect_write_default_interfaces(&intro
, impl
->manager
);
144 return log_error_errno(r
, "Failed to write introspection data: %m");
146 /* Check if there is a non-fallback path that applies to the given interface, also
147 * print it. This is useful in the case of units: o.fd.systemd1.Service is declared
148 * as a fallback vtable for o/fd/systemd1/unit, and we also want to print
149 * o.fd.systemd1.Unit, which is the non-fallback implementation. */
150 if (impl
->fallback_vtables
&& is_interface
)
151 main_impl
= find_implementation(impl
->path
, bus_objects
);
154 bus_introspect_implementation(&intro
, main_impl
);
156 if (impl
!= main_impl
)
157 bus_introspect_implementation(&intro
, impl
);
159 _cleanup_set_free_ Set
*nodes
= NULL
;
161 for (size_t i
= 0; impl
->children
&& impl
->children
[i
]; i
++) {
162 r
= set_put_strdup(&nodes
, impl
->children
[i
]->path
);
167 r
= introspect_write_child_nodes(&intro
, nodes
, impl
->path
);
171 r
= introspect_finish(&intro
, &s
);
173 return log_error_errno(r
, "Failed to write introspection data: %m");