chiark / gitweb /
31d761e2154a98b18ef3e7432fb57b5481f15bc6
[elogind.git] / src / libsystemd-bus / bus-objects.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "strv.h"
23 #include "set.h"
24 #include "bus-internal.h"
25 #include "bus-message.h"
26 #include "bus-type.h"
27 #include "bus-signature.h"
28 #include "bus-introspect.h"
29 #include "bus-objects.h"
30 #include "bus-util.h"
31
32 static int node_vtable_get_userdata(
33                 sd_bus *bus,
34                 const char *path,
35                 struct node_vtable *c,
36                 void **userdata) {
37
38         void *u;
39         int r;
40
41         assert(bus);
42         assert(path);
43         assert(c);
44
45         u = c->userdata;
46         if (c->find) {
47                 r = c->find(bus, path, c->interface, &u, u);
48                 if (r <= 0)
49                         return r;
50         }
51
52         if (userdata)
53                 *userdata = u;
54
55         return 1;
56 }
57
58 static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) {
59         assert(p);
60
61         return (uint8_t*) u + p->x.property.offset;
62 }
63
64 static int vtable_property_get_userdata(
65                 sd_bus *bus,
66                 const char *path,
67                 struct vtable_member *p,
68                 void **userdata) {
69
70         void *u;
71         int r;
72
73         assert(bus);
74         assert(path);
75         assert(p);
76         assert(userdata);
77
78         r = node_vtable_get_userdata(bus, path, p->parent, &u);
79         if (r <= 0)
80                 return r;
81         if (bus->nodes_modified)
82                 return 0;
83
84         *userdata = vtable_property_convert_userdata(p->vtable, u);
85         return 1;
86 }
87
88 static int add_enumerated_to_set(
89                 sd_bus *bus,
90                 const char *prefix,
91                 struct node_enumerator *first,
92                 Set *s) {
93
94         struct node_enumerator *c;
95         int r;
96
97         assert(bus);
98         assert(prefix);
99         assert(s);
100
101         LIST_FOREACH(enumerators, c, first) {
102                 char **children = NULL, **k;
103
104                 if (bus->nodes_modified)
105                         return 0;
106
107                 r = c->callback(bus, prefix, &children, c->userdata);
108                 if (r < 0)
109                         return r;
110
111                 STRV_FOREACH(k, children) {
112                         if (r < 0) {
113                                 free(*k);
114                                 continue;
115                         }
116
117                         if (!object_path_is_valid(*k) && object_path_startswith(*k, prefix)) {
118                                 free(*k);
119                                 r = -EINVAL;
120                                 continue;
121                         }
122
123                         r = set_consume(s, *k);
124                 }
125
126                 free(children);
127                 if (r < 0)
128                         return r;
129         }
130
131         return 0;
132 }
133
134 static int add_subtree_to_set(
135                 sd_bus *bus,
136                 const char *prefix,
137                 struct node *n,
138                 Set *s) {
139
140         struct node *i;
141         int r;
142
143         assert(bus);
144         assert(prefix);
145         assert(n);
146         assert(s);
147
148         r = add_enumerated_to_set(bus, prefix, n->enumerators, s);
149         if (r < 0)
150                 return r;
151         if (bus->nodes_modified)
152                 return 0;
153
154         LIST_FOREACH(siblings, i, n->child) {
155                 char *t;
156
157                 t = strdup(i->path);
158                 if (!t)
159                         return -ENOMEM;
160
161                 r = set_consume(s, t);
162                 if (r < 0 && r != -EEXIST)
163                         return r;
164
165                 r = add_subtree_to_set(bus, prefix, i, s);
166                 if (r < 0)
167                         return r;
168                 if (bus->nodes_modified)
169                         return 0;
170         }
171
172         return 0;
173 }
174
175 static int get_child_nodes(
176                 sd_bus *bus,
177                 const char *prefix,
178                 struct node *n,
179                 Set **_s) {
180
181         Set *s = NULL;
182         int r;
183
184         assert(bus);
185         assert(prefix);
186         assert(n);
187         assert(_s);
188
189         s = set_new(string_hash_func, string_compare_func);
190         if (!s)
191                 return -ENOMEM;
192
193         r = add_subtree_to_set(bus, prefix, n, s);
194         if (r < 0) {
195                 set_free_free(s);
196                 return r;
197         }
198
199         *_s = s;
200         return 0;
201 }
202
203 static int node_callbacks_run(
204                 sd_bus *bus,
205                 sd_bus_message *m,
206                 struct node_callback *first,
207                 bool require_fallback,
208                 bool *found_object) {
209
210         struct node_callback *c;
211         int r;
212
213         assert(bus);
214         assert(m);
215         assert(found_object);
216
217         LIST_FOREACH(callbacks, c, first) {
218                 if (bus->nodes_modified)
219                         return 0;
220
221                 if (require_fallback && !c->is_fallback)
222                         continue;
223
224                 *found_object = true;
225
226                 if (c->last_iteration == bus->iteration_counter)
227                         continue;
228
229                 c->last_iteration = bus->iteration_counter;
230
231                 r = sd_bus_message_rewind(m, true);
232                 if (r < 0)
233                         return r;
234
235                 r = c->callback(bus, m, c->userdata);
236                 if (r != 0)
237                         return r;
238         }
239
240         return 0;
241 }
242
243 static int method_callbacks_run(
244                 sd_bus *bus,
245                 sd_bus_message *m,
246                 struct vtable_member *c,
247                 bool require_fallback,
248                 bool *found_object) {
249
250         const char *signature;
251         void *u;
252         int r;
253
254         assert(bus);
255         assert(m);
256         assert(c);
257         assert(found_object);
258
259         if (require_fallback && !c->parent->is_fallback)
260                 return 0;
261
262         r = node_vtable_get_userdata(bus, m->path, c->parent, &u);
263         if (r <= 0)
264                 return r;
265         if (bus->nodes_modified)
266                 return 0;
267
268         *found_object = true;
269
270         if (c->last_iteration == bus->iteration_counter)
271                 return 0;
272
273         c->last_iteration = bus->iteration_counter;
274
275         r = sd_bus_message_rewind(m, true);
276         if (r < 0)
277                 return r;
278
279         signature = sd_bus_message_get_signature(m, true);
280         if (!signature)
281                 return -EINVAL;
282
283         if (!streq(strempty(c->vtable->x.method.signature), signature)) {
284                 r = sd_bus_reply_method_errorf(bus, m,
285                                                SD_BUS_ERROR_INVALID_ARGS,
286                                                "Invalid arguments '%s' to call %s:%s, expecting '%s'.",
287                                                signature, c->interface, c->member, strempty(c->vtable->x.method.signature));
288                 if (r < 0)
289                         return r;
290
291                 return 1;
292         }
293
294         if (c->vtable->x.method.handler)
295                 return c->vtable->x.method.handler(bus, m, u);
296
297         /* If the method callback is NULL, make this a successful NOP */
298         r = sd_bus_reply_method_return(bus, m, NULL);
299         if (r < 0)
300                 return r;
301
302         return 1;
303 }
304
305 static int invoke_property_get(
306                 sd_bus *bus,
307                 const sd_bus_vtable *v,
308                 const char *path,
309                 const char *interface,
310                 const char *property,
311                 sd_bus_message *m,
312                 sd_bus_error *error,
313                 void *userdata) {
314
315         int r;
316         const void *p;
317
318         assert(bus);
319         assert(v);
320         assert(path);
321         assert(interface);
322         assert(property);
323         assert(m);
324
325         if (v->x.property.get)
326                 return v->x.property.get(bus, path, interface, property, m, error, userdata);
327
328         /* Automatic handling if no callback is defined. */
329
330         assert(signature_is_single(v->x.property.signature, false));
331         assert(bus_type_is_basic(v->x.property.signature[0]));
332
333         switch (v->x.property.signature[0]) {
334
335         case SD_BUS_TYPE_STRING:
336         case SD_BUS_TYPE_SIGNATURE:
337                 p = strempty(*(char**) userdata);
338                 break;
339
340         case SD_BUS_TYPE_OBJECT_PATH:
341                 p = *(char**) userdata;
342                 assert(p);
343                 break;
344
345         default:
346                 p = userdata;
347                 break;
348         }
349
350         r = sd_bus_message_append_basic(m, v->x.property.signature[0], p);
351         if (r < 0)
352                 return r;
353
354         return 1;
355 }
356
357 static int invoke_property_set(
358                 sd_bus *bus,
359                 const sd_bus_vtable *v,
360                 const char *path,
361                 const char *interface,
362                 const char *property,
363                 sd_bus_message *value,
364                 sd_bus_error *error,
365                 void *userdata) {
366
367         int r;
368
369         assert(bus);
370         assert(v);
371         assert(path);
372         assert(interface);
373         assert(property);
374         assert(value);
375
376         if (v->x.property.set)
377                 return v->x.property.set(bus, path, interface, property, value, error, userdata);
378
379         /*  Automatic handling if no callback is defined. */
380
381         assert(signature_is_single(v->x.property.signature, false));
382         assert(bus_type_is_basic(v->x.property.signature[0]));
383
384         switch (v->x.property.signature[0]) {
385
386         case SD_BUS_TYPE_STRING:
387         case SD_BUS_TYPE_OBJECT_PATH:
388         case SD_BUS_TYPE_SIGNATURE: {
389                 const char *p;
390                 char *n;
391
392                 r = sd_bus_message_read_basic(value, v->x.property.signature[0], &p);
393                 if (r < 0)
394                         return r;
395
396                 n = strdup(p);
397                 if (!n)
398                         return -ENOMEM;
399
400                 free(*(char**) userdata);
401                 *(char**) userdata = n;
402
403                 break;
404         }
405
406         default:
407                 r = sd_bus_message_read_basic(value, v->x.property.signature[0], userdata);
408                 if (r < 0)
409                         return r;
410
411                 break;
412         }
413
414         return 1;
415 }
416
417 static int property_get_set_callbacks_run(
418                 sd_bus *bus,
419                 sd_bus_message *m,
420                 struct vtable_member *c,
421                 bool require_fallback,
422                 bool is_get,
423                 bool *found_object) {
424
425         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
426         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
427         void *u;
428         int r;
429
430         assert(bus);
431         assert(m);
432         assert(c);
433         assert(found_object);
434
435         if (require_fallback && !c->parent->is_fallback)
436                 return 0;
437
438         r = vtable_property_get_userdata(bus, m->path, c, &u);
439         if (r <= 0)
440                 return r;
441         if (bus->nodes_modified)
442                 return 0;
443
444         *found_object = true;
445
446         r = sd_bus_message_new_method_return(bus, m, &reply);
447         if (r < 0)
448                 return r;
449
450         if (is_get) {
451                 /* Note that we do not protect against reexecution
452                  * here (using the last_iteration check, see below),
453                  * should the node tree have changed and we got called
454                  * again. We assume that property Get() calls are
455                  * ultimately without side-effects or if they aren't
456                  * then at least idempotent. */
457
458                 r = sd_bus_message_open_container(reply, 'v', c->vtable->x.property.signature);
459                 if (r < 0)
460                         return r;
461
462                 r = invoke_property_get(bus, c->vtable, m->path, c->interface, c->member, reply, &error, u);
463                 if (r < 0)
464                         return r;
465
466                 if (sd_bus_error_is_set(&error)) {
467                         r = sd_bus_reply_method_error(bus, m, &error);
468                         if (r < 0)
469                                 return r;
470
471                         return 1;
472                 }
473
474                 if (bus->nodes_modified)
475                         return 0;
476
477                 r = sd_bus_message_close_container(reply);
478                 if (r < 0)
479                         return r;
480
481         } else {
482                 if (c->vtable->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
483                         sd_bus_error_setf(&error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Property '%s' is not writable.", c->member);
484                 else  {
485                         /* Avoid that we call the set routine more
486                          * than once if the processing of this message
487                          * got restarted because the node tree
488                          * changed. */
489                         if (c->last_iteration == bus->iteration_counter)
490                                 return 0;
491
492                         c->last_iteration = bus->iteration_counter;
493
494                         r = sd_bus_message_enter_container(m, 'v', c->vtable->x.property.signature);
495                         if (r < 0)
496                                 return r;
497
498                         r = invoke_property_set(bus, c->vtable, m->path, c->interface, c->member, m, &error, u);
499                         if (r < 0)
500                                 return r;
501                 }
502
503                 if (sd_bus_error_is_set(&error)) {
504                         r = sd_bus_reply_method_error(bus, m, &error);
505                         if (r < 0)
506                                 return r;
507
508                         return 1;
509                 }
510
511                 if (bus->nodes_modified)
512                         return 0;
513
514                 r = sd_bus_message_exit_container(m);
515                 if (r < 0)
516                         return r;
517         }
518
519         r = sd_bus_send(bus, reply, NULL);
520         if (r < 0)
521                 return r;
522
523         return 1;
524 }
525
526 static int vtable_append_all_properties(
527                 sd_bus *bus,
528                 sd_bus_message *reply,
529                 const char *path,
530                 struct node_vtable *c,
531                 void *userdata,
532                 sd_bus_error *error) {
533
534         const sd_bus_vtable *v;
535         int r;
536
537         assert(bus);
538         assert(reply);
539         assert(path);
540         assert(c);
541
542         for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
543                 if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
544                         continue;
545
546                 r = sd_bus_message_open_container(reply, 'e', "sv");
547                 if (r < 0)
548                         return r;
549
550                 r = sd_bus_message_append(reply, "s", v->x.property.member);
551                 if (r < 0)
552                         return r;
553
554                 r = sd_bus_message_open_container(reply, 'v', v->x.property.signature);
555                 if (r < 0)
556                         return r;
557
558                 r = invoke_property_get(bus, v, path, c->interface, v->x.property.member, reply, error, vtable_property_convert_userdata(v, userdata));
559                 if (r < 0)
560                         return r;
561                 if (sd_bus_error_is_set(error))
562                         return 0;
563                 if (bus->nodes_modified)
564                         return 0;
565
566                 r = sd_bus_message_close_container(reply);
567                 if (r < 0)
568                         return r;
569
570                 r = sd_bus_message_close_container(reply);
571                 if (r < 0)
572                         return r;
573         }
574
575         return 1;
576 }
577
578 static int property_get_all_callbacks_run(
579                 sd_bus *bus,
580                 sd_bus_message *m,
581                 struct node_vtable *first,
582                 bool require_fallback,
583                 const char *iface,
584                 bool *found_object) {
585
586         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
587         struct node_vtable *c;
588         bool found_interface = false;
589         int r;
590
591         assert(bus);
592         assert(m);
593         assert(found_object);
594
595         r = sd_bus_message_new_method_return(bus, m, &reply);
596         if (r < 0)
597                 return r;
598
599         r = sd_bus_message_open_container(reply, 'a', "{sv}");
600         if (r < 0)
601                 return r;
602
603         LIST_FOREACH(vtables, c, first) {
604                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
605                 void *u;
606
607                 if (require_fallback && !c->is_fallback)
608                         continue;
609
610                 r = node_vtable_get_userdata(bus, m->path, c, &u);
611                 if (r < 0)
612                         return r;
613                 if (bus->nodes_modified)
614                         return 0;
615                 if (r == 0)
616                         continue;
617
618                 *found_object = true;
619
620                 if (iface && !streq(c->interface, iface))
621                         continue;
622                 found_interface = true;
623
624                 r = vtable_append_all_properties(bus, reply, m->path, c, u, &error);
625                 if (r < 0)
626                         return r;
627
628                 if (sd_bus_error_is_set(&error)) {
629                         r = sd_bus_reply_method_error(bus, m, &error);
630                         if (r < 0)
631                                 return r;
632
633                         return 1;
634                 }
635                 if (bus->nodes_modified)
636                         return 0;
637         }
638
639         if (!found_interface) {
640                 r = sd_bus_reply_method_errorf(
641                                 bus, m,
642                                 SD_BUS_ERROR_UNKNOWN_INTERFACE,
643                                 "Unknown interface '%s'.", iface);
644                 if (r < 0)
645                         return r;
646
647                 return 1;
648         }
649
650         r = sd_bus_message_close_container(reply);
651         if (r < 0)
652                 return r;
653
654         r = sd_bus_send(bus, reply, NULL);
655         if (r < 0)
656                 return r;
657
658         return 1;
659 }
660
661 static bool bus_node_with_object_manager(sd_bus *bus, struct node *n) {
662         assert(bus);
663         assert(n);
664
665         if (n->object_manager)
666                 return true;
667
668         if (n->parent)
669                 return bus_node_with_object_manager(bus, n->parent);
670
671         return false;
672 }
673
674 static bool bus_node_exists(
675                 sd_bus *bus,
676                 struct node *n,
677                 const char *path,
678                 bool require_fallback) {
679
680         struct node_vtable *c;
681         struct node_callback *k;
682
683         assert(bus);
684         assert(n);
685         assert(path);
686
687         /* Tests if there's anything attached directly to this node
688          * for the specified path */
689
690         LIST_FOREACH(callbacks, k, n->callbacks) {
691                 if (require_fallback && !k->is_fallback)
692                         continue;
693
694                 return true;
695         }
696
697         LIST_FOREACH(vtables, c, n->vtables) {
698
699                 if (require_fallback && !c->is_fallback)
700                         continue;
701
702                 if (node_vtable_get_userdata(bus, path, c, NULL) > 0)
703                         return true;
704                 if (bus->nodes_modified)
705                         return false;
706         }
707
708         return !require_fallback && (n->enumerators || n->object_manager);
709 }
710
711 static int process_introspect(
712                 sd_bus *bus,
713                 sd_bus_message *m,
714                 struct node *n,
715                 bool require_fallback,
716                 bool *found_object) {
717
718         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
719         _cleanup_set_free_free_ Set *s = NULL;
720         struct introspect intro;
721         struct node_vtable *c;
722         bool empty;
723         int r;
724
725         assert(bus);
726         assert(m);
727         assert(n);
728         assert(found_object);
729
730         r = get_child_nodes(bus, m->path, n, &s);
731         if (r < 0)
732                 return r;
733         if (bus->nodes_modified)
734                 return 0;
735
736         r = introspect_begin(&intro);
737         if (r < 0)
738                 return r;
739
740         r = introspect_write_default_interfaces(&intro, bus_node_with_object_manager(bus, n));
741         if (r < 0)
742                 return r;
743
744         empty = set_isempty(s);
745
746         LIST_FOREACH(vtables, c, n->vtables) {
747                 if (require_fallback && !c->is_fallback)
748                         continue;
749
750                 r = node_vtable_get_userdata(bus, m->path, c, NULL);
751                 if (r < 0)
752                         return r;
753                 if (bus->nodes_modified)
754                         return 0;
755                 if (r == 0)
756                         continue;
757
758                 empty = false;
759
760                 r = introspect_write_interface(&intro, c->interface, c->vtable);
761                 if (r < 0)
762                         goto finish;
763         }
764
765         if (empty) {
766                 /* Nothing?, let's see if we exist at all, and if not
767                  * refuse to do anything */
768                 r = bus_node_exists(bus, n, m->path, require_fallback);
769                 if (r < 0)
770                         return r;
771                 if (bus->nodes_modified)
772                         return 0;
773                 if (r == 0)
774                         goto finish;
775         }
776
777         *found_object = true;
778
779         r = introspect_write_child_nodes(&intro, s, m->path);
780         if (r < 0)
781                 goto finish;
782
783         r = introspect_finish(&intro, bus, m, &reply);
784         if (r < 0)
785                 goto finish;
786
787         r = sd_bus_send(bus, reply, NULL);
788         if (r < 0)
789                 goto finish;
790
791         r = 1;
792
793 finish:
794         introspect_free(&intro);
795         return r;
796 }
797
798 static int object_manager_serialize_vtable(
799                 sd_bus *bus,
800                 sd_bus_message *reply,
801                 const char *path,
802                 struct node_vtable *c,
803                 sd_bus_error *error,
804                 void *userdata) {
805
806         int r;
807
808         assert(bus);
809         assert(reply);
810         assert(path);
811         assert(c);
812         assert(error);
813
814         r = sd_bus_message_open_container(reply, 'e', "sa{sv}");
815         if (r < 0)
816                 return r;
817
818         r = sd_bus_message_append(reply, "s", c->interface);
819         if (r < 0)
820                 return r;
821
822         r = sd_bus_message_open_container(reply, 'a', "{sv}");
823         if (r < 0)
824                 return r;
825
826         r = vtable_append_all_properties(bus, reply, path, c, userdata, error);
827         if (r < 0)
828                 return r;
829         if (bus->nodes_modified)
830                 return 0;
831
832         r = sd_bus_message_close_container(reply);
833         if (r < 0)
834                 return r;
835
836         r = sd_bus_message_close_container(reply);
837         if (r < 0)
838                 return r;
839
840         return 0;
841 }
842
843 static int object_manager_serialize_path(
844                 sd_bus *bus,
845                 sd_bus_message *reply,
846                 const char *prefix,
847                 const char *path,
848                 bool require_fallback,
849                 sd_bus_error *error) {
850
851         struct node_vtable *i;
852         struct node *n;
853         bool found_something = false;
854         int r;
855
856         assert(bus);
857         assert(reply);
858         assert(prefix);
859         assert(path);
860         assert(error);
861
862         n = hashmap_get(bus->nodes, prefix);
863         if (!n)
864                 return 0;
865
866         LIST_FOREACH(vtables, i, n->vtables) {
867                 void *u;
868
869                 if (require_fallback && !i->is_fallback)
870                         continue;
871
872                 r = node_vtable_get_userdata(bus, path, i, &u);
873                 if (r < 0)
874                         return r;
875                 if (bus->nodes_modified)
876                         return 0;
877                 if (r == 0)
878                         continue;
879
880                 if (!found_something) {
881                         r = sd_bus_message_open_container(reply, 'e', "oa{sa{sv}}");
882                         if (r < 0)
883                                 return r;
884
885                         r = sd_bus_message_append(reply, "o", path);
886                         if (r < 0)
887                                 return r;
888
889                         r = sd_bus_message_open_container(reply, 'a', "{sa{sv}}");
890                         if (r < 0)
891                                 return r;
892
893                         found_something = true;
894                 }
895
896                 r = object_manager_serialize_vtable(bus, reply, path, i, error, u);
897                 if (r < 0)
898                         return r;
899                 if (sd_bus_error_is_set(error))
900                         return 0;
901                 if (bus->nodes_modified)
902                         return 0;
903         }
904
905         if (found_something) {
906                 r = sd_bus_message_close_container(reply);
907                 if (r < 0)
908                         return r;
909
910                 r = sd_bus_message_close_container(reply);
911                 if (r < 0)
912                         return r;
913         }
914
915         return 1;
916 }
917
918 static int object_manager_serialize_path_and_fallbacks(
919                 sd_bus *bus,
920                 sd_bus_message *reply,
921                 const char *path,
922                 sd_bus_error *error) {
923
924         char *prefix;
925         int r;
926
927         assert(bus);
928         assert(reply);
929         assert(path);
930         assert(error);
931
932         /* First, add all vtables registered for this path */
933         r = object_manager_serialize_path(bus, reply, path, path, false, error);
934         if (r < 0)
935                 return r;
936         if (sd_bus_error_is_set(error))
937                 return 0;
938         if (bus->nodes_modified)
939                 return 0;
940
941         /* Second, add fallback vtables registered for any of the prefixes */
942         prefix = alloca(strlen(path) + 1);
943         OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
944                 r = object_manager_serialize_path(bus, reply, prefix, path, true, error);
945                 if (r < 0)
946                         return r;
947                 if (sd_bus_error_is_set(error))
948                         return 0;
949                 if (bus->nodes_modified)
950                         return 0;
951         }
952
953         return 0;
954 }
955
956 static int process_get_managed_objects(
957                 sd_bus *bus,
958                 sd_bus_message *m,
959                 struct node *n,
960                 bool require_fallback,
961                 bool *found_object) {
962
963         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
964         _cleanup_set_free_free_ Set *s = NULL;
965         bool empty;
966         int r;
967
968         assert(bus);
969         assert(m);
970         assert(n);
971         assert(found_object);
972
973         if (!bus_node_with_object_manager(bus, n))
974                 return 0;
975
976         r = get_child_nodes(bus, m->path, n, &s);
977         if (r < 0)
978                 return r;
979         if (bus->nodes_modified)
980                 return 0;
981
982         r = sd_bus_message_new_method_return(bus, m, &reply);
983         if (r < 0)
984                 return r;
985
986         r = sd_bus_message_open_container(reply, 'a', "{oa{sa{sv}}}");
987         if (r < 0)
988                 return r;
989
990         empty = set_isempty(s);
991         if (empty) {
992                 struct node_vtable *c;
993
994                 /* Hmm, so we have no children? Then let's check
995                  * whether we exist at all, i.e. whether at least one
996                  * vtable exists. */
997
998                 LIST_FOREACH(vtables, c, n->vtables) {
999
1000                         if (require_fallback && !c->is_fallback)
1001                                 continue;
1002
1003                         if (r < 0)
1004                                 return r;
1005                         if (r == 0)
1006                                 continue;
1007
1008                         empty = false;
1009                         break;
1010                 }
1011
1012                 if (empty)
1013                         return 0;
1014         } else {
1015                 Iterator i;
1016                 char *path;
1017
1018                 SET_FOREACH(path, s, i) {
1019                         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1020
1021                         r = object_manager_serialize_path_and_fallbacks(bus, reply, path, &error);
1022                         if (r < 0)
1023                                 return -ENOMEM;
1024
1025                         if (sd_bus_error_is_set(&error)) {
1026                                 r = sd_bus_reply_method_error(bus, m, &error);
1027                                 if (r < 0)
1028                                         return r;
1029
1030                                 return 1;
1031                         }
1032
1033                         if (bus->nodes_modified)
1034                                 return 0;
1035                 }
1036         }
1037
1038         r = sd_bus_message_close_container(reply);
1039         if (r < 0)
1040                 return r;
1041
1042         r = sd_bus_send(bus, reply, NULL);
1043         if (r < 0)
1044                 return r;
1045
1046         return 1;
1047 }
1048
1049 static int object_find_and_run(
1050                 sd_bus *bus,
1051                 sd_bus_message *m,
1052                 const char *p,
1053                 bool require_fallback,
1054                 bool *found_object) {
1055
1056         struct node *n;
1057         struct vtable_member vtable_key, *v;
1058         int r;
1059
1060         assert(bus);
1061         assert(m);
1062         assert(p);
1063         assert(found_object);
1064
1065         n = hashmap_get(bus->nodes, p);
1066         if (!n)
1067                 return 0;
1068
1069         /* First, try object callbacks */
1070         r = node_callbacks_run(bus, m, n->callbacks, require_fallback, found_object);
1071         if (r != 0)
1072                 return r;
1073         if (bus->nodes_modified)
1074                 return 0;
1075
1076         if (!m->interface || !m->member)
1077                 return 0;
1078
1079         /* Then, look for a known method */
1080         vtable_key.path = (char*) p;
1081         vtable_key.interface = m->interface;
1082         vtable_key.member = m->member;
1083
1084         v = hashmap_get(bus->vtable_methods, &vtable_key);
1085         if (v) {
1086                 r = method_callbacks_run(bus, m, v, require_fallback, found_object);
1087                 if (r != 0)
1088                         return r;
1089                 if (bus->nodes_modified)
1090                         return 0;
1091         }
1092
1093         /* Then, look for a known property */
1094         if (streq(m->interface, "org.freedesktop.DBus.Properties")) {
1095                 bool get = false;
1096
1097                 get = streq(m->member, "Get");
1098
1099                 if (get || streq(m->member, "Set")) {
1100
1101                         r = sd_bus_message_rewind(m, true);
1102                         if (r < 0)
1103                                 return r;
1104
1105                         vtable_key.path = (char*) p;
1106
1107                         r = sd_bus_message_read(m, "ss", &vtable_key.interface, &vtable_key.member);
1108                         if (r < 0)
1109                                 return r;
1110
1111                         v = hashmap_get(bus->vtable_properties, &vtable_key);
1112                         if (v) {
1113                                 r = property_get_set_callbacks_run(bus, m, v, require_fallback, get, found_object);
1114                                 if (r != 0)
1115                                         return r;
1116                         }
1117
1118                 } else if (streq(m->member, "GetAll")) {
1119                         const char *iface;
1120
1121                         r = sd_bus_message_rewind(m, true);
1122                         if (r < 0)
1123                                 return r;
1124
1125                         r = sd_bus_message_read(m, "s", &iface);
1126                         if (r < 0)
1127                                 return r;
1128
1129                         if (iface[0] == 0)
1130                                 iface = NULL;
1131
1132                         r = property_get_all_callbacks_run(bus, m, n->vtables, require_fallback, iface, found_object);
1133                         if (r != 0)
1134                                 return r;
1135                 }
1136
1137         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1138
1139                 r = process_introspect(bus, m, n, require_fallback, found_object);
1140                 if (r != 0)
1141                         return r;
1142
1143         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.ObjectManager", "GetManagedObjects")) {
1144
1145                 r = process_get_managed_objects(bus, m, n, require_fallback, found_object);
1146                 if (r != 0)
1147                         return r;
1148         }
1149
1150         if (bus->nodes_modified)
1151                 return 0;
1152
1153         if (!*found_object) {
1154                 r = bus_node_exists(bus, n, m->path, require_fallback);
1155                 if (r < 0)
1156                         return r;
1157                 if (r > 0)
1158                         *found_object = true;
1159         }
1160
1161         return 0;
1162 }
1163
1164 int bus_process_object(sd_bus *bus, sd_bus_message *m) {
1165         int r;
1166         size_t pl;
1167         bool found_object = false;
1168
1169         assert(bus);
1170         assert(m);
1171
1172         if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1173                 return 0;
1174
1175         if (!m->path)
1176                 return 0;
1177
1178         if (hashmap_isempty(bus->nodes))
1179                 return 0;
1180
1181         pl = strlen(m->path);
1182         do {
1183                 char prefix[pl+1];
1184
1185                 bus->nodes_modified = false;
1186
1187                 r = object_find_and_run(bus, m, m->path, false, &found_object);
1188                 if (r != 0)
1189                         return r;
1190
1191                 /* Look for fallback prefixes */
1192                 OBJECT_PATH_FOREACH_PREFIX(prefix, m->path) {
1193
1194                         if (bus->nodes_modified)
1195                                 break;
1196
1197                         r = object_find_and_run(bus, m, prefix, true, &found_object);
1198                         if (r != 0)
1199                                 return r;
1200                 }
1201
1202         } while (bus->nodes_modified);
1203
1204         if (!found_object)
1205                 return 0;
1206
1207         if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Get") ||
1208             sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Set"))
1209                 r = sd_bus_reply_method_errorf(
1210                                 bus, m,
1211                                 SD_BUS_ERROR_UNKNOWN_PROPERTY,
1212                                 "Unknown property or interface.");
1213         else
1214                 r = sd_bus_reply_method_errorf(
1215                                 bus, m,
1216                                 SD_BUS_ERROR_UNKNOWN_METHOD,
1217                                 "Unknown method '%s' or interface '%s'.", m->member, m->interface);
1218
1219         if (r < 0)
1220                 return r;
1221
1222         return 1;
1223 }
1224
1225 static struct node *bus_node_allocate(sd_bus *bus, const char *path) {
1226         struct node *n, *parent;
1227         const char *e;
1228         char *s, *p;
1229         int r;
1230
1231         assert(bus);
1232         assert(path);
1233         assert(path[0] == '/');
1234
1235         n = hashmap_get(bus->nodes, path);
1236         if (n)
1237                 return n;
1238
1239         r = hashmap_ensure_allocated(&bus->nodes, string_hash_func, string_compare_func);
1240         if (r < 0)
1241                 return NULL;
1242
1243         s = strdup(path);
1244         if (!s)
1245                 return NULL;
1246
1247         if (streq(path, "/"))
1248                 parent = NULL;
1249         else {
1250                 e = strrchr(path, '/');
1251                 assert(e);
1252
1253                 p = strndupa(path, MAX(1, path - e));
1254
1255                 parent = bus_node_allocate(bus, p);
1256                 if (!parent) {
1257                         free(s);
1258                         return NULL;
1259                 }
1260         }
1261
1262         n = new0(struct node, 1);
1263         if (!n)
1264                 return NULL;
1265
1266         n->parent = parent;
1267         n->path = s;
1268
1269         r = hashmap_put(bus->nodes, s, n);
1270         if (r < 0) {
1271                 free(s);
1272                 free(n);
1273                 return NULL;
1274         }
1275
1276         if (parent)
1277                 LIST_PREPEND(siblings, parent->child, n);
1278
1279         return n;
1280 }
1281
1282 static void bus_node_gc(sd_bus *b, struct node *n) {
1283         assert(b);
1284
1285         if (!n)
1286                 return;
1287
1288         if (n->child ||
1289             n->callbacks ||
1290             n->vtables ||
1291             n->enumerators ||
1292             n->object_manager)
1293                 return;
1294
1295         assert(hashmap_remove(b->nodes, n->path) == n);
1296
1297         if (n->parent)
1298                 LIST_REMOVE(siblings, n->parent->child, n);
1299
1300         free(n->path);
1301         bus_node_gc(b, n->parent);
1302         free(n);
1303 }
1304
1305 static int bus_add_object(
1306                 sd_bus *bus,
1307                 bool fallback,
1308                 const char *path,
1309                 sd_bus_message_handler_t callback,
1310                 void *userdata) {
1311
1312         struct node_callback *c;
1313         struct node *n;
1314         int r;
1315
1316         assert_return(bus, -EINVAL);
1317         assert_return(object_path_is_valid(path), -EINVAL);
1318         assert_return(callback, -EINVAL);
1319         assert_return(!bus_pid_changed(bus), -ECHILD);
1320
1321         n = bus_node_allocate(bus, path);
1322         if (!n)
1323                 return -ENOMEM;
1324
1325         c = new0(struct node_callback, 1);
1326         if (!c) {
1327                 r = -ENOMEM;
1328                 goto fail;
1329         }
1330
1331         c->node = n;
1332         c->callback = callback;
1333         c->userdata = userdata;
1334         c->is_fallback = fallback;
1335
1336         LIST_PREPEND(callbacks, n->callbacks, c);
1337         bus->nodes_modified = true;
1338
1339         return 0;
1340
1341 fail:
1342         free(c);
1343         bus_node_gc(bus, n);
1344         return r;
1345 }
1346
1347 static int bus_remove_object(
1348                 sd_bus *bus,
1349                 bool fallback,
1350                 const char *path,
1351                 sd_bus_message_handler_t callback,
1352                 void *userdata) {
1353
1354         struct node_callback *c;
1355         struct node *n;
1356
1357         assert_return(bus, -EINVAL);
1358         assert_return(object_path_is_valid(path), -EINVAL);
1359         assert_return(callback, -EINVAL);
1360         assert_return(!bus_pid_changed(bus), -ECHILD);
1361
1362         n = hashmap_get(bus->nodes, path);
1363         if (!n)
1364                 return 0;
1365
1366         LIST_FOREACH(callbacks, c, n->callbacks)
1367                 if (c->callback == callback && c->userdata == userdata && c->is_fallback == fallback)
1368                         break;
1369         if (!c)
1370                 return 0;
1371
1372         LIST_REMOVE(callbacks, n->callbacks, c);
1373         free(c);
1374
1375         bus_node_gc(bus, n);
1376         bus->nodes_modified = true;
1377
1378         return 1;
1379 }
1380
1381 int sd_bus_add_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
1382         return bus_add_object(bus, false, path, callback, userdata);
1383 }
1384
1385 int sd_bus_remove_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
1386         return bus_remove_object(bus, false, path, callback, userdata);
1387 }
1388
1389 int sd_bus_add_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
1390         return bus_add_object(bus, true, prefix, callback, userdata);
1391 }
1392
1393 int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
1394         return bus_remove_object(bus, true, prefix, callback, userdata);
1395 }
1396
1397 static void free_node_vtable(sd_bus *bus, struct node_vtable *w) {
1398         assert(bus);
1399
1400         if (!w)
1401                 return;
1402
1403         if (w->interface && w->node && w->vtable) {
1404                 const sd_bus_vtable *v;
1405
1406                 for (v = w->vtable; v->type != _SD_BUS_VTABLE_END; v++) {
1407                         struct vtable_member *x = NULL;
1408
1409                         switch (v->type) {
1410
1411                         case _SD_BUS_VTABLE_METHOD: {
1412                                 struct vtable_member key;
1413
1414                                 key.path = w->node->path;
1415                                 key.interface = w->interface;
1416                                 key.member = v->x.method.member;
1417
1418                                 x = hashmap_remove(bus->vtable_methods, &key);
1419                                 break;
1420                         }
1421
1422                         case _SD_BUS_VTABLE_PROPERTY:
1423                         case _SD_BUS_VTABLE_WRITABLE_PROPERTY: {
1424                                 struct vtable_member key;
1425
1426                                 key.path = w->node->path;
1427                                 key.interface = w->interface;
1428                                 key.member = v->x.property.member;
1429                                 x = hashmap_remove(bus->vtable_properties, &key);
1430                                 break;
1431                         }}
1432
1433                         free(x);
1434                 }
1435         }
1436
1437         free(w->interface);
1438         free(w);
1439 }
1440
1441 static unsigned vtable_member_hash_func(const void *a) {
1442         const struct vtable_member *m = a;
1443
1444         assert(m);
1445
1446         return
1447                 string_hash_func(m->path) ^
1448                 string_hash_func(m->interface) ^
1449                 string_hash_func(m->member);
1450 }
1451
1452 static int vtable_member_compare_func(const void *a, const void *b) {
1453         const struct vtable_member *x = a, *y = b;
1454         int r;
1455
1456         assert(x);
1457         assert(y);
1458
1459         r = strcmp(x->path, y->path);
1460         if (r != 0)
1461                 return r;
1462
1463         r = strcmp(x->interface, y->interface);
1464         if (r != 0)
1465                 return r;
1466
1467         return strcmp(x->member, y->member);
1468 }
1469
1470 static int add_object_vtable_internal(
1471                 sd_bus *bus,
1472                 const char *path,
1473                 const char *interface,
1474                 const sd_bus_vtable *vtable,
1475                 bool fallback,
1476                 sd_bus_object_find_t find,
1477                 void *userdata) {
1478
1479         struct node_vtable *c = NULL, *i;
1480         const sd_bus_vtable *v;
1481         struct node *n;
1482         int r;
1483
1484         assert_return(bus, -EINVAL);
1485         assert_return(object_path_is_valid(path), -EINVAL);
1486         assert_return(interface_name_is_valid(interface), -EINVAL);
1487         assert_return(vtable, -EINVAL);
1488         assert_return(vtable[0].type == _SD_BUS_VTABLE_START, -EINVAL);
1489         assert_return(vtable[0].x.start.element_size == sizeof(struct sd_bus_vtable), -EINVAL);
1490         assert_return(!bus_pid_changed(bus), -ECHILD);
1491
1492         r = hashmap_ensure_allocated(&bus->vtable_methods, vtable_member_hash_func, vtable_member_compare_func);
1493         if (r < 0)
1494                 return r;
1495
1496         r = hashmap_ensure_allocated(&bus->vtable_properties, vtable_member_hash_func, vtable_member_compare_func);
1497         if (r < 0)
1498                 return r;
1499
1500         n = bus_node_allocate(bus, path);
1501         if (!n)
1502                 return -ENOMEM;
1503
1504         LIST_FOREACH(vtables, i, n->vtables) {
1505                 if (streq(i->interface, interface)) {
1506                         r = -EEXIST;
1507                         goto fail;
1508                 }
1509
1510                 if (i->is_fallback != fallback) {
1511                         r = -EPROTOTYPE;
1512                         goto fail;
1513                 }
1514         }
1515
1516         c = new0(struct node_vtable, 1);
1517         if (!c) {
1518                 r = -ENOMEM;
1519                 goto fail;
1520         }
1521
1522         c->node = n;
1523         c->is_fallback = fallback;
1524         c->vtable = vtable;
1525         c->userdata = userdata;
1526         c->find = find;
1527
1528         c->interface = strdup(interface);
1529         if (!c->interface) {
1530                 r = -ENOMEM;
1531                 goto fail;
1532         }
1533
1534         for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
1535
1536                 switch (v->type) {
1537
1538                 case _SD_BUS_VTABLE_METHOD: {
1539                         struct vtable_member *m;
1540
1541                         if (!member_name_is_valid(v->x.method.member) ||
1542                             !signature_is_valid(strempty(v->x.method.signature), false) ||
1543                             !signature_is_valid(strempty(v->x.method.result), false) ||
1544                             !(v->x.method.handler || (isempty(v->x.method.signature) && isempty(v->x.method.result))) ||
1545                             v->flags & (SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY)) {
1546                                 r = -EINVAL;
1547                                 goto fail;
1548                         }
1549
1550                         m = new0(struct vtable_member, 1);
1551                         if (!m) {
1552                                 r = -ENOMEM;
1553                                 goto fail;
1554                         }
1555
1556                         m->parent = c;
1557                         m->path = n->path;
1558                         m->interface = c->interface;
1559                         m->member = v->x.method.member;
1560                         m->vtable = v;
1561
1562                         r = hashmap_put(bus->vtable_methods, m, m);
1563                         if (r < 0) {
1564                                 free(m);
1565                                 goto fail;
1566                         }
1567
1568                         break;
1569                 }
1570
1571                 case _SD_BUS_VTABLE_WRITABLE_PROPERTY:
1572
1573                         if (!(v->x.property.set || bus_type_is_basic(v->x.property.signature[0]))) {
1574                                 r = -EINVAL;
1575                                 goto fail;
1576                         }
1577
1578                         /* Fall through */
1579
1580                 case _SD_BUS_VTABLE_PROPERTY: {
1581                         struct vtable_member *m;
1582
1583                         if (!member_name_is_valid(v->x.property.member) ||
1584                             !signature_is_single(v->x.property.signature, false) ||
1585                             !(v->x.property.get || bus_type_is_basic(v->x.property.signature[0])) ||
1586                             v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY ||
1587                             (v->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY && !(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))) {
1588                                 r = -EINVAL;
1589                                 goto fail;
1590                         }
1591
1592
1593                         m = new0(struct vtable_member, 1);
1594                         if (!m) {
1595                                 r = -ENOMEM;
1596                                 goto fail;
1597                         }
1598
1599                         m->parent = c;
1600                         m->path = n->path;
1601                         m->interface = c->interface;
1602                         m->member = v->x.property.member;
1603                         m->vtable = v;
1604
1605                         r = hashmap_put(bus->vtable_properties, m, m);
1606                         if (r < 0) {
1607                                 free(m);
1608                                 goto fail;
1609                         }
1610
1611                         break;
1612                 }
1613
1614                 case _SD_BUS_VTABLE_SIGNAL:
1615
1616                         if (!member_name_is_valid(v->x.signal.member) ||
1617                             !signature_is_single(strempty(v->x.signal.signature), false)) {
1618                                 r = -EINVAL;
1619                                 goto fail;
1620                         }
1621
1622                         break;
1623
1624                 default:
1625                         r = -EINVAL;
1626                         goto fail;
1627                 }
1628         }
1629
1630         LIST_PREPEND(vtables, n->vtables, c);
1631         bus->nodes_modified = true;
1632
1633         return 0;
1634
1635 fail:
1636         if (c)
1637                 free_node_vtable(bus, c);
1638
1639         bus_node_gc(bus, n);
1640         return r;
1641 }
1642
1643 static int remove_object_vtable_internal(
1644                 sd_bus *bus,
1645                 const char *path,
1646                 const char *interface,
1647                 bool fallback) {
1648
1649         struct node_vtable *c;
1650         struct node *n;
1651
1652         assert_return(bus, -EINVAL);
1653         assert_return(object_path_is_valid(path), -EINVAL);
1654         assert_return(interface_name_is_valid(interface), -EINVAL);
1655         assert_return(!bus_pid_changed(bus), -ECHILD);
1656
1657         n = hashmap_get(bus->nodes, path);
1658         if (!n)
1659                 return 0;
1660
1661         LIST_FOREACH(vtables, c, n->vtables)
1662                 if (streq(c->interface, interface) && c->is_fallback == fallback)
1663                         break;
1664
1665         if (!c)
1666                 return 0;
1667
1668         LIST_REMOVE(vtables, n->vtables, c);
1669
1670         free_node_vtable(bus, c);
1671         bus_node_gc(bus, n);
1672
1673         bus->nodes_modified = true;
1674
1675         return 1;
1676 }
1677
1678 int sd_bus_add_object_vtable(
1679                 sd_bus *bus,
1680                 const char *path,
1681                 const char *interface,
1682                 const sd_bus_vtable *vtable,
1683                 void *userdata) {
1684
1685         return add_object_vtable_internal(bus, path, interface, vtable, false, NULL, userdata);
1686 }
1687
1688 int sd_bus_remove_object_vtable(
1689                 sd_bus *bus,
1690                 const char *path,
1691                 const char *interface) {
1692
1693         return remove_object_vtable_internal(bus, path, interface, false);
1694 }
1695
1696 int sd_bus_add_fallback_vtable(
1697                 sd_bus *bus,
1698                 const char *path,
1699                 const char *interface,
1700                 const sd_bus_vtable *vtable,
1701                 sd_bus_object_find_t find,
1702                 void *userdata) {
1703
1704         return add_object_vtable_internal(bus, path, interface, vtable, true, find, userdata);
1705 }
1706
1707 int sd_bus_remove_fallback_vtable(
1708                 sd_bus *bus,
1709                 const char *path,
1710                 const char *interface) {
1711
1712         return remove_object_vtable_internal(bus, path, interface, true);
1713 }
1714
1715 int sd_bus_add_node_enumerator(
1716                 sd_bus *bus,
1717                 const char *path,
1718                 sd_bus_node_enumerator_t callback,
1719                 void *userdata) {
1720
1721         struct node_enumerator *c;
1722         struct node *n;
1723         int r;
1724
1725         assert_return(bus, -EINVAL);
1726         assert_return(object_path_is_valid(path), -EINVAL);
1727         assert_return(callback, -EINVAL);
1728         assert_return(!bus_pid_changed(bus), -ECHILD);
1729
1730         n = bus_node_allocate(bus, path);
1731         if (!n)
1732                 return -ENOMEM;
1733
1734         c = new0(struct node_enumerator, 1);
1735         if (!c) {
1736                 r = -ENOMEM;
1737                 goto fail;
1738         }
1739
1740         c->node = n;
1741         c->callback = callback;
1742         c->userdata = userdata;
1743
1744         LIST_PREPEND(enumerators, n->enumerators, c);
1745
1746         bus->nodes_modified = true;
1747
1748         return 0;
1749
1750 fail:
1751         free(c);
1752         bus_node_gc(bus, n);
1753         return r;
1754 }
1755
1756 int sd_bus_remove_node_enumerator(
1757                 sd_bus *bus,
1758                 const char *path,
1759                 sd_bus_node_enumerator_t callback,
1760                 void *userdata) {
1761
1762         struct node_enumerator *c;
1763         struct node *n;
1764
1765         assert_return(bus, -EINVAL);
1766         assert_return(object_path_is_valid(path), -EINVAL);
1767         assert_return(callback, -EINVAL);
1768         assert_return(!bus_pid_changed(bus), -ECHILD);
1769
1770         n = hashmap_get(bus->nodes, path);
1771         if (!n)
1772                 return 0;
1773
1774         LIST_FOREACH(enumerators, c, n->enumerators)
1775                 if (c->callback == callback && c->userdata == userdata)
1776                         break;
1777
1778         if (!c)
1779                 return 0;
1780
1781         LIST_REMOVE(enumerators, n->enumerators, c);
1782         free(c);
1783
1784         bus_node_gc(bus, n);
1785
1786         bus->nodes_modified = true;
1787
1788         return 1;
1789 }
1790
1791 static int emit_properties_changed_on_interface(
1792                 sd_bus *bus,
1793                 const char *prefix,
1794                 const char *path,
1795                 const char *interface,
1796                 bool require_fallback,
1797                 char **names) {
1798
1799         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1800         bool has_invalidating = false;
1801         struct vtable_member key;
1802         struct node_vtable *c;
1803         struct node *n;
1804         char **property;
1805         void *u = NULL;
1806         int r;
1807
1808         assert(bus);
1809         assert(prefix);
1810         assert(path);
1811         assert(interface);
1812
1813         n = hashmap_get(bus->nodes, prefix);
1814         if (!n)
1815                 return 0;
1816
1817         LIST_FOREACH(vtables, c, n->vtables) {
1818                 if (require_fallback && !c->is_fallback)
1819                         continue;
1820
1821                 if (streq(c->interface, interface))
1822                         break;
1823         }
1824
1825         if (!c)
1826                 return 0;
1827
1828         r = node_vtable_get_userdata(bus, path, c, &u);
1829         if (r <= 0)
1830                 return r;
1831         if (bus->nodes_modified)
1832                 return 0;
1833
1834         r = sd_bus_message_new_signal(bus, path, "org.freedesktop.DBus.Properties", "PropertiesChanged", &m);
1835         if (r < 0)
1836                 return r;
1837
1838         r = sd_bus_message_append(m, "s", interface);
1839         if (r < 0)
1840                 return r;
1841
1842         r = sd_bus_message_open_container(m, 'a', "{sv}");
1843         if (r < 0)
1844                 return r;
1845
1846         key.path = prefix;
1847         key.interface = interface;
1848
1849         STRV_FOREACH(property, names) {
1850                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1851                 struct vtable_member *v;
1852
1853                 assert_return(member_name_is_valid(*property), -EINVAL);
1854
1855                 key.member = *property;
1856                 v = hashmap_get(bus->vtable_properties, &key);
1857                 if (!v)
1858                         return -ENOENT;
1859
1860                 assert(c == v->parent);
1861                 assert_return(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE, -EDOM);
1862
1863                 if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY) {
1864                         has_invalidating = true;
1865                         continue;
1866                 }
1867
1868                 r = sd_bus_message_open_container(m, 'e', "sv");
1869                 if (r < 0)
1870                         return r;
1871
1872                 r = sd_bus_message_append(m, "s", *property);
1873                 if (r < 0)
1874                         return r;
1875
1876                 r = sd_bus_message_open_container(m, 'v', v->vtable->x.property.signature);
1877                 if (r < 0)
1878                         return r;
1879
1880                 r = invoke_property_get(bus, v->vtable, m->path, interface, *property, m, &error, vtable_property_convert_userdata(v->vtable, u));
1881                 if (r < 0)
1882                         return r;
1883                 if (bus->nodes_modified)
1884                         return 0;
1885
1886                 r = sd_bus_message_close_container(m);
1887                 if (r < 0)
1888                         return r;
1889
1890                 r = sd_bus_message_close_container(m);
1891                 if (r < 0)
1892                         return r;
1893         }
1894
1895         r = sd_bus_message_close_container(m);
1896         if (r < 0)
1897                 return r;
1898
1899         r = sd_bus_message_open_container(m, 'a', "s");
1900         if (r < 0)
1901                 return r;
1902
1903         if (has_invalidating) {
1904                 STRV_FOREACH(property, names) {
1905                         struct vtable_member *v;
1906
1907                         key.member = *property;
1908                         assert_se(v = hashmap_get(bus->vtable_properties, &key));
1909                         assert(c == v->parent);
1910
1911                         if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY))
1912                                 continue;
1913
1914                         r = sd_bus_message_append(m, "s", *property);
1915                         if (r < 0)
1916                                 return r;
1917                 }
1918         }
1919
1920         r = sd_bus_message_close_container(m);
1921         if (r < 0)
1922                 return r;
1923
1924         r = sd_bus_send(bus, m, NULL);
1925         if (r < 0)
1926                 return r;
1927
1928         return 1;
1929 }
1930
1931 int sd_bus_emit_properties_changed_strv(
1932                 sd_bus *bus,
1933                 const char *path,
1934                 const char *interface,
1935                 char **names) {
1936
1937         BUS_DONT_DESTROY(bus);
1938         char *prefix;
1939         int r;
1940
1941         assert_return(bus, -EINVAL);
1942         assert_return(object_path_is_valid(path), -EINVAL);
1943         assert_return(interface_name_is_valid(interface), -EINVAL);
1944         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1945         assert_return(!bus_pid_changed(bus), -ECHILD);
1946
1947         if (strv_isempty(names))
1948                 return 0;
1949
1950         do {
1951                 bus->nodes_modified = false;
1952
1953                 r = emit_properties_changed_on_interface(bus, path, path, interface, false, names);
1954                 if (r != 0)
1955                         return r;
1956                 if (bus->nodes_modified)
1957                         continue;
1958
1959                 prefix = alloca(strlen(path) + 1);
1960                 OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
1961                         r = emit_properties_changed_on_interface(bus, prefix, path, interface, true, names);
1962                         if (r != 0)
1963                                 return r;
1964                         if (bus->nodes_modified)
1965                                 break;
1966                 }
1967
1968         } while (bus->nodes_modified);
1969
1970         return -ENOENT;
1971 }
1972
1973 int sd_bus_emit_properties_changed(
1974                 sd_bus *bus,
1975                 const char *path,
1976                 const char *interface,
1977                 const char *name, ...)  {
1978
1979         char **names;
1980
1981         assert_return(bus, -EINVAL);
1982         assert_return(object_path_is_valid(path), -EINVAL);
1983         assert_return(interface_name_is_valid(interface), -EINVAL);
1984         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1985         assert_return(!bus_pid_changed(bus), -ECHILD);
1986
1987         if (!name)
1988                 return 0;
1989
1990         names = strv_from_stdarg_alloca(name);
1991
1992         return sd_bus_emit_properties_changed_strv(bus, path, interface, names);
1993 }
1994
1995 static int interfaces_added_append_one_prefix(
1996                 sd_bus *bus,
1997                 sd_bus_message *m,
1998                 const char *prefix,
1999                 const char *path,
2000                 const char *interface,
2001                 bool require_fallback) {
2002
2003         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2004         struct node_vtable *c;
2005         struct node *n;
2006         void *u = NULL;
2007         int r;
2008
2009         assert(bus);
2010         assert(m);
2011         assert(prefix);
2012         assert(path);
2013         assert(interface);
2014
2015         n = hashmap_get(bus->nodes, prefix);
2016         if (!n)
2017                 return 0;
2018
2019         LIST_FOREACH(vtables, c, n->vtables) {
2020                 if (require_fallback && !c->is_fallback)
2021                         continue;
2022
2023                 if (streq(c->interface, interface))
2024                         break;
2025         }
2026
2027         if (!c)
2028                 return 0;
2029
2030         r = node_vtable_get_userdata(bus, path, c, &u);
2031         if (r <= 0)
2032                 return r;
2033         if (bus->nodes_modified)
2034                 return 0;
2035
2036         r = sd_bus_message_append_basic(m, 's', interface);
2037         if (r < 0)
2038                 return r;
2039
2040         r = sd_bus_message_open_container(m, 'a', "{sv}");
2041         if (r < 0)
2042                 return r;
2043
2044         r = vtable_append_all_properties(bus, m,path, c, u, &error);
2045         if (r < 0)
2046                 return r;
2047         if (bus->nodes_modified)
2048                 return 0;
2049
2050         r = sd_bus_message_close_container(m);
2051         if (r < 0)
2052                 return r;
2053
2054         return 1;
2055 }
2056
2057 static int interfaces_added_append_one(
2058                 sd_bus *bus,
2059                 sd_bus_message *m,
2060                 const char *path,
2061                 const char *interface) {
2062
2063         char *prefix;
2064         int r;
2065
2066         assert(bus);
2067         assert(m);
2068         assert(path);
2069         assert(interface);
2070
2071         r = interfaces_added_append_one_prefix(bus, m, path, path, interface, false);
2072         if (r != 0)
2073                 return r;
2074         if (bus->nodes_modified)
2075                 return 0;
2076
2077         prefix = alloca(strlen(path) + 1);
2078         OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
2079                 r = interfaces_added_append_one_prefix(bus, m, prefix, path, interface, true);
2080                 if (r != 0)
2081                         return r;
2082                 if (bus->nodes_modified)
2083                         return 0;
2084         }
2085
2086         return -ENOENT;
2087 }
2088
2089 int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) {
2090         BUS_DONT_DESTROY(bus);
2091
2092         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2093         char **i;
2094         int r;
2095
2096         assert_return(bus, -EINVAL);
2097         assert_return(object_path_is_valid(path), -EINVAL);
2098         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
2099         assert_return(!bus_pid_changed(bus), -ECHILD);
2100
2101         if (strv_isempty(interfaces))
2102                 return 0;
2103
2104         do {
2105                 bus->nodes_modified = false;
2106
2107                 if (m)
2108                         m = sd_bus_message_unref(m);
2109
2110                 r = sd_bus_message_new_signal(bus, path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded", &m);
2111                 if (r < 0)
2112                         return r;
2113
2114                 r = sd_bus_message_append_basic(m, 'o', path);
2115                 if (r < 0)
2116                         return r;
2117
2118                 r = sd_bus_message_open_container(m, 'a', "{sa{sv}}");
2119                 if (r < 0)
2120                         return r;
2121
2122                 STRV_FOREACH(i, interfaces) {
2123                         assert_return(interface_name_is_valid(*i), -EINVAL);
2124
2125                         r = sd_bus_message_open_container(m, 'e', "sa{sv}");
2126                         if (r < 0)
2127                                 return r;
2128
2129                         r = interfaces_added_append_one(bus, m, path, *i);
2130                         if (r < 0)
2131                                 return r;
2132
2133                         if (bus->nodes_modified)
2134                                 break;
2135
2136                         r = sd_bus_message_close_container(m);
2137                         if (r < 0)
2138                                 return r;
2139                 }
2140
2141                 if (bus->nodes_modified)
2142                         continue;
2143
2144                 r = sd_bus_message_close_container(m);
2145                 if (r < 0)
2146                         return r;
2147
2148         } while (bus->nodes_modified);
2149
2150         return sd_bus_send(bus, m, NULL);
2151 }
2152
2153 int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) {
2154         char **interfaces;
2155
2156         assert_return(bus, -EINVAL);
2157         assert_return(object_path_is_valid(path), -EINVAL);
2158         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
2159         assert_return(!bus_pid_changed(bus), -ECHILD);
2160
2161         interfaces = strv_from_stdarg_alloca(interface);
2162
2163         return sd_bus_emit_interfaces_added_strv(bus, path, interfaces);
2164 }
2165
2166 int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) {
2167         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2168         int r;
2169
2170         assert_return(bus, -EINVAL);
2171         assert_return(object_path_is_valid(path), -EINVAL);
2172         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
2173         assert_return(!bus_pid_changed(bus), -ECHILD);
2174
2175         if (strv_isempty(interfaces))
2176                 return 0;
2177
2178         r = sd_bus_message_new_signal(bus, path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved", &m);
2179         if (r < 0)
2180                 return r;
2181
2182         r = sd_bus_message_append_basic(m, 'o', path);
2183         if (r < 0)
2184                 return r;
2185
2186         r = sd_bus_message_append_strv(m, interfaces);
2187         if (r < 0)
2188                 return r;
2189
2190         return sd_bus_send(bus, m, NULL);
2191 }
2192
2193 int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) {
2194         char **interfaces;
2195
2196         assert_return(bus, -EINVAL);
2197         assert_return(object_path_is_valid(path), -EINVAL);
2198         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
2199         assert_return(!bus_pid_changed(bus), -ECHILD);
2200
2201         interfaces = strv_from_stdarg_alloca(interface);
2202
2203         return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces);
2204 }
2205
2206 int sd_bus_add_object_manager(sd_bus *bus, const char *path) {
2207         struct node *n;
2208
2209         assert_return(bus, -EINVAL);
2210         assert_return(object_path_is_valid(path), -EINVAL);
2211         assert_return(!bus_pid_changed(bus), -ECHILD);
2212
2213         n = bus_node_allocate(bus, path);
2214         if (!n)
2215                 return -ENOMEM;
2216
2217         n->object_manager = true;
2218         bus->nodes_modified = true;
2219         return 0;
2220 }
2221
2222 int sd_bus_remove_object_manager(sd_bus *bus, const char *path) {
2223         struct node *n;
2224
2225         assert_return(bus, -EINVAL);
2226         assert_return(object_path_is_valid(path), -EINVAL);
2227         assert_return(!bus_pid_changed(bus), -ECHILD);
2228
2229         n = hashmap_get(bus->nodes, path);
2230         if (!n)
2231                 return 0;
2232
2233         if (!n->object_manager)
2234                 return 0;
2235
2236         n->object_manager = false;
2237         bus->nodes_modified = true;
2238         bus_node_gc(bus, n);
2239
2240         return 1;
2241 }