chiark / gitweb /
kdbus: update kdbus.h from upstream
[elogind.git] / src / libsystemd-bus / bus-match.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 "bus-internal.h"
23 #include "bus-message.h"
24 #include "bus-match.h"
25
26 /* Example:
27  *
28  *  A: type=signal,sender=foo,interface=bar
29  *  B: type=signal,sender=quux,interface=fips
30  *  C: type=signal,sender=quux,interface=waldo
31  *  D: type=signal,member=test
32  *  E: sender=miau
33  *  F: type=signal
34  *  G: type=signal
35  *
36  *  results in this tree:
37  *
38  *  BUS_MATCH_ROOT
39  *  + BUS_MATCH_MESSAGE_TYPE
40  *  | ` BUS_MATCH_VALUE: value == signal
41  *  |   + DBUS_MATCH_SENDER
42  *  |   | + BUS_MATCH_VALUE: value == foo
43  *  |   | | ` DBUS_MATCH_INTERFACE
44  *  |   | |   ` BUS_MATCH_VALUE: value == bar
45  *  |   | |     ` BUS_MATCH_LEAF: A
46  *  |   | ` BUS_MATCH_VALUE: value == quux
47  *  |   |   ` DBUS_MATCH_INTERFACE
48  *  |   |     | BUS_MATCH_VALUE: value == fips
49  *  |   |     | ` BUS_MATCH_LEAF: B
50  *  |   |     ` BUS_MATCH_VALUE: value == waldo
51  *  |   |       ` BUS_MATCH_LEAF: C
52  *  |   + DBUS_MATCH_MEMBER
53  *  |   | ` BUS_MATCH_VALUE: value == test
54  *  |   |   ` BUS_MATCH_LEAF: D
55  *  |   + BUS_MATCH_LEAF: F
56  *  |   ` BUS_MATCH_LEAF: G
57  *  ` BUS_MATCH_SENDER
58  *    ` BUS_MATCH_VALUE: value == miau
59  *      ` BUS_MATCH_LEAF: E
60  */
61
62 static inline bool BUS_MATCH_IS_COMPARE(enum bus_match_node_type t) {
63         return t >= BUS_MATCH_MESSAGE_TYPE && t <= BUS_MATCH_ARG_NAMESPACE_LAST;
64 }
65
66 static inline bool BUS_MATCH_CAN_HASH(enum bus_match_node_type t) {
67         return (t >= BUS_MATCH_MESSAGE_TYPE && t <= BUS_MATCH_PATH) ||
68                 (t >= BUS_MATCH_ARG && t <= BUS_MATCH_ARG_LAST);
69 }
70
71 static void bus_match_node_free(struct bus_match_node *node) {
72         assert(node);
73         assert(node->parent);
74         assert(!node->child);
75         assert(node->type != BUS_MATCH_ROOT);
76         assert(node->type < _BUS_MATCH_NODE_TYPE_MAX);
77
78         if (node->parent->child) {
79                 /* We are apparently linked into the parent's child
80                  * list. Let's remove us from there. */
81                 if (node->prev) {
82                         assert(node->prev->next == node);
83                         node->prev->next = node->next;
84                 } else {
85                         assert(node->parent->child == node);
86                         node->parent->child = node->next;
87                 }
88
89                 if (node->next)
90                         node->next->prev = node->prev;
91         }
92
93         if (node->type == BUS_MATCH_VALUE) {
94                 /* We might be in the parent's hash table, so clean
95                  * this up */
96
97                 if (node->parent->type == BUS_MATCH_MESSAGE_TYPE)
98                         hashmap_remove(node->parent->compare.children, UINT_TO_PTR(node->value.u8));
99                 else if (BUS_MATCH_CAN_HASH(node->parent->type) && node->value.str)
100                         hashmap_remove(node->parent->compare.children, node->value.str);
101
102                 free(node->value.str);
103         }
104
105         if (BUS_MATCH_IS_COMPARE(node->type)) {
106                 assert(hashmap_isempty(node->compare.children));
107                 hashmap_free(node->compare.children);
108         }
109
110         free(node);
111 }
112
113 static bool bus_match_node_maybe_free(struct bus_match_node *node) {
114         assert(node);
115
116         if (node->child)
117                 return false;
118
119         if (BUS_MATCH_IS_COMPARE(node->type) && !hashmap_isempty(node->compare.children))
120                 return true;
121
122         bus_match_node_free(node);
123         return true;
124 }
125
126 static bool value_node_test(
127                 struct bus_match_node *node,
128                 enum bus_match_node_type parent_type,
129                 uint8_t value_u8,
130                 const char *value_str) {
131
132         assert(node);
133         assert(node->type == BUS_MATCH_VALUE);
134
135         /* Tests parameters against this value node, doing prefix
136          * magic and stuff. */
137
138         switch (parent_type) {
139
140         case BUS_MATCH_MESSAGE_TYPE:
141                 return node->value.u8 == value_u8;
142
143         case BUS_MATCH_SENDER:
144         case BUS_MATCH_DESTINATION:
145         case BUS_MATCH_INTERFACE:
146         case BUS_MATCH_MEMBER:
147         case BUS_MATCH_PATH:
148         case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
149                 return streq_ptr(node->value.str, value_str);
150
151         case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
152                 return namespace_simple_pattern(node->value.str, value_str);
153
154         case BUS_MATCH_PATH_NAMESPACE:
155                 return path_simple_pattern(node->value.str, value_str);
156
157         case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
158                 return path_complex_pattern(node->value.str, value_str);
159
160         default:
161                 assert_not_reached("Invalid node type");
162         }
163 }
164
165 static bool value_node_same(
166                 struct bus_match_node *node,
167                 enum bus_match_node_type parent_type,
168                 uint8_t value_u8,
169                 const char *value_str) {
170
171         /* Tests parameters against this value node, not doing prefix
172          * magic and stuff, i.e. this one actually compares the match
173          * itself.*/
174
175         assert(node);
176         assert(node->type == BUS_MATCH_VALUE);
177
178         switch (parent_type) {
179
180         case BUS_MATCH_MESSAGE_TYPE:
181                 return node->value.u8 == value_u8;
182
183         case BUS_MATCH_SENDER:
184         case BUS_MATCH_DESTINATION:
185         case BUS_MATCH_INTERFACE:
186         case BUS_MATCH_MEMBER:
187         case BUS_MATCH_PATH:
188         case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
189         case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
190         case BUS_MATCH_PATH_NAMESPACE:
191         case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
192                 return streq(node->value.str, value_str);
193
194         default:
195                 assert_not_reached("Invalid node type");
196         }
197 }
198
199 int bus_match_run(
200                 sd_bus *bus,
201                 struct bus_match_node *node,
202                 int ret,
203                 sd_bus_message *m) {
204
205
206         const char *test_str = NULL;
207         uint8_t test_u8 = 0;
208         int r;
209
210         assert(m);
211
212         if (!node)
213                 return 0;
214
215         if (bus && bus->match_callbacks_modified)
216                 return 0;
217
218         /* Not these special semantics: when traversing the tree we
219          * usually let bus_match_run() when called for a node
220          * recursively invoke bus_match_run(). There's are two
221          * exceptions here though, which are BUS_NODE_ROOT (which
222          * cannot have a sibling), and BUS_NODE_VALUE (whose siblings
223          * are invoked anyway by its parent. */
224
225         switch (node->type) {
226
227         case BUS_MATCH_ROOT:
228
229                 /* Run all children. Since we cannot have any siblings
230                  * we won't call any. The children of the root node
231                  * are compares or leaves, they will automatically
232                  * call their siblings. */
233                 return bus_match_run(bus, node->child, ret, m);
234
235         case BUS_MATCH_VALUE:
236
237                 /* Run all children. We don't execute any siblings, we
238                  * assume our caller does that. The children of value
239                  * nodes are compares or leaves, they will
240                  * automatically call their siblings */
241
242                 assert(node->child);
243                 return bus_match_run(bus, node->child, ret, m);
244
245         case BUS_MATCH_LEAF:
246
247                 if (bus) {
248                         if (node->leaf.last_iteration == bus->iteration_counter)
249                                 return 0;
250
251                         node->leaf.last_iteration = bus->iteration_counter;
252                 }
253
254                 r = sd_bus_message_rewind(m, true);
255                 if (r < 0)
256                         return r;
257
258                 /* Run the callback. And then invoke siblings. */
259                 assert(node->leaf.callback);
260                 r = node->leaf.callback(bus, ret, m, node->leaf.userdata);
261                 if (r != 0)
262                         return r;
263
264                 return bus_match_run(bus, node->next, ret, m);
265
266         case BUS_MATCH_MESSAGE_TYPE:
267                 test_u8 = m->header->type;
268                 break;
269
270         case BUS_MATCH_SENDER:
271                 test_str = m->sender;
272                 /* FIXME: resolve test_str from a well-known to a unique name first */
273                 break;
274
275         case BUS_MATCH_DESTINATION:
276                 test_str = m->destination;
277                 break;
278
279         case BUS_MATCH_INTERFACE:
280                 test_str = m->interface;
281                 break;
282
283         case BUS_MATCH_MEMBER:
284                 test_str = m->member;
285                 break;
286
287         case BUS_MATCH_PATH:
288         case BUS_MATCH_PATH_NAMESPACE:
289                 test_str = m->path;
290                 break;
291
292         case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
293                 test_str = bus_message_get_arg(m, node->type - BUS_MATCH_ARG);
294                 break;
295
296         case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
297                 test_str = bus_message_get_arg(m, node->type - BUS_MATCH_ARG_PATH);
298                 break;
299
300         case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
301                 test_str = bus_message_get_arg(m, node->type - BUS_MATCH_ARG_NAMESPACE);
302                 break;
303
304         default:
305                 assert_not_reached("Unknown match type.");
306         }
307
308         if (BUS_MATCH_CAN_HASH(node->type)) {
309                 struct bus_match_node *found;
310
311                 /* Lookup via hash table, nice! So let's jump directly. */
312
313                 if (test_str)
314                         found = hashmap_get(node->compare.children, test_str);
315                 else if (node->type == BUS_MATCH_MESSAGE_TYPE)
316                         found = hashmap_get(node->compare.children, UINT_TO_PTR(test_u8));
317                 else
318                         found = NULL;
319
320                 if (found) {
321                         r = bus_match_run(bus, found, ret, m);
322                         if (r != 0)
323                                 return r;
324                 }
325         } else {
326                 struct bus_match_node *c;
327
328                 /* No hash table, so let's iterate manually... */
329
330                 for (c = node->child; c; c = c->next) {
331                         if (!value_node_test(c, node->type, test_u8, test_str))
332                                 continue;
333
334                         r = bus_match_run(bus, c, ret, m);
335                         if (r != 0)
336                                 return r;
337                 }
338         }
339
340         if (bus && bus->match_callbacks_modified)
341                 return 0;
342
343         /* And now, let's invoke our siblings */
344         return bus_match_run(bus, node->next, ret, m);
345 }
346
347 static int bus_match_add_compare_value(
348                 struct bus_match_node *where,
349                 enum bus_match_node_type t,
350                 uint8_t value_u8,
351                 const char *value_str,
352                 struct bus_match_node **ret) {
353
354         struct bus_match_node *c = NULL, *n = NULL;
355         int r;
356
357         assert(where);
358         assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
359         assert(BUS_MATCH_IS_COMPARE(t));
360         assert(ret);
361
362         for (c = where->child; c && c->type != t; c = c->next)
363                 ;
364
365         if (c) {
366                 /* Comparison node already exists? Then let's see if
367                  * the value node exists too. */
368
369                 if (t == BUS_MATCH_MESSAGE_TYPE)
370                         n = hashmap_get(c->compare.children, UINT_TO_PTR(value_u8));
371                 else if (BUS_MATCH_CAN_HASH(t))
372                         n = hashmap_get(c->compare.children, value_str);
373                 else {
374                         for (n = c->child; n && !value_node_same(n, t, value_u8, value_str); n = n->next)
375                                 ;
376                 }
377
378                 if (n) {
379                         *ret = n;
380                         return 0;
381                 }
382         } else {
383                 /* Comparison node, doesn't exist yet? Then let's
384                  * create it. */
385
386                 c = new0(struct bus_match_node, 1);
387                 if (!c) {
388                         r = -ENOMEM;
389                         goto fail;
390                 }
391
392                 c->type = t;
393                 c->parent = where;
394                 c->next = where->child;
395                 if (c->next)
396                         c->next->prev = c;
397                 where->child = c;
398
399                 if (t == BUS_MATCH_MESSAGE_TYPE) {
400                         c->compare.children = hashmap_new(trivial_hash_func, trivial_compare_func);
401                         if (!c->compare.children) {
402                                 r = -ENOMEM;
403                                 goto fail;
404                         }
405                 } else if (BUS_MATCH_CAN_HASH(t)) {
406                         c->compare.children = hashmap_new(string_hash_func, string_compare_func);
407                         if (!c->compare.children) {
408                                 r = -ENOMEM;
409                                 goto fail;
410                         }
411                 }
412         }
413
414         n = new0(struct bus_match_node, 1);
415         if (!n) {
416                 r = -ENOMEM;
417                 goto fail;
418         }
419
420         n->type = BUS_MATCH_VALUE;
421         n->value.u8 = value_u8;
422         if (value_str) {
423                 n->value.str = strdup(value_str);
424                 if (!n->value.str) {
425                         r = -ENOMEM;
426                         goto fail;
427                 }
428         }
429
430         n->parent = c;
431         if (c->compare.children) {
432
433                 if (t == BUS_MATCH_MESSAGE_TYPE)
434                         r = hashmap_put(c->compare.children, UINT_TO_PTR(value_u8), n);
435                 else
436                         r = hashmap_put(c->compare.children, n->value.str, n);
437
438                 if (r < 0)
439                         goto fail;
440         } else {
441                 n->next = c->child;
442                 if (n->next)
443                         n->next->prev = n;
444                 c->child = n;
445         }
446
447         *ret = n;
448         return 1;
449
450 fail:
451         if (c)
452                 bus_match_node_maybe_free(c);
453
454         if (n) {
455                 free(n->value.str);
456                 free(n);
457         }
458
459         return r;
460 }
461
462 static int bus_match_find_compare_value(
463                 struct bus_match_node *where,
464                 enum bus_match_node_type t,
465                 uint8_t value_u8,
466                 const char *value_str,
467                 struct bus_match_node **ret) {
468
469         struct bus_match_node *c, *n;
470
471         assert(where);
472         assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
473         assert(BUS_MATCH_IS_COMPARE(t));
474         assert(ret);
475
476         for (c = where->child; c && c->type != t; c = c->next)
477                 ;
478
479         if (!c)
480                 return 0;
481
482         if (t == BUS_MATCH_MESSAGE_TYPE)
483                 n = hashmap_get(c->compare.children, UINT_TO_PTR(value_u8));
484         else if (BUS_MATCH_CAN_HASH(t))
485                 n = hashmap_get(c->compare.children, value_str);
486         else {
487                 for (n = c->child; !value_node_same(n, t, value_u8, value_str); n = n->next)
488                         ;
489         }
490
491         if (n) {
492                 *ret = n;
493                 return 1;
494         }
495
496         return 0;
497 }
498
499 static int bus_match_add_leaf(
500                 struct bus_match_node *where,
501                 sd_bus_message_handler_t callback,
502                 void *userdata,
503                 struct bus_match_node **ret) {
504
505         struct bus_match_node *n;
506
507         assert(where);
508         assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
509         assert(ret);
510
511         n = new0(struct bus_match_node, 1);
512         if (!n)
513                 return -ENOMEM;
514
515         n->type = BUS_MATCH_LEAF;
516         n->parent = where;
517         n->next = where->child;
518         if (n->next)
519                 n->next->prev = n;
520         n->leaf.callback = callback;
521         n->leaf.userdata = userdata;
522
523         where->child = n;
524
525         *ret = n;
526         return 1;
527 }
528
529 static int bus_match_find_leaf(
530                 struct bus_match_node *where,
531                 sd_bus_message_handler_t callback,
532                 void *userdata,
533                 struct bus_match_node **ret) {
534
535         struct bus_match_node *c;
536
537         assert(where);
538         assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
539         assert(ret);
540
541         for (c = where->child; c; c = c->next) {
542                 if (c->type == BUS_MATCH_LEAF &&
543                     c->leaf.callback == callback &&
544                     c->leaf.userdata == userdata) {
545                         *ret = c;
546                         return 1;
547                 }
548         }
549
550         return 0;
551 }
552
553 enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n) {
554         assert(k);
555
556         if (n == 4 && memcmp(k, "type", 4) == 0)
557                 return BUS_MATCH_MESSAGE_TYPE;
558         if (n == 6 && memcmp(k, "sender", 6) == 0)
559                 return BUS_MATCH_SENDER;
560         if (n == 11 && memcmp(k, "destination", 11) == 0)
561                 return BUS_MATCH_DESTINATION;
562         if (n == 9 && memcmp(k, "interface", 9) == 0)
563                 return BUS_MATCH_INTERFACE;
564         if (n == 6 && memcmp(k, "member", 6) == 0)
565                 return BUS_MATCH_MEMBER;
566         if (n == 4 && memcmp(k, "path", 4) == 0)
567                 return BUS_MATCH_PATH;
568         if (n == 14 && memcmp(k, "path_namespace", 14) == 0)
569                 return BUS_MATCH_PATH_NAMESPACE;
570
571         if (n == 4 && memcmp(k, "arg", 3) == 0) {
572                 int j;
573
574                 j = undecchar(k[3]);
575                 if (j < 0)
576                         return -EINVAL;
577
578                 return BUS_MATCH_ARG + j;
579         }
580
581         if (n == 5 && memcmp(k, "arg", 3) == 0) {
582                 int a, b;
583                 enum bus_match_node_type t;
584
585                 a = undecchar(k[3]);
586                 b = undecchar(k[4]);
587                 if (a <= 0 || b < 0)
588                         return -EINVAL;
589
590                 t = BUS_MATCH_ARG + a * 10 + b;
591                 if (t > BUS_MATCH_ARG_LAST)
592                         return -EINVAL;
593
594                 return t;
595         }
596
597         if (n == 8 && memcmp(k, "arg", 3) == 0 && memcmp(k + 4, "path", 4) == 0) {
598                 int j;
599
600                 j = undecchar(k[3]);
601                 if (j < 0)
602                         return -EINVAL;
603
604                 return BUS_MATCH_ARG_PATH + j;
605         }
606
607         if (n == 9 && memcmp(k, "arg", 3) == 0 && memcmp(k + 5, "path", 4) == 0) {
608                 enum bus_match_node_type t;
609                 int a, b;
610
611                 a = undecchar(k[3]);
612                 b = undecchar(k[4]);
613                 if (a <= 0 || b < 0)
614                         return -EINVAL;
615
616                 t = BUS_MATCH_ARG_PATH + a * 10 + b;
617                 if (t > BUS_MATCH_ARG_PATH_LAST)
618                         return -EINVAL;
619
620                 return t;
621         }
622
623         if (n == 13 && memcmp(k, "arg", 3) == 0 && memcmp(k + 4, "namespace", 9) == 0) {
624                 int j;
625
626                 j = undecchar(k[3]);
627                 if (j < 0)
628                         return -EINVAL;
629
630                 return BUS_MATCH_ARG_NAMESPACE + j;
631         }
632
633         if (n == 14 && memcmp(k, "arg", 3) == 0 && memcmp(k + 5, "namespace", 9) == 0) {
634                 enum bus_match_node_type t;
635                 int a, b;
636
637                 a = undecchar(k[3]);
638                 b = undecchar(k[4]);
639                 if (a <= 0 || b < 0)
640                         return -EINVAL;
641
642                 t = BUS_MATCH_ARG_NAMESPACE + a * 10 + b;
643                 if (t > BUS_MATCH_ARG_NAMESPACE_LAST)
644                         return -EINVAL;
645
646                 return t;
647         }
648
649         return -EINVAL;
650 }
651
652 struct match_component {
653         enum bus_match_node_type type;
654         uint8_t value_u8;
655         char *value_str;
656 };
657
658 static int match_component_compare(const void *a, const void *b) {
659         const struct match_component *x = a, *y = b;
660
661         if (x->type < y->type)
662                 return -1;
663         if (x->type > y->type)
664                 return 1;
665
666         return 0;
667 }
668
669 static void free_components(struct match_component *components, unsigned n_components) {
670         unsigned i;
671
672         for (i = 0; i < n_components; i++)
673                 free(components[i].value_str);
674
675         free(components);
676 }
677
678 static int parse_match(
679                 const char *match,
680                 struct match_component **_components,
681                 unsigned *_n_components) {
682
683         const char *p = match;
684         struct match_component *components = NULL;
685         size_t components_allocated = 0;
686         unsigned n_components = 0, i;
687         _cleanup_free_ char *value = NULL;
688         int r;
689
690         assert(match);
691         assert(_components);
692         assert(_n_components);
693
694         while (*p != 0) {
695                 const char *eq, *q;
696                 enum bus_match_node_type t;
697                 unsigned j = 0;
698                 size_t value_allocated = 0;
699                 bool escaped = false;
700                 uint8_t u;
701
702                 eq = strchr(p, '=');
703                 if (!eq)
704                         return -EINVAL;
705
706                 if (eq[1] != '\'')
707                         return -EINVAL;
708
709                 t = bus_match_node_type_from_string(p, eq - p);
710                 if (t < 0)
711                         return -EINVAL;
712
713                 for (q = eq + 2;; q++) {
714
715                         if (*q == 0) {
716                                 r = -EINVAL;
717                                 goto fail;
718                         }
719
720                         if (!escaped) {
721                                 if (*q == '\\') {
722                                         escaped = true;
723                                         continue;
724                                 }
725                                 if (*q == '\'') {
726                                         if (value)
727                                                 value[j] = 0;
728                                         break;
729                                 }
730                         }
731
732                         if (!GREEDY_REALLOC(value, value_allocated, j + 2)) {
733                                 r = -ENOMEM;
734                                 goto fail;
735                         }
736
737                         value[j++] = *q;
738                         escaped = false;
739                 }
740
741                 if (t == BUS_MATCH_MESSAGE_TYPE) {
742                         r = bus_message_type_from_string(value, &u);
743                         if (r < 0)
744                                 goto fail;
745
746                         free(value);
747                         value = NULL;
748                 } else
749                         u = 0;
750
751                 if (!GREEDY_REALLOC(components, components_allocated, n_components + 1)) {
752                         r = -ENOMEM;
753                         goto fail;
754                 }
755
756                 components[n_components].type = t;
757                 components[n_components].value_str = value;
758                 components[n_components].value_u8 = u;
759                 n_components++;
760
761                 value = NULL;
762
763                 if (q[1] == 0)
764                         break;
765
766                 if (q[1] != ',') {
767                         r = -EINVAL;
768                         goto fail;
769                 }
770
771                 p = q + 2;
772         }
773
774         /* Order the whole thing, so that we always generate the same tree */
775         qsort(components, n_components, sizeof(struct match_component), match_component_compare);
776
777         /* Check for duplicates */
778         for (i = 0; i+1 < n_components; i++)
779                 if (components[i].type == components[i+1].type) {
780                         r = -EINVAL;
781                         goto fail;
782                 }
783
784         *_components = components;
785         *_n_components = n_components;
786
787         return 0;
788
789 fail:
790         free_components(components, n_components);
791         return r;
792 }
793
794 int bus_match_add(
795                 struct bus_match_node *root,
796                 const char *match,
797                 sd_bus_message_handler_t callback,
798                 void *userdata,
799                 struct bus_match_node **ret) {
800
801         struct match_component *components = NULL;
802         unsigned n_components = 0, i;
803         struct bus_match_node *n;
804         int r;
805
806         assert(root);
807         assert(match);
808         assert(callback);
809
810         r = parse_match(match, &components, &n_components);
811         if (r < 0)
812                 return r;
813
814         n = root;
815         for (i = 0; i < n_components; i++) {
816                 r = bus_match_add_compare_value(
817                                 n, components[i].type,
818                                 components[i].value_u8, components[i].value_str, &n);
819                 if (r < 0)
820                         goto finish;
821         }
822
823         r = bus_match_add_leaf(n, callback, userdata, &n);
824         if (r < 0)
825                 goto finish;
826
827         if (ret)
828                 *ret = n;
829
830 finish:
831         free_components(components, n_components);
832         return r;
833 }
834
835 int bus_match_remove(
836                 struct bus_match_node *root,
837                 const char *match,
838                 sd_bus_message_handler_t callback,
839                 void *userdata) {
840
841         struct match_component *components = NULL;
842         unsigned n_components = 0, i;
843         struct bus_match_node *n, **gc;
844         int r;
845
846         assert(root);
847         assert(match);
848
849         r = parse_match(match, &components, &n_components);
850         if (r < 0)
851                 return r;
852
853         gc = newa(struct bus_match_node*, n_components);
854
855         n = root;
856         for (i = 0; i < n_components; i++) {
857                 r = bus_match_find_compare_value(
858                                 n, components[i].type,
859                                 components[i].value_u8, components[i].value_str,
860                                 &n);
861                 if (r <= 0)
862                         goto finish;
863
864                 gc[i] = n;
865         }
866
867         r = bus_match_find_leaf(n, callback, userdata, &n);
868         if (r <= 0)
869                 goto finish;
870
871         /* Free the leaf */
872         bus_match_node_free(n);
873
874         /* Prune the tree above */
875         for (i = n_components; i > 0; i --) {
876                 struct bus_match_node *p = gc[i-1]->parent;
877
878                 if (!bus_match_node_maybe_free(gc[i-1]))
879                         break;
880
881                 if (!bus_match_node_maybe_free(p))
882                         break;
883         }
884
885 finish:
886         free_components(components, n_components);
887         return r;
888 }
889
890 void bus_match_free(struct bus_match_node *node) {
891         struct bus_match_node *c;
892
893         if (!node)
894                 return;
895
896         if (BUS_MATCH_CAN_HASH(node->type)) {
897                 Iterator i;
898
899                 HASHMAP_FOREACH(c, node->compare.children, i)
900                         bus_match_free(c);
901
902                 assert(hashmap_isempty(node->compare.children));
903         }
904
905         while ((c = node->child))
906                 bus_match_free(c);
907
908         if (node->type != BUS_MATCH_ROOT)
909                 bus_match_node_free(node);
910 }
911
912 const char* bus_match_node_type_to_string(enum bus_match_node_type t, char buf[], size_t l) {
913         switch (t) {
914
915         case BUS_MATCH_ROOT:
916                 return "root";
917
918         case BUS_MATCH_VALUE:
919                 return "value";
920
921         case BUS_MATCH_LEAF:
922                 return "leaf";
923
924         case BUS_MATCH_MESSAGE_TYPE:
925                 return "type";
926
927         case BUS_MATCH_SENDER:
928                 return "sender";
929
930         case BUS_MATCH_DESTINATION:
931                 return "destination";
932
933         case BUS_MATCH_INTERFACE:
934                 return "interface";
935
936         case BUS_MATCH_MEMBER:
937                 return "member";
938
939         case BUS_MATCH_PATH:
940                 return "path";
941
942         case BUS_MATCH_PATH_NAMESPACE:
943                 return "path_namespace";
944
945         case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
946                 snprintf(buf, l, "arg%i", t - BUS_MATCH_ARG);
947                 return buf;
948
949         case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
950                 snprintf(buf, l, "arg%ipath", t - BUS_MATCH_ARG_PATH);
951                 return buf;
952
953         case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
954                 snprintf(buf, l, "arg%inamespace", t - BUS_MATCH_ARG_NAMESPACE);
955                 return buf;
956
957         default:
958                 return NULL;
959         }
960 }
961
962 void bus_match_dump(struct bus_match_node *node, unsigned level) {
963         struct bus_match_node *c;
964         _cleanup_free_ char *pfx = NULL;
965         char buf[32];
966
967         if (!node)
968                 return;
969
970         pfx = strrep("  ", level);
971         printf("%s[%s]", strempty(pfx), bus_match_node_type_to_string(node->type, buf, sizeof(buf)));
972
973         if (node->type == BUS_MATCH_VALUE) {
974                 if (node->parent->type == BUS_MATCH_MESSAGE_TYPE)
975                         printf(" <%u>\n", node->value.u8);
976                 else
977                         printf(" <%s>\n", node->value.str);
978         } else if (node->type == BUS_MATCH_ROOT)
979                 puts(" root");
980         else if (node->type == BUS_MATCH_LEAF)
981                 printf(" %p/%p\n", node->leaf.callback, node->leaf.userdata);
982         else
983                 putchar('\n');
984
985         if (BUS_MATCH_CAN_HASH(node->type)) {
986                 Iterator i;
987
988                 HASHMAP_FOREACH(c, node->compare.children, i)
989                         bus_match_dump(c, level + 1);
990         }
991
992         for (c = node->child; c; c = c->next)
993                 bus_match_dump(c, level + 1);
994 }