[systemd-commits] 6 commits - src/libsystemd-bus src/stdio-bridge

Daniel Mack zonque at kemper.freedesktop.org
Fri Nov 29 05:09:51 PST 2013


 src/libsystemd-bus/bus-control.c |  127 ++++++++++++++++++++++++++++-----------
 src/libsystemd-bus/bus-kernel.c  |   30 +++++++--
 src/libsystemd-bus/bus-kernel.h  |   16 ++--
 src/stdio-bridge/stdio-bridge.c  |  102 +++++++++++++++++++++++++++----
 4 files changed, 215 insertions(+), 60 deletions(-)

New commits:
commit 71008e18a0bf9e9b96348fe2fb751aea23397186
Author: Daniel Mack <zonque at gmail.com>
Date:   Fri Nov 15 18:05:27 2013 +0100

    systemd-stdio-bridge: make it socket-activatable and usable as kdbus bridge
    
    Augment systemd-stdio-bridge a bit to make it a 1:1 bridge from legacy
    DBus clients to kdbus. In particular,
    
     * allow setting the bus path of the upstream bus as command line
       argument
     * use sd_listen_fds() for systemd's socket activation
     * omit calling sd_bus_negotiate_fds() when upstream bus is kdbus
     * reply to bus send errors with proper dbus error messages
     * treat -ECONNRESET as expected end-of-connection condition

diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c
index 07218e9..9c49e0e 100644
--- a/src/stdio-bridge/stdio-bridge.c
+++ b/src/stdio-bridge/stdio-bridge.c
@@ -28,6 +28,7 @@
 #include <errno.h>
 #include <sys/poll.h>
 #include <stddef.h>
+#include <getopt.h>
 
 #include "log.h"
 #include "util.h"
@@ -37,25 +38,99 @@
 #include "bus-internal.h"
 #include "bus-message.h"
 #include "bus-util.h"
+#include "build.h"
+
+#define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket"
+
+const char *arg_bus_path = DEFAULT_BUS_PATH;
+
+static int help(void) {
+
+        printf("%s [OPTIONS...]\n\n"
+               "STDIO or socket-activatable proxy to a given DBus endpoint.\n\n"
+               "  -h --help              Show this help\n"
+               "     --version           Show package version\n"
+               "     --bus-path=PATH     Path to the kernel bus (default: %s)\n",
+               program_invocation_short_name, DEFAULT_BUS_PATH);
+
+        return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+
+        enum {
+                ARG_VERSION = 0x100,
+        };
+
+        static const struct option options[] = {
+                { "help",            no_argument,       NULL, 'h'     },
+                { "bus-path",        required_argument, NULL, 'p'     },
+                { NULL,              0,                 NULL, 0       }
+        };
+
+        int c;
+
+        assert(argc >= 0);
+        assert(argv);
+
+        while ((c = getopt_long(argc, argv, "hsup:", options, NULL)) >= 0) {
+
+                switch (c) {
+
+                case 'h':
+                        help();
+                        return 0;
+
+                case ARG_VERSION:
+                        puts(PACKAGE_STRING);
+                        puts(SYSTEMD_FEATURES);
+                        return 0;
+
+                case '?':
+                        return -EINVAL;
+
+                case 'p':
+                        arg_bus_path = optarg;
+                        break;
+
+                default:
+                        log_error("Unknown option code %c", c);
+                        return -EINVAL;
+                }
+        }
+
+        return 1;
+}
 
 int main(int argc, char *argv[]) {
         _cleanup_bus_unref_ sd_bus *a = NULL, *b = NULL;
         sd_id128_t server_id;
         bool is_unix;
-        int r;
-
-        if (argc > 1) {
-                log_error("This program takes no argument.");
-                return EXIT_FAILURE;
-        }
+        int r, in_fd, out_fd;
 
         log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
         log_parse_environment();
         log_open();
 
+        r = parse_argv(argc, argv);
+        if (r <= 0)
+                goto finish;
+
+        r = sd_listen_fds(0);
+        if (r == 0) {
+                in_fd = STDIN_FILENO;
+                out_fd = STDOUT_FILENO;
+        } else if (r == 1) {
+                in_fd = SD_LISTEN_FDS_START;
+                out_fd = SD_LISTEN_FDS_START;
+        } else {
+                log_error("Illegal number of file descriptors passed\n");
+                goto finish;
+        }
+
         is_unix =
-                sd_is_socket(STDIN_FILENO, AF_UNIX, 0, 0) > 0 &&
-                sd_is_socket(STDOUT_FILENO, AF_UNIX, 0, 0) > 0;
+                sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
+                sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
 
         r = sd_bus_new(&a);
         if (r < 0) {
@@ -63,7 +138,7 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        r = sd_bus_set_address(a, "unix:path=/run/dbus/system_bus_socket");
+        r = sd_bus_set_address(a, arg_bus_path);
         if (r < 0) {
                 log_error("Failed to set address to connect to: %s", strerror(-r));
                 goto finish;
@@ -93,7 +168,7 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        r = sd_bus_set_fd(b, STDIN_FILENO, STDOUT_FILENO);
+        r = sd_bus_set_fd(b, in_fd, out_fd);
         if (r < 0) {
                 log_error("Failed to set fds: %s", strerror(-r));
                 goto finish;
@@ -131,7 +206,7 @@ int main(int argc, char *argv[]) {
 
                 r = sd_bus_process(a, &m);
                 if (r < 0) {
-                        log_error("Failed to process bus: %s", strerror(-r));
+                        log_error("Failed to process bus a: %s", strerror(-r));
                         goto finish;
                 }
 
@@ -148,7 +223,10 @@ int main(int argc, char *argv[]) {
 
                 r = sd_bus_process(b, &m);
                 if (r < 0) {
-                        log_error("Failed to process bus: %s", strerror(-r));
+                        /* treat 'connection reset by peer' as clean exit condition */
+                        if (r == -ECONNRESET)
+                                r = 0;
+
                         goto finish;
                 }
 

commit ed99569df8e568c1998c3b47bea33ec24b89d787
Author: Daniel Mack <zonque at gmail.com>
Date:   Tue Nov 26 17:24:18 2013 +0100

    libsystemd-bus: sd_bus_request_name: fix return value for kdbus
    
    kdbus returns -EALREADY if the requesting connection is already the
    owner of a name, and -EEXIST if the name already exists and the
    connection is not able to take it over.
    
    Also, n->flags needs a translation as well to match the SD_BUS_* enum
    values.

diff --git a/src/libsystemd-bus/bus-control.c b/src/libsystemd-bus/bus-control.c
index eeeb77b..b222175 100644
--- a/src/libsystemd-bus/bus-control.c
+++ b/src/libsystemd-bus/bus-control.c
@@ -84,10 +84,20 @@ _public_ int sd_bus_request_name(sd_bus *bus, const char *name, int flags) {
 #endif
 
                 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
-                if (r < 0)
+                if (r < 0) {
+                        if (errno == -EALREADY)
+                                return SD_BUS_NAME_ALREADY_OWNER;
+
+                        if (errno == -EEXIST)
+                                return SD_BUS_NAME_EXISTS;
+
                         return -errno;
+                }
 
-                return n->flags;
+                if (n->flags & KDBUS_NAME_IN_QUEUE)
+                        return SD_BUS_NAME_IN_QUEUE;
+
+                return SD_BUS_NAME_PRIMARY_OWNER;
         } else {
                 r = sd_bus_call_method(
                                 bus,

commit 0253ddccbb60918d177c13aa6a70c5e1fc9a7e78
Author: Daniel Mack <zonque at gmail.com>
Date:   Tue Nov 26 16:45:50 2013 +0100

    libsystemd-bus: kernel: add sd_bus_kernel_translate_request_name_flags
    
    Flags used to request a name from kdbus are not identical to what DBus
    and sd_bus use internally. Introduce a simple function to do the
    translation for us. It's factored out to a separate function so the
    dbus-driver instance can make use of it as well.

diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c
index 9d4b6cf..08f1851 100644
--- a/src/libsystemd-bus/bus-kernel.c
+++ b/src/libsystemd-bus/bus-kernel.c
@@ -806,3 +806,21 @@ void bus_kernel_flush_memfd(sd_bus *b) {
         for (i = 0; i < b->n_memfd_cache; i++)
                 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].size);
 }
+
+int sd_bus_kernel_translate_request_name_flags(uint64_t sd_bus_flags, uint64_t *kdbus_flags) {
+
+        assert_return(kdbus_flags != NULL, -EINVAL);
+
+        *kdbus_flags = 0;
+
+        if (sd_bus_flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
+                *kdbus_flags |= KDBUS_NAME_ALLOW_REPLACEMENT;
+
+        if (sd_bus_flags & SD_BUS_NAME_REPLACE_EXISTING)
+                *kdbus_flags |= KDBUS_NAME_REPLACE_EXISTING;
+
+        if (!(sd_bus_flags & SD_BUS_NAME_DO_NOT_QUEUE))
+                *kdbus_flags |= KDBUS_NAME_QUEUE;
+
+        return 0;
+}
diff --git a/src/libsystemd-bus/bus-kernel.h b/src/libsystemd-bus/bus-kernel.h
index 69df4f4..779a7de 100644
--- a/src/libsystemd-bus/bus-kernel.h
+++ b/src/libsystemd-bus/bus-kernel.h
@@ -68,3 +68,5 @@ void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size);
 void bus_kernel_flush_memfd(sd_bus *bus);
 
 int bus_kernel_parse_unique_name(const char *s, uint64_t *id);
+
+int sd_bus_kernel_translate_request_name_flags(uint64_t sd_bus_flags, uint64_t *kdbus_flags);

commit b6bd53c1ee90338ceb83bf81cc11e81560561204
Author: Daniel Mack <zonque at gmail.com>
Date:   Tue Nov 19 16:33:05 2013 +0100

    libsystemd-bus: make sd_bus_list_names return all connections, including unique names

diff --git a/src/libsystemd-bus/bus-control.c b/src/libsystemd-bus/bus-control.c
index f988cc7..eeeb77b 100644
--- a/src/libsystemd-bus/bus-control.c
+++ b/src/libsystemd-bus/bus-control.c
@@ -195,6 +195,7 @@ _public_ int sd_bus_list_names(sd_bus *bus, char ***l) {
                                 return -ENOMEM;
 
                         names->size = size;
+                        names->flags = KDBUS_NAME_LIST_UNIQUE_NAMES;
 
                         r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, names);
                         if (r < 0) {
@@ -210,7 +211,14 @@ _public_ int sd_bus_list_names(sd_bus *bus, char ***l) {
                 }
 
                 KDBUS_PART_FOREACH(name, names, names) {
-                        r = strv_extend(&x, name->name);
+                        char *n;
+
+                        if (name->size > sizeof(*name))
+                                n = name->name;
+                        else
+                                asprintf(&n, ":1.%llu", (unsigned long long) name->id);
+
+                        r = strv_extend(&x, n);
                         if (r < 0)
                                 return -ENOMEM;
                 }

commit b147398450c5719022a7b68721bebb9f2df48f29
Author: Daniel Mack <zonque at gmail.com>
Date:   Fri Nov 15 16:04:32 2013 +0100

    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.

diff --git a/src/libsystemd-bus/bus-control.c b/src/libsystemd-bus/bus-control.c
index 7cb7d44..f988cc7 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;
 }
 

commit 9eb34e82257599399c3defa443d9b3d6aed8c57f
Author: Daniel Mack <zonque at gmail.com>
Date:   Fri Nov 15 15:55:27 2013 +0100

    libsystemd-bus: bring definitions in sync with kdbus
    
    In particular, KDBUS_ITEM_NEXT is now called KDBUS_PART_NEXT, and
    KDBUS_ITEM_FOREACH was renamed to KDBUS_PART_FOREACH and takes one more
    argument to make it more flexible.

diff --git a/src/libsystemd-bus/bus-control.c b/src/libsystemd-bus/bus-control.c
index 1d416b7..7cb7d44 100644
--- a/src/libsystemd-bus/bus-control.c
+++ b/src/libsystemd-bus/bus-control.c
@@ -507,7 +507,7 @@ int bus_add_match_internal(
                         item->type = KDBUS_MATCH_BLOOM;
                         memcpy(item->data64, bloom, BLOOM_SIZE);
 
-                        item = KDBUS_ITEM_NEXT(item);
+                        item = KDBUS_PART_NEXT(item);
                 }
 
                 if (sender) {
diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c
index f2b130b..9d4b6cf 100644
--- a/src/libsystemd-bus/bus-kernel.c
+++ b/src/libsystemd-bus/bus-kernel.c
@@ -409,7 +409,7 @@ static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
         off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
         ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
 
-        KDBUS_ITEM_FOREACH(d, k) {
+        KDBUS_PART_FOREACH(d, k, items) {
 
                 if (d->type == KDBUS_MSG_FDS)
                         close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
@@ -435,7 +435,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess
         if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
                 return 0;
 
-        KDBUS_ITEM_FOREACH(d, k) {
+        KDBUS_PART_FOREACH(d, k, items) {
                 size_t l;
 
                 l = d->size - offsetof(struct kdbus_item, data);
@@ -489,7 +489,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess
         if (r < 0)
                 return r;
 
-        KDBUS_ITEM_FOREACH(d, k) {
+        KDBUS_PART_FOREACH(d, k, items) {
                 size_t l;
 
                 l = d->size - offsetof(struct kdbus_item, data);
@@ -685,13 +685,13 @@ int bus_kernel_create(const char *name, char **s) {
 
         l = strlen(name);
         make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
-                       KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t) +
-                       KDBUS_ITEM_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
+                       KDBUS_PART_HEADER_SIZE + sizeof(uint64_t) +
+                       KDBUS_PART_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
 
         n = make->items;
         n->type = KDBUS_MAKE_NAME;
         sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
-        n->size = KDBUS_ITEM_HEADER_SIZE + strlen(n->str) + 1;
+        n->size = KDBUS_PART_HEADER_SIZE + strlen(n->str) + 1;
 
         make->size = offsetof(struct kdbus_cmd_bus_make, items) + n->size;
         make->flags = KDBUS_MAKE_POLICY_OPEN;
diff --git a/src/libsystemd-bus/bus-kernel.h b/src/libsystemd-bus/bus-kernel.h
index c4573c9..69df4f4 100644
--- a/src/libsystemd-bus/bus-kernel.h
+++ b/src/libsystemd-bus/bus-kernel.h
@@ -23,16 +23,16 @@
 
 #include "sd-bus.h"
 
-#define KDBUS_ITEM_NEXT(item) \
+#define KDBUS_PART_NEXT(item) \
         (typeof(item))(((uint8_t *)item) + ALIGN8((item)->size))
 
-#define KDBUS_ITEM_FOREACH(item, head)                                          \
-        for (item = (head)->items;                                              \
-             (uint8_t *)(item) < (uint8_t *)(head) + (head)->size;              \
-             item = KDBUS_ITEM_NEXT(item))
+#define KDBUS_PART_FOREACH(part, head, first)                           \
+        for (part = (head)->first;                                      \
+             (uint8_t *)(part) < (uint8_t *)(head) + (head)->size;      \
+             part = KDBUS_PART_NEXT(part))
 
-#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
-#define KDBUS_ITEM_SIZE(s) ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
+#define KDBUS_PART_HEADER_SIZE offsetof(struct kdbus_item, data)
+#define KDBUS_ITEM_SIZE(s) ALIGN8((s) + KDBUS_PART_HEADER_SIZE)
 
 #define MEMFD_CACHE_MAX 32
 



More information about the systemd-commits mailing list