bus: unify code to find parents of an object path with
authorLennart Poettering <lennart@poettering.net>
Fri, 11 Oct 2013 21:20:54 +0000 (23:20 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 11 Oct 2013 21:20:54 +0000 (23:20 +0200)
src/libsystemd-bus/bus-internal.h
src/libsystemd-bus/bus-objects.c
src/libsystemd-bus/test-bus-signature.c

index 5795f74..6499d6b 100644 (file)
@@ -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), '/'))
index c306c54..dbbb194 100644 (file)
@@ -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;
index c430469..3fc565c 100644 (file)
@@ -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;
 }