From b147398450c5719022a7b68721bebb9f2df48f29 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 15 Nov 2013 16:04:32 +0100 Subject: [PATCH] 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. --- src/libsystemd-bus/bus-control.c | 103 +++++++++++++++++++++---------- 1 file changed, 71 insertions(+), 32 deletions(-) diff --git a/src/libsystemd-bus/bus-control.c b/src/libsystemd-bus/bus-control.c index 7cb7d44ae..f988cc7c5 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; } -- 2.30.2