From: Lennart Poettering Date: Fri, 11 Oct 2013 21:20:54 +0000 (+0200) Subject: bus: unify code to find parents of an object path with X-Git-Tag: v209~1916 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=92e189e57297b110a1a12703aa17557e3600cf4f;p=elogind.git bus: unify code to find parents of an object path with --- diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h index 5795f7469..6499d6b01 100644 --- a/src/libsystemd-bus/bus-internal.h +++ b/src/libsystemd-bus/bus-internal.h @@ -289,3 +289,8 @@ int bus_start_running(sd_bus *bus); int bus_next_address(sd_bus *bus); bool bus_pid_changed(sd_bus *bus); + +#define OBJECT_PATH_FOREACH_PREFIX(prefix, path) \ + for (char *_slash = ({ strcpy((prefix), (path)); streq((prefix), "/") ? NULL : strrchr((prefix), '/'); }) ; \ + _slash && !(_slash[(_slash) == (prefix)] = 0); \ + _slash = streq((prefix), "/") ? NULL : strrchr((prefix), '/')) diff --git a/src/libsystemd-bus/bus-objects.c b/src/libsystemd-bus/bus-objects.c index c306c54df..dbbb19444 100644 --- a/src/libsystemd-bus/bus-objects.c +++ b/src/libsystemd-bus/bus-objects.c @@ -847,7 +847,7 @@ static int object_manager_serialize_path_and_fallbacks( const char *path, sd_bus_error *error) { - size_t pl; + char *prefix; int r; assert(bus); @@ -863,27 +863,14 @@ static int object_manager_serialize_path_and_fallbacks( return 0; /* Second, add fallback vtables registered for any of the prefixes */ - pl = strlen(path); - if (pl > 1) { - char p[pl + 1]; - strcpy(p, path); - - for (;;) { - char *e; - - e = strrchr(p, '/'); - if (e == p || !e) - break; - - *e = 0; - - r = object_manager_serialize_path(bus, reply, p, path, true, error); - if (r < 0) - return r; + prefix = alloca(strlen(path) + 1); + OBJECT_PATH_FOREACH_PREFIX(prefix, path) { + r = object_manager_serialize_path(bus, reply, prefix, path, true, error); + if (r < 0) + return r; - if (sd_bus_error_is_set(error)) - return 0; - } + if (sd_bus_error_is_set(error)) + return 0; } return 0; @@ -1105,7 +1092,7 @@ int bus_process_object(sd_bus *bus, sd_bus_message *m) { pl = strlen(m->path); do { - char p[pl+1]; + char prefix[pl+1]; bus->nodes_modified = false; @@ -1114,24 +1101,12 @@ int bus_process_object(sd_bus *bus, sd_bus_message *m) { return r; /* Look for fallback prefixes */ - strcpy(p, m->path); - for (;;) { - char *e; - - if (streq(p, "/")) - break; + OBJECT_PATH_FOREACH_PREFIX(prefix, m->path) { if (bus->nodes_modified) break; - e = strrchr(p, '/'); - assert(e); - if (e == p) - *(e+1) = 0; - else - *e = 0; - - r = object_find_and_run(bus, m, p, true, &found_object); + r = object_find_and_run(bus, m, prefix, true, &found_object); if (r != 0) return r; } @@ -1858,7 +1833,7 @@ int sd_bus_emit_properties_changed_strv( const char *interface, char **names) { - size_t pl; + char *prefix; int r; assert_return(bus, -EINVAL); @@ -1874,28 +1849,11 @@ int sd_bus_emit_properties_changed_strv( if (r != 0) return r; - pl = strlen(path); - if (pl > 1 ) { - char p[pl+1]; - - strcpy(p, path); - for (;;) { - char *e; - - if (streq(p, "/")) - break; - - e = strrchr(p, '/'); - assert(e); - if (e == p) - *(e+1) = 0; - else - *e = 0; - - r = emit_properties_changed_on_interface(bus, p, path, interface, true, names); - if (r != 0) - return r; - } + prefix = alloca(strlen(path) + 1); + OBJECT_PATH_FOREACH_PREFIX(prefix, path) { + r = emit_properties_changed_on_interface(bus, prefix, path, interface, true, names); + if (r != 0) + return r; } return -ENOENT; diff --git a/src/libsystemd-bus/test-bus-signature.c b/src/libsystemd-bus/test-bus-signature.c index c4304697f..3fc565c62 100644 --- a/src/libsystemd-bus/test-bus-signature.c +++ b/src/libsystemd-bus/test-bus-signature.c @@ -27,6 +27,8 @@ #include "bus-internal.h" int main(int argc, char *argv[]) { + char prefix[256]; + int r; assert_se(signature_is_single("y", false)); assert_se(signature_is_single("u", false)); @@ -133,5 +135,29 @@ int main(int argc, char *argv[]) { assert_se(!object_path_is_valid("/foo//bar")); assert_se(!object_path_is_valid("/foo/aaaäöä")); + OBJECT_PATH_FOREACH_PREFIX(prefix, "/") { + log_info("<%s>", prefix); + assert_not_reached("???"); + } + + r = 0; + OBJECT_PATH_FOREACH_PREFIX(prefix, "/xxx") { + log_info("<%s>", prefix); + assert_se(streq(prefix, "/")); + assert_se(r == 0); + r++; + } + assert_se(r == 1); + + r = 0; + OBJECT_PATH_FOREACH_PREFIX(prefix, "/xxx/yyy/zzz") { + log_info("<%s>", prefix); + assert_se(r != 0 || streq(prefix, "/xxx/yyy")); + assert_se(r != 1 || streq(prefix, "/xxx")); + assert_se(r != 2 || streq(prefix, "/")); + r++; + } + assert_se(r == 3); + return 0; }