[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