X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-bus%2Fbus-match.c;h=0e92a85ef756fdaf177e8abdcf9c61394c5531dc;hb=412c18f10c9df3f0a02358d8c0e707ed2e5fa186;hp=ffc97562fd8e286d12db6f6deeabf82f3c440f57;hpb=607553f9306286fdccf0b356bc3d1087adfe21c4;p=elogind.git diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c index ffc97562f..0e92a85ef 100644 --- a/src/libsystemd/sd-bus/bus-match.c +++ b/src/libsystemd/sd-bus/bus-match.c @@ -116,6 +116,9 @@ static void bus_match_node_free(struct bus_match_node *node) { static bool bus_match_node_maybe_free(struct bus_match_node *node) { assert(node); + if (node->type == BUS_MATCH_ROOT) + return false; + if (node->child) return false; @@ -275,10 +278,10 @@ int bus_match_run( case BUS_MATCH_LEAF: if (bus) { - if (node->leaf.last_iteration == bus->iteration_counter) + if (node->leaf.callback->last_iteration == bus->iteration_counter) return 0; - node->leaf.last_iteration = bus->iteration_counter; + node->leaf.callback->last_iteration = bus->iteration_counter; } r = sd_bus_message_rewind(m, true); @@ -286,13 +289,29 @@ int bus_match_run( return r; /* Run the callback. And then invoke siblings. */ - if (node->leaf.callback) { + if (node->leaf.callback->callback) { _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL; + sd_bus_slot *slot; + + slot = container_of(node->leaf.callback, sd_bus_slot, match_callback); + if (bus) { + bus->current_slot = sd_bus_slot_ref(slot); + bus->current_handler = node->leaf.callback->callback; + bus->current_userdata = slot->userdata; + } + r = node->leaf.callback->callback(bus, m, slot->userdata, &error_buffer); + if (bus) { + bus->current_userdata = NULL; + bus->current_handler = NULL; + bus->current_slot = sd_bus_slot_unref(slot); + } - r = node->leaf.callback(bus, m, node->leaf.userdata, &error_buffer); r = bus_maybe_reply_error(m, r, &error_buffer); if (r != 0) return r; + + if (bus && bus->match_callbacks_modified) + return 0; } return bus_match_run(bus, node->next, m); @@ -431,13 +450,13 @@ static int bus_match_add_compare_value( where->child = c; if (t == BUS_MATCH_MESSAGE_TYPE) { - c->compare.children = hashmap_new(trivial_hash_func, trivial_compare_func); + c->compare.children = hashmap_new(NULL); if (!c->compare.children) { r = -ENOMEM; goto fail; } } else if (BUS_MATCH_CAN_HASH(t)) { - c->compare.children = hashmap_new(string_hash_func, string_compare_func); + c->compare.children = hashmap_new(&string_hash_ops); if (!c->compare.children) { r = -ENOMEM; goto fail; @@ -518,7 +537,7 @@ static int bus_match_find_compare_value( else if (BUS_MATCH_CAN_HASH(t)) n = hashmap_get(c->compare.children, value_str); else { - for (n = c->child; !value_node_same(n, t, value_u8, value_str); n = n->next) + for (n = c->child; n && !value_node_same(n, t, value_u8, value_str); n = n->next) ; } @@ -532,16 +551,13 @@ static int bus_match_find_compare_value( 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 match_callback *callback) { struct bus_match_node *n; assert(where); assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE); - assert(ret); + assert(callback); n = new0(struct bus_match_node, 1); if (!n) @@ -552,13 +568,12 @@ static int bus_match_add_leaf( n->next = where->child; if (n->next) n->next->prev = n; + n->leaf.callback = callback; - n->leaf.userdata = userdata; - n->leaf.cookie = cookie; + callback->match_node = n; where->child = n; - *ret = n; return 1; } @@ -575,9 +590,13 @@ static int bus_match_find_leaf( assert(ret); for (c = where->child; c; c = c->next) { + sd_bus_slot *s; + + s = container_of(c->leaf.callback, sd_bus_slot, match_callback); + if (c->type == BUS_MATCH_LEAF && - c->leaf.callback == callback && - c->leaf.userdata == userdata) { + c->leaf.callback->callback == callback && + s->userdata == userdata) { *ret = c; return 1; } @@ -729,6 +748,9 @@ int bus_match_parse( bool escaped = false, quoted; uint8_t u; + /* Avahi's match rules appear to include whitespace, skip over it */ + p += strspn(p, " "); + eq = strchr(p, '='); if (!eq) return -EINVAL; @@ -814,7 +836,7 @@ int bus_match_parse( value = NULL; - if (q[1] == 0) + if (q[quoted] == 0) break; if (q[quoted] != ',') { @@ -889,16 +911,14 @@ 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) { + struct match_callback *callback) { unsigned i; struct bus_match_node *n; int r; assert(root); + assert(callback); n = root; for (i = 0; i < n_components; i++) { @@ -909,29 +929,56 @@ int bus_match_add( return r; } - r = bus_match_add_leaf(n, callback, userdata, cookie, &n); - if (r < 0) - return r; + return bus_match_add_leaf(n, callback); +} - if (ret) - *ret = n; +int bus_match_remove( + struct bus_match_node *root, + struct match_callback *callback) { - return 0; + struct bus_match_node *node, *pp; + + assert(root); + assert(callback); + + node = callback->match_node; + if (!node) + return 0; + + assert(node->type == BUS_MATCH_LEAF); + + callback->match_node = NULL; + + /* Free the leaf */ + pp = node->parent; + bus_match_node_free(node); + + /* Prune the tree above */ + while (pp) { + node = pp; + pp = node->parent; + + if (!bus_match_node_maybe_free(node)) + break; + } + + return 1; } -int bus_match_remove( +int bus_match_find( 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 match_callback **ret) { - unsigned i; struct bus_match_node *n, **gc; + unsigned i; int r; assert(root); + assert(ret); gc = newa(struct bus_match_node*, n_components); @@ -951,24 +998,8 @@ int bus_match_remove( if (r <= 0) return r; - if (cookie) - *cookie = n->leaf.cookie; - - /* Free the leaf */ - bus_match_node_free(n); - - /* Prune the tree above */ - for (i = n_components; i > 0; i --) { - struct bus_match_node *p = gc[i-1]->parent; - - if (!bus_match_node_maybe_free(gc[i-1])) - break; - - if (!bus_match_node_maybe_free(p)) - break; - } - - return r; + *ret = n->leaf.callback; + return 1; } void bus_match_free(struct bus_match_node *node) { @@ -1062,7 +1093,7 @@ void bus_match_dump(struct bus_match_node *node, unsigned level) { } else if (node->type == BUS_MATCH_ROOT) puts(" root"); else if (node->type == BUS_MATCH_LEAF) - printf(" %p/%p\n", node->leaf.callback, node->leaf.userdata); + printf(" %p/%p\n", node->leaf.callback->callback, container_of(node->leaf.callback, sd_bus_slot, match_callback)->userdata); else putchar('\n');