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