[systemd-commits] 7 commits - src/libsystemd-bus src/systemd
Lennart Poettering
lennart at kemper.freedesktop.org
Fri Oct 11 14:24:04 PDT 2013
src/libsystemd-bus/bus-internal.h | 5
src/libsystemd-bus/bus-introspect.c | 6
src/libsystemd-bus/bus-message.c | 33 +
src/libsystemd-bus/bus-objects.c | 535 +++++++++++++++++++++-----------
src/libsystemd-bus/test-bus-objects.c | 51 ++-
src/libsystemd-bus/test-bus-signature.c | 26 +
src/systemd/sd-bus.h | 9
7 files changed, 479 insertions(+), 186 deletions(-)
New commits:
commit 4be391639f47b71ce021d8b5cb0f97c105a80156
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Oct 11 23:22:29 2013 +0200
bus: properly implement logic for generating InterfacesAdded/InterfacesRemoved signals of ObjectManager
diff --git a/src/libsystemd-bus/bus-objects.c b/src/libsystemd-bus/bus-objects.c
index 08261fc..1d32566 100644
--- a/src/libsystemd-bus/bus-objects.c
+++ b/src/libsystemd-bus/bus-objects.c
@@ -1897,12 +1897,206 @@ int sd_bus_emit_properties_changed(
return sd_bus_emit_properties_changed_strv(bus, path, interface, names);
}
-int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interfaces, ...) {
- return -ENOSYS;
+static int interfaces_added_append_one_prefix(
+ sd_bus *bus,
+ sd_bus_message *m,
+ const char *prefix,
+ const char *path,
+ const char *interface,
+ bool require_fallback) {
+
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ struct node_vtable *c;
+ struct node *n;
+ void *u = NULL;
+ int r;
+
+ assert(bus);
+ assert(m);
+ assert(prefix);
+ assert(path);
+ assert(interface);
+
+ n = hashmap_get(bus->nodes, prefix);
+ if (!n)
+ return 0;
+
+ LIST_FOREACH(vtables, c, n->vtables) {
+ if (require_fallback && !c->is_fallback)
+ continue;
+
+ if (streq(c->interface, interface))
+ break;
+ }
+
+ if (!c)
+ return 0;
+
+ r = node_vtable_get_userdata(bus, path, c, &u);
+ if (r <= 0)
+ return r;
+
+ r = sd_bus_message_append_basic(m, 's', interface);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(m, 'a', "{sv}");
+ if (r < 0)
+ return r;
+
+ r = vtable_append_all_properties(bus, m,path, c, u, &error);
+ if (r < 0)
+ return r;
+
+ if (sd_bus_error_is_set(&error))
+ return bus_error_to_errno(&error);
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return r;
+
+ return 1;
+}
+
+static int interfaces_added_append_one(
+ sd_bus *bus,
+ sd_bus_message *m,
+ const char *path,
+ const char *interface) {
+
+ char *prefix;
+ int r;
+
+ assert(bus);
+ assert(m);
+ assert(path);
+ assert(interface);
+
+ r = interfaces_added_append_one_prefix(bus, m, path, path, interface, false);
+ if (r != 0)
+ return r;
+
+ prefix = alloca(strlen(path) + 1);
+ OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
+ r = interfaces_added_append_one_prefix(bus, m, prefix, path, interface, true);
+ if (r != 0)
+ return r;
+ }
+
+ return -ENOENT;
}
-int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interfaces, ...) {
- return -ENOSYS;
+int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) {
+ _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ char **i;
+ int r;
+
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ if (strv_isempty(interfaces))
+ return 0;
+
+ r = sd_bus_message_new_signal(bus, path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded", &m);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append_basic(m, 'o', path);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(m, 'a', "{sa{sv}}");
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(i, interfaces) {
+ assert_return(interface_name_is_valid(*i), -EINVAL);
+
+ r = sd_bus_message_open_container(m, 'e', "sa{sv}");
+ if (r < 0)
+ return r;
+
+ r = interfaces_added_append_one(bus, m, path, *i);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return r;
+
+ return sd_bus_send(bus, m, NULL);
+}
+
+int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) {
+ _cleanup_strv_free_ char **interfaces = NULL;
+ va_list ap;
+
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ va_start(ap, interface);
+ interfaces = strv_new_ap(interface, ap);
+ va_end(ap);
+
+ if (!interfaces)
+ return -ENOMEM;
+
+ return sd_bus_emit_interfaces_added_strv(bus, path, interfaces);
+}
+
+int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) {
+ _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ int r;
+
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ if (strv_isempty(interfaces))
+ return 0;
+
+ r = sd_bus_message_new_signal(bus, path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved", &m);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append_basic(m, 'o', path);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append_strv(m, interfaces);
+ if (r < 0)
+ return r;
+
+ return sd_bus_send(bus, m, NULL);
+}
+
+int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) {
+ _cleanup_strv_free_ char **interfaces = NULL;
+ va_list ap;
+
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ va_start(ap, interface);
+ interfaces = strv_new_ap(interface, ap);
+ va_end(ap);
+
+ if (!interfaces)
+ return -ENOMEM;
+
+ return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces);
}
int sd_bus_add_object_manager(sd_bus *bus, const char *path) {
diff --git a/src/libsystemd-bus/test-bus-objects.c b/src/libsystemd-bus/test-bus-objects.c
index 1c23c21..2757f69 100644
--- a/src/libsystemd-bus/test-bus-objects.c
+++ b/src/libsystemd-bus/test-bus-objects.c
@@ -39,7 +39,6 @@
* Add in:
*
* node hierarchy updates during dispatching
- * emit_interfaces_added/emit_interfaces_removed
*
*/
@@ -147,6 +146,28 @@ static int notify_test(sd_bus *bus, sd_bus_message *m, void *userdata) {
return 1;
}
+static int emit_interfaces_added(sd_bus *bus, sd_bus_message *m, void *userdata) {
+ int r;
+
+ assert_se(sd_bus_emit_interfaces_added(bus, m->path, "org.freedesktop.systemd.test", NULL) >= 0);
+
+ r = sd_bus_reply_method_return(bus, m, NULL);
+ assert_se(r >= 0);
+
+ return 1;
+}
+
+static int emit_interfaces_removed(sd_bus *bus, sd_bus_message *m, void *userdata) {
+ int r;
+
+ assert_se(sd_bus_emit_interfaces_removed(bus, m->path, "org.freedesktop.systemd.test", NULL) >= 0);
+
+ r = sd_bus_reply_method_return(bus, m, NULL);
+ assert_se(r >= 0);
+
+ return 1;
+}
+
static const sd_bus_vtable vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_METHOD("AlterSomething", "s", "s", something_handler, 0),
@@ -154,7 +175,9 @@ static const sd_bus_vtable vtable[] = {
SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0),
SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL, offsetof(struct context, automatic_string_property), 0),
SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL, offsetof(struct context, automatic_integer_property), 0),
- SD_BUS_METHOD("NoOperation", "", "", NULL, 0),
+ SD_BUS_METHOD("NoOperation", NULL, NULL, NULL, 0),
+ SD_BUS_METHOD("EmitInterfacesAdded", NULL, NULL, emit_interfaces_added, 0),
+ SD_BUS_METHOD("EmitInterfacesRemoved", NULL, NULL, emit_interfaces_removed, 0),
SD_BUS_VTABLE_END
};
@@ -385,6 +408,30 @@ static int client(struct context *c) {
sd_bus_message_unref(reply);
reply = NULL;
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesAdded", &error, NULL, "");
+ assert_se(r >= 0);
+
+ r = sd_bus_process(bus, &reply);
+ assert_se(r > 0);
+
+ assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
+ bus_message_dump(reply);
+
+ sd_bus_message_unref(reply);
+ reply = NULL;
+
+ r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesRemoved", &error, NULL, "");
+ assert_se(r >= 0);
+
+ r = sd_bus_process(bus, &reply);
+ assert_se(r > 0);
+
+ assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
+ bus_message_dump(reply);
+
+ sd_bus_message_unref(reply);
+ reply = NULL;
+
r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, "");
assert_se(r >= 0);
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index e7ce56d..9b7ba5a 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -217,10 +217,10 @@ int sd_bus_emit_signal(sd_bus *bus, const char *path, const char *interface, con
int sd_bus_emit_properties_changed_strv(sd_bus *bus, const char *path, const char *interface, char **names);
int sd_bus_emit_properties_changed(sd_bus *bus, const char *path, const char *interface, const char *name, ...) _sd_sentinel_attr_;
-int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces); /* MISSING */
-int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) _sd_sentinel_attr_; /* MISSING */
-int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces); /* MISSING */
-int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) _sd_sentinel_attr_; /* MISSING */
+int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces);
+int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) _sd_sentinel_attr_;
+int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces);
+int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) _sd_sentinel_attr_;
/* Bus management */
commit 92db139e34fcd3102054574f8f11f404a751dbb0
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Oct 11 23:21:22 2013 +0200
bus: in GetManagedObjects() only return each object once.
diff --git a/src/libsystemd-bus/bus-objects.c b/src/libsystemd-bus/bus-objects.c
index dbbb194..08261fc 100644
--- a/src/libsystemd-bus/bus-objects.c
+++ b/src/libsystemd-bus/bus-objects.c
@@ -742,9 +742,9 @@ static int object_manager_serialize_vtable(
sd_bus_message *reply,
const char *path,
struct node_vtable *c,
- sd_bus_error *error) {
+ sd_bus_error *error,
+ void *userdata) {
- void *u;
int r;
assert(bus);
@@ -753,10 +753,6 @@ static int object_manager_serialize_vtable(
assert(c);
assert(error);
- r = node_vtable_get_userdata(bus, path, c, &u);
- if (r <= 0)
- return r;
-
r = sd_bus_message_open_container(reply, 'e', "sa{sv}");
if (r < 0)
return r;
@@ -769,7 +765,7 @@ static int object_manager_serialize_vtable(
if (r < 0)
return r;
- r = vtable_append_all_properties(bus, reply, path, c, u, error);
+ r = vtable_append_all_properties(bus, reply, path, c, userdata, error);
if (r < 0)
return r;
@@ -794,6 +790,7 @@ static int object_manager_serialize_path(
struct node_vtable *i;
struct node *n;
+ bool found_something = false;
int r;
assert(bus);
@@ -806,37 +803,50 @@ static int object_manager_serialize_path(
if (!n)
return 0;
- r = sd_bus_message_open_container(reply, 'e', "oa{sa{sv}}");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(reply, "o", path);
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(reply, 'a', "{sa{sv}}");
- if (r < 0)
- return r;
-
LIST_FOREACH(vtables, i, n->vtables) {
+ void *u;
if (require_fallback && !i->is_fallback)
continue;
- r = object_manager_serialize_vtable(bus, reply, path, i, error);
+ r = node_vtable_get_userdata(bus, path, i, &u);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ continue;
+
+ if (!found_something) {
+ r = sd_bus_message_open_container(reply, 'e', "oa{sa{sv}}");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(reply, "o", path);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(reply, 'a', "{sa{sv}}");
+ if (r < 0)
+ return r;
+
+ found_something = true;
+ }
+
+ r = object_manager_serialize_vtable(bus, reply, path, i, error, u);
if (r < 0)
return r;
if (sd_bus_error_is_set(error))
return 0;
}
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
+ if (found_something) {
+ r = sd_bus_message_close_container(reply);
+ if (r < 0)
+ return r;
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
+ r = sd_bus_message_close_container(reply);
+ if (r < 0)
+ return r;
+ }
return 1;
}
commit 92e189e57297b110a1a12703aa17557e3600cf4f
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Oct 11 23:20:54 2013 +0200
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 5795f74..6499d6b 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 c306c54..dbbb194 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 c430469..3fc565c 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;
}
commit 8e4e652b92c8c2f640f8ac1c839dd4a0fd11f3c4
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Oct 11 23:19:40 2013 +0200
bus: properly generate GetAll reply
diff --git a/src/libsystemd-bus/bus-objects.c b/src/libsystemd-bus/bus-objects.c
index 8302092..c306c54 100644
--- a/src/libsystemd-bus/bus-objects.c
+++ b/src/libsystemd-bus/bus-objects.c
@@ -499,7 +499,7 @@ static int vtable_append_all_properties(
if (r < 0)
return r;
- r = sd_bus_message_append(reply, "s", c->interface);
+ r = sd_bus_message_append(reply, "s", v->x.property.member);
if (r < 0)
return r;
commit 55736ed0c7ead8c93f2156f751399326a4656055
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Oct 11 23:02:47 2013 +0200
bus: add sd_bus_message_append_strv() to easily add a NULL terminated string array to a message
diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c
index 264a2f6..18c2d1c 100644
--- a/src/libsystemd-bus/bus-message.c
+++ b/src/libsystemd-bus/bus-message.c
@@ -2304,14 +2304,10 @@ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
void *a;
int r;
- if (!m)
- return -EINVAL;
- if (!memfd)
- return -EINVAL;
- if (m->sealed)
- return -EPERM;
- if (m->poisoned)
- return -ESTALE;
+ assert_return(m, -EINVAL);
+ assert_return(memfd, -EINVAL);
+ assert_return(!m->sealed, -EPERM);
+ assert_return(!m->poisoned, -ESTALE);
r = sd_memfd_set_sealed(memfd, true);
if (r < 0)
@@ -2376,6 +2372,27 @@ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
return 0;
}
+int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
+ char **i;
+ int r;
+
+ assert_return(m, -EINVAL);
+ assert_return(!m->sealed, -EPERM);
+ assert_return(!m->poisoned, -ESTALE);
+
+ r = sd_bus_message_open_container(m, 'a', "s");
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(i, l) {
+ r = sd_bus_message_append_basic(m, 's', *i);
+ if (r < 0)
+ return r;
+ }
+
+ return sd_bus_message_close_container(m);
+}
+
int bus_body_part_map(struct bus_body_part *part) {
void *p;
size_t psz;
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index bbeec13..e7ce56d 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -191,6 +191,7 @@ int sd_bus_message_append_array_space(sd_bus_message *m, char type, size_t size,
int sd_bus_message_append_array_memfd(sd_bus_message *m, char type, sd_memfd *memfd);
int sd_bus_message_append_string_space(sd_bus_message *m, size_t size, char **s);
int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd* memfd);
+int sd_bus_message_append_strv(sd_bus_message *m, char **l);
int sd_bus_message_open_container(sd_bus_message *m, char type, const char *contents);
int sd_bus_message_close_container(sd_bus_message *m);
commit f11ca85a897c770c10bf5aef79b31e955bcb3c13
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Oct 11 23:01:35 2013 +0200
bus: make sure introspection can be generated correctly with NULL method signatures
diff --git a/src/libsystemd-bus/bus-introspect.c b/src/libsystemd-bus/bus-introspect.c
index c04d9b5..3178878 100644
--- a/src/libsystemd-bus/bus-introspect.c
+++ b/src/libsystemd-bus/bus-introspect.c
@@ -129,8 +129,8 @@ int introspect_write_interface(struct introspect *i, const char *interface, cons
case _SD_BUS_VTABLE_METHOD:
fprintf(i->f, " <method name=\"%s\">\n", v->x.method.member);
- introspect_write_arguments(i, v->x.method.signature, "in");
- introspect_write_arguments(i, v->x.method.result, "out");
+ introspect_write_arguments(i, strempty(v->x.method.signature), "in");
+ introspect_write_arguments(i, strempty(v->x.method.result), "out");
introspect_write_flags(i, v->type, v->flags);
fputs(" </method>\n", i->f);
break;
@@ -147,7 +147,7 @@ int introspect_write_interface(struct introspect *i, const char *interface, cons
case _SD_BUS_VTABLE_SIGNAL:
fprintf(i->f, " <signal name=\"%s\">\n", v->x.signal.member);
- introspect_write_arguments(i, v->x.signal.signature, NULL);
+ introspect_write_arguments(i, strempty(v->x.signal.signature), NULL);
introspect_write_flags(i, v->type, v->flags);
fputs(" </signal>\n", i->f);
break;
commit dfa927250e4d72f2aaf0cecfb0691eebb18dadaa
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Oct 11 21:27:59 2013 +0200
bus: beef up parameter checking in vtable handling
diff --git a/src/libsystemd-bus/bus-objects.c b/src/libsystemd-bus/bus-objects.c
index 8d95376..8302092 100644
--- a/src/libsystemd-bus/bus-objects.c
+++ b/src/libsystemd-bus/bus-objects.c
@@ -82,7 +82,12 @@ static int vtable_property_get_userdata(
return 1;
}
-static int add_enumerated_to_set(sd_bus *bus, const char *prefix, struct node_enumerator *first, Set *s) {
+static int add_enumerated_to_set(
+ sd_bus *bus,
+ const char *prefix,
+ struct node_enumerator *first,
+ Set *s) {
+
struct node_enumerator *c;
int r;
@@ -120,7 +125,12 @@ static int add_enumerated_to_set(sd_bus *bus, const char *prefix, struct node_en
return 0;
}
-static int add_subtree_to_set(sd_bus *bus, const char *prefix, struct node *n, Set *s) {
+static int add_subtree_to_set(
+ sd_bus *bus,
+ const char *prefix,
+ struct node *n,
+ Set *s) {
+
struct node *i;
int r;
@@ -152,11 +162,17 @@ static int add_subtree_to_set(sd_bus *bus, const char *prefix, struct node *n, S
return 0;
}
-static int get_child_nodes(sd_bus *bus, const char *prefix, struct node *n, Set **_s) {
+static int get_child_nodes(
+ sd_bus *bus,
+ const char *prefix,
+ struct node *n,
+ Set **_s) {
+
Set *s = NULL;
int r;
assert(bus);
+ assert(prefix);
assert(n);
assert(_s);
@@ -279,6 +295,10 @@ static int invoke_property_get(
assert(bus);
assert(v);
+ assert(path);
+ assert(interface);
+ assert(property);
+ assert(m);
if (v->x.property.get)
return v->x.property.get(bus, path, interface, property, m, error, userdata);
@@ -322,6 +342,10 @@ static int invoke_property_set(
assert(bus);
assert(v);
+ assert(path);
+ assert(interface);
+ assert(property);
+ assert(value);
if (v->x.property.set)
return v->x.property.set(bus, path, interface, property, value, error, userdata);
@@ -379,6 +403,7 @@ static int property_get_set_callbacks_run(
assert(bus);
assert(m);
+ assert(c);
assert(found_object);
if (require_fallback && !c->parent->is_fallback)
@@ -463,6 +488,7 @@ static int vtable_append_all_properties(
assert(bus);
assert(reply);
+ assert(path);
assert(c);
for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
@@ -583,6 +609,7 @@ static int property_get_all_callbacks_run(
static bool bus_node_with_object_manager(sd_bus *bus, struct node *n) {
assert(bus);
+ assert(n);
if (n->object_manager)
return true;
@@ -593,12 +620,18 @@ static bool bus_node_with_object_manager(sd_bus *bus, struct node *n) {
return false;
}
-static bool bus_node_exists(sd_bus *bus, struct node *n, const char *path, bool require_fallback) {
+static bool bus_node_exists(
+ sd_bus *bus,
+ struct node *n,
+ const char *path,
+ bool require_fallback) {
+
struct node_vtable *c;
struct node_callback *k;
assert(bus);
assert(n);
+ assert(path);
/* Tests if there's anything attached directly to this node
* for the specified path */
@@ -1207,7 +1240,7 @@ static void bus_node_gc(sd_bus *b, struct node *n) {
}
static int bus_add_object(
- sd_bus *b,
+ sd_bus *bus,
bool fallback,
const char *path,
sd_bus_message_handler_t callback,
@@ -1217,16 +1250,12 @@ static int bus_add_object(
struct node *n;
int r;
- if (!b)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (!callback)
- return -EINVAL;
- if (bus_pid_changed(b))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(callback, -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
- n = bus_node_allocate(b, path);
+ n = bus_node_allocate(bus, path);
if (!n)
return -ENOMEM;
@@ -1246,7 +1275,7 @@ static int bus_add_object(
fail:
free(c);
- bus_node_gc(b, n);
+ bus_node_gc(bus, n);
return r;
}
@@ -1260,14 +1289,10 @@ static int bus_remove_object(
struct node_callback *c;
struct node *n;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (!callback)
- return -EINVAL;
- if (bus_pid_changed(bus))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(callback, -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
n = hashmap_get(bus->nodes, path);
if (!n)
@@ -1350,6 +1375,8 @@ static void free_node_vtable(sd_bus *bus, struct node_vtable *w) {
static unsigned vtable_member_hash_func(const void *a) {
const struct vtable_member *m = a;
+ assert(m);
+
return
string_hash_func(m->path) ^
string_hash_func(m->interface) ^
@@ -1360,6 +1387,9 @@ static int vtable_member_compare_func(const void *a, const void *b) {
const struct vtable_member *x = a, *y = b;
int r;
+ assert(x);
+ assert(y);
+
r = strcmp(x->path, y->path);
if (r != 0)
return r;
@@ -1385,16 +1415,13 @@ static int add_object_vtable_internal(
struct node *n;
int r;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (!interface_name_is_valid(interface))
- return -EINVAL;
- if (!vtable || vtable[0].type != _SD_BUS_VTABLE_START || vtable[0].x.start.element_size != sizeof(struct sd_bus_vtable))
- return -EINVAL;
- if (bus_pid_changed(bus))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(interface_name_is_valid(interface), -EINVAL);
+ assert_return(vtable, -EINVAL);
+ assert_return(vtable[0].type == _SD_BUS_VTABLE_START, -EINVAL);
+ assert_return(vtable[0].x.start.element_size == sizeof(struct sd_bus_vtable), -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
r = hashmap_ensure_allocated(&bus->vtable_methods, vtable_member_hash_func, vtable_member_compare_func);
if (r < 0)
@@ -1554,14 +1581,10 @@ static int remove_object_vtable_internal(
struct node_vtable *c;
struct node *n;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (!interface_name_is_valid(interface))
- return -EINVAL;
- if (bus_pid_changed(bus))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(interface_name_is_valid(interface), -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
n = hashmap_get(bus->nodes, path);
if (!n)
@@ -1577,6 +1600,8 @@ static int remove_object_vtable_internal(
LIST_REMOVE(struct node_vtable, vtables, n->vtables, c);
free_node_vtable(bus, c);
+ bus_node_gc(bus, n);
+
return 1;
}
@@ -1627,14 +1652,10 @@ int sd_bus_add_node_enumerator(
struct node *n;
int r;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (!callback)
- return -EINVAL;
- if (bus_pid_changed(bus))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(callback, -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
n = bus_node_allocate(bus, path);
if (!n)
@@ -1668,14 +1689,10 @@ int sd_bus_remove_node_enumerator(
struct node_enumerator *c;
struct node *n;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (!callback)
- return -EINVAL;
- if (bus_pid_changed(bus))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(callback, -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
n = hashmap_get(bus->nodes, path);
if (!n)
@@ -1714,6 +1731,7 @@ static int emit_properties_changed_on_interface(
int r;
assert(bus);
+ assert(prefix);
assert(path);
assert(interface);
@@ -1755,15 +1773,16 @@ static int emit_properties_changed_on_interface(
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
struct vtable_member *v;
+ assert_return(member_name_is_valid(*property), -EINVAL);
+
key.member = *property;
v = hashmap_get(bus->vtable_properties, &key);
if (!v)
return -ENOENT;
assert(c == v->parent);
+ assert_return(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE, -EDOM);
- if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))
- return -EDOM;
if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY) {
has_invalidating = true;
continue;
@@ -1833,16 +1852,23 @@ static int emit_properties_changed_on_interface(
return 1;
}
-int sd_bus_emit_properties_changed_strv(sd_bus *bus, const char *path, const char *interface, char **names) {
+int sd_bus_emit_properties_changed_strv(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ char **names) {
+
size_t pl;
int r;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (!interface_name_is_valid(interface))
- return -EINVAL;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(interface_name_is_valid(interface), -EINVAL);
+ assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ if (strv_isempty(names))
+ return 0;
r = emit_properties_changed_on_interface(bus, path, path, interface, false, names);
if (r != 0)
@@ -1875,10 +1901,24 @@ int sd_bus_emit_properties_changed_strv(sd_bus *bus, const char *path, const cha
return -ENOENT;
}
-int sd_bus_emit_properties_changed(sd_bus *bus, const char *path, const char *interface, const char *name, ...) {
+int sd_bus_emit_properties_changed(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *name, ...) {
+
_cleanup_strv_free_ char **names = NULL;
va_list ap;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(interface_name_is_valid(interface), -EINVAL);
+ assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ if (!name)
+ return 0;
+
va_start(ap, name);
names = strv_new_ap(name, ap);
va_end(ap);
@@ -1900,12 +1940,9 @@ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *in
int sd_bus_add_object_manager(sd_bus *bus, const char *path) {
struct node *n;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (bus_pid_changed(bus))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
n = bus_node_allocate(bus, path);
if (!n)
@@ -1918,12 +1955,9 @@ int sd_bus_add_object_manager(sd_bus *bus, const char *path) {
int sd_bus_remove_object_manager(sd_bus *bus, const char *path) {
struct node *n;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (bus_pid_changed(bus))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
n = hashmap_get(bus->nodes, path);
if (!n)
@@ -1934,5 +1968,6 @@ int sd_bus_remove_object_manager(sd_bus *bus, const char *path) {
n->object_manager = false;
bus_node_gc(bus, n);
+
return 1;
}
More information about the systemd-commits
mailing list