Bug Summary

File:build-scan/../src/libsystemd/sd-bus/bus-objects.c
Warning:line 1390, column 32
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_A23 = ((c)); (sd_bus_slot*)( (char *)__unique_prefix_A23
- __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_A24 = ((c)); (sd_bus_slot*)( (char *)__unique_prefix_A24
- __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_A25 = ((c)); (sd_bus_slot*)( (char *)__unique_prefix_A25
- __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_A26 = ((c->parent)); (sd_bus_slot*)( (
char *)__unique_prefix_A26 - __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_A27 = ((c->parent)); (sd_bus_slot*)( (
char *)__unique_prefix_A27 - __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_A28 = ((c)); (sd_bus_slot*)( (char *)__unique_prefix_A28
- __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)
;
1
Assuming 'bus' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
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)
;
4
Assuming 'm' is non-null
5
Taking false branch
6
Loop condition is false. Exiting loop
1362
1363 if (bus->is_monitor)
7
Assuming field 'is_monitor' is false
8
Taking false branch
1364 return 0;
1365
1366 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
9
Assuming field 'type' is equal to SD_BUS_MESSAGE_METHOD_CALL
10
Taking false branch
1367 return 0;
1368
1369 if (hashmap_isempty(bus->nodes))
11
Taking false branch
1370 return 0;
1371
1372 /* Never respond to broadcast messages */
1373 if (bus->bus_client && !m->destination)
12
Assuming field 'bus_client' is false
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)
;
13
Assuming field 'path' is non-null
14
Taking false branch
15
Loop condition is false. Exiting loop
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)
;
16
Assuming field 'member' is non-null
17
Taking false branch
18
Loop condition is false. Exiting loop
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)
;
19
Assuming the condition is true
20
Taking false branch
21
Loop condition is false. Exiting loop
1381 prefix = new(char, pl + 1)((char*) malloc_multiply(sizeof(char), (pl + 1)));
22
Calling 'malloc_multiply'
25
Returned allocated memory
1382 if (!prefix)
26
Assuming 'prefix' is non-null
27
Taking false branch
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)
28
Assuming 'r' is not equal to 0
29
Taking true branch
1390 return r;
30
Potential leak of memory pointed to by 'prefix'
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_A29
= ((1)); const typeof((e - path)) __unique_prefix_B30 = ((e -
path)); __unique_prefix_A29 > __unique_prefix_B30 ? __unique_prefix_A29
: __unique_prefix_B30; }))); 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)
;
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)
;
1509
1510 n = hashmap_get(bus->nodes, path);
1511 if (!n) {
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)
;
1517 prefix = new(char, pl + 1)((char*) malloc_multiply(sizeof(char), (pl + 1)));
1518 if (!prefix)
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), '/'
))
{
1522 n = hashmap_get(bus->nodes, prefix);
1523 if (n)
1524 break;
1525 }
1526 }
1527
1528 while (n && !n->object_managers)
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)
;
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)
;
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)
;
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)
;
2785
2786 if (!BUS_IS_OPEN(bus->state))
2787 return -ENOTCONN107;
2788
2789 if (strv_isempty(interfaces))
2790 return 0;
2791
2792 r = bus_find_parent_object_manager(bus, &object_manager, path);
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)
;
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)
;
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)
;
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)
;
2820
2821 if (!BUS_IS_OPEN(bus->state))
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; }
)
;
2825
2826 return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces);
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))
23
Taking false branch
61 return NULL((void*)0);
62
63 return malloc(size * need);
24
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 })