X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-bus%2Fbus-match.c;h=3a31aa0ebfc9cc6a79470314332b795c62ae7190;hb=fed1e721fd0c81e60c77120539f34e16c2585634;hp=b868159b5c8233fd49e30650d3d74fe15f40e306;hpb=19befb2d5fc087f96e40ddc432b2cc9385666209;p=elogind.git diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c index b868159b5..3a31aa0eb 100644 --- a/src/libsystemd/sd-bus/bus-match.c +++ b/src/libsystemd/sd-bus/bus-match.c @@ -134,6 +134,7 @@ static bool value_node_test( enum bus_match_node_type parent_type, uint8_t value_u8, const char *value_str, + char **value_strv, sd_bus_message *m) { assert(node); @@ -179,17 +180,46 @@ static bool value_node_test( case BUS_MATCH_INTERFACE: case BUS_MATCH_MEMBER: case BUS_MATCH_PATH: - case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: - return streq_ptr(node->value.str, value_str); + case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: { + char **i; - case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: - return namespace_simple_pattern(node->value.str, value_str); + if (value_str) + return streq_ptr(node->value.str, value_str); + + STRV_FOREACH(i, value_strv) + if (streq_ptr(node->value.str, *i)) + return true; + + return false; + } + + case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: { + char **i; + + if (value_str) + return namespace_simple_pattern(node->value.str, value_str); + + STRV_FOREACH(i, value_strv) + if (namespace_simple_pattern(node->value.str, *i)) + return true; + return false; + } case BUS_MATCH_PATH_NAMESPACE: return path_simple_pattern(node->value.str, value_str); - case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: - return path_complex_pattern(node->value.str, value_str); + case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: { + char **i; + + if (value_str) + return path_complex_pattern(node->value.str, value_str); + + STRV_FOREACH(i, value_strv) + if (path_complex_pattern(node->value.str, *i)) + return true; + + return false; + } default: assert_not_reached("Invalid node type"); @@ -235,7 +265,7 @@ int bus_match_run( struct bus_match_node *node, sd_bus_message *m) { - + _cleanup_strv_free_ char **test_strv = NULL; const char *test_str = NULL; uint8_t test_u8 = 0; int r; @@ -289,17 +319,22 @@ int bus_match_run( return r; /* Run the callback. And then invoke siblings. */ - if (node->leaf.callback) { - sd_bus_slot *slot; - + 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 = slot; + 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_slot = NULL; + if (bus) { + bus->current_userdata = NULL; + bus->current_handler = NULL; + bus->current_slot = sd_bus_slot_unref(slot); + } r = bus_maybe_reply_error(m, r, &error_buffer); if (r != 0) @@ -338,15 +373,15 @@ int bus_match_run( break; case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: - test_str = bus_message_get_arg(m, node->type - BUS_MATCH_ARG); + (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG, &test_str, &test_strv); break; case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: - test_str = bus_message_get_arg(m, node->type - BUS_MATCH_ARG_PATH); + (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_PATH, &test_str, &test_strv); break; case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: - test_str = bus_message_get_arg(m, node->type - BUS_MATCH_ARG_NAMESPACE); + (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_NAMESPACE, &test_str, &test_strv); break; default: @@ -360,7 +395,20 @@ int bus_match_run( if (test_str) found = hashmap_get(node->compare.children, test_str); - else if (node->type == BUS_MATCH_MESSAGE_TYPE) + else if (test_strv) { + char **i; + + STRV_FOREACH(i, test_strv) { + found = hashmap_get(node->compare.children, *i); + if (found) { + r = bus_match_run(bus, found, m); + if (r != 0) + return r; + } + } + + found = NULL; + } else if (node->type == BUS_MATCH_MESSAGE_TYPE) found = hashmap_get(node->compare.children, UINT_TO_PTR(test_u8)); else found = NULL; @@ -376,7 +424,7 @@ int bus_match_run( /* No hash table, so let's iterate manually... */ for (c = node->child; c; c = c->next) { - if (!value_node_test(c, node->type, test_u8, test_str, m)) + if (!value_node_test(c, node->type, test_u8, test_str, test_strv, m)) continue; r = bus_match_run(bus, c, m); @@ -445,13 +493,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; @@ -532,7 +580,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) ; } @@ -743,6 +791,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;