Bug Summary

File:build-scan/../src/libsystemd/sd-bus/bus-objects.c
Warning:line 1528, column 16
Potential leak of memory pointed to by 'prefix'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name bus-objects.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/libsystemd/libsystemd_static.a.p -I src/libsystemd -I ../src/libsystemd -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility default -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/libsystemd/sd-bus/bus-objects.c

../src/libsystemd/sd-bus/bus-objects.c

1/* SPDX-License-Identifier: LGPL-2.1+ */
2/***
3***/
4
5#include "alloc-util.h"
6#include "bus-internal.h"
7#include "bus-introspect.h"
8#include "bus-message.h"
9#include "bus-objects.h"
10#include "bus-signature.h"
11#include "bus-slot.h"
12#include "bus-type.h"
13#include "bus-util.h"
14#include "set.h"
15#include "string-util.h"
16#include "strv.h"
17
18static int node_vtable_get_userdata(
19 sd_bus *bus,
20 const char *path,
21 struct node_vtable *c,
22 void **userdata,
23 sd_bus_error *error) {
24
25 sd_bus_slot *s;
26 void *u, *found_u;
27 int r;
28
29 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 29, __PRETTY_FUNCTION__); } while (0)
;
30 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 30, __PRETTY_FUNCTION__); } while (0)
;
31 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-objects.c"
, 31, __PRETTY_FUNCTION__); } while (0)
;
32
33 s = container_of(c, sd_bus_slot, node_vtable)__extension__ ({ const typeof( ((sd_bus_slot*)0)->node_vtable
) *__unique_prefix_A39 = ((c)); (sd_bus_slot*)( (char *)__unique_prefix_A39
- __builtin_offsetof(sd_bus_slot, node_vtable) ); })
;
34 u = s->userdata;
35 if (c->find) {
36 bus->current_slot = sd_bus_slot_ref(s);
37 bus->current_userdata = u;
38 r = c->find(bus, path, c->interface, u, &found_u, error);
39 bus->current_userdata = NULL((void*)0);
40 bus->current_slot = sd_bus_slot_unref(s);
41
42 if (r < 0)
43 return r;
44 if (sd_bus_error_is_set(error))
45 return -sd_bus_error_get_errno(error);
46 if (r == 0)
47 return r;
48 } else
49 found_u = u;
50
51 if (userdata)
52 *userdata = found_u;
53
54 return 1;
55}
56
57static void *vtable_method_convert_userdata(const sd_bus_vtable *p, void *u) {
58 assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p"), "../src/libsystemd/sd-bus/bus-objects.c"
, 58, __PRETTY_FUNCTION__); } while (0)
;
59
60 return (uint8_t*) u + p->x.method.offset;
61}
62
63static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) {
64 assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p"), "../src/libsystemd/sd-bus/bus-objects.c"
, 64, __PRETTY_FUNCTION__); } while (0)
;
65
66 return (uint8_t*) u + p->x.property.offset;
67}
68
69static int vtable_property_get_userdata(
70 sd_bus *bus,
71 const char *path,
72 struct vtable_member *p,
73 void **userdata,
74 sd_bus_error *error) {
75
76 void *u;
77 int r;
78
79 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 79, __PRETTY_FUNCTION__); } while (0)
;
80 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 80, __PRETTY_FUNCTION__); } while (0)
;
81 assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p"), "../src/libsystemd/sd-bus/bus-objects.c"
, 81, __PRETTY_FUNCTION__); } while (0)
;
82 assert(userdata)do { if ((__builtin_expect(!!(!(userdata)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("userdata"), "../src/libsystemd/sd-bus/bus-objects.c"
, 82, __PRETTY_FUNCTION__); } while (0)
;
83
84 r = node_vtable_get_userdata(bus, path, p->parent, &u, error);
85 if (r <= 0)
86 return r;
87 if (bus->nodes_modified)
88 return 0;
89
90 *userdata = vtable_property_convert_userdata(p->vtable, u);
91 return 1;
92}
93
94static int add_enumerated_to_set(
95 sd_bus *bus,
96 const char *prefix,
97 struct node_enumerator *first,
98 Set *s,
99 sd_bus_error *error) {
100
101 struct node_enumerator *c;
102 int r;
103
104 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 104, __PRETTY_FUNCTION__); } while (0)
;
105 assert(prefix)do { if ((__builtin_expect(!!(!(prefix)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("prefix"), "../src/libsystemd/sd-bus/bus-objects.c"
, 105, __PRETTY_FUNCTION__); } while (0)
;
106 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/libsystemd/sd-bus/bus-objects.c"
, 106, __PRETTY_FUNCTION__); } while (0)
;
107
108 LIST_FOREACH(enumerators, c, first)for ((c) = (first); (c); (c) = (c)->enumerators_next) {
109 char **children = NULL((void*)0), **k;
110 sd_bus_slot *slot;
111
112 if (bus->nodes_modified)
113 return 0;
114
115 slot = container_of(c, sd_bus_slot, node_enumerator)__extension__ ({ const typeof( ((sd_bus_slot*)0)->node_enumerator
) *__unique_prefix_A40 = ((c)); (sd_bus_slot*)( (char *)__unique_prefix_A40
- __builtin_offsetof(sd_bus_slot, node_enumerator) ); })
;
116
117 bus->current_slot = sd_bus_slot_ref(slot);
118 bus->current_userdata = slot->userdata;
119 r = c->callback(bus, prefix, slot->userdata, &children, error);
120 bus->current_userdata = NULL((void*)0);
121 bus->current_slot = sd_bus_slot_unref(slot);
122
123 if (r < 0)
124 return r;
125 if (sd_bus_error_is_set(error))
126 return -sd_bus_error_get_errno(error);
127
128 STRV_FOREACH(k, children)for ((k) = (children); (k) && *(k); (k)++) {
129 if (r < 0) {
130 free(*k);
131 continue;
132 }
133
134 if (!object_path_is_valid(*k)) {
135 free(*k);
136 r = -EINVAL22;
137 continue;
138 }
139
140 if (!object_path_startswith(*k, prefix)) {
141 free(*k);
142 continue;
143 }
144
145 r = set_consume(s, *k);
146 if (r == -EEXIST17)
147 r = 0;
148 }
149
150 free(children);
151 if (r < 0)
152 return r;
153 }
154
155 return 0;
156}
157
158enum {
159 /* if set, add_subtree() works recursively */
160 CHILDREN_RECURSIVE = 1 << 0,
161 /* if set, add_subtree() scans object-manager hierarchies recursively */
162 CHILDREN_SUBHIERARCHIES = 1 << 1,
163};
164
165static int add_subtree_to_set(
166 sd_bus *bus,
167 const char *prefix,
168 struct node *n,
169 unsigned int flags,
170 Set *s,
171 sd_bus_error *error) {
172
173 struct node *i;
174 int r;
175
176 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 176, __PRETTY_FUNCTION__); } while (0)
;
177 assert(prefix)do { if ((__builtin_expect(!!(!(prefix)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("prefix"), "../src/libsystemd/sd-bus/bus-objects.c"
, 177, __PRETTY_FUNCTION__); } while (0)
;
178 assert(n)do { if ((__builtin_expect(!!(!(n)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n"), "../src/libsystemd/sd-bus/bus-objects.c"
, 178, __PRETTY_FUNCTION__); } while (0)
;
179 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/libsystemd/sd-bus/bus-objects.c"
, 179, __PRETTY_FUNCTION__); } while (0)
;
180
181 r = add_enumerated_to_set(bus, prefix, n->enumerators, s, error);
182 if (r < 0)
183 return r;
184 if (bus->nodes_modified)
185 return 0;
186
187 LIST_FOREACH(siblings, i, n->child)for ((i) = (n->child); (i); (i) = (i)->siblings_next) {
188 char *t;
189
190 if (!object_path_startswith(i->path, prefix))
191 continue;
192
193 t = strdup(i->path);
194 if (!t)
195 return -ENOMEM12;
196
197 r = set_consume(s, t);
198 if (r < 0 && r != -EEXIST17)
199 return r;
200
201 if ((flags & CHILDREN_RECURSIVE) &&
202 ((flags & CHILDREN_SUBHIERARCHIES) || !i->object_managers)) {
203 r = add_subtree_to_set(bus, prefix, i, flags, s, error);
204 if (r < 0)
205 return r;
206 if (bus->nodes_modified)
207 return 0;
208 }
209 }
210
211 return 0;
212}
213
214static int get_child_nodes(
215 sd_bus *bus,
216 const char *prefix,
217 struct node *n,
218 unsigned int flags,
219 Set **_s,
220 sd_bus_error *error) {
221
222 Set *s = NULL((void*)0);
223 int r;
224
225 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 225, __PRETTY_FUNCTION__); } while (0)
;
226 assert(prefix)do { if ((__builtin_expect(!!(!(prefix)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("prefix"), "../src/libsystemd/sd-bus/bus-objects.c"
, 226, __PRETTY_FUNCTION__); } while (0)
;
227 assert(n)do { if ((__builtin_expect(!!(!(n)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n"), "../src/libsystemd/sd-bus/bus-objects.c"
, 227, __PRETTY_FUNCTION__); } while (0)
;
228 assert(_s)do { if ((__builtin_expect(!!(!(_s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_s"), "../src/libsystemd/sd-bus/bus-objects.c"
, 228, __PRETTY_FUNCTION__); } while (0)
;
229
230 s = set_new(&string_hash_ops)internal_set_new(&string_hash_ops );
231 if (!s)
232 return -ENOMEM12;
233
234 r = add_subtree_to_set(bus, prefix, n, flags, s, error);
235 if (r < 0) {
236 set_free_free(s);
237 return r;
238 }
239
240 *_s = s;
241 return 0;
242}
243
244static int node_callbacks_run(
245 sd_bus *bus,
246 sd_bus_message *m,
247 struct node_callback *first,
248 bool_Bool require_fallback,
249 bool_Bool *found_object) {
250
251 struct node_callback *c;
252 int r;
253
254 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 254, __PRETTY_FUNCTION__); } while (0)
;
255 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 255, __PRETTY_FUNCTION__); } while (0)
;
256 assert(found_object)do { if ((__builtin_expect(!!(!(found_object)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("found_object"), "../src/libsystemd/sd-bus/bus-objects.c"
, 256, __PRETTY_FUNCTION__); } while (0)
;
257
258 LIST_FOREACH(callbacks, c, first)for ((c) = (first); (c); (c) = (c)->callbacks_next) {
259 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error_buffer = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
260 sd_bus_slot *slot;
261
262 if (bus->nodes_modified)
263 return 0;
264
265 if (require_fallback && !c->is_fallback)
266 continue;
267
268 *found_object = true1;
269
270 if (c->last_iteration == bus->iteration_counter)
271 continue;
272
273 c->last_iteration = bus->iteration_counter;
274
275 r = sd_bus_message_rewind(m, true1);
276 if (r < 0)
277 return r;
278
279 slot = container_of(c, sd_bus_slot, node_callback)__extension__ ({ const typeof( ((sd_bus_slot*)0)->node_callback
) *__unique_prefix_A41 = ((c)); (sd_bus_slot*)( (char *)__unique_prefix_A41
- __builtin_offsetof(sd_bus_slot, node_callback) ); })
;
280
281 bus->current_slot = sd_bus_slot_ref(slot);
282 bus->current_handler = c->callback;
283 bus->current_userdata = slot->userdata;
284 r = c->callback(m, slot->userdata, &error_buffer);
285 bus->current_userdata = NULL((void*)0);
286 bus->current_handler = NULL((void*)0);
287 bus->current_slot = sd_bus_slot_unref(slot);
288
289 r = bus_maybe_reply_error(m, r, &error_buffer);
290 if (r != 0)
291 return r;
292 }
293
294 return 0;
295}
296
297#define CAPABILITY_SHIFT(x)(((x) >> __builtin_ctzll(_SD_BUS_VTABLE_CAPABILITY_MASK
)) & 0xFFFF)
(((x) >> __builtin_ctzll(_SD_BUS_VTABLE_CAPABILITY_MASK)) & 0xFFFF)
298
299static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c, sd_bus_error *error) {
300 uint64_t cap;
301 int r;
302
303 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 303, __PRETTY_FUNCTION__); } while (0)
;
304 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 304, __PRETTY_FUNCTION__); } while (0)
;
305 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-objects.c"
, 305, __PRETTY_FUNCTION__); } while (0)
;
306
307 /* If the entire bus is trusted let's grant access */
308 if (bus->trusted)
309 return 0;
310
311 /* If the member is marked UNPRIVILEGED let's grant access */
312 if (c->vtable->flags & SD_BUS_VTABLE_UNPRIVILEGED)
313 return 0;
314
315 /* Check have the caller has the requested capability
316 * set. Note that the flags value contains the capability
317 * number plus one, which we need to subtract here. We do this
318 * so that we have 0 as special value for "default
319 * capability". */
320 cap = CAPABILITY_SHIFT(c->vtable->flags)(((c->vtable->flags) >> __builtin_ctzll(_SD_BUS_VTABLE_CAPABILITY_MASK
)) & 0xFFFF)
;
321 if (cap == 0)
322 cap = CAPABILITY_SHIFT(c->parent->vtable[0].flags)(((c->parent->vtable[0].flags) >> __builtin_ctzll
(_SD_BUS_VTABLE_CAPABILITY_MASK)) & 0xFFFF)
;
323 if (cap == 0)
324 cap = CAP_SYS_ADMIN21;
325 else
326 cap--;
327
328 r = sd_bus_query_sender_privilege(m, cap);
329 if (r < 0)
330 return r;
331 if (r > 0)
332 return 0;
333
334 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED"org.freedesktop.DBus.Error.AccessDenied", "Access to %s.%s() not permitted.", c->interface, c->member);
335}
336
337static int method_callbacks_run(
338 sd_bus *bus,
339 sd_bus_message *m,
340 struct vtable_member *c,
341 bool_Bool require_fallback,
342 bool_Bool *found_object) {
343
344 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
345 const char *signature;
346 void *u;
347 int r;
348
349 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 349, __PRETTY_FUNCTION__); } while (0)
;
350 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 350, __PRETTY_FUNCTION__); } while (0)
;
351 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-objects.c"
, 351, __PRETTY_FUNCTION__); } while (0)
;
352 assert(found_object)do { if ((__builtin_expect(!!(!(found_object)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("found_object"), "../src/libsystemd/sd-bus/bus-objects.c"
, 352, __PRETTY_FUNCTION__); } while (0)
;
353
354 if (require_fallback && !c->parent->is_fallback)
355 return 0;
356
357 r = check_access(bus, m, c, &error);
358 if (r < 0)
359 return bus_maybe_reply_error(m, r, &error);
360
361 r = node_vtable_get_userdata(bus, m->path, c->parent, &u, &error);
362 if (r <= 0)
363 return bus_maybe_reply_error(m, r, &error);
364 if (bus->nodes_modified)
365 return 0;
366
367 u = vtable_method_convert_userdata(c->vtable, u);
368
369 *found_object = true1;
370
371 if (c->last_iteration == bus->iteration_counter)
372 return 0;
373
374 c->last_iteration = bus->iteration_counter;
375
376 r = sd_bus_message_rewind(m, true1);
377 if (r < 0)
378 return r;
379
380 signature = sd_bus_message_get_signature(m, true1);
381 if (!signature)
382 return -EINVAL22;
383
384 if (!streq(strempty(c->vtable->x.method.signature), signature)(strcmp((strempty(c->vtable->x.method.signature)),(signature
)) == 0)
)
385 return sd_bus_reply_method_errorf(
386 m,
387 SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs",
388 "Invalid arguments '%s' to call %s.%s(), expecting '%s'.",
389 signature, c->interface, c->member, strempty(c->vtable->x.method.signature));
390
391 /* Keep track what the signature of the reply to this message
392 * should be, so that this can be enforced when sealing the
393 * reply. */
394 m->enforced_reply_signature = strempty(c->vtable->x.method.result);
395
396 if (c->vtable->x.method.handler) {
397 sd_bus_slot *slot;
398
399 slot = container_of(c->parent, sd_bus_slot, node_vtable)__extension__ ({ const typeof( ((sd_bus_slot*)0)->node_vtable
) *__unique_prefix_A42 = ((c->parent)); (sd_bus_slot*)( (
char *)__unique_prefix_A42 - __builtin_offsetof(sd_bus_slot, node_vtable
) ); })
;
400
401 bus->current_slot = sd_bus_slot_ref(slot);
402 bus->current_handler = c->vtable->x.method.handler;
403 bus->current_userdata = u;
404 r = c->vtable->x.method.handler(m, u, &error);
405 bus->current_userdata = NULL((void*)0);
406 bus->current_handler = NULL((void*)0);
407 bus->current_slot = sd_bus_slot_unref(slot);
408
409 return bus_maybe_reply_error(m, r, &error);
410 }
411
412 /* If the method callback is NULL, make this a successful NOP */
413 r = sd_bus_reply_method_return(m, NULL((void*)0));
414 if (r < 0)
415 return r;
416
417 return 1;
418}
419
420static int invoke_property_get(
421 sd_bus *bus,
422 sd_bus_slot *slot,
423 const sd_bus_vtable *v,
424 const char *path,
425 const char *interface,
426 const char *property,
427 sd_bus_message *reply,
428 void *userdata,
429 sd_bus_error *error) {
430
431 const void *p;
432 int r;
433
434 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 434, __PRETTY_FUNCTION__); } while (0)
;
435 assert(slot)do { if ((__builtin_expect(!!(!(slot)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("slot"), "../src/libsystemd/sd-bus/bus-objects.c"
, 435, __PRETTY_FUNCTION__); } while (0)
;
436 assert(v)do { if ((__builtin_expect(!!(!(v)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("v"), "../src/libsystemd/sd-bus/bus-objects.c"
, 436, __PRETTY_FUNCTION__); } while (0)
;
437 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 437, __PRETTY_FUNCTION__); } while (0)
;
438 assert(interface)do { if ((__builtin_expect(!!(!(interface)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("interface"), "../src/libsystemd/sd-bus/bus-objects.c"
, 438, __PRETTY_FUNCTION__); } while (0)
;
439 assert(property)do { if ((__builtin_expect(!!(!(property)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("property"), "../src/libsystemd/sd-bus/bus-objects.c"
, 439, __PRETTY_FUNCTION__); } while (0)
;
440 assert(reply)do { if ((__builtin_expect(!!(!(reply)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("reply"), "../src/libsystemd/sd-bus/bus-objects.c"
, 440, __PRETTY_FUNCTION__); } while (0)
;
441
442 if (v->x.property.get) {
443
444 bus->current_slot = sd_bus_slot_ref(slot);
445 bus->current_userdata = userdata;
446 r = v->x.property.get(bus, path, interface, property, reply, userdata, error);
447 bus->current_userdata = NULL((void*)0);
448 bus->current_slot = sd_bus_slot_unref(slot);
449
450 if (r < 0)
451 return r;
452 if (sd_bus_error_is_set(error))
453 return -sd_bus_error_get_errno(error);
454 return r;
455 }
456
457 /* Automatic handling if no callback is defined. */
458
459 if (streq(v->x.property.signature, "as")(strcmp((v->x.property.signature),("as")) == 0))
460 return sd_bus_message_append_strv(reply, *(char***) userdata);
461
462 assert(signature_is_single(v->x.property.signature, false))do { if ((__builtin_expect(!!(!(signature_is_single(v->x.property
.signature, 0))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("signature_is_single(v->x.property.signature, false)"),
"../src/libsystemd/sd-bus/bus-objects.c", 462, __PRETTY_FUNCTION__
); } while (0)
;
463 assert(bus_type_is_basic(v->x.property.signature[0]))do { if ((__builtin_expect(!!(!(bus_type_is_basic(v->x.property
.signature[0]))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("bus_type_is_basic(v->x.property.signature[0])"), "../src/libsystemd/sd-bus/bus-objects.c"
, 463, __PRETTY_FUNCTION__); } while (0)
;
464
465 switch (v->x.property.signature[0]) {
466
467 case SD_BUS_TYPE_STRING:
468 case SD_BUS_TYPE_SIGNATURE:
469 p = strempty(*(char**) userdata);
470 break;
471
472 case SD_BUS_TYPE_OBJECT_PATH:
473 p = *(char**) userdata;
474 assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p"), "../src/libsystemd/sd-bus/bus-objects.c"
, 474, __PRETTY_FUNCTION__); } while (0)
;
475 break;
476
477 default:
478 p = userdata;
479 break;
480 }
481
482 return sd_bus_message_append_basic(reply, v->x.property.signature[0], p);
483}
484
485static int invoke_property_set(
486 sd_bus *bus,
487 sd_bus_slot *slot,
488 const sd_bus_vtable *v,
489 const char *path,
490 const char *interface,
491 const char *property,
492 sd_bus_message *value,
493 void *userdata,
494 sd_bus_error *error) {
495
496 int r;
497
498 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 498, __PRETTY_FUNCTION__); } while (0)
;
499 assert(slot)do { if ((__builtin_expect(!!(!(slot)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("slot"), "../src/libsystemd/sd-bus/bus-objects.c"
, 499, __PRETTY_FUNCTION__); } while (0)
;
500 assert(v)do { if ((__builtin_expect(!!(!(v)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("v"), "../src/libsystemd/sd-bus/bus-objects.c"
, 500, __PRETTY_FUNCTION__); } while (0)
;
501 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 501, __PRETTY_FUNCTION__); } while (0)
;
502 assert(interface)do { if ((__builtin_expect(!!(!(interface)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("interface"), "../src/libsystemd/sd-bus/bus-objects.c"
, 502, __PRETTY_FUNCTION__); } while (0)
;
503 assert(property)do { if ((__builtin_expect(!!(!(property)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("property"), "../src/libsystemd/sd-bus/bus-objects.c"
, 503, __PRETTY_FUNCTION__); } while (0)
;
504 assert(value)do { if ((__builtin_expect(!!(!(value)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("value"), "../src/libsystemd/sd-bus/bus-objects.c"
, 504, __PRETTY_FUNCTION__); } while (0)
;
505
506 if (v->x.property.set) {
507
508 bus->current_slot = sd_bus_slot_ref(slot);
509 bus->current_userdata = userdata;
510 r = v->x.property.set(bus, path, interface, property, value, userdata, error);
511 bus->current_userdata = NULL((void*)0);
512 bus->current_slot = sd_bus_slot_unref(slot);
513
514 if (r < 0)
515 return r;
516 if (sd_bus_error_is_set(error))
517 return -sd_bus_error_get_errno(error);
518 return r;
519 }
520
521 /* Automatic handling if no callback is defined. */
522
523 assert(signature_is_single(v->x.property.signature, false))do { if ((__builtin_expect(!!(!(signature_is_single(v->x.property
.signature, 0))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("signature_is_single(v->x.property.signature, false)"),
"../src/libsystemd/sd-bus/bus-objects.c", 523, __PRETTY_FUNCTION__
); } while (0)
;
524 assert(bus_type_is_basic(v->x.property.signature[0]))do { if ((__builtin_expect(!!(!(bus_type_is_basic(v->x.property
.signature[0]))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("bus_type_is_basic(v->x.property.signature[0])"), "../src/libsystemd/sd-bus/bus-objects.c"
, 524, __PRETTY_FUNCTION__); } while (0)
;
525
526 switch (v->x.property.signature[0]) {
527
528 case SD_BUS_TYPE_STRING:
529 case SD_BUS_TYPE_OBJECT_PATH:
530 case SD_BUS_TYPE_SIGNATURE: {
531 const char *p;
532 char *n;
533
534 r = sd_bus_message_read_basic(value, v->x.property.signature[0], &p);
535 if (r < 0)
536 return r;
537
538 n = strdup(p);
539 if (!n)
540 return -ENOMEM12;
541
542 free(*(char**) userdata);
543 *(char**) userdata = n;
544
545 break;
546 }
547
548 default:
549 r = sd_bus_message_read_basic(value, v->x.property.signature[0], userdata);
550 if (r < 0)
551 return r;
552
553 break;
554 }
555
556 return 1;
557}
558
559static int property_get_set_callbacks_run(
560 sd_bus *bus,
561 sd_bus_message *m,
562 struct vtable_member *c,
563 bool_Bool require_fallback,
564 bool_Bool is_get,
565 bool_Bool *found_object) {
566
567 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
568 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *reply = NULL((void*)0);
569 sd_bus_slot *slot;
570 void *u = NULL((void*)0);
571 int r;
572
573 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 573, __PRETTY_FUNCTION__); } while (0)
;
574 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 574, __PRETTY_FUNCTION__); } while (0)
;
575 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-objects.c"
, 575, __PRETTY_FUNCTION__); } while (0)
;
576 assert(found_object)do { if ((__builtin_expect(!!(!(found_object)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("found_object"), "../src/libsystemd/sd-bus/bus-objects.c"
, 576, __PRETTY_FUNCTION__); } while (0)
;
577
578 if (require_fallback && !c->parent->is_fallback)
579 return 0;
580
581 r = vtable_property_get_userdata(bus, m->path, c, &u, &error);
582 if (r <= 0)
583 return bus_maybe_reply_error(m, r, &error);
584 if (bus->nodes_modified)
585 return 0;
586
587 slot = container_of(c->parent, sd_bus_slot, node_vtable)__extension__ ({ const typeof( ((sd_bus_slot*)0)->node_vtable
) *__unique_prefix_A43 = ((c->parent)); (sd_bus_slot*)( (
char *)__unique_prefix_A43 - __builtin_offsetof(sd_bus_slot, node_vtable
) ); })
;
588
589 *found_object = true1;
590
591 r = sd_bus_message_new_method_return(m, &reply);
592 if (r < 0)
593 return r;
594
595 if (is_get) {
596 /* Note that we do not protect against reexecution
597 * here (using the last_iteration check, see below),
598 * should the node tree have changed and we got called
599 * again. We assume that property Get() calls are
600 * ultimately without side-effects or if they aren't
601 * then at least idempotent. */
602
603 r = sd_bus_message_open_container(reply, 'v', c->vtable->x.property.signature);
604 if (r < 0)
605 return r;
606
607 /* Note that we do not do an access check here. Read
608 * access to properties is always unrestricted, since
609 * PropertiesChanged signals broadcast contents
610 * anyway. */
611
612 r = invoke_property_get(bus, slot, c->vtable, m->path, c->interface, c->member, reply, u, &error);
613 if (r < 0)
614 return bus_maybe_reply_error(m, r, &error);
615
616 if (bus->nodes_modified)
617 return 0;
618
619 r = sd_bus_message_close_container(reply);
620 if (r < 0)
621 return r;
622
623 } else {
624 const char *signature = NULL((void*)0);
625 char type = 0;
626
627 if (c->vtable->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
628 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_PROPERTY_READ_ONLY"org.freedesktop.DBus.Error.PropertyReadOnly", "Property '%s' is not writable.", c->member);
629
630 /* Avoid that we call the set routine more than once
631 * if the processing of this message got restarted
632 * because the node tree changed. */
633 if (c->last_iteration == bus->iteration_counter)
634 return 0;
635
636 c->last_iteration = bus->iteration_counter;
637
638 r = sd_bus_message_peek_type(m, &type, &signature);
639 if (r < 0)
640 return r;
641
642 if (type != 'v' || !streq(strempty(signature), strempty(c->vtable->x.property.signature))(strcmp((strempty(signature)),(strempty(c->vtable->x.property
.signature))) == 0)
)
643 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Incorrect parameters for property '%s', expected '%s', got '%s'.", c->member, strempty(c->vtable->x.property.signature), strempty(signature));
644
645 r = sd_bus_message_enter_container(m, 'v', c->vtable->x.property.signature);
646 if (r < 0)
647 return r;
648
649 r = check_access(bus, m, c, &error);
650 if (r < 0)
651 return bus_maybe_reply_error(m, r, &error);
652
653 r = invoke_property_set(bus, slot, c->vtable, m->path, c->interface, c->member, m, u, &error);
654 if (r < 0)
655 return bus_maybe_reply_error(m, r, &error);
656
657 if (bus->nodes_modified)
658 return 0;
659
660 r = sd_bus_message_exit_container(m);
661 if (r < 0)
662 return r;
663 }
664
665 r = sd_bus_send(bus, reply, NULL((void*)0));
666 if (r < 0)
667 return r;
668
669 return 1;
670}
671
672static int vtable_append_one_property(
673 sd_bus *bus,
674 sd_bus_message *reply,
675 const char *path,
676 struct node_vtable *c,
677 const sd_bus_vtable *v,
678 void *userdata,
679 sd_bus_error *error) {
680
681 sd_bus_slot *slot;
682 int r;
683
684 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 684, __PRETTY_FUNCTION__); } while (0)
;
685 assert(reply)do { if ((__builtin_expect(!!(!(reply)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("reply"), "../src/libsystemd/sd-bus/bus-objects.c"
, 685, __PRETTY_FUNCTION__); } while (0)
;
686 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 686, __PRETTY_FUNCTION__); } while (0)
;
687 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-objects.c"
, 687, __PRETTY_FUNCTION__); } while (0)
;
688 assert(v)do { if ((__builtin_expect(!!(!(v)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("v"), "../src/libsystemd/sd-bus/bus-objects.c"
, 688, __PRETTY_FUNCTION__); } while (0)
;
689
690 r = sd_bus_message_open_container(reply, 'e', "sv");
691 if (r < 0)
692 return r;
693
694 r = sd_bus_message_append(reply, "s", v->x.property.member);
695 if (r < 0)
696 return r;
697
698 r = sd_bus_message_open_container(reply, 'v', v->x.property.signature);
699 if (r < 0)
700 return r;
701
702 slot = container_of(c, sd_bus_slot, node_vtable)__extension__ ({ const typeof( ((sd_bus_slot*)0)->node_vtable
) *__unique_prefix_A44 = ((c)); (sd_bus_slot*)( (char *)__unique_prefix_A44
- __builtin_offsetof(sd_bus_slot, node_vtable) ); })
;
703
704 r = invoke_property_get(bus, slot, v, path, c->interface, v->x.property.member, reply, vtable_property_convert_userdata(v, userdata), error);
705 if (r < 0)
706 return r;
707 if (bus->nodes_modified)
708 return 0;
709
710 r = sd_bus_message_close_container(reply);
711 if (r < 0)
712 return r;
713
714 r = sd_bus_message_close_container(reply);
715 if (r < 0)
716 return r;
717
718 return 0;
719}
720
721static int vtable_append_all_properties(
722 sd_bus *bus,
723 sd_bus_message *reply,
724 const char *path,
725 struct node_vtable *c,
726 void *userdata,
727 sd_bus_error *error) {
728
729 const sd_bus_vtable *v;
730 int r;
731
732 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 732, __PRETTY_FUNCTION__); } while (0)
;
733 assert(reply)do { if ((__builtin_expect(!!(!(reply)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("reply"), "../src/libsystemd/sd-bus/bus-objects.c"
, 733, __PRETTY_FUNCTION__); } while (0)
;
734 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 734, __PRETTY_FUNCTION__); } while (0)
;
735 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/libsystemd/sd-bus/bus-objects.c"
, 735, __PRETTY_FUNCTION__); } while (0)
;
736
737 if (c->vtable[0].flags & SD_BUS_VTABLE_HIDDEN)
738 return 1;
739
740 for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
741 if (!IN_SET(v->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){_SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY
})/sizeof(int)]; switch(v->type) { case _SD_BUS_VTABLE_PROPERTY
: case _SD_BUS_VTABLE_WRITABLE_PROPERTY: _found = 1; break; default
: break; } _found; })
)
742 continue;
743
744 if (v->flags & SD_BUS_VTABLE_HIDDEN)
745 continue;
746
747 if (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)
748 continue;
749
750 r = vtable_append_one_property(bus, reply, path, c, v, userdata, error);
751 if (r < 0)
752 return r;
753 if (bus->nodes_modified)
754 return 0;
755 }
756
757 return 1;
758}
759
760static int property_get_all_callbacks_run(
761 sd_bus *bus,
762 sd_bus_message *m,
763 struct node_vtable *first,
764 bool_Bool require_fallback,
765 const char *iface,
766 bool_Bool *found_object) {
767
768 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *reply = NULL((void*)0);
769 struct node_vtable *c;
770 bool_Bool found_interface;
771 int r;
772
773 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 773, __PRETTY_FUNCTION__); } while (0)
;
774 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 774, __PRETTY_FUNCTION__); } while (0)
;
775 assert(found_object)do { if ((__builtin_expect(!!(!(found_object)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("found_object"), "../src/libsystemd/sd-bus/bus-objects.c"
, 775, __PRETTY_FUNCTION__); } while (0)
;
776
777 r = sd_bus_message_new_method_return(m, &reply);
778 if (r < 0)
779 return r;
780
781 r = sd_bus_message_open_container(reply, 'a', "{sv}");
782 if (r < 0)
783 return r;
784
785 found_interface = !iface ||
786 streq(iface, "org.freedesktop.DBus.Properties")(strcmp((iface),("org.freedesktop.DBus.Properties")) == 0) ||
787 streq(iface, "org.freedesktop.DBus.Peer")(strcmp((iface),("org.freedesktop.DBus.Peer")) == 0) ||
788 streq(iface, "org.freedesktop.DBus.Introspectable")(strcmp((iface),("org.freedesktop.DBus.Introspectable")) == 0
)
;
789
790 LIST_FOREACH(vtables, c, first)for ((c) = (first); (c); (c) = (c)->vtables_next) {
791 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
792 void *u;
793
794 if (require_fallback && !c->is_fallback)
795 continue;
796
797 r = node_vtable_get_userdata(bus, m->path, c, &u, &error);
798 if (r < 0)
799 return bus_maybe_reply_error(m, r, &error);
800 if (bus->nodes_modified)
801 return 0;
802 if (r == 0)
803 continue;
804
805 *found_object = true1;
806
807 if (iface && !streq(c->interface, iface)(strcmp((c->interface),(iface)) == 0))
808 continue;
809 found_interface = true1;
810
811 r = vtable_append_all_properties(bus, reply, m->path, c, u, &error);
812 if (r < 0)
813 return bus_maybe_reply_error(m, r, &error);
814 if (bus->nodes_modified)
815 return 0;
816 }
817
818 if (!*found_object)
819 return 0;
820
821 if (!found_interface) {
822 r = sd_bus_reply_method_errorf(
823 m,
824 SD_BUS_ERROR_UNKNOWN_INTERFACE"org.freedesktop.DBus.Error.UnknownInterface",
825 "Unknown interface '%s'.", iface);
826 if (r < 0)
827 return r;
828
829 return 1;
830 }
831
832 r = sd_bus_message_close_container(reply);
833 if (r < 0)
834 return r;
835
836 r = sd_bus_send(bus, reply, NULL((void*)0));
837 if (r < 0)
838 return r;
839
840 return 1;
841}
842
843static int bus_node_exists(
844 sd_bus *bus,
845 struct node *n,
846 const char *path,
847 bool_Bool require_fallback) {
848
849 struct node_vtable *c;
850 struct node_callback *k;
851 int r;
852
853 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 853, __PRETTY_FUNCTION__); } while (0)
;
854 assert(n)do { if ((__builtin_expect(!!(!(n)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n"), "../src/libsystemd/sd-bus/bus-objects.c"
, 854, __PRETTY_FUNCTION__); } while (0)
;
855 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 855, __PRETTY_FUNCTION__); } while (0)
;
856
857 /* Tests if there's anything attached directly to this node
858 * for the specified path */
859
860 if (!require_fallback && (n->enumerators || n->object_managers))
861 return true1;
862
863 LIST_FOREACH(callbacks, k, n->callbacks)for ((k) = (n->callbacks); (k); (k) = (k)->callbacks_next
)
{
864 if (require_fallback && !k->is_fallback)
865 continue;
866
867 return 1;
868 }
869
870 LIST_FOREACH(vtables, c, n->vtables)for ((c) = (n->vtables); (c); (c) = (c)->vtables_next) {
871 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
872
873 if (require_fallback && !c->is_fallback)
874 continue;
875
876 r = node_vtable_get_userdata(bus, path, c, NULL((void*)0), &error);
877 if (r != 0)
878 return r;
879 if (bus->nodes_modified)
880 return 0;
881 }
882
883 return 0;
884}
885
886static int process_introspect(
887 sd_bus *bus,
888 sd_bus_message *m,
889 struct node *n,
890 bool_Bool require_fallback,
891 bool_Bool *found_object) {
892
893 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
894 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *reply = NULL((void*)0);
895 _cleanup_set_free_free___attribute__((cleanup(set_free_freep))) Set *s = NULL((void*)0);
896 const char *previous_interface = NULL((void*)0);
897 struct introspect intro;
898 struct node_vtable *c;
899 bool_Bool empty;
900 int r;
901
902 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 902, __PRETTY_FUNCTION__); } while (0)
;
903 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 903, __PRETTY_FUNCTION__); } while (0)
;
904 assert(n)do { if ((__builtin_expect(!!(!(n)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n"), "../src/libsystemd/sd-bus/bus-objects.c"
, 904, __PRETTY_FUNCTION__); } while (0)
;
905 assert(found_object)do { if ((__builtin_expect(!!(!(found_object)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("found_object"), "../src/libsystemd/sd-bus/bus-objects.c"
, 905, __PRETTY_FUNCTION__); } while (0)
;
906
907 r = get_child_nodes(bus, m->path, n, 0, &s, &error);
908 if (r < 0)
909 return bus_maybe_reply_error(m, r, &error);
910 if (bus->nodes_modified)
911 return 0;
912
913 r = introspect_begin(&intro, bus->trusted);
914 if (r < 0)
915 return r;
916
917 r = introspect_write_default_interfaces(&intro, !require_fallback && n->object_managers);
918 if (r < 0)
919 return r;
920
921 empty = set_isempty(s);
922
923 LIST_FOREACH(vtables, c, n->vtables)for ((c) = (n->vtables); (c); (c) = (c)->vtables_next) {
924 if (require_fallback && !c->is_fallback)
925 continue;
926
927 r = node_vtable_get_userdata(bus, m->path, c, NULL((void*)0), &error);
928 if (r < 0) {
929 r = bus_maybe_reply_error(m, r, &error);
930 goto finish;
931 }
932 if (bus->nodes_modified) {
933 r = 0;
934 goto finish;
935 }
936 if (r == 0)
937 continue;
938
939 empty = false0;
940
941 if (c->vtable[0].flags & SD_BUS_VTABLE_HIDDEN)
942 continue;
943
944 if (!streq_ptr(previous_interface, c->interface)) {
945
946 if (previous_interface)
947 fputs(" </interface>\n", intro.f);
948
949 fprintf(intro.f, " <interface name=\"%s\">\n", c->interface);
950 }
951
952 r = introspect_write_interface(&intro, c->vtable);
953 if (r < 0)
954 goto finish;
955
956 previous_interface = c->interface;
957 }
958
959 if (previous_interface)
960 fputs(" </interface>\n", intro.f);
961
962 if (empty) {
963 /* Nothing?, let's see if we exist at all, and if not
964 * refuse to do anything */
965 r = bus_node_exists(bus, n, m->path, require_fallback);
966 if (r <= 0) {
967 r = bus_maybe_reply_error(m, r, &error);
968 goto finish;
969 }
970 if (bus->nodes_modified) {
971 r = 0;
972 goto finish;
973 }
974 }
975
976 *found_object = true1;
977
978 r = introspect_write_child_nodes(&intro, s, m->path);
979 if (r < 0)
980 goto finish;
981
982 r = introspect_finish(&intro, bus, m, &reply);
983 if (r < 0)
984 goto finish;
985
986 r = sd_bus_send(bus, reply, NULL((void*)0));
987 if (r < 0)
988 goto finish;
989
990 r = 1;
991
992finish:
993 introspect_free(&intro);
994 return r;
995}
996
997static int object_manager_serialize_path(
998 sd_bus *bus,
999 sd_bus_message *reply,
1000 const char *prefix,
1001 const char *path,
1002 bool_Bool require_fallback,
1003 sd_bus_error *error) {
1004
1005 const char *previous_interface = NULL((void*)0);
1006 bool_Bool found_something = false0;
1007 struct node_vtable *i;
1008 struct node *n;
1009 int r;
1010
1011 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1011, __PRETTY_FUNCTION__); } while (0)
;
1012 assert(reply)do { if ((__builtin_expect(!!(!(reply)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("reply"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1012, __PRETTY_FUNCTION__); } while (0)
;
1013 assert(prefix)do { if ((__builtin_expect(!!(!(prefix)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("prefix"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1013, __PRETTY_FUNCTION__); } while (0)
;
1014 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1014, __PRETTY_FUNCTION__); } while (0)
;
1015 assert(error)do { if ((__builtin_expect(!!(!(error)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("error"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1015, __PRETTY_FUNCTION__); } while (0)
;
1016
1017 n = hashmap_get(bus->nodes, prefix);
1018 if (!n)
1019 return 0;
1020
1021 LIST_FOREACH(vtables, i, n->vtables)for ((i) = (n->vtables); (i); (i) = (i)->vtables_next) {
1022 void *u;
1023
1024 if (require_fallback && !i->is_fallback)
1025 continue;
1026
1027 r = node_vtable_get_userdata(bus, path, i, &u, error);
1028 if (r < 0)
1029 return r;
1030 if (bus->nodes_modified)
1031 return 0;
1032 if (r == 0)
1033 continue;
1034
1035 if (!found_something) {
1036
1037 /* Open the object part */
1038
1039 r = sd_bus_message_open_container(reply, 'e', "oa{sa{sv}}");
1040 if (r < 0)
1041 return r;
1042
1043 r = sd_bus_message_append(reply, "o", path);
1044 if (r < 0)
1045 return r;
1046
1047 r = sd_bus_message_open_container(reply, 'a', "{sa{sv}}");
1048 if (r < 0)
1049 return r;
1050
1051 r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.Peer", 0);
1052 if (r < 0)
1053 return r;
1054
1055 r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.Introspectable", 0);
1056 if (r < 0)
1057 return r;
1058
1059 r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.Properties", 0);
1060 if (r < 0)
1061 return r;
1062
1063 r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.ObjectManager", 0);
1064 if (r < 0)
1065 return r;
1066
1067 found_something = true1;
1068 }
1069
1070 if (!streq_ptr(previous_interface, i->interface)) {
1071
1072 /* Maybe close the previous interface part */
1073
1074 if (previous_interface) {
1075 r = sd_bus_message_close_container(reply);
1076 if (r < 0)
1077 return r;
1078
1079 r = sd_bus_message_close_container(reply);
1080 if (r < 0)
1081 return r;
1082 }
1083
1084 /* Open the new interface part */
1085
1086 r = sd_bus_message_open_container(reply, 'e', "sa{sv}");
1087 if (r < 0)
1088 return r;
1089
1090 r = sd_bus_message_append(reply, "s", i->interface);
1091 if (r < 0)
1092 return r;
1093
1094 r = sd_bus_message_open_container(reply, 'a', "{sv}");
1095 if (r < 0)
1096 return r;
1097 }
1098
1099 r = vtable_append_all_properties(bus, reply, path, i, u, error);
1100 if (r < 0)
1101 return r;
1102 if (bus->nodes_modified)
1103 return 0;
1104
1105 previous_interface = i->interface;
1106 }
1107
1108 if (previous_interface) {
1109 r = sd_bus_message_close_container(reply);
1110 if (r < 0)
1111 return r;
1112
1113 r = sd_bus_message_close_container(reply);
1114 if (r < 0)
1115 return r;
1116 }
1117
1118 if (found_something) {
1119 r = sd_bus_message_close_container(reply);
1120 if (r < 0)
1121 return r;
1122
1123 r = sd_bus_message_close_container(reply);
1124 if (r < 0)
1125 return r;
1126 }
1127
1128 return 1;
1129}
1130
1131static int object_manager_serialize_path_and_fallbacks(
1132 sd_bus *bus,
1133 sd_bus_message *reply,
1134 const char *path,
1135 sd_bus_error *error) {
1136
1137 _cleanup_free___attribute__((cleanup(freep))) char *prefix = NULL((void*)0);
1138 size_t pl;
1139 int r;
1140
1141 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1141, __PRETTY_FUNCTION__); } while (0)
;
1142 assert(reply)do { if ((__builtin_expect(!!(!(reply)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("reply"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1142, __PRETTY_FUNCTION__); } while (0)
;
1143 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1143, __PRETTY_FUNCTION__); } while (0)
;
1144 assert(error)do { if ((__builtin_expect(!!(!(error)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("error"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1144, __PRETTY_FUNCTION__); } while (0)
;
1145
1146 /* First, add all vtables registered for this path */
1147 r = object_manager_serialize_path(bus, reply, path, path, false0, error);
1148 if (r < 0)
1149 return r;
1150 if (bus->nodes_modified)
1151 return 0;
1152
1153 /* Second, add fallback vtables registered for any of the prefixes */
1154 pl = strlen(path);
1155 assert(pl <= BUS_PATH_SIZE_MAX)do { if ((__builtin_expect(!!(!(pl <= (64*1024))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("pl <= BUS_PATH_SIZE_MAX"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1155, __PRETTY_FUNCTION__); } while (0)
;
1156 prefix = new(char, pl + 1)((char*) malloc_multiply(sizeof(char), (pl + 1)));
1157 if (!prefix)
1158 return -ENOMEM12;
1159
1160 OBJECT_PATH_FOREACH_PREFIX(prefix, path)for (char *_slash = ({ strcpy((prefix), (path)); (strcmp(((prefix
)),("/")) == 0) ? ((void*)0) : strrchr((prefix), '/'); }) ; _slash
&& !(_slash[(_slash) == (prefix)] = 0); _slash = (strcmp
(((prefix)),("/")) == 0) ? ((void*)0) : strrchr((prefix), '/'
))
{
1161 r = object_manager_serialize_path(bus, reply, prefix, path, true1, error);
1162 if (r < 0)
1163 return r;
1164 if (bus->nodes_modified)
1165 return 0;
1166 }
1167
1168 return 0;
1169}
1170
1171static int process_get_managed_objects(
1172 sd_bus *bus,
1173 sd_bus_message *m,
1174 struct node *n,
1175 bool_Bool require_fallback,
1176 bool_Bool *found_object) {
1177
1178 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
1179 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *reply = NULL((void*)0);
1180 _cleanup_set_free_free___attribute__((cleanup(set_free_freep))) Set *s = NULL((void*)0);
1181 Iterator i;
1182 char *path;
1183 int r;
1184
1185 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1185, __PRETTY_FUNCTION__); } while (0)
;
1186 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1186, __PRETTY_FUNCTION__); } while (0)
;
1187 assert(n)do { if ((__builtin_expect(!!(!(n)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1187, __PRETTY_FUNCTION__); } while (0)
;
1188 assert(found_object)do { if ((__builtin_expect(!!(!(found_object)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("found_object"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1188, __PRETTY_FUNCTION__); } while (0)
;
1189
1190 /* Spec says, GetManagedObjects() is only implemented on the root of a
1191 * sub-tree. Therefore, we require a registered object-manager on
1192 * exactly the queried path, otherwise, we refuse to respond. */
1193
1194 if (require_fallback || !n->object_managers)
1195 return 0;
1196
1197 r = get_child_nodes(bus, m->path, n, CHILDREN_RECURSIVE, &s, &error);
1198 if (r < 0)
1199 return bus_maybe_reply_error(m, r, &error);
1200 if (bus->nodes_modified)
1201 return 0;
1202
1203 r = sd_bus_message_new_method_return(m, &reply);
1204 if (r < 0)
1205 return r;
1206
1207 r = sd_bus_message_open_container(reply, 'a', "{oa{sa{sv}}}");
1208 if (r < 0)
1209 return r;
1210
1211 SET_FOREACH(path, s, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((s), &(i), (void**)
&(path)); )
{
1212 r = object_manager_serialize_path_and_fallbacks(bus, reply, path, &error);
1213 if (r < 0)
1214 return bus_maybe_reply_error(m, r, &error);
1215
1216 if (bus->nodes_modified)
1217 return 0;
1218 }
1219
1220 r = sd_bus_message_close_container(reply);
1221 if (r < 0)
1222 return r;
1223
1224 r = sd_bus_send(bus, reply, NULL((void*)0));
1225 if (r < 0)
1226 return r;
1227
1228 return 1;
1229}
1230
1231static int object_find_and_run(
1232 sd_bus *bus,
1233 sd_bus_message *m,
1234 const char *p,
1235 bool_Bool require_fallback,
1236 bool_Bool *found_object) {
1237
1238 struct node *n;
1239 struct vtable_member vtable_key, *v;
1240 int r;
1241
1242 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1242, __PRETTY_FUNCTION__); } while (0)
;
1243 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1243, __PRETTY_FUNCTION__); } while (0)
;
1244 assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1244, __PRETTY_FUNCTION__); } while (0)
;
1245 assert(found_object)do { if ((__builtin_expect(!!(!(found_object)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("found_object"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1245, __PRETTY_FUNCTION__); } while (0)
;
1246
1247 n = hashmap_get(bus->nodes, p);
1248 if (!n)
1249 return 0;
1250
1251 /* First, try object callbacks */
1252 r = node_callbacks_run(bus, m, n->callbacks, require_fallback, found_object);
1253 if (r != 0)
1254 return r;
1255 if (bus->nodes_modified)
1256 return 0;
1257
1258 if (!m->interface || !m->member)
1259 return 0;
1260
1261 /* Then, look for a known method */
1262 vtable_key.path = (char*) p;
1263 vtable_key.interface = m->interface;
1264 vtable_key.member = m->member;
1265
1266 v = hashmap_get(bus->vtable_methods, &vtable_key);
1267 if (v) {
1268 r = method_callbacks_run(bus, m, v, require_fallback, found_object);
1269 if (r != 0)
1270 return r;
1271 if (bus->nodes_modified)
1272 return 0;
1273 }
1274
1275 /* Then, look for a known property */
1276 if (streq(m->interface, "org.freedesktop.DBus.Properties")(strcmp((m->interface),("org.freedesktop.DBus.Properties")
) == 0)
) {
1277 bool_Bool get = false0;
1278
1279 get = streq(m->member, "Get")(strcmp((m->member),("Get")) == 0);
1280
1281 if (get || streq(m->member, "Set")(strcmp((m->member),("Set")) == 0)) {
1282
1283 r = sd_bus_message_rewind(m, true1);
1284 if (r < 0)
1285 return r;
1286
1287 vtable_key.path = (char*) p;
1288
1289 r = sd_bus_message_read(m, "ss", &vtable_key.interface, &vtable_key.member);
1290 if (r < 0)
1291 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Expected interface and member parameters");
1292
1293 v = hashmap_get(bus->vtable_properties, &vtable_key);
1294 if (v) {
1295 r = property_get_set_callbacks_run(bus, m, v, require_fallback, get, found_object);
1296 if (r != 0)
1297 return r;
1298 }
1299
1300 } else if (streq(m->member, "GetAll")(strcmp((m->member),("GetAll")) == 0)) {
1301 const char *iface;
1302
1303 r = sd_bus_message_rewind(m, true1);
1304 if (r < 0)
1305 return r;
1306
1307 r = sd_bus_message_read(m, "s", &iface);
1308 if (r < 0)
1309 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Expected interface parameter");
1310
1311 if (iface[0] == 0)
1312 iface = NULL((void*)0);
1313
1314 r = property_get_all_callbacks_run(bus, m, n->vtables, require_fallback, iface, found_object);
1315 if (r != 0)
1316 return r;
1317 }
1318
1319 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1320
1321 if (!isempty(sd_bus_message_get_signature(m, true1)))
1322 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Expected no parameters");
1323
1324 r = process_introspect(bus, m, n, require_fallback, found_object);
1325 if (r != 0)
1326 return r;
1327
1328 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.ObjectManager", "GetManagedObjects")) {
1329
1330 if (!isempty(sd_bus_message_get_signature(m, true1)))
1331 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Expected no parameters");
1332
1333 r = process_get_managed_objects(bus, m, n, require_fallback, found_object);
1334 if (r != 0)
1335 return r;
1336 }
1337
1338 if (bus->nodes_modified)
1339 return 0;
1340
1341 if (!*found_object) {
1342 r = bus_node_exists(bus, n, m->path, require_fallback);
1343 if (r < 0)
1344 return bus_maybe_reply_error(m, r, NULL((void*)0));
1345 if (bus->nodes_modified)
1346 return 0;
1347 if (r > 0)
1348 *found_object = true1;
1349 }
1350
1351 return 0;
1352}
1353
1354int bus_process_object(sd_bus *bus, sd_bus_message *m) {
1355 _cleanup_free___attribute__((cleanup(freep))) char *prefix = NULL((void*)0);
1356 int r;
1357 size_t pl;
1358 bool_Bool found_object = false0;
1359
1360 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1360, __PRETTY_FUNCTION__); } while (0)
;
1361 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1361, __PRETTY_FUNCTION__); } while (0)
;
1362
1363 if (bus->is_monitor)
1364 return 0;
1365
1366 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1367 return 0;
1368
1369 if (hashmap_isempty(bus->nodes))
1370 return 0;
1371
1372 /* Never respond to broadcast messages */
1373 if (bus->bus_client && !m->destination)
1374 return 0;
1375
1376 assert(m->path)do { if ((__builtin_expect(!!(!(m->path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m->path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1376, __PRETTY_FUNCTION__); } while (0)
;
1377 assert(m->member)do { if ((__builtin_expect(!!(!(m->member)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m->member"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1377, __PRETTY_FUNCTION__); } while (0)
;
1378
1379 pl = strlen(m->path);
1380 assert(pl <= BUS_PATH_SIZE_MAX)do { if ((__builtin_expect(!!(!(pl <= (64*1024))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("pl <= BUS_PATH_SIZE_MAX"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1380, __PRETTY_FUNCTION__); } while (0)
;
1381 prefix = new(char, pl + 1)((char*) malloc_multiply(sizeof(char), (pl + 1)));
1382 if (!prefix)
1383 return -ENOMEM12;
1384
1385 do {
1386 bus->nodes_modified = false0;
1387
1388 r = object_find_and_run(bus, m, m->path, false0, &found_object);
1389 if (r != 0)
1390 return r;
1391
1392 /* Look for fallback prefixes */
1393 OBJECT_PATH_FOREACH_PREFIX(prefix, m->path)for (char *_slash = ({ strcpy((prefix), (m->path)); (strcmp
(((prefix)),("/")) == 0) ? ((void*)0) : strrchr((prefix), '/'
); }) ; _slash && !(_slash[(_slash) == (prefix)] = 0)
; _slash = (strcmp(((prefix)),("/")) == 0) ? ((void*)0) : strrchr
((prefix), '/'))
{
1394
1395 if (bus->nodes_modified)
1396 break;
1397
1398 r = object_find_and_run(bus, m, prefix, true1, &found_object);
1399 if (r != 0)
1400 return r;
1401 }
1402
1403 } while (bus->nodes_modified);
1404
1405 if (!found_object)
1406 return 0;
1407
1408 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Get") ||
1409 sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Set"))
1410 r = sd_bus_reply_method_errorf(
1411 m,
1412 SD_BUS_ERROR_UNKNOWN_PROPERTY"org.freedesktop.DBus.Error.UnknownProperty",
1413 "Unknown property or interface.");
1414 else
1415 r = sd_bus_reply_method_errorf(
1416 m,
1417 SD_BUS_ERROR_UNKNOWN_METHOD"org.freedesktop.DBus.Error.UnknownMethod",
1418 "Unknown method '%s' or interface '%s'.", m->member, m->interface);
1419
1420 if (r < 0)
1421 return r;
1422
1423 return 1;
1424}
1425
1426static struct node *bus_node_allocate(sd_bus *bus, const char *path) {
1427 struct node *n, *parent;
1428 const char *e;
1429 _cleanup_free___attribute__((cleanup(freep))) char *s = NULL((void*)0);
1430 char *p;
1431 int r;
1432
1433 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1433, __PRETTY_FUNCTION__); } while (0)
;
1434 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1434, __PRETTY_FUNCTION__); } while (0)
;
1435 assert(path[0] == '/')do { if ((__builtin_expect(!!(!(path[0] == '/')),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path[0] == '/'"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1435, __PRETTY_FUNCTION__); } while (0)
;
1436
1437 n = hashmap_get(bus->nodes, path);
1438 if (n)
1439 return n;
1440
1441 r = hashmap_ensure_allocated(&bus->nodes, &string_hash_ops)internal_hashmap_ensure_allocated(&bus->nodes, &string_hash_ops
)
;
1442 if (r < 0)
1443 return NULL((void*)0);
1444
1445 s = strdup(path);
1446 if (!s)
1447 return NULL((void*)0);
1448
1449 if (streq(path, "/")(strcmp((path),("/")) == 0))
1450 parent = NULL((void*)0);
1451 else {
1452 e = strrchr(path, '/');
1453 assert(e)do { if ((__builtin_expect(!!(!(e)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("e"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1453, __PRETTY_FUNCTION__); } while (0)
;
1454
1455 p = strndupa(path, MAX(1, e - path))(__extension__ ({ const char *__old = (path); size_t __len = strnlen
(__old, (__extension__ ({ const typeof((1)) __unique_prefix_A45
= ((1)); const typeof((e - path)) __unique_prefix_B46 = ((e -
path)); __unique_prefix_A45 > __unique_prefix_B46 ? __unique_prefix_A45
: __unique_prefix_B46; }))); char *__new = (char *) __builtin_alloca
(__len + 1); __new[__len] = '\0'; (char *) memcpy (__new, __old
, __len); }))
;
1456
1457 parent = bus_node_allocate(bus, p);
1458 if (!parent)
1459 return NULL((void*)0);
1460 }
1461
1462 n = new0(struct node, 1)((struct node*) calloc((1), sizeof(struct node)));
1463 if (!n)
1464 return NULL((void*)0);
1465
1466 n->parent = parent;
1467 n->path = TAKE_PTR(s)({ typeof(s) _ptr_ = (s); (s) = ((void*)0); _ptr_; });
1468
1469 r = hashmap_put(bus->nodes, n->path, n);
1470 if (r < 0) {
1471 free(n->path);
1472 return mfree(n);
1473 }
1474
1475 if (parent)
1476 LIST_PREPEND(siblings, parent->child, n)do { typeof(*(parent->child)) **_head = &(parent->child
), *_item = (n); do { if ((__builtin_expect(!!(!(_item)),0)))
log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1476, __PRETTY_FUNCTION__); } while (0); if ((_item->siblings_next
= *_head)) _item->siblings_next->siblings_prev = _item
; _item->siblings_prev = ((void*)0); *_head = _item; } while
(0)
;
1477
1478 return n;
1479}
1480
1481void bus_node_gc(sd_bus *b, struct node *n) {
1482 assert(b)do { if ((__builtin_expect(!!(!(b)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("b"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1482, __PRETTY_FUNCTION__); } while (0)
;
1483
1484 if (!n)
1485 return;
1486
1487 if (n->child ||
1488 n->callbacks ||
1489 n->vtables ||
1490 n->enumerators ||
1491 n->object_managers)
1492 return;
1493
1494 assert_se(hashmap_remove(b->nodes, n->path) == n)do { if ((__builtin_expect(!!(!(hashmap_remove(b->nodes, n
->path) == n)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("hashmap_remove(b->nodes, n->path) == n"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1494, __PRETTY_FUNCTION__); } while (0)
;
1495
1496 if (n->parent)
1497 LIST_REMOVE(siblings, n->parent->child, n)do { typeof(*(n->parent->child)) **_head = &(n->
parent->child), *_item = (n); do { if ((__builtin_expect(!
!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, (
"_item"), "../src/libsystemd/sd-bus/bus-objects.c", 1497, __PRETTY_FUNCTION__
); } while (0); if (_item->siblings_next) _item->siblings_next
->siblings_prev = _item->siblings_prev; if (_item->siblings_prev
) _item->siblings_prev->siblings_next = _item->siblings_next
; else { do { if ((__builtin_expect(!!(!(*_head == _item)),0)
)) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*_head == _item"
), "../src/libsystemd/sd-bus/bus-objects.c", 1497, __PRETTY_FUNCTION__
); } while (0); *_head = _item->siblings_next; } _item->
siblings_next = _item->siblings_prev = ((void*)0); } while
(0)
;
1498
1499 free(n->path);
1500 bus_node_gc(b, n->parent);
1501 free(n);
1502}
1503
1504static int bus_find_parent_object_manager(sd_bus *bus, struct node **out, const char *path) {
1505 struct node *n;
1506
1507 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1507, __PRETTY_FUNCTION__); } while (0)
;
46
Taking false branch
47
Loop condition is false. Exiting loop
1508 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1508, __PRETTY_FUNCTION__); } while (0)
;
48
Assuming 'path' is non-null
49
Taking false branch
50
Loop condition is false. Exiting loop
1509
1510 n = hashmap_get(bus->nodes, path);
1511 if (!n) {
51
Assuming 'n' is null
52
Taking true branch
1512 _cleanup_free___attribute__((cleanup(freep))) char *prefix = NULL((void*)0);
1513 size_t pl;
1514
1515 pl = strlen(path);
1516 assert(pl <= BUS_PATH_SIZE_MAX)do { if ((__builtin_expect(!!(!(pl <= (64*1024))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("pl <= BUS_PATH_SIZE_MAX"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1516, __PRETTY_FUNCTION__); } while (0)
;
53
Assuming the condition is true
54
Taking false branch
55
Loop condition is false. Exiting loop
1517 prefix = new(char, pl + 1)((char*) malloc_multiply(sizeof(char), (pl + 1)));
56
Calling 'malloc_multiply'
59
Returned allocated memory
1518 if (!prefix)
60
Assuming 'prefix' is non-null
61
Taking false branch
1519 return -ENOMEM12;
1520
1521 OBJECT_PATH_FOREACH_PREFIX(prefix, path)for (char *_slash = ({ strcpy((prefix), (path)); (strcmp(((prefix
)),("/")) == 0) ? ((void*)0) : strrchr((prefix), '/'); }) ; _slash
&& !(_slash[(_slash) == (prefix)] = 0); _slash = (strcmp
(((prefix)),("/")) == 0) ? ((void*)0) : strrchr((prefix), '/'
))
{
62
Assuming the condition is true
63
'?' condition is true
1522 n = hashmap_get(bus->nodes, prefix);
1523 if (n)
1524 break;
1525 }
1526 }
1527
1528 while (n && !n->object_managers)
64
Potential leak of memory pointed to by 'prefix'
1529 n = n->parent;
1530
1531 if (out)
1532 *out = n;
1533 return !!n;
1534}
1535
1536static int bus_add_object(
1537 sd_bus *bus,
1538 sd_bus_slot **slot,
1539 bool_Bool fallback,
1540 const char *path,
1541 sd_bus_message_handler_t callback,
1542 void *userdata) {
1543
1544 sd_bus_slot *s;
1545 struct node *n;
1546 int r;
1547
1548 assert_return(bus, -EINVAL)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1548, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1549 assert_return(bus = bus_resolve(bus), -ENOPKG)do { if (!(((__builtin_expect(!!(bus = bus_resolve(bus)),1)))
? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"bus = bus_resolve(bus)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1549, __PRETTY_FUNCTION__), 0))) return (-65); } while (0)
;
1550 assert_return(object_path_is_valid(path), -EINVAL)do { if (!(((__builtin_expect(!!(object_path_is_valid(path)),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("object_path_is_valid(path)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1550, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1551 assert_return(callback, -EINVAL)do { if (!(((__builtin_expect(!!(callback),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("callback"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1551, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1552 assert_return(!bus_pid_changed(bus), -ECHILD)do { if (!(((__builtin_expect(!!(!bus_pid_changed(bus)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!bus_pid_changed(bus)"
), "../src/libsystemd/sd-bus/bus-objects.c", 1552, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
1553
1554 n = bus_node_allocate(bus, path);
1555 if (!n)
1556 return -ENOMEM12;
1557
1558 s = bus_slot_allocate(bus, !slot, BUS_NODE_CALLBACK, sizeof(struct node_callback), userdata);
1559 if (!s) {
1560 r = -ENOMEM12;
1561 goto fail;
1562 }
1563
1564 s->node_callback.callback = callback;
1565 s->node_callback.is_fallback = fallback;
1566
1567 s->node_callback.node = n;
1568 LIST_PREPEND(callbacks, n->callbacks, &s->node_callback)do { typeof(*(n->callbacks)) **_head = &(n->callbacks
), *_item = (&s->node_callback); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/libsystemd/sd-bus/bus-objects.c", 1568, __PRETTY_FUNCTION__
); } while (0); if ((_item->callbacks_next = *_head)) _item
->callbacks_next->callbacks_prev = _item; _item->callbacks_prev
= ((void*)0); *_head = _item; } while (0)
;
1569 bus->nodes_modified = true1;
1570
1571 if (slot)
1572 *slot = s;
1573
1574 return 0;
1575
1576fail:
1577 sd_bus_slot_unref(s);
1578 bus_node_gc(bus, n);
1579
1580 return r;
1581}
1582
1583_public___attribute__ ((visibility("default"))) int sd_bus_add_object(
1584 sd_bus *bus,
1585 sd_bus_slot **slot,
1586 const char *path,
1587 sd_bus_message_handler_t callback,
1588 void *userdata) {
1589
1590 return bus_add_object(bus, slot, false0, path, callback, userdata);
1591}
1592
1593_public___attribute__ ((visibility("default"))) int sd_bus_add_fallback(
1594 sd_bus *bus,
1595 sd_bus_slot **slot,
1596 const char *prefix,
1597 sd_bus_message_handler_t callback,
1598 void *userdata) {
1599
1600 return bus_add_object(bus, slot, true1, prefix, callback, userdata);
1601}
1602
1603static void vtable_member_hash_func(const void *a, struct siphash *state) {
1604 const struct vtable_member *m = a;
1605
1606 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1606, __PRETTY_FUNCTION__); } while (0)
;
1607
1608 string_hash_func(m->path, state);
1609 string_hash_func(m->interface, state);
1610 string_hash_func(m->member, state);
1611}
1612
1613static int vtable_member_compare_func(const void *a, const void *b) {
1614 const struct vtable_member *x = a, *y = b;
1615 int r;
1616
1617 assert(x)do { if ((__builtin_expect(!!(!(x)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("x"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1617, __PRETTY_FUNCTION__); } while (0)
;
1618 assert(y)do { if ((__builtin_expect(!!(!(y)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("y"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1618, __PRETTY_FUNCTION__); } while (0)
;
1619
1620 r = strcmp(x->path, y->path);
1621 if (r != 0)
1622 return r;
1623
1624 r = strcmp(x->interface, y->interface);
1625 if (r != 0)
1626 return r;
1627
1628 return strcmp(x->member, y->member);
1629}
1630
1631static const struct hash_ops vtable_member_hash_ops = {
1632 .hash = vtable_member_hash_func,
1633 .compare = vtable_member_compare_func
1634};
1635
1636static int add_object_vtable_internal(
1637 sd_bus *bus,
1638 sd_bus_slot **slot,
1639 const char *path,
1640 const char *interface,
1641 const sd_bus_vtable *vtable,
1642 bool_Bool fallback,
1643 sd_bus_object_find_t find,
1644 void *userdata) {
1645
1646 sd_bus_slot *s = NULL((void*)0);
1647 struct node_vtable *i, *existing = NULL((void*)0);
1648 const sd_bus_vtable *v;
1649 struct node *n;
1650 int r;
1651
1652 assert_return(bus, -EINVAL)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1652, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1653 assert_return(bus = bus_resolve(bus), -ENOPKG)do { if (!(((__builtin_expect(!!(bus = bus_resolve(bus)),1)))
? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"bus = bus_resolve(bus)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1653, __PRETTY_FUNCTION__), 0))) return (-65); } while (0)
;
1654 assert_return(object_path_is_valid(path), -EINVAL)do { if (!(((__builtin_expect(!!(object_path_is_valid(path)),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("object_path_is_valid(path)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1654, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1655 assert_return(interface_name_is_valid(interface), -EINVAL)do { if (!(((__builtin_expect(!!(interface_name_is_valid(interface
)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("interface_name_is_valid(interface)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1655, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1656 assert_return(vtable, -EINVAL)do { if (!(((__builtin_expect(!!(vtable),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("vtable"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1656, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1657 assert_return(vtable[0].type == _SD_BUS_VTABLE_START, -EINVAL)do { if (!(((__builtin_expect(!!(vtable[0].type == _SD_BUS_VTABLE_START
),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("vtable[0].type == _SD_BUS_VTABLE_START"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1657, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1658 assert_return(vtable[0].x.start.element_size == sizeof(struct sd_bus_vtable), -EINVAL)do { if (!(((__builtin_expect(!!(vtable[0].x.start.element_size
== sizeof(struct sd_bus_vtable)),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("vtable[0].x.start.element_size == sizeof(struct sd_bus_vtable)"
), "../src/libsystemd/sd-bus/bus-objects.c", 1658, __PRETTY_FUNCTION__
), 0))) return (-22); } while (0)
;
1659 assert_return(!bus_pid_changed(bus), -ECHILD)do { if (!(((__builtin_expect(!!(!bus_pid_changed(bus)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!bus_pid_changed(bus)"
), "../src/libsystemd/sd-bus/bus-objects.c", 1659, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
1660 assert_return(!streq(interface, "org.freedesktop.DBus.Properties") &&do { if (!(((__builtin_expect(!!(!(strcmp((interface),("org.freedesktop.DBus.Properties"
)) == 0) && !(strcmp((interface),("org.freedesktop.DBus.Introspectable"
)) == 0) && !(strcmp((interface),("org.freedesktop.DBus.Peer"
)) == 0) && !(strcmp((interface),("org.freedesktop.DBus.ObjectManager"
)) == 0)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("!streq(interface, \"org.freedesktop.DBus.Properties\") && !streq(interface, \"org.freedesktop.DBus.Introspectable\") && !streq(interface, \"org.freedesktop.DBus.Peer\") && !streq(interface, \"org.freedesktop.DBus.ObjectManager\")"
), "../src/libsystemd/sd-bus/bus-objects.c", 1663, __PRETTY_FUNCTION__
), 0))) return (-22); } while (0)
1661 !streq(interface, "org.freedesktop.DBus.Introspectable") &&do { if (!(((__builtin_expect(!!(!(strcmp((interface),("org.freedesktop.DBus.Properties"
)) == 0) && !(strcmp((interface),("org.freedesktop.DBus.Introspectable"
)) == 0) && !(strcmp((interface),("org.freedesktop.DBus.Peer"
)) == 0) && !(strcmp((interface),("org.freedesktop.DBus.ObjectManager"
)) == 0)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("!streq(interface, \"org.freedesktop.DBus.Properties\") && !streq(interface, \"org.freedesktop.DBus.Introspectable\") && !streq(interface, \"org.freedesktop.DBus.Peer\") && !streq(interface, \"org.freedesktop.DBus.ObjectManager\")"
), "../src/libsystemd/sd-bus/bus-objects.c", 1663, __PRETTY_FUNCTION__
), 0))) return (-22); } while (0)
1662 !streq(interface, "org.freedesktop.DBus.Peer") &&do { if (!(((__builtin_expect(!!(!(strcmp((interface),("org.freedesktop.DBus.Properties"
)) == 0) && !(strcmp((interface),("org.freedesktop.DBus.Introspectable"
)) == 0) && !(strcmp((interface),("org.freedesktop.DBus.Peer"
)) == 0) && !(strcmp((interface),("org.freedesktop.DBus.ObjectManager"
)) == 0)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("!streq(interface, \"org.freedesktop.DBus.Properties\") && !streq(interface, \"org.freedesktop.DBus.Introspectable\") && !streq(interface, \"org.freedesktop.DBus.Peer\") && !streq(interface, \"org.freedesktop.DBus.ObjectManager\")"
), "../src/libsystemd/sd-bus/bus-objects.c", 1663, __PRETTY_FUNCTION__
), 0))) return (-22); } while (0)
1663 !streq(interface, "org.freedesktop.DBus.ObjectManager"), -EINVAL)do { if (!(((__builtin_expect(!!(!(strcmp((interface),("org.freedesktop.DBus.Properties"
)) == 0) && !(strcmp((interface),("org.freedesktop.DBus.Introspectable"
)) == 0) && !(strcmp((interface),("org.freedesktop.DBus.Peer"
)) == 0) && !(strcmp((interface),("org.freedesktop.DBus.ObjectManager"
)) == 0)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("!streq(interface, \"org.freedesktop.DBus.Properties\") && !streq(interface, \"org.freedesktop.DBus.Introspectable\") && !streq(interface, \"org.freedesktop.DBus.Peer\") && !streq(interface, \"org.freedesktop.DBus.ObjectManager\")"
), "../src/libsystemd/sd-bus/bus-objects.c", 1663, __PRETTY_FUNCTION__
), 0))) return (-22); } while (0)
;
1664
1665 r = hashmap_ensure_allocated(&bus->vtable_methods, &vtable_member_hash_ops)internal_hashmap_ensure_allocated(&bus->vtable_methods
, &vtable_member_hash_ops )
;
1666 if (r < 0)
1667 return r;
1668
1669 r = hashmap_ensure_allocated(&bus->vtable_properties, &vtable_member_hash_ops)internal_hashmap_ensure_allocated(&bus->vtable_properties
, &vtable_member_hash_ops )
;
1670 if (r < 0)
1671 return r;
1672
1673 n = bus_node_allocate(bus, path);
1674 if (!n)
1675 return -ENOMEM12;
1676
1677 LIST_FOREACH(vtables, i, n->vtables)for ((i) = (n->vtables); (i); (i) = (i)->vtables_next) {
1678 if (i->is_fallback != fallback) {
1679 r = -EPROTOTYPE91;
1680 goto fail;
1681 }
1682
1683 if (streq(i->interface, interface)(strcmp((i->interface),(interface)) == 0)) {
1684
1685 if (i->vtable == vtable) {
1686 r = -EEXIST17;
1687 goto fail;
1688 }
1689
1690 existing = i;
1691 }
1692 }
1693
1694 s = bus_slot_allocate(bus, !slot, BUS_NODE_VTABLE, sizeof(struct node_vtable), userdata);
1695 if (!s) {
1696 r = -ENOMEM12;
1697 goto fail;
1698 }
1699
1700 s->node_vtable.is_fallback = fallback;
1701 s->node_vtable.vtable = vtable;
1702 s->node_vtable.find = find;
1703
1704 s->node_vtable.interface = strdup(interface);
1705 if (!s->node_vtable.interface) {
1706 r = -ENOMEM12;
1707 goto fail;
1708 }
1709
1710 for (v = s->node_vtable.vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
1711
1712 switch (v->type) {
1713
1714 case _SD_BUS_VTABLE_METHOD: {
1715 struct vtable_member *m;
1716
1717 if (!member_name_is_valid(v->x.method.member) ||
1718 !signature_is_valid(strempty(v->x.method.signature), false0) ||
1719 !signature_is_valid(strempty(v->x.method.result), false0) ||
1720 !(v->x.method.handler || (isempty(v->x.method.signature) && isempty(v->x.method.result))) ||
1721 v->flags & (SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) {
1722 r = -EINVAL22;
1723 goto fail;
1724 }
1725
1726 m = new0(struct vtable_member, 1)((struct vtable_member*) calloc((1), sizeof(struct vtable_member
)))
;
1727 if (!m) {
1728 r = -ENOMEM12;
1729 goto fail;
1730 }
1731
1732 m->parent = &s->node_vtable;
1733 m->path = n->path;
1734 m->interface = s->node_vtable.interface;
1735 m->member = v->x.method.member;
1736 m->vtable = v;
1737
1738 r = hashmap_put(bus->vtable_methods, m, m);
1739 if (r < 0) {
1740 free(m);
1741 goto fail;
1742 }
1743
1744 break;
1745 }
1746
1747 case _SD_BUS_VTABLE_WRITABLE_PROPERTY:
1748
1749 if (!(v->x.property.set || bus_type_is_basic(v->x.property.signature[0]))) {
1750 r = -EINVAL22;
1751 goto fail;
1752 }
1753
1754 if (v->flags & SD_BUS_VTABLE_PROPERTY_CONST) {
1755 r = -EINVAL22;
1756 goto fail;
1757 }
1758
1759 _fallthrough_;
1760 case _SD_BUS_VTABLE_PROPERTY: {
1761 struct vtable_member *m;
1762
1763 if (!member_name_is_valid(v->x.property.member) ||
1764 !signature_is_single(v->x.property.signature, false0) ||
1765 !(v->x.property.get || bus_type_is_basic(v->x.property.signature[0]) || streq(v->x.property.signature, "as")(strcmp((v->x.property.signature),("as")) == 0)) ||
1766 (v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) ||
1767 (!!(v->flags & SD_BUS_VTABLE_PROPERTY_CONST) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) > 1 ||
1768 ((v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) && (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)) ||
1769 (v->flags & SD_BUS_VTABLE_UNPRIVILEGED && v->type == _SD_BUS_VTABLE_PROPERTY)) {
1770 r = -EINVAL22;
1771 goto fail;
1772 }
1773
1774 m = new0(struct vtable_member, 1)((struct vtable_member*) calloc((1), sizeof(struct vtable_member
)))
;
1775 if (!m) {
1776 r = -ENOMEM12;
1777 goto fail;
1778 }
1779
1780 m->parent = &s->node_vtable;
1781 m->path = n->path;
1782 m->interface = s->node_vtable.interface;
1783 m->member = v->x.property.member;
1784 m->vtable = v;
1785
1786 r = hashmap_put(bus->vtable_properties, m, m);
1787 if (r < 0) {
1788 free(m);
1789 goto fail;
1790 }
1791
1792 break;
1793 }
1794
1795 case _SD_BUS_VTABLE_SIGNAL:
1796
1797 if (!member_name_is_valid(v->x.signal.member) ||
1798 !signature_is_valid(strempty(v->x.signal.signature), false0) ||
1799 v->flags & SD_BUS_VTABLE_UNPRIVILEGED) {
1800 r = -EINVAL22;
1801 goto fail;
1802 }
1803
1804 break;
1805
1806 default:
1807 r = -EINVAL22;
1808 goto fail;
1809 }
1810 }
1811
1812 s->node_vtable.node = n;
1813 LIST_INSERT_AFTER(vtables, n->vtables, existing, &s->node_vtable)do { typeof(*(n->vtables)) **_head = &(n->vtables),
*_a = (existing), *_b = (&s->node_vtable); do { if ((
__builtin_expect(!!(!(_b)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("_b"), "../src/libsystemd/sd-bus/bus-objects.c", 1813, __PRETTY_FUNCTION__
); } while (0); if (!_a) { if ((_b->vtables_next = *_head)
) _b->vtables_next->vtables_prev = _b; _b->vtables_prev
= ((void*)0); *_head = _b; } else { if ((_b->vtables_next
= _a->vtables_next)) _b->vtables_next->vtables_prev
= _b; _b->vtables_prev = _a; _a->vtables_next = _b; } }
while (0)
;
1814 bus->nodes_modified = true1;
1815
1816 if (slot)
1817 *slot = s;
1818
1819 return 0;
1820
1821fail:
1822 sd_bus_slot_unref(s);
1823 bus_node_gc(bus, n);
1824
1825 return r;
1826}
1827
1828_public___attribute__ ((visibility("default"))) int sd_bus_add_object_vtable(
1829 sd_bus *bus,
1830 sd_bus_slot **slot,
1831 const char *path,
1832 const char *interface,
1833 const sd_bus_vtable *vtable,
1834 void *userdata) {
1835
1836 return add_object_vtable_internal(bus, slot, path, interface, vtable, false0, NULL((void*)0), userdata);
1837}
1838
1839_public___attribute__ ((visibility("default"))) int sd_bus_add_fallback_vtable(
1840 sd_bus *bus,
1841 sd_bus_slot **slot,
1842 const char *prefix,
1843 const char *interface,
1844 const sd_bus_vtable *vtable,
1845 sd_bus_object_find_t find,
1846 void *userdata) {
1847
1848 return add_object_vtable_internal(bus, slot, prefix, interface, vtable, true1, find, userdata);
1849}
1850
1851_public___attribute__ ((visibility("default"))) int sd_bus_add_node_enumerator(
1852 sd_bus *bus,
1853 sd_bus_slot **slot,
1854 const char *path,
1855 sd_bus_node_enumerator_t callback,
1856 void *userdata) {
1857
1858 sd_bus_slot *s;
1859 struct node *n;
1860 int r;
1861
1862 assert_return(bus, -EINVAL)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1862, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1863 assert_return(bus = bus_resolve(bus), -ENOPKG)do { if (!(((__builtin_expect(!!(bus = bus_resolve(bus)),1)))
? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"bus = bus_resolve(bus)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1863, __PRETTY_FUNCTION__), 0))) return (-65); } while (0)
;
1864 assert_return(object_path_is_valid(path), -EINVAL)do { if (!(((__builtin_expect(!!(object_path_is_valid(path)),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("object_path_is_valid(path)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1864, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1865 assert_return(callback, -EINVAL)do { if (!(((__builtin_expect(!!(callback),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("callback"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1865, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1866 assert_return(!bus_pid_changed(bus), -ECHILD)do { if (!(((__builtin_expect(!!(!bus_pid_changed(bus)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!bus_pid_changed(bus)"
), "../src/libsystemd/sd-bus/bus-objects.c", 1866, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
1867
1868 n = bus_node_allocate(bus, path);
1869 if (!n)
1870 return -ENOMEM12;
1871
1872 s = bus_slot_allocate(bus, !slot, BUS_NODE_ENUMERATOR, sizeof(struct node_enumerator), userdata);
1873 if (!s) {
1874 r = -ENOMEM12;
1875 goto fail;
1876 }
1877
1878 s->node_enumerator.callback = callback;
1879
1880 s->node_enumerator.node = n;
1881 LIST_PREPEND(enumerators, n->enumerators, &s->node_enumerator)do { typeof(*(n->enumerators)) **_head = &(n->enumerators
), *_item = (&s->node_enumerator); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/libsystemd/sd-bus/bus-objects.c", 1881, __PRETTY_FUNCTION__
); } while (0); if ((_item->enumerators_next = *_head)) _item
->enumerators_next->enumerators_prev = _item; _item->
enumerators_prev = ((void*)0); *_head = _item; } while (0)
;
1882 bus->nodes_modified = true1;
1883
1884 if (slot)
1885 *slot = s;
1886
1887 return 0;
1888
1889fail:
1890 sd_bus_slot_unref(s);
1891 bus_node_gc(bus, n);
1892
1893 return r;
1894}
1895
1896static int emit_properties_changed_on_interface(
1897 sd_bus *bus,
1898 const char *prefix,
1899 const char *path,
1900 const char *interface,
1901 bool_Bool require_fallback,
1902 bool_Bool *found_interface,
1903 char **names) {
1904
1905 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
1906 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *m = NULL((void*)0);
1907 bool_Bool has_invalidating = false0, has_changing = false0;
1908 struct vtable_member key = {};
1909 struct node_vtable *c;
1910 struct node *n;
1911 char **property;
1912 void *u = NULL((void*)0);
1913 int r;
1914
1915 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1915, __PRETTY_FUNCTION__); } while (0)
;
1916 assert(prefix)do { if ((__builtin_expect(!!(!(prefix)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("prefix"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1916, __PRETTY_FUNCTION__); } while (0)
;
1917 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1917, __PRETTY_FUNCTION__); } while (0)
;
1918 assert(interface)do { if ((__builtin_expect(!!(!(interface)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("interface"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1918, __PRETTY_FUNCTION__); } while (0)
;
1919 assert(found_interface)do { if ((__builtin_expect(!!(!(found_interface)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("found_interface"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1919, __PRETTY_FUNCTION__); } while (0)
;
1920
1921 n = hashmap_get(bus->nodes, prefix);
1922 if (!n)
1923 return 0;
1924
1925 r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
1926 if (r < 0)
1927 return r;
1928
1929 r = sd_bus_message_append(m, "s", interface);
1930 if (r < 0)
1931 return r;
1932
1933 r = sd_bus_message_open_container(m, 'a', "{sv}");
1934 if (r < 0)
1935 return r;
1936
1937 key.path = prefix;
1938 key.interface = interface;
1939
1940 LIST_FOREACH(vtables, c, n->vtables)for ((c) = (n->vtables); (c); (c) = (c)->vtables_next) {
1941 if (require_fallback && !c->is_fallback)
1942 continue;
1943
1944 if (!streq(c->interface, interface)(strcmp((c->interface),(interface)) == 0))
1945 continue;
1946
1947 r = node_vtable_get_userdata(bus, path, c, &u, &error);
1948 if (r < 0)
1949 return r;
1950 if (bus->nodes_modified)
1951 return 0;
1952 if (r == 0)
1953 continue;
1954
1955 *found_interface = true1;
1956
1957 if (names) {
1958 /* If the caller specified a list of
1959 * properties we include exactly those in the
1960 * PropertiesChanged message */
1961
1962 STRV_FOREACH(property, names)for ((property) = (names); (property) && *(property);
(property)++)
{
1963 struct vtable_member *v;
1964
1965 assert_return(member_name_is_valid(*property), -EINVAL)do { if (!(((__builtin_expect(!!(member_name_is_valid(*property
)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("member_name_is_valid(*property)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 1965, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1966
1967 key.member = *property;
1968 v = hashmap_get(bus->vtable_properties, &key);
1969 if (!v)
1970 return -ENOENT2;
1971
1972 /* If there are two vtables for the same
1973 * interface, let's handle this property when
1974 * we come to that vtable. */
1975 if (c != v->parent)
1976 continue;
1977
1978 assert_return(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE ||do { if (!(((__builtin_expect(!!(v->vtable->flags &
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE || v->vtable->flags
& SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE || v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION"
), "../src/libsystemd/sd-bus/bus-objects.c", 1979, __PRETTY_FUNCTION__
), 0))) return (-33); } while (0)
1979 v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION, -EDOM)do { if (!(((__builtin_expect(!!(v->vtable->flags &
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE || v->vtable->flags
& SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),1))) ? (1) :
(log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE || v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION"
), "../src/libsystemd/sd-bus/bus-objects.c", 1979, __PRETTY_FUNCTION__
), 0))) return (-33); } while (0)
;
1980
1981 assert_return(!(v->vtable->flags & SD_BUS_VTABLE_HIDDEN), -EDOM)do { if (!(((__builtin_expect(!!(!(v->vtable->flags &
SD_BUS_VTABLE_HIDDEN)),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("!(v->vtable->flags & SD_BUS_VTABLE_HIDDEN)"
), "../src/libsystemd/sd-bus/bus-objects.c", 1981, __PRETTY_FUNCTION__
), 0))) return (-33); } while (0)
;
1982
1983 if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) {
1984 has_invalidating = true1;
1985 continue;
1986 }
1987
1988 has_changing = true1;
1989
1990 r = vtable_append_one_property(bus, m, m->path, c, v->vtable, u, &error);
1991 if (r < 0)
1992 return r;
1993 if (bus->nodes_modified)
1994 return 0;
1995 }
1996 } else {
1997 const sd_bus_vtable *v;
1998
1999 /* If the caller specified no properties list
2000 * we include all properties that are marked
2001 * as changing in the message. */
2002
2003 for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
2004 if (!IN_SET(v->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){_SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY
})/sizeof(int)]; switch(v->type) { case _SD_BUS_VTABLE_PROPERTY
: case _SD_BUS_VTABLE_WRITABLE_PROPERTY: _found = 1; break; default
: break; } _found; })
)
2005 continue;
2006
2007 if (v->flags & SD_BUS_VTABLE_HIDDEN)
2008 continue;
2009
2010 if (v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) {
2011 has_invalidating = true1;
2012 continue;
2013 }
2014
2015 if (!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))
2016 continue;
2017
2018 has_changing = true1;
2019
2020 r = vtable_append_one_property(bus, m, m->path, c, v, u, &error);
2021 if (r < 0)
2022 return r;
2023 if (bus->nodes_modified)
2024 return 0;
2025 }
2026 }
2027 }
2028
2029 if (!has_invalidating && !has_changing)
2030 return 0;
2031
2032 r = sd_bus_message_close_container(m);
2033 if (r < 0)
2034 return r;
2035
2036 r = sd_bus_message_open_container(m, 'a', "s");
2037 if (r < 0)
2038 return r;
2039
2040 if (has_invalidating) {
2041 LIST_FOREACH(vtables, c, n->vtables)for ((c) = (n->vtables); (c); (c) = (c)->vtables_next) {
2042 if (require_fallback && !c->is_fallback)
2043 continue;
2044
2045 if (!streq(c->interface, interface)(strcmp((c->interface),(interface)) == 0))
2046 continue;
2047
2048 r = node_vtable_get_userdata(bus, path, c, &u, &error);
2049 if (r < 0)
2050 return r;
2051 if (bus->nodes_modified)
2052 return 0;
2053 if (r == 0)
2054 continue;
2055
2056 if (names) {
2057 STRV_FOREACH(property, names)for ((property) = (names); (property) && *(property);
(property)++)
{
2058 struct vtable_member *v;
2059
2060 key.member = *property;
2061 assert_se(v = hashmap_get(bus->vtable_properties, &key))do { if ((__builtin_expect(!!(!(v = hashmap_get(bus->vtable_properties
, &key))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("v = hashmap_get(bus->vtable_properties, &key)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2061, __PRETTY_FUNCTION__); } while (0)
;
2062 assert(c == v->parent)do { if ((__builtin_expect(!!(!(c == v->parent)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c == v->parent"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2062, __PRETTY_FUNCTION__); } while (0)
;
2063
2064 if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION))
2065 continue;
2066
2067 r = sd_bus_message_append(m, "s", *property);
2068 if (r < 0)
2069 return r;
2070 }
2071 } else {
2072 const sd_bus_vtable *v;
2073
2074 for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
2075 if (!IN_SET(v->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){_SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY
})/sizeof(int)]; switch(v->type) { case _SD_BUS_VTABLE_PROPERTY
: case _SD_BUS_VTABLE_WRITABLE_PROPERTY: _found = 1; break; default
: break; } _found; })
)
2076 continue;
2077
2078 if (v->flags & SD_BUS_VTABLE_HIDDEN)
2079 continue;
2080
2081 if (!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION))
2082 continue;
2083
2084 r = sd_bus_message_append(m, "s", v->x.property.member);
2085 if (r < 0)
2086 return r;
2087 }
2088 }
2089 }
2090 }
2091
2092 r = sd_bus_message_close_container(m);
2093 if (r < 0)
2094 return r;
2095
2096 r = sd_bus_send(bus, m, NULL((void*)0));
2097 if (r < 0)
2098 return r;
2099
2100 return 1;
2101}
2102
2103_public___attribute__ ((visibility("default"))) int sd_bus_emit_properties_changed_strv(
2104 sd_bus *bus,
2105 const char *path,
2106 const char *interface,
2107 char **names) {
2108
2109 _cleanup_free___attribute__((cleanup(freep))) char *prefix = NULL((void*)0);
2110 bool_Bool found_interface = false0;
2111 size_t pl;
2112 int r;
2113
2114 assert_return(bus, -EINVAL)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2114, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2115 assert_return(bus = bus_resolve(bus), -ENOPKG)do { if (!(((__builtin_expect(!!(bus = bus_resolve(bus)),1)))
? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"bus = bus_resolve(bus)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2115, __PRETTY_FUNCTION__), 0))) return (-65); } while (0)
;
2116 assert_return(object_path_is_valid(path), -EINVAL)do { if (!(((__builtin_expect(!!(object_path_is_valid(path)),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("object_path_is_valid(path)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2116, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2117 assert_return(interface_name_is_valid(interface), -EINVAL)do { if (!(((__builtin_expect(!!(interface_name_is_valid(interface
)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("interface_name_is_valid(interface)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2117, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2118 assert_return(!bus_pid_changed(bus), -ECHILD)do { if (!(((__builtin_expect(!!(!bus_pid_changed(bus)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!bus_pid_changed(bus)"
), "../src/libsystemd/sd-bus/bus-objects.c", 2118, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
2119
2120 if (!BUS_IS_OPEN(bus->state))
2121 return -ENOTCONN107;
2122
2123 /* A non-NULL but empty names list means nothing needs to be
2124 generated. A NULL list OTOH indicates that all properties
2125 that are set to EMITS_CHANGE or EMITS_INVALIDATION shall be
2126 included in the PropertiesChanged message. */
2127 if (names && names[0] == NULL((void*)0))
2128 return 0;
2129
2130 BUS_DONT_DESTROY(bus)__attribute__((cleanup(sd_bus_unrefp))) __attribute__ ((unused
)) sd_bus *_dont_destroy_bus = sd_bus_ref(bus)
;
2131
2132 pl = strlen(path);
2133 assert(pl <= BUS_PATH_SIZE_MAX)do { if ((__builtin_expect(!!(!(pl <= (64*1024))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("pl <= BUS_PATH_SIZE_MAX"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2133, __PRETTY_FUNCTION__); } while (0)
;
2134 prefix = new(char, pl + 1)((char*) malloc_multiply(sizeof(char), (pl + 1)));
2135 if (!prefix)
2136 return -ENOMEM12;
2137
2138 do {
2139 bus->nodes_modified = false0;
2140
2141 r = emit_properties_changed_on_interface(bus, path, path, interface, false0, &found_interface, names);
2142 if (r != 0)
2143 return r;
2144 if (bus->nodes_modified)
2145 continue;
2146
2147 OBJECT_PATH_FOREACH_PREFIX(prefix, path)for (char *_slash = ({ strcpy((prefix), (path)); (strcmp(((prefix
)),("/")) == 0) ? ((void*)0) : strrchr((prefix), '/'); }) ; _slash
&& !(_slash[(_slash) == (prefix)] = 0); _slash = (strcmp
(((prefix)),("/")) == 0) ? ((void*)0) : strrchr((prefix), '/'
))
{
2148 r = emit_properties_changed_on_interface(bus, prefix, path, interface, true1, &found_interface, names);
2149 if (r != 0)
2150 return r;
2151 if (bus->nodes_modified)
2152 break;
2153 }
2154
2155 } while (bus->nodes_modified);
2156
2157 return found_interface ? 0 : -ENOENT2;
2158}
2159
2160_public___attribute__ ((visibility("default"))) int sd_bus_emit_properties_changed(
2161 sd_bus *bus,
2162 const char *path,
2163 const char *interface,
2164 const char *name, ...) {
2165
2166 char **names;
2167
2168 assert_return(bus, -EINVAL)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2168, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2169 assert_return(bus = bus_resolve(bus), -ENOPKG)do { if (!(((__builtin_expect(!!(bus = bus_resolve(bus)),1)))
? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"bus = bus_resolve(bus)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2169, __PRETTY_FUNCTION__), 0))) return (-65); } while (0)
;
2170 assert_return(object_path_is_valid(path), -EINVAL)do { if (!(((__builtin_expect(!!(object_path_is_valid(path)),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("object_path_is_valid(path)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2170, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2171 assert_return(interface_name_is_valid(interface), -EINVAL)do { if (!(((__builtin_expect(!!(interface_name_is_valid(interface
)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("interface_name_is_valid(interface)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2171, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2172 assert_return(!bus_pid_changed(bus), -ECHILD)do { if (!(((__builtin_expect(!!(!bus_pid_changed(bus)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!bus_pid_changed(bus)"
), "../src/libsystemd/sd-bus/bus-objects.c", 2172, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
2173
2174 if (!BUS_IS_OPEN(bus->state))
2175 return -ENOTCONN107;
2176
2177 if (!name)
2178 return 0;
2179
2180 names = strv_from_stdarg_alloca(name)({ char **_l; if (!name) _l = (char**) &name; else { size_t
_n; va_list _ap; _n = 1; __builtin_va_start(_ap, name); while
(__builtin_va_arg(_ap, char*)) _n++; __builtin_va_end(_ap); _l
= ({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow
(sizeof(char*), _n+1))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("!size_multiply_overflow(sizeof(char*), _n+1)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2180, __PRETTY_FUNCTION__); } while (0); (char**) __builtin_alloca
(sizeof(char*)*(_n+1)); }); _l[_n = 0] = (char*) name; __builtin_va_start
(_ap, name); for (;;) { _l[++_n] = __builtin_va_arg(_ap, char
*); if (!_l[_n]) break; } __builtin_va_end(_ap); } _l; })
;
2181
2182 return sd_bus_emit_properties_changed_strv(bus, path, interface, names);
2183}
2184
2185static int object_added_append_all_prefix(
2186 sd_bus *bus,
2187 sd_bus_message *m,
2188 Set *s,
2189 const char *prefix,
2190 const char *path,
2191 bool_Bool require_fallback) {
2192
2193 const char *previous_interface = NULL((void*)0);
2194 struct node_vtable *c;
2195 struct node *n;
2196 int r;
2197
2198 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2198, __PRETTY_FUNCTION__); } while (0)
;
2199 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2199, __PRETTY_FUNCTION__); } while (0)
;
2200 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2200, __PRETTY_FUNCTION__); } while (0)
;
2201 assert(prefix)do { if ((__builtin_expect(!!(!(prefix)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("prefix"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2201, __PRETTY_FUNCTION__); } while (0)
;
2202 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2202, __PRETTY_FUNCTION__); } while (0)
;
2203
2204 n = hashmap_get(bus->nodes, prefix);
2205 if (!n)
2206 return 0;
2207
2208 LIST_FOREACH(vtables, c, n->vtables)for ((c) = (n->vtables); (c); (c) = (c)->vtables_next) {
2209 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
2210 void *u = NULL((void*)0);
2211
2212 if (require_fallback && !c->is_fallback)
2213 continue;
2214
2215 r = node_vtable_get_userdata(bus, path, c, &u, &error);
2216 if (r < 0)
2217 return r;
2218 if (bus->nodes_modified)
2219 return 0;
2220 if (r == 0)
2221 continue;
2222
2223 if (!streq_ptr(c->interface, previous_interface)) {
2224 /* If a child-node already handled this interface, we
2225 * skip it on any of its parents. The child vtables
2226 * always fully override any conflicting vtables of
2227 * any parent node. */
2228 if (set_get(s, c->interface))
2229 continue;
2230
2231 r = set_put(s, c->interface);
2232 if (r < 0)
2233 return r;
2234
2235 if (previous_interface) {
2236 r = sd_bus_message_close_container(m);
2237 if (r < 0)
2238 return r;
2239 r = sd_bus_message_close_container(m);
2240 if (r < 0)
2241 return r;
2242 }
2243
2244 r = sd_bus_message_open_container(m, 'e', "sa{sv}");
2245 if (r < 0)
2246 return r;
2247 r = sd_bus_message_append(m, "s", c->interface);
2248 if (r < 0)
2249 return r;
2250 r = sd_bus_message_open_container(m, 'a', "{sv}");
2251 if (r < 0)
2252 return r;
2253
2254 previous_interface = c->interface;
2255 }
2256
2257 r = vtable_append_all_properties(bus, m, path, c, u, &error);
2258 if (r < 0)
2259 return r;
2260 if (bus->nodes_modified)
2261 return 0;
2262 }
2263
2264 if (previous_interface) {
2265 r = sd_bus_message_close_container(m);
2266 if (r < 0)
2267 return r;
2268 r = sd_bus_message_close_container(m);
2269 if (r < 0)
2270 return r;
2271 }
2272
2273 return 0;
2274}
2275
2276static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *path) {
2277 _cleanup_set_free___attribute__((cleanup(set_freep))) Set *s = NULL((void*)0);
2278 _cleanup_free___attribute__((cleanup(freep))) char *prefix = NULL((void*)0);
2279 size_t pl;
2280 int r;
2281
2282 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2282, __PRETTY_FUNCTION__); } while (0)
;
2283 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2283, __PRETTY_FUNCTION__); } while (0)
;
2284 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2284, __PRETTY_FUNCTION__); } while (0)
;
2285
2286 /*
2287 * This appends all interfaces registered on path @path. We first add
2288 * the builtin interfaces, which are always available and handled by
2289 * sd-bus. Then, we add all interfaces registered on the exact node,
2290 * followed by all fallback interfaces registered on any parent prefix.
2291 *
2292 * If an interface is registered multiple times on the same node with
2293 * different vtables, we merge all the properties across all vtables.
2294 * However, if a child node has the same interface registered as one of
2295 * its parent nodes has as fallback, we make the child overwrite the
2296 * parent instead of extending it. Therefore, we keep a "Set" of all
2297 * handled interfaces during parent traversal, so we skip interfaces on
2298 * a parent that were overwritten by a child.
2299 */
2300
2301 s = set_new(&string_hash_ops)internal_set_new(&string_hash_ops );
2302 if (!s)
2303 return -ENOMEM12;
2304
2305 r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.Peer", 0);
2306 if (r < 0)
2307 return r;
2308 r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.Introspectable", 0);
2309 if (r < 0)
2310 return r;
2311 r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.Properties", 0);
2312 if (r < 0)
2313 return r;
2314 r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.ObjectManager", 0);
2315 if (r < 0)
2316 return r;
2317
2318 r = object_added_append_all_prefix(bus, m, s, path, path, false0);
2319 if (r < 0)
2320 return r;
2321 if (bus->nodes_modified)
2322 return 0;
2323
2324 pl = strlen(path);
2325 assert(pl <= BUS_PATH_SIZE_MAX)do { if ((__builtin_expect(!!(!(pl <= (64*1024))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("pl <= BUS_PATH_SIZE_MAX"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2325, __PRETTY_FUNCTION__); } while (0)
;
2326 prefix = new(char, pl + 1)((char*) malloc_multiply(sizeof(char), (pl + 1)));
2327 if (!prefix)
2328 return -ENOMEM12;
2329
2330 OBJECT_PATH_FOREACH_PREFIX(prefix, path)for (char *_slash = ({ strcpy((prefix), (path)); (strcmp(((prefix
)),("/")) == 0) ? ((void*)0) : strrchr((prefix), '/'); }) ; _slash
&& !(_slash[(_slash) == (prefix)] = 0); _slash = (strcmp
(((prefix)),("/")) == 0) ? ((void*)0) : strrchr((prefix), '/'
))
{
2331 r = object_added_append_all_prefix(bus, m, s, prefix, path, true1);
2332 if (r < 0)
2333 return r;
2334 if (bus->nodes_modified)
2335 return 0;
2336 }
2337
2338 return 0;
2339}
2340
2341_public___attribute__ ((visibility("default"))) int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
2342 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *m = NULL((void*)0);
2343 struct node *object_manager;
2344 int r;
2345
2346 /*
2347 * This emits an InterfacesAdded signal on the given path, by iterating
2348 * all registered vtables and fallback vtables on the path. All
2349 * properties are queried and included in the signal.
2350 * This call is equivalent to sd_bus_emit_interfaces_added() with an
2351 * explicit list of registered interfaces. However, unlike
2352 * interfaces_added(), this call can figure out the list of supported
2353 * interfaces itself. Furthermore, it properly adds the builtin
2354 * org.freedesktop.DBus.* interfaces.
2355 */
2356
2357 assert_return(bus, -EINVAL)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2357, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2358 assert_return(bus = bus_resolve(bus), -ENOPKG)do { if (!(((__builtin_expect(!!(bus = bus_resolve(bus)),1)))
? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"bus = bus_resolve(bus)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2358, __PRETTY_FUNCTION__), 0))) return (-65); } while (0)
;
2359 assert_return(object_path_is_valid(path), -EINVAL)do { if (!(((__builtin_expect(!!(object_path_is_valid(path)),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("object_path_is_valid(path)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2359, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2360 assert_return(!bus_pid_changed(bus), -ECHILD)do { if (!(((__builtin_expect(!!(!bus_pid_changed(bus)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!bus_pid_changed(bus)"
), "../src/libsystemd/sd-bus/bus-objects.c", 2360, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
2361
2362 if (!BUS_IS_OPEN(bus->state))
2363 return -ENOTCONN107;
2364
2365 r = bus_find_parent_object_manager(bus, &object_manager, path);
2366 if (r < 0)
2367 return r;
2368 if (r == 0)
2369 return -ESRCH3;
2370
2371 BUS_DONT_DESTROY(bus)__attribute__((cleanup(sd_bus_unrefp))) __attribute__ ((unused
)) sd_bus *_dont_destroy_bus = sd_bus_ref(bus)
;
2372
2373 do {
2374 bus->nodes_modified = false0;
2375 m = sd_bus_message_unref(m);
2376
2377 r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
2378 if (r < 0)
2379 return r;
2380
2381 r = sd_bus_message_append_basic(m, 'o', path);
2382 if (r < 0)
2383 return r;
2384
2385 r = sd_bus_message_open_container(m, 'a', "{sa{sv}}");
2386 if (r < 0)
2387 return r;
2388
2389 r = object_added_append_all(bus, m, path);
2390 if (r < 0)
2391 return r;
2392
2393 if (bus->nodes_modified)
2394 continue;
2395
2396 r = sd_bus_message_close_container(m);
2397 if (r < 0)
2398 return r;
2399
2400 } while (bus->nodes_modified);
2401
2402 return sd_bus_send(bus, m, NULL((void*)0));
2403}
2404
2405static int object_removed_append_all_prefix(
2406 sd_bus *bus,
2407 sd_bus_message *m,
2408 Set *s,
2409 const char *prefix,
2410 const char *path,
2411 bool_Bool require_fallback) {
2412
2413 const char *previous_interface = NULL((void*)0);
2414 struct node_vtable *c;
2415 struct node *n;
2416 int r;
2417
2418 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2418, __PRETTY_FUNCTION__); } while (0)
;
2419 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2419, __PRETTY_FUNCTION__); } while (0)
;
2420 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2420, __PRETTY_FUNCTION__); } while (0)
;
2421 assert(prefix)do { if ((__builtin_expect(!!(!(prefix)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("prefix"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2421, __PRETTY_FUNCTION__); } while (0)
;
2422 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2422, __PRETTY_FUNCTION__); } while (0)
;
2423
2424 n = hashmap_get(bus->nodes, prefix);
2425 if (!n)
2426 return 0;
2427
2428 LIST_FOREACH(vtables, c, n->vtables)for ((c) = (n->vtables); (c); (c) = (c)->vtables_next) {
2429 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
2430 void *u = NULL((void*)0);
2431
2432 if (require_fallback && !c->is_fallback)
2433 continue;
2434 if (streq_ptr(c->interface, previous_interface))
2435 continue;
2436
2437 /* If a child-node already handled this interface, we
2438 * skip it on any of its parents. The child vtables
2439 * always fully override any conflicting vtables of
2440 * any parent node. */
2441 if (set_get(s, c->interface))
2442 continue;
2443
2444 r = node_vtable_get_userdata(bus, path, c, &u, &error);
2445 if (r < 0)
2446 return r;
2447 if (bus->nodes_modified)
2448 return 0;
2449 if (r == 0)
2450 continue;
2451
2452 r = set_put(s, c->interface);
2453 if (r < 0)
2454 return r;
2455
2456 r = sd_bus_message_append(m, "s", c->interface);
2457 if (r < 0)
2458 return r;
2459
2460 previous_interface = c->interface;
2461 }
2462
2463 return 0;
2464}
2465
2466static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char *path) {
2467 _cleanup_set_free___attribute__((cleanup(set_freep))) Set *s = NULL((void*)0);
2468 _cleanup_free___attribute__((cleanup(freep))) char *prefix = NULL((void*)0);
2469 size_t pl;
2470 int r;
2471
2472 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2472, __PRETTY_FUNCTION__); } while (0)
;
2473 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2473, __PRETTY_FUNCTION__); } while (0)
;
2474 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2474, __PRETTY_FUNCTION__); } while (0)
;
2475
2476 /* see sd_bus_emit_object_added() for details */
2477
2478 s = set_new(&string_hash_ops)internal_set_new(&string_hash_ops );
2479 if (!s)
2480 return -ENOMEM12;
2481
2482 r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.Peer");
2483 if (r < 0)
2484 return r;
2485 r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.Introspectable");
2486 if (r < 0)
2487 return r;
2488 r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.Properties");
2489 if (r < 0)
2490 return r;
2491 r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.ObjectManager");
2492 if (r < 0)
2493 return r;
2494
2495 r = object_removed_append_all_prefix(bus, m, s, path, path, false0);
2496 if (r < 0)
2497 return r;
2498 if (bus->nodes_modified)
2499 return 0;
2500
2501 pl = strlen(path);
2502 assert(pl <= BUS_PATH_SIZE_MAX)do { if ((__builtin_expect(!!(!(pl <= (64*1024))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("pl <= BUS_PATH_SIZE_MAX"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2502, __PRETTY_FUNCTION__); } while (0)
;
2503 prefix = new(char, pl + 1)((char*) malloc_multiply(sizeof(char), (pl + 1)));
2504 if (!prefix)
2505 return -ENOMEM12;
2506
2507 OBJECT_PATH_FOREACH_PREFIX(prefix, path)for (char *_slash = ({ strcpy((prefix), (path)); (strcmp(((prefix
)),("/")) == 0) ? ((void*)0) : strrchr((prefix), '/'); }) ; _slash
&& !(_slash[(_slash) == (prefix)] = 0); _slash = (strcmp
(((prefix)),("/")) == 0) ? ((void*)0) : strrchr((prefix), '/'
))
{
2508 r = object_removed_append_all_prefix(bus, m, s, prefix, path, true1);
2509 if (r < 0)
2510 return r;
2511 if (bus->nodes_modified)
2512 return 0;
2513 }
2514
2515 return 0;
2516}
2517
2518_public___attribute__ ((visibility("default"))) int sd_bus_emit_object_removed(sd_bus *bus, const char *path) {
2519 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *m = NULL((void*)0);
2520 struct node *object_manager;
2521 int r;
2522
2523 /*
2524 * This is like sd_bus_emit_object_added(), but emits an
2525 * InterfacesRemoved signal on the given path. This only includes any
2526 * registered interfaces but skips the properties. Note that this will
2527 * call into the find() callbacks of any registered vtable. Therefore,
2528 * you must call this function before destroying/unlinking your object.
2529 * Otherwise, the list of interfaces will be incomplete. However, note
2530 * that this will *NOT* call into any property callback. Therefore, the
2531 * object might be in an "destructed" state, as long as we can find it.
2532 */
2533
2534 assert_return(bus, -EINVAL)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2534, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2535 assert_return(bus = bus_resolve(bus), -ENOPKG)do { if (!(((__builtin_expect(!!(bus = bus_resolve(bus)),1)))
? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"bus = bus_resolve(bus)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2535, __PRETTY_FUNCTION__), 0))) return (-65); } while (0)
;
2536 assert_return(object_path_is_valid(path), -EINVAL)do { if (!(((__builtin_expect(!!(object_path_is_valid(path)),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("object_path_is_valid(path)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2536, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2537 assert_return(!bus_pid_changed(bus), -ECHILD)do { if (!(((__builtin_expect(!!(!bus_pid_changed(bus)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!bus_pid_changed(bus)"
), "../src/libsystemd/sd-bus/bus-objects.c", 2537, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
2538
2539 if (!BUS_IS_OPEN(bus->state))
2540 return -ENOTCONN107;
2541
2542 r = bus_find_parent_object_manager(bus, &object_manager, path);
2543 if (r < 0)
2544 return r;
2545 if (r == 0)
2546 return -ESRCH3;
2547
2548 BUS_DONT_DESTROY(bus)__attribute__((cleanup(sd_bus_unrefp))) __attribute__ ((unused
)) sd_bus *_dont_destroy_bus = sd_bus_ref(bus)
;
2549
2550 do {
2551 bus->nodes_modified = false0;
2552 m = sd_bus_message_unref(m);
2553
2554 r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
2555 if (r < 0)
2556 return r;
2557
2558 r = sd_bus_message_append_basic(m, 'o', path);
2559 if (r < 0)
2560 return r;
2561
2562 r = sd_bus_message_open_container(m, 'a', "s");
2563 if (r < 0)
2564 return r;
2565
2566 r = object_removed_append_all(bus, m, path);
2567 if (r < 0)
2568 return r;
2569
2570 if (bus->nodes_modified)
2571 continue;
2572
2573 r = sd_bus_message_close_container(m);
2574 if (r < 0)
2575 return r;
2576
2577 } while (bus->nodes_modified);
2578
2579 return sd_bus_send(bus, m, NULL((void*)0));
2580}
2581
2582static int interfaces_added_append_one_prefix(
2583 sd_bus *bus,
2584 sd_bus_message *m,
2585 const char *prefix,
2586 const char *path,
2587 const char *interface,
2588 bool_Bool require_fallback) {
2589
2590 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
2591 bool_Bool found_interface = false0;
2592 struct node_vtable *c;
2593 struct node *n;
2594 void *u = NULL((void*)0);
2595 int r;
2596
2597 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2597, __PRETTY_FUNCTION__); } while (0)
;
2598 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2598, __PRETTY_FUNCTION__); } while (0)
;
2599 assert(prefix)do { if ((__builtin_expect(!!(!(prefix)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("prefix"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2599, __PRETTY_FUNCTION__); } while (0)
;
2600 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2600, __PRETTY_FUNCTION__); } while (0)
;
2601 assert(interface)do { if ((__builtin_expect(!!(!(interface)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("interface"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2601, __PRETTY_FUNCTION__); } while (0)
;
2602
2603 n = hashmap_get(bus->nodes, prefix);
2604 if (!n)
2605 return 0;
2606
2607 LIST_FOREACH(vtables, c, n->vtables)for ((c) = (n->vtables); (c); (c) = (c)->vtables_next) {
2608 if (require_fallback && !c->is_fallback)
2609 continue;
2610
2611 if (!streq(c->interface, interface)(strcmp((c->interface),(interface)) == 0))
2612 continue;
2613
2614 r = node_vtable_get_userdata(bus, path, c, &u, &error);
2615 if (r < 0)
2616 return r;
2617 if (bus->nodes_modified)
2618 return 0;
2619 if (r == 0)
2620 continue;
2621
2622 if (!found_interface) {
2623 r = sd_bus_message_append_basic(m, 's', interface);
2624 if (r < 0)
2625 return r;
2626
2627 r = sd_bus_message_open_container(m, 'a', "{sv}");
2628 if (r < 0)
2629 return r;
2630
2631 found_interface = true1;
2632 }
2633
2634 r = vtable_append_all_properties(bus, m, path, c, u, &error);
2635 if (r < 0)
2636 return r;
2637 if (bus->nodes_modified)
2638 return 0;
2639 }
2640
2641 if (found_interface) {
2642 r = sd_bus_message_close_container(m);
2643 if (r < 0)
2644 return r;
2645 }
2646
2647 return found_interface;
2648}
2649
2650static int interfaces_added_append_one(
2651 sd_bus *bus,
2652 sd_bus_message *m,
2653 const char *path,
2654 const char *interface) {
2655
2656 _cleanup_free___attribute__((cleanup(freep))) char *prefix = NULL((void*)0);
2657 size_t pl;
2658 int r;
2659
2660 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2660, __PRETTY_FUNCTION__); } while (0)
;
2661 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2661, __PRETTY_FUNCTION__); } while (0)
;
2662 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2662, __PRETTY_FUNCTION__); } while (0)
;
2663 assert(interface)do { if ((__builtin_expect(!!(!(interface)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("interface"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2663, __PRETTY_FUNCTION__); } while (0)
;
2664
2665 r = interfaces_added_append_one_prefix(bus, m, path, path, interface, false0);
2666 if (r != 0)
2667 return r;
2668 if (bus->nodes_modified)
2669 return 0;
2670
2671 pl = strlen(path);
2672 assert(pl <= BUS_PATH_SIZE_MAX)do { if ((__builtin_expect(!!(!(pl <= (64*1024))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("pl <= BUS_PATH_SIZE_MAX"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2672, __PRETTY_FUNCTION__); } while (0)
;
2673 prefix = new(char, pl + 1)((char*) malloc_multiply(sizeof(char), (pl + 1)));
2674 if (!prefix)
2675 return -ENOMEM12;
2676
2677 OBJECT_PATH_FOREACH_PREFIX(prefix, path)for (char *_slash = ({ strcpy((prefix), (path)); (strcmp(((prefix
)),("/")) == 0) ? ((void*)0) : strrchr((prefix), '/'); }) ; _slash
&& !(_slash[(_slash) == (prefix)] = 0); _slash = (strcmp
(((prefix)),("/")) == 0) ? ((void*)0) : strrchr((prefix), '/'
))
{
2678 r = interfaces_added_append_one_prefix(bus, m, prefix, path, interface, true1);
2679 if (r != 0)
2680 return r;
2681 if (bus->nodes_modified)
2682 return 0;
2683 }
2684
2685 return -ENOENT2;
2686}
2687
2688_public___attribute__ ((visibility("default"))) int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) {
2689 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *m = NULL((void*)0);
2690 struct node *object_manager;
2691 char **i;
2692 int r;
2693
2694 assert_return(bus, -EINVAL)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2694, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2695 assert_return(bus = bus_resolve(bus), -ENOPKG)do { if (!(((__builtin_expect(!!(bus = bus_resolve(bus)),1)))
? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"bus = bus_resolve(bus)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2695, __PRETTY_FUNCTION__), 0))) return (-65); } while (0)
;
2696 assert_return(object_path_is_valid(path), -EINVAL)do { if (!(((__builtin_expect(!!(object_path_is_valid(path)),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("object_path_is_valid(path)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2696, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2697 assert_return(!bus_pid_changed(bus), -ECHILD)do { if (!(((__builtin_expect(!!(!bus_pid_changed(bus)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!bus_pid_changed(bus)"
), "../src/libsystemd/sd-bus/bus-objects.c", 2697, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
2698
2699 if (!BUS_IS_OPEN(bus->state))
2700 return -ENOTCONN107;
2701
2702 if (strv_isempty(interfaces))
2703 return 0;
2704
2705 r = bus_find_parent_object_manager(bus, &object_manager, path);
2706 if (r < 0)
2707 return r;
2708 if (r == 0)
2709 return -ESRCH3;
2710
2711 BUS_DONT_DESTROY(bus)__attribute__((cleanup(sd_bus_unrefp))) __attribute__ ((unused
)) sd_bus *_dont_destroy_bus = sd_bus_ref(bus)
;
2712
2713 do {
2714 bus->nodes_modified = false0;
2715 m = sd_bus_message_unref(m);
2716
2717 r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
2718 if (r < 0)
2719 return r;
2720
2721 r = sd_bus_message_append_basic(m, 'o', path);
2722 if (r < 0)
2723 return r;
2724
2725 r = sd_bus_message_open_container(m, 'a', "{sa{sv}}");
2726 if (r < 0)
2727 return r;
2728
2729 STRV_FOREACH(i, interfaces)for ((i) = (interfaces); (i) && *(i); (i)++) {
2730 assert_return(interface_name_is_valid(*i), -EINVAL)do { if (!(((__builtin_expect(!!(interface_name_is_valid(*i))
,1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("interface_name_is_valid(*i)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2730, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2731
2732 r = sd_bus_message_open_container(m, 'e', "sa{sv}");
2733 if (r < 0)
2734 return r;
2735
2736 r = interfaces_added_append_one(bus, m, path, *i);
2737 if (r < 0)
2738 return r;
2739
2740 if (bus->nodes_modified)
2741 break;
2742
2743 r = sd_bus_message_close_container(m);
2744 if (r < 0)
2745 return r;
2746 }
2747
2748 if (bus->nodes_modified)
2749 continue;
2750
2751 r = sd_bus_message_close_container(m);
2752 if (r < 0)
2753 return r;
2754
2755 } while (bus->nodes_modified);
2756
2757 return sd_bus_send(bus, m, NULL((void*)0));
2758}
2759
2760_public___attribute__ ((visibility("default"))) int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) {
2761 char **interfaces;
2762
2763 assert_return(bus, -EINVAL)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2763, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2764 assert_return(bus = bus_resolve(bus), -ENOPKG)do { if (!(((__builtin_expect(!!(bus = bus_resolve(bus)),1)))
? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"bus = bus_resolve(bus)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2764, __PRETTY_FUNCTION__), 0))) return (-65); } while (0)
;
2765 assert_return(object_path_is_valid(path), -EINVAL)do { if (!(((__builtin_expect(!!(object_path_is_valid(path)),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("object_path_is_valid(path)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2765, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2766 assert_return(!bus_pid_changed(bus), -ECHILD)do { if (!(((__builtin_expect(!!(!bus_pid_changed(bus)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!bus_pid_changed(bus)"
), "../src/libsystemd/sd-bus/bus-objects.c", 2766, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
2767
2768 if (!BUS_IS_OPEN(bus->state))
2769 return -ENOTCONN107;
2770
2771 interfaces = strv_from_stdarg_alloca(interface)({ char **_l; if (!interface) _l = (char**) &interface; else
{ size_t _n; va_list _ap; _n = 1; __builtin_va_start(_ap, interface
); while (__builtin_va_arg(_ap, char*)) _n++; __builtin_va_end
(_ap); _l = ({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow
(sizeof(char*), _n+1))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("!size_multiply_overflow(sizeof(char*), _n+1)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2771, __PRETTY_FUNCTION__); } while (0); (char**) __builtin_alloca
(sizeof(char*)*(_n+1)); }); _l[_n = 0] = (char*) interface; __builtin_va_start
(_ap, interface); for (;;) { _l[++_n] = __builtin_va_arg(_ap,
char*); if (!_l[_n]) break; } __builtin_va_end(_ap); } _l; }
)
;
2772
2773 return sd_bus_emit_interfaces_added_strv(bus, path, interfaces);
2774}
2775
2776_public___attribute__ ((visibility("default"))) int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) {
2777 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *m = NULL((void*)0);
2778 struct node *object_manager;
2779 int r;
2780
2781 assert_return(bus, -EINVAL)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2781, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
28
'?' condition is true
29
Taking false branch
30
Loop condition is false. Exiting loop
2782 assert_return(bus = bus_resolve(bus), -ENOPKG)do { if (!(((__builtin_expect(!!(bus = bus_resolve(bus)),1)))
? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"bus = bus_resolve(bus)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2782, __PRETTY_FUNCTION__), 0))) return (-65); } while (0)
;
31
Assuming 'bus' is non-null
32
'?' condition is true
33
Taking false branch
34
Loop condition is false. Exiting loop
2783 assert_return(object_path_is_valid(path), -EINVAL)do { if (!(((__builtin_expect(!!(object_path_is_valid(path)),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("object_path_is_valid(path)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2783, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
35
Assuming the condition is false
36
'?' condition is true
37
Taking false branch
38
Loop condition is false. Exiting loop
2784 assert_return(!bus_pid_changed(bus), -ECHILD)do { if (!(((__builtin_expect(!!(!bus_pid_changed(bus)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!bus_pid_changed(bus)"
), "../src/libsystemd/sd-bus/bus-objects.c", 2784, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
39
Assuming the condition is true
40
'?' condition is true
41
Taking false branch
42
Loop condition is false. Exiting loop
2785
2786 if (!BUS_IS_OPEN(bus->state))
43
Taking false branch
2787 return -ENOTCONN107;
2788
2789 if (strv_isempty(interfaces))
44
Taking false branch
2790 return 0;
2791
2792 r = bus_find_parent_object_manager(bus, &object_manager, path);
45
Calling 'bus_find_parent_object_manager'
2793 if (r < 0)
2794 return r;
2795 if (r == 0)
2796 return -ESRCH3;
2797
2798 r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
2799 if (r < 0)
2800 return r;
2801
2802 r = sd_bus_message_append_basic(m, 'o', path);
2803 if (r < 0)
2804 return r;
2805
2806 r = sd_bus_message_append_strv(m, interfaces);
2807 if (r < 0)
2808 return r;
2809
2810 return sd_bus_send(bus, m, NULL((void*)0));
2811}
2812
2813_public___attribute__ ((visibility("default"))) int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) {
2814 char **interfaces;
2815
2816 assert_return(bus, -EINVAL)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2816, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
1
Assuming 'bus' is non-null
2
'?' condition is true
3
Taking false branch
4
Loop condition is false. Exiting loop
2817 assert_return(bus = bus_resolve(bus), -ENOPKG)do { if (!(((__builtin_expect(!!(bus = bus_resolve(bus)),1)))
? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"bus = bus_resolve(bus)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2817, __PRETTY_FUNCTION__), 0))) return (-65); } while (0)
;
5
Assuming 'bus' is non-null
6
'?' condition is true
7
Taking false branch
8
Loop condition is false. Exiting loop
2818 assert_return(object_path_is_valid(path), -EINVAL)do { if (!(((__builtin_expect(!!(object_path_is_valid(path)),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("object_path_is_valid(path)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2818, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
9
Assuming the condition is false
10
'?' condition is true
11
Taking false branch
12
Loop condition is false. Exiting loop
2819 assert_return(!bus_pid_changed(bus), -ECHILD)do { if (!(((__builtin_expect(!!(!bus_pid_changed(bus)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!bus_pid_changed(bus)"
), "../src/libsystemd/sd-bus/bus-objects.c", 2819, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
13
Assuming the condition is true
14
'?' condition is true
15
Taking false branch
16
Loop condition is false. Exiting loop
2820
2821 if (!BUS_IS_OPEN(bus->state))
17
Taking false branch
2822 return -ENOTCONN107;
2823
2824 interfaces = strv_from_stdarg_alloca(interface)({ char **_l; if (!interface) _l = (char**) &interface; else
{ size_t _n; va_list _ap; _n = 1; __builtin_va_start(_ap, interface
); while (__builtin_va_arg(_ap, char*)) _n++; __builtin_va_end
(_ap); _l = ({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow
(sizeof(char*), _n+1))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("!size_multiply_overflow(sizeof(char*), _n+1)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2824, __PRETTY_FUNCTION__); } while (0); (char**) __builtin_alloca
(sizeof(char*)*(_n+1)); }); _l[_n = 0] = (char*) interface; __builtin_va_start
(_ap, interface); for (;;) { _l[++_n] = __builtin_va_arg(_ap,
char*); if (!_l[_n]) break; } __builtin_va_end(_ap); } _l; }
)
;
18
Assuming 'interface' is non-null
19
Taking false branch
20
Loop condition is false. Execution continues on line 2824
21
Taking false branch
22
Loop condition is false. Exiting loop
23
Loop condition is true. Entering loop body
24
Assuming the condition is true
25
Taking true branch
26
Execution continues on line 2824
2825
2826 return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces);
27
Calling 'sd_bus_emit_interfaces_removed_strv'
2827}
2828
2829_public___attribute__ ((visibility("default"))) int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path) {
2830 sd_bus_slot *s;
2831 struct node *n;
2832 int r;
2833
2834 assert_return(bus, -EINVAL)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2834, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2835 assert_return(bus = bus_resolve(bus), -ENOPKG)do { if (!(((__builtin_expect(!!(bus = bus_resolve(bus)),1)))
? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, (
"bus = bus_resolve(bus)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2835, __PRETTY_FUNCTION__), 0))) return (-65); } while (0)
;
2836 assert_return(object_path_is_valid(path), -EINVAL)do { if (!(((__builtin_expect(!!(object_path_is_valid(path)),
1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("object_path_is_valid(path)"), "../src/libsystemd/sd-bus/bus-objects.c"
, 2836, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
2837 assert_return(!bus_pid_changed(bus), -ECHILD)do { if (!(((__builtin_expect(!!(!bus_pid_changed(bus)),1))) ?
(1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("!bus_pid_changed(bus)"
), "../src/libsystemd/sd-bus/bus-objects.c", 2837, __PRETTY_FUNCTION__
), 0))) return (-10); } while (0)
;
2838
2839 n = bus_node_allocate(bus, path);
2840 if (!n)
2841 return -ENOMEM12;
2842
2843 s = bus_slot_allocate(bus, !slot, BUS_NODE_OBJECT_MANAGER, sizeof(struct node_object_manager), NULL((void*)0));
2844 if (!s) {
2845 r = -ENOMEM12;
2846 goto fail;
2847 }
2848
2849 s->node_object_manager.node = n;
2850 LIST_PREPEND(object_managers, n->object_managers, &s->node_object_manager)do { typeof(*(n->object_managers)) **_head = &(n->object_managers
), *_item = (&s->node_object_manager); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/libsystemd/sd-bus/bus-objects.c", 2850, __PRETTY_FUNCTION__
); } while (0); if ((_item->object_managers_next = *_head)
) _item->object_managers_next->object_managers_prev = _item
; _item->object_managers_prev = ((void*)0); *_head = _item
; } while (0)
;
2851 bus->nodes_modified = true1;
2852
2853 if (slot)
2854 *slot = s;
2855
2856 return 0;
2857
2858fail:
2859 sd_bus_slot_unref(s);
2860 bus_node_gc(bus, n);
2861
2862 return r;
2863}

../src/basic/alloc-util.h

1/* SPDX-License-Identifier: LGPL-2.1+ */
2#pragma once
3
4#include <alloca.h>
5#include <stddef.h>
6#include <stdlib.h>
7#include <string.h>
8
9#include "macro.h"
10
11#define new(t, n)((t*) malloc_multiply(sizeof(t), (n))) ((t*) malloc_multiply(sizeof(t), (n)))
12
13#define new0(t, n)((t*) calloc((n), sizeof(t))) ((t*) calloc((n), sizeof(t)))
14
15#define newa(t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)"
), "../src/basic/alloc-util.h", 15, __PRETTY_FUNCTION__); } while
(0); (t*) __builtin_alloca (sizeof(t)*(n)); })
\
16 ({ \
17 assert(!size_multiply_overflow(sizeof(t), n))do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)"
), "../src/basic/alloc-util.h", 17, __PRETTY_FUNCTION__); } while
(0)
; \
18 (t*) alloca(sizeof(t)*(n))__builtin_alloca (sizeof(t)*(n)); \
19 })
20
21#define newa0(t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)"
), "../src/basic/alloc-util.h", 21, __PRETTY_FUNCTION__); } while
(0); (t*) ({ char *_new_; size_t _len_ = sizeof(t)*(n); _new_
= __builtin_alloca (_len_); (void *) memset(_new_, 0, _len_)
; }); })
\
22 ({ \
23 assert(!size_multiply_overflow(sizeof(t), n))do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)"
), "../src/basic/alloc-util.h", 23, __PRETTY_FUNCTION__); } while
(0)
; \
24 (t*) alloca0(sizeof(t)*(n))({ char *_new_; size_t _len_ = sizeof(t)*(n); _new_ = __builtin_alloca
(_len_); (void *) memset(_new_, 0, _len_); })
; \
25 })
26
27#define newdup(t, p, n)((t*) memdup_multiply(p, sizeof(t), (n))) ((t*) memdup_multiply(p, sizeof(t), (n)))
28
29#define newdup_suffix0(t, p, n)((t*) memdup_suffix0_multiply(p, sizeof(t), (n))) ((t*) memdup_suffix0_multiply(p, sizeof(t), (n)))
30
31#define malloc0(n)(calloc(1, (n))) (calloc(1, (n)))
32
33static inline void *mfree(void *memory) {
34 free(memory);
35 return NULL((void*)0);
36}
37
38#define free_and_replace(a, b)({ free(a); (a) = (b); (b) = ((void*)0); 0; }) \
39 ({ \
40 free(a); \
41 (a) = (b); \
42 (b) = NULL((void*)0); \
43 0; \
44 })
45
46void* memdup(const void *p, size_t l) _alloc_(2);
47void* memdup_suffix0(const void *p, size_t l) _alloc_(2);
48
49static inline void freep(void *p) {
50 free(*(void**) p);
51}
52
53#define _cleanup_free___attribute__((cleanup(freep))) _cleanup_(freep)__attribute__((cleanup(freep)))
54
55static inline bool_Bool size_multiply_overflow(size_t size, size_t need) {
56 return _unlikely_(need != 0 && size > (SIZE_MAX / need))(__builtin_expect(!!(need != 0 && size > ((18446744073709551615UL
) / need)),0))
;
57}
58
59_malloc___attribute__ ((malloc)) _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t need) {
60 if (size_multiply_overflow(size, need))
57
Taking false branch
61 return NULL((void*)0);
62
63 return malloc(size * need);
58
Memory is allocated
64}
65
66#if !HAVE_REALLOCARRAY1
67_alloc_(2, 3) static inline void *reallocarray(void *p, size_t need, size_t size) {
68 if (size_multiply_overflow(size, need))
69 return NULL((void*)0);
70
71 return realloc(p, size * need);
72}
73#endif
74
75_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) {
76 if (size_multiply_overflow(size, need))
77 return NULL((void*)0);
78
79 return memdup(p, size * need);
80}
81
82_alloc_(2, 3) static inline void *memdup_suffix0_multiply(const void *p, size_t size, size_t need) {
83 if (size_multiply_overflow(size, need))
84 return NULL((void*)0);
85
86 return memdup_suffix0(p, size * need);
87}
88
89void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
90void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
91
92#define GREEDY_REALLOC(array, allocated, need)greedy_realloc((void**) &(array), &(allocated), (need
), sizeof((array)[0]))
\
93 greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0]))
94
95#define GREEDY_REALLOC0(array, allocated, need)greedy_realloc0((void**) &(array), &(allocated), (need
), sizeof((array)[0]))
\
96 greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0]))
97
98#define alloca0(n)({ char *_new_; size_t _len_ = n; _new_ = __builtin_alloca (_len_
); (void *) memset(_new_, 0, _len_); })
\
99 ({ \
100 char *_new_; \
101 size_t _len_ = n; \
102 _new_ = alloca(_len_)__builtin_alloca (_len_); \
103 (void *) memset(_new_, 0, _len_); \
104 })
105
106/* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */
107#define alloca_align(size, align)({ void *_ptr_; size_t _mask_ = (align) - 1; _ptr_ = __builtin_alloca
((size) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) &
~_mask_); })
\
108 ({ \
109 void *_ptr_; \
110 size_t _mask_ = (align) - 1; \
111 _ptr_ = alloca((size) + _mask_)__builtin_alloca ((size) + _mask_); \
112 (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \
113 })
114
115#define alloca0_align(size, align)({ void *_new_; size_t _size_ = (size); _new_ = ({ void *_ptr_
; size_t _mask_ = ((align)) - 1; _ptr_ = __builtin_alloca ((_size_
) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_
); }); (void*)memset(_new_, 0, _size_); })
\
116 ({ \
117 void *_new_; \
118 size_t _size_ = (size); \
119 _new_ = alloca_align(_size_, (align))({ void *_ptr_; size_t _mask_ = ((align)) - 1; _ptr_ = __builtin_alloca
((_size_) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) &
~_mask_); })
; \
120 (void*)memset(_new_, 0, _size_); \
121 })
122
123/* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to
124 * NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */
125#define TAKE_PTR(ptr)({ typeof(ptr) _ptr_ = (ptr); (ptr) = ((void*)0); _ptr_; }) \
126 ({ \
127 typeof(ptr) _ptr_ = (ptr); \
128 (ptr) = NULL((void*)0); \
129 _ptr_; \
130 })