From: Lennart Poettering Date: Sun, 19 May 2013 16:39:08 +0000 (+0200) Subject: bus: calculate bloom filter for match X-Git-Tag: v205~215 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=c78196699d3d805b2237896a1d2b8efeec6068d0 bus: calculate bloom filter for match Yay! Filtering using kernel bloom filter matches works now! Yippieh! --- diff --git a/TODO b/TODO index fb5f0c381..561e7ceb3 100644 --- a/TODO +++ b/TODO @@ -43,6 +43,8 @@ Features: - move to gvariant - merge busctl into systemctl or so? - synthesize sd_bus_message objects from kernel messages + - properly implement name registry ioctls for kdbus + - get rid of object hash table, use decision tree instead? * in the final killing spree, detect processes from the root directory, and complain loudly if they have argv[0][0] == '@' set. diff --git a/src/libsystemd-bus/bus-control.c b/src/libsystemd-bus/bus-control.c index 177bd882a..ae0d7f976 100644 --- a/src/libsystemd-bus/bus-control.c +++ b/src/libsystemd-bus/bus-control.c @@ -32,6 +32,7 @@ #include "bus-internal.h" #include "bus-message.h" #include "bus-control.h" +#include "bus-bloom.h" int sd_bus_get_unique_name(sd_bus *bus, const char **unique) { int r; @@ -339,36 +340,174 @@ int sd_bus_get_owner_pid(sd_bus *bus, const char *name, pid_t *pid) { return 0; } -int bus_add_match_internal(sd_bus *bus, const char *match) { +int bus_add_match_internal( + sd_bus *bus, + const char *match, + struct bus_match_component *components, + unsigned n_components, + uint64_t cookie) { + + int r; + assert(bus); assert(match); - return sd_bus_call_method( - bus, - "org.freedesktop.DBus", - "/", - "org.freedesktop.DBus", - "AddMatch", - NULL, - NULL, - "s", - match); + if (bus->is_kernel) { + struct kdbus_cmd_match *m; + struct kdbus_item *item; + uint64_t bloom[BLOOM_SIZE/8]; + size_t sz; + const char *sender = NULL; + size_t sender_length = 0; + uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY; + bool using_bloom = false; + unsigned i; + + zero(bloom); + + sz = offsetof(struct kdbus_cmd_match, items); + + for (i = 0; i < n_components; i++) { + struct bus_match_component *c = &components[i]; + + switch (c->type) { + + case BUS_MATCH_SENDER: + r = bus_kernel_parse_unique_name(c->value_str, &src_id); + if (r < 0) + return r; + + if (r > 0) { + sender = c->value_str; + sender_length = strlen(sender); + sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1); + } + + break; + + case BUS_MATCH_DESTINATION: + /* The bloom filter does not include + the destination, since it is only + available for broadcast messages + which do not carry a destination + since they are undirected. */ + break; + + case BUS_MATCH_INTERFACE: + bloom_add_pair(bloom, "interface", c->value_str); + using_bloom = true; + break; + + case BUS_MATCH_MEMBER: + bloom_add_pair(bloom, "member", c->value_str); + using_bloom = true; + break; + + case BUS_MATCH_PATH: + bloom_add_pair(bloom, "path", c->value_str); + using_bloom = true; + break; + + case BUS_MATCH_PATH_NAMESPACE: + bloom_add_pair(bloom, "path-slash-prefix", c->value_str); + using_bloom = true; + break; + + case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: + case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: + case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: + case BUS_MATCH_MESSAGE_TYPE: + assert_not_reached("FIXME!"); + break; + + case BUS_MATCH_ROOT: + case BUS_MATCH_VALUE: + case BUS_MATCH_LEAF: + case _BUS_MATCH_NODE_TYPE_MAX: + case _BUS_MATCH_NODE_TYPE_INVALID: + assert_not_reached("Invalid match type?"); + } + } + + if (using_bloom) + sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE); + + m = alloca0(sz); + m->size = sz; + m->cookie = cookie; + m->src_id = src_id; + + item = m->items; + + if (using_bloom) { + item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE; + item->type = KDBUS_MATCH_BLOOM; + memcpy(item->data64, bloom, BLOOM_SIZE); + + item = KDBUS_ITEM_NEXT(item); + } + + if (sender) { + item->size = offsetof(struct kdbus_item, str) + sender_length + 1; + item->type = KDBUS_MATCH_SRC_NAME; + memcpy(item->str, sender, sender_length + 1); + } + + r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); + if (r < 0) + return -errno; + + } else { + return sd_bus_call_method( + bus, + "org.freedesktop.DBus", + "/", + "org.freedesktop.DBus", + "AddMatch", + NULL, + NULL, + "s", + match); + } + + return 0; } -int bus_remove_match_internal(sd_bus *bus, const char *match) { +int bus_remove_match_internal( + sd_bus *bus, + const char *match, + uint64_t cookie) { + + int r; + assert(bus); assert(match); - return sd_bus_call_method( - bus, - "org.freedesktop.DBus", - "/", - "org.freedesktop.DBus", - "RemoveMatch", - NULL, - NULL, - "s", - match); + if (bus->is_kernel) { + struct kdbus_cmd_match m; + + zero(m); + m.size = offsetof(struct kdbus_cmd_match, items); + m.cookie = cookie; + + r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m); + if (r < 0) + return -errno; + + } else { + return sd_bus_call_method( + bus, + "org.freedesktop.DBus", + "/", + "org.freedesktop.DBus", + "RemoveMatch", + NULL, + NULL, + "s", + match); + } + + return 0; } int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) { diff --git a/src/libsystemd-bus/bus-control.h b/src/libsystemd-bus/bus-control.h index 34ecb260c..2cac5d83a 100644 --- a/src/libsystemd-bus/bus-control.h +++ b/src/libsystemd-bus/bus-control.h @@ -23,5 +23,5 @@ #include "sd-bus.h" -int bus_add_match_internal(sd_bus *bus, const char *match); -int bus_remove_match_internal(sd_bus *bus, const char *match); +int bus_add_match_internal(sd_bus *bus, const char *match, struct bus_match_component *components, unsigned n_components, uint64_t cookie); +int bus_remove_match_internal(sd_bus *bus, const char *match, uint64_t cookie); diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h index e775b0941..147a83c04 100644 --- a/src/libsystemd-bus/bus-internal.h +++ b/src/libsystemd-bus/bus-internal.h @@ -182,6 +182,8 @@ struct sd_bus { pid_t original_pid; uint64_t hello_flags; + + uint64_t match_cookie; }; static inline void bus_unrefp(sd_bus **b) { diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c index 50b28e728..33c25a4fd 100644 --- a/src/libsystemd-bus/bus-kernel.c +++ b/src/libsystemd-bus/bus-kernel.c @@ -34,18 +34,7 @@ #include "bus-kernel.h" #include "bus-bloom.h" -#define KDBUS_ITEM_NEXT(item) \ - (typeof(item))(((uint8_t *)item) + ALIGN8((item)->size)) - -#define KDBUS_ITEM_FOREACH(item, head) \ - for (item = (head)->items; \ - (uint8_t *)(item) < (uint8_t *)(head) + (head)->size; \ - item = KDBUS_ITEM_NEXT(item)) - -#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data) -#define KDBUS_ITEM_SIZE(s) ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE) - -static int parse_unique_name(const char *s, uint64_t *id) { +int bus_kernel_parse_unique_name(const char *s, uint64_t *id) { int r; assert(s); @@ -215,7 +204,7 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { return 0; if (m->destination) { - r = parse_unique_name(m->destination, &unique); + r = bus_kernel_parse_unique_name(m->destination, &unique); if (r < 0) return r; diff --git a/src/libsystemd-bus/bus-kernel.h b/src/libsystemd-bus/bus-kernel.h index 8cf153ab4..dddecfb21 100644 --- a/src/libsystemd-bus/bus-kernel.h +++ b/src/libsystemd-bus/bus-kernel.h @@ -23,6 +23,17 @@ #include "sd-bus.h" +#define KDBUS_ITEM_NEXT(item) \ + (typeof(item))(((uint8_t *)item) + ALIGN8((item)->size)) + +#define KDBUS_ITEM_FOREACH(item, head) \ + for (item = (head)->items; \ + (uint8_t *)(item) < (uint8_t *)(head) + (head)->size; \ + item = KDBUS_ITEM_NEXT(item)) + +#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data) +#define KDBUS_ITEM_SIZE(s) ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE) + #define MEMFD_CACHE_MAX 32 /* When we cache a memfd block for reuse, we will truncate blocks @@ -55,3 +66,5 @@ int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size); void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size); void bus_kernel_flush_memfd(sd_bus *bus); + +int bus_kernel_parse_unique_name(const char *s, uint64_t *id); diff --git a/src/libsystemd-bus/bus-match.c b/src/libsystemd-bus/bus-match.c index ed871d9d7..95e625be0 100644 --- a/src/libsystemd-bus/bus-match.c +++ b/src/libsystemd-bus/bus-match.c @@ -255,10 +255,11 @@ int bus_match_run( return r; /* Run the callback. And then invoke siblings. */ - assert(node->leaf.callback); - r = node->leaf.callback(bus, m, node->leaf.userdata); - if (r != 0) - return r; + if (node->leaf.callback) { + r = node->leaf.callback(bus, m, node->leaf.userdata); + if (r != 0) + return r; + } return bus_match_run(bus, node->next, m); @@ -499,6 +500,7 @@ static int bus_match_add_leaf( struct bus_match_node *where, sd_bus_message_handler_t callback, void *userdata, + uint64_t cookie, struct bus_match_node **ret) { struct bus_match_node *n; @@ -518,6 +520,7 @@ static int bus_match_add_leaf( n->next->prev = n; n->leaf.callback = callback; n->leaf.userdata = userdata; + n->leaf.cookie = cookie; where->child = n; @@ -648,14 +651,8 @@ enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n return -EINVAL; } -struct match_component { - enum bus_match_node_type type; - uint8_t value_u8; - char *value_str; -}; - static int match_component_compare(const void *a, const void *b) { - const struct match_component *x = a, *y = b; + const struct bus_match_component *x = a, *y = b; if (x->type < y->type) return -1; @@ -665,7 +662,7 @@ static int match_component_compare(const void *a, const void *b) { return 0; } -static void free_components(struct match_component *components, unsigned n_components) { +void bus_match_parse_free(struct bus_match_component *components, unsigned n_components) { unsigned i; for (i = 0; i < n_components; i++) @@ -674,13 +671,13 @@ static void free_components(struct match_component *components, unsigned n_compo free(components); } -static int parse_match( +int bus_match_parse( const char *match, - struct match_component **_components, + struct bus_match_component **_components, unsigned *_n_components) { const char *p = match; - struct match_component *components = NULL; + struct bus_match_component *components = NULL; size_t components_allocated = 0; unsigned n_components = 0, i; _cleanup_free_ char *value = NULL; @@ -771,7 +768,7 @@ static int parse_match( } /* Order the whole thing, so that we always generate the same tree */ - qsort(components, n_components, sizeof(struct match_component), match_component_compare); + qsort(components, n_components, sizeof(struct bus_match_component), match_component_compare); /* Check for duplicates */ for (i = 0; i+1 < n_components; i++) @@ -786,29 +783,24 @@ static int parse_match( return 0; fail: - free_components(components, n_components); + bus_match_parse_free(components, n_components); return r; } int bus_match_add( struct bus_match_node *root, - const char *match, + struct bus_match_component *components, + unsigned n_components, sd_bus_message_handler_t callback, void *userdata, + uint64_t cookie, struct bus_match_node **ret) { - struct match_component *components = NULL; - unsigned n_components = 0, i; + unsigned i; struct bus_match_node *n; int r; assert(root); - assert(match); - assert(callback); - - r = parse_match(match, &components, &n_components); - if (r < 0) - return r; n = root; for (i = 0; i < n_components; i++) { @@ -816,38 +808,32 @@ int bus_match_add( n, components[i].type, components[i].value_u8, components[i].value_str, &n); if (r < 0) - goto finish; + return r; } - r = bus_match_add_leaf(n, callback, userdata, &n); + r = bus_match_add_leaf(n, callback, userdata, cookie, &n); if (r < 0) - goto finish; + return r; if (ret) *ret = n; -finish: - free_components(components, n_components); - return r; + return 0; } int bus_match_remove( struct bus_match_node *root, - const char *match, + struct bus_match_component *components, + unsigned n_components, sd_bus_message_handler_t callback, - void *userdata) { + void *userdata, + uint64_t *cookie) { - struct match_component *components = NULL; - unsigned n_components = 0, i; + unsigned i; struct bus_match_node *n, **gc; int r; assert(root); - assert(match); - - r = parse_match(match, &components, &n_components); - if (r < 0) - return r; gc = newa(struct bus_match_node*, n_components); @@ -858,14 +844,17 @@ int bus_match_remove( components[i].value_u8, components[i].value_str, &n); if (r <= 0) - goto finish; + return r; gc[i] = n; } r = bus_match_find_leaf(n, callback, userdata, &n); if (r <= 0) - goto finish; + return r; + + if (cookie) + *cookie = n->leaf.cookie; /* Free the leaf */ bus_match_node_free(n); @@ -881,8 +870,6 @@ int bus_match_remove( break; } -finish: - free_components(components, n_components); return r; } diff --git a/src/libsystemd-bus/bus-match.h b/src/libsystemd-bus/bus-match.h index 4d46cf9af..d24aeec43 100644 --- a/src/libsystemd-bus/bus-match.h +++ b/src/libsystemd-bus/bus-match.h @@ -61,6 +61,7 @@ struct bus_match_node { sd_bus_message_handler_t callback; void *userdata; unsigned last_iteration; + uint64_t cookie; } leaf; struct { /* If this is set, then the child is NULL */ @@ -69,10 +70,16 @@ struct bus_match_node { }; }; +struct bus_match_component { + enum bus_match_node_type type; + uint8_t value_u8; + char *value_str; +}; + int bus_match_run(sd_bus *bus, struct bus_match_node *root, sd_bus_message *m); -int bus_match_add(struct bus_match_node *root, const char *match, sd_bus_message_handler_t callback, void *userdata, struct bus_match_node **ret); -int bus_match_remove(struct bus_match_node *root, const char *match, sd_bus_message_handler_t callback, void *userdata); +int bus_match_add(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, uint64_t cookie, struct bus_match_node **ret); +int bus_match_remove(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, uint64_t *cookie); void bus_match_free(struct bus_match_node *node); @@ -80,3 +87,6 @@ void bus_match_dump(struct bus_match_node *node, unsigned level); const char* bus_match_node_type_to_string(enum bus_match_node_type t, char buf[], size_t l); enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n); + +int bus_match_parse(const char *match, struct bus_match_component **_components, unsigned *_n_components); +void bus_match_parse_free(struct bus_match_component *components, unsigned n_components); diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 6033aa744..7ae32036b 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -2404,6 +2404,9 @@ int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handl } int sd_bus_add_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) { + struct bus_match_component *components = NULL; + unsigned n_components = 0; + uint64_t cookie = 0; int r = 0; if (!bus) @@ -2413,27 +2416,35 @@ int sd_bus_add_match(sd_bus *bus, const char *match, sd_bus_message_handler_t ca if (bus_pid_changed(bus)) return -ECHILD; + r = bus_match_parse(match, &components, &n_components); + if (r < 0) + goto finish; + if (bus->bus_client) { - r = bus_add_match_internal(bus, match); + cookie = ++bus->match_cookie; + + r = bus_add_match_internal(bus, match, components, n_components, cookie); if (r < 0) - return r; + goto finish; } - if (callback) { - bus->match_callbacks_modified = true; - r = bus_match_add(&bus->match_callbacks, match, callback, userdata, NULL); - if (r < 0) { - - if (bus->bus_client) - bus_remove_match_internal(bus, match); - } + bus->match_callbacks_modified = true; + r = bus_match_add(&bus->match_callbacks, components, n_components, callback, userdata, cookie, NULL); + if (r < 0) { + if (bus->bus_client) + bus_remove_match_internal(bus, match, cookie); } +finish: + bus_match_parse_free(components, n_components); return r; } int sd_bus_remove_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) { + struct bus_match_component *components = NULL; + unsigned n_components = 0; int r = 0, q = 0; + uint64_t cookie = 0; if (!bus) return -EINVAL; @@ -2442,17 +2453,19 @@ int sd_bus_remove_match(sd_bus *bus, const char *match, sd_bus_message_handler_t if (bus_pid_changed(bus)) return -ECHILD; + r = bus_match_parse(match, &components, &n_components); + if (r < 0) + return r; + + bus->match_callbacks_modified = true; + r = bus_match_remove(&bus->match_callbacks, components, n_components, callback, userdata, &cookie); + if (bus->bus_client) - r = bus_remove_match_internal(bus, match); + q = bus_remove_match_internal(bus, match, cookie); - if (callback) { - bus->match_callbacks_modified = true; - q = bus_match_remove(&bus->match_callbacks, match, callback, userdata); - } + bus_match_parse_free(components, n_components); - if (r < 0) - return r; - return q; + return r < 0 ? r : q; } int sd_bus_emit_signal( diff --git a/src/libsystemd-bus/test-bus-kernel.c b/src/libsystemd-bus/test-bus-kernel.c index b8e89e41b..0a2457a6d 100644 --- a/src/libsystemd-bus/test-bus-kernel.c +++ b/src/libsystemd-bus/test-bus-kernel.c @@ -92,19 +92,8 @@ int main(int argc, char *argv[]) { printf("unique b: %s\n", ub); - { - //FIXME: - struct kdbus_cmd_match cmd_match; - - cmd_match.size = sizeof(cmd_match); - cmd_match.src_id = KDBUS_MATCH_SRC_ID_ANY; - - r = ioctl(sd_bus_get_fd(a), KDBUS_CMD_MATCH_ADD, &cmd_match); - assert_se(r >= 0); - - r = ioctl(sd_bus_get_fd(b), KDBUS_CMD_MATCH_ADD, &cmd_match); - assert_se(r >= 0); - } + /* interface='waldo.com',member='Piep' */ + assert_se(sd_bus_add_match(b, "interface='waldo.com'", NULL, NULL) >= 0); r = sd_bus_emit_signal(a, "/foo/bar/waldo", "waldo.com", "Piep", "sss", "I am a string", "/this/is/a/path", "and.this.a.domain.name"); assert_se(r >= 0); diff --git a/src/libsystemd-bus/test-bus-match.c b/src/libsystemd-bus/test-bus-match.c index 605d86a85..db977f726 100644 --- a/src/libsystemd-bus/test-bus-match.c +++ b/src/libsystemd-bus/test-bus-match.c @@ -55,6 +55,36 @@ static bool mask_contains(unsigned a[], unsigned n) { return true; } +static int match_add(struct bus_match_node *root, const char *match, int value) { + struct bus_match_component *components = NULL; + unsigned n_components = 0; + int r; + + r = bus_match_parse(match, &components, &n_components); + if (r < 0) + return r; + + r = bus_match_add(root, components, n_components, filter, INT_TO_PTR(value), 0, NULL); + bus_match_parse_free(components, n_components); + + return r; +} + +static int match_remove(struct bus_match_node *root, const char *match, int value) { + struct bus_match_component *components = NULL; + unsigned n_components = 0; + int r; + + r = bus_match_parse(match, &components, &n_components); + if (r < 0) + return r; + + r = bus_match_remove(root, components, n_components, filter, INT_TO_PTR(value), 0); + bus_match_parse_free(components, n_components); + + return r; +} + int main(int argc, char *argv[]) { struct bus_match_node root; _cleanup_bus_message_unref_ sd_bus_message *m = NULL; @@ -63,20 +93,20 @@ int main(int argc, char *argv[]) { zero(root); root.type = BUS_MATCH_ROOT; - assert_se(bus_match_add(&root, "arg2='wal\\'do',sender='foo',type='signal',interface='bar',", filter, INT_TO_PTR(1), NULL) >= 0); - assert_se(bus_match_add(&root, "arg2='wal\\'do2',sender='foo',type='signal',interface='bar',", filter, INT_TO_PTR(2), NULL) >= 0); - assert_se(bus_match_add(&root, "arg3='test',sender='foo',type='signal',interface='bar',", filter, INT_TO_PTR(3), NULL) >= 0); - assert_se(bus_match_add(&root, "arg3='test',sender='foo',type='method_call',interface='bar',", filter, INT_TO_PTR(4), NULL) >= 0); - assert_se(bus_match_add(&root, "", filter, INT_TO_PTR(5), NULL) >= 0); - assert_se(bus_match_add(&root, "interface='quux'", filter, INT_TO_PTR(6), NULL) >= 0); - assert_se(bus_match_add(&root, "interface='bar'", filter, INT_TO_PTR(7), NULL) >= 0); - assert_se(bus_match_add(&root, "member='waldo',path='/foo/bar'", filter, INT_TO_PTR(8), NULL) >= 0); - assert_se(bus_match_add(&root, "path='/foo/bar'", filter, INT_TO_PTR(9), NULL) >= 0); - assert_se(bus_match_add(&root, "path_namespace='/foo'", filter, INT_TO_PTR(10), NULL) >= 0); - assert_se(bus_match_add(&root, "path_namespace='/foo/quux'", filter, INT_TO_PTR(11), NULL) >= 0); - assert_se(bus_match_add(&root, "arg1='two'", filter, INT_TO_PTR(12), NULL) >= 0); - assert_se(bus_match_add(&root, "member='waldo',arg2path='/prefix/'", filter, INT_TO_PTR(13), NULL) >= 0); - assert_se(bus_match_add(&root, "member='waldo',path='/foo/bar',arg3namespace='prefix'", filter, INT_TO_PTR(14), NULL) >= 0); + assert_se(match_add(&root, "arg2='wal\\'do',sender='foo',type='signal',interface='bar',", 1) >= 0); + assert_se(match_add(&root, "arg2='wal\\'do2',sender='foo',type='signal',interface='bar',", 2) >= 0); + assert_se(match_add(&root, "arg3='test',sender='foo',type='signal',interface='bar',", 3) >= 0); + assert_se(match_add(&root, "arg3='test',sender='foo',type='method_call',interface='bar',", 4) >= 0); + assert_se(match_add(&root, "", 5) >= 0); + assert_se(match_add(&root, "interface='quux'", 6) >= 0); + assert_se(match_add(&root, "interface='bar'", 7) >= 0); + assert_se(match_add(&root, "member='waldo',path='/foo/bar'", 8) >= 0); + assert_se(match_add(&root, "path='/foo/bar'", 9) >= 0); + assert_se(match_add(&root, "path_namespace='/foo'", 10) >= 0); + assert_se(match_add(&root, "path_namespace='/foo/quux'", 11) >= 0); + assert_se(match_add(&root, "arg1='two'", 12) >= 0); + assert_se(match_add(&root, "member='waldo',arg2path='/prefix/'", 13) >= 0); + assert_se(match_add(&root, "member='waldo',path='/foo/bar',arg3namespace='prefix'", 14) >= 0); bus_match_dump(&root, 0); @@ -88,9 +118,9 @@ int main(int argc, char *argv[]) { assert_se(bus_match_run(NULL, &root, m) == 0); assert_se(mask_contains((unsigned[]) { 9, 8, 7, 5, 10, 12, 13, 14 }, 8)); - assert_se(bus_match_remove(&root, "member='waldo',path='/foo/bar'", filter, INT_TO_PTR(8)) > 0); - assert_se(bus_match_remove(&root, "arg2path='/prefix/',member='waldo'", filter, INT_TO_PTR(13)) > 0); - assert_se(bus_match_remove(&root, "interface='barxx'", filter, INT_TO_PTR(7)) == 0); + assert_se(match_remove(&root, "member='waldo',path='/foo/bar'", 8) > 0); + assert_se(match_remove(&root, "arg2path='/prefix/',member='waldo'", 13) > 0); + assert_se(match_remove(&root, "interface='barxx'", 7) == 0); bus_match_dump(&root, 0);