summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libsystemd-bus/bus-internal.h5
-rw-r--r--src/libsystemd-bus/bus-objects.c76
-rw-r--r--src/libsystemd-bus/test-bus-signature.c26
3 files changed, 48 insertions, 59 deletions
diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h
index 5795f74693..6499d6b013 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 c306c54df6..dbbb194444 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 c4304697f0..3fc565c620 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;
}