summaryrefslogtreecommitdiff
path: root/src/libsystemd-bus/bus-control.c
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2013-11-15 16:04:32 +0100
committerDaniel Mack <zonque@gmail.com>2013-11-29 14:06:49 +0100
commitb147398450c5719022a7b68721bebb9f2df48f29 (patch)
tree2bf4bc4642be6a346ecf7a63f282c4bedb6578d2 /src/libsystemd-bus/bus-control.c
parent9eb34e82257599399c3defa443d9b3d6aed8c57f (diff)
libsystemd-bus: add kdbus support for sd_bus_list_names()
kdbus will tell us the minimum buffer size it needs in case the default 8kb buffer doesn't suffice.
Diffstat (limited to 'src/libsystemd-bus/bus-control.c')
-rw-r--r--src/libsystemd-bus/bus-control.c103
1 files changed, 71 insertions, 32 deletions
diff --git a/src/libsystemd-bus/bus-control.c b/src/libsystemd-bus/bus-control.c
index 7cb7d44ae9..f988cc7c59 100644
--- a/src/libsystemd-bus/bus-control.c
+++ b/src/libsystemd-bus/bus-control.c
@@ -180,43 +180,82 @@ _public_ int sd_bus_list_names(sd_bus *bus, char ***l) {
if (bus_pid_changed(bus))
return -ECHILD;
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.DBus",
- "/",
- "org.freedesktop.DBus",
- "ListNames",
- NULL,
- &reply1,
- NULL);
- if (r < 0)
- return r;
+ if (bus->is_kernel) {
+ _cleanup_free_ struct kdbus_cmd_names *names = NULL;
+ struct kdbus_cmd_name *name;
+ size_t size;
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.DBus",
- "/",
- "org.freedesktop.DBus",
- "ListActivatableNames",
- NULL,
- &reply2,
- NULL);
- if (r < 0)
- return r;
+ /* assume 8k size first. If that doesn't suffice, kdbus will tell us
+ * how big the buffer needs to be. */
+ size = 8192;
- r = bus_message_read_strv_extend(reply1, &x);
- if (r < 0) {
- strv_free(x);
- return r;
- }
+ for(;;) {
+ names = realloc(names, size);
+ if (!names)
+ return -ENOMEM;
- r = bus_message_read_strv_extend(reply2, &x);
- if (r < 0) {
- strv_free(x);
- return r;
+ names->size = size;
+
+ r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, names);
+ if (r < 0) {
+ if (errno == ENOBUFS && size != names->size) {
+ size = names->size;
+ continue;
+ }
+
+ return -errno;
+ }
+
+ break;
+ }
+
+ KDBUS_PART_FOREACH(name, names, names) {
+ r = strv_extend(&x, name->name);
+ if (r < 0)
+ return -ENOMEM;
+ }
+
+ *l = x;
+ } else {
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.DBus",
+ "/",
+ "org.freedesktop.DBus",
+ "ListNames",
+ NULL,
+ &reply1,
+ NULL);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.DBus",
+ "/",
+ "org.freedesktop.DBus",
+ "ListActivatableNames",
+ NULL,
+ &reply2,
+ NULL);
+ if (r < 0)
+ return r;
+
+ r = bus_message_read_strv_extend(reply1, &x);
+ if (r < 0) {
+ strv_free(x);
+ return r;
+ }
+
+ r = bus_message_read_strv_extend(reply2, &x);
+ if (r < 0) {
+ strv_free(x);
+ return r;
+ }
+
+ *l = strv_uniq(x);
}
- *l = strv_uniq(x);
return 0;
}