X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-bus%2Fsd-bus.c;h=ca7c428a31628d043d94a83e3705d8db6689a919;hp=4fdc246b7e1a1948638cd51cd0654f7bf94f526d;hb=82923adfe5c4fa09cc91fd2a2e374c936cd4a186;hpb=f389bf15d0b732027669690ed9606a96c0568bbd diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 4fdc246b7..ca7c428a3 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -36,6 +36,7 @@ #include "missing.h" #include "def.h" #include "cgroup-util.h" +#include "bus-label.h" #include "sd-bus.h" #include "bus-internal.h" @@ -50,6 +51,7 @@ #include "bus-util.h" #include "bus-container.h" #include "bus-protocol.h" +#include "bus-track.h" static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec); static int attach_io_events(sd_bus *b); @@ -130,8 +132,13 @@ static void bus_free(sd_bus *b) { assert(b); + assert(!b->track_queue); + sd_bus_detach_event(b); + if (b->default_bus_ptr) + *b->default_bus_ptr = NULL; + bus_close_fds(b); if (b->kdbus_buffer) @@ -396,11 +403,11 @@ static int bus_send_hello(sd_bus *bus) { r = sd_bus_message_new_method_call( bus, + &m, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", - "Hello", - &m); + "Hello"); if (r < 0) return r; @@ -791,7 +798,7 @@ static int parse_container_unix_address(sd_bus *b, const char **p, char **guid) b->sockaddr.un.sun_family = AF_UNIX; strncpy(b->sockaddr.un.sun_path, "/var/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path)); - b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + sizeof("/var/run/dbus/system_bus_socket") - 1; + b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + strlen("/var/run/dbus/system_bus_socket"); return 0; } @@ -1182,7 +1189,8 @@ _public_ int sd_bus_open_user(sd_bus **ret) { #ifdef ENABLE_KDBUS asprintf(&b->address, KERNEL_USER_BUS_FMT, (unsigned long) getuid()); #else - return -ECONNREFUSED; + r = -ECONNREFUSED; + goto fail; #endif } @@ -1211,7 +1219,7 @@ fail: return r; } -_public_ int sd_bus_open_system_remote(const char *host, sd_bus **ret) { +_public_ int sd_bus_open_system_remote(sd_bus **ret, const char *host) { _cleanup_free_ char *e = NULL; char *p = NULL; sd_bus *bus; @@ -1247,7 +1255,7 @@ _public_ int sd_bus_open_system_remote(const char *host, sd_bus **ret) { return 0; } -_public_ int sd_bus_open_system_container(const char *machine, sd_bus **ret) { +_public_ int sd_bus_open_system_container(sd_bus **ret, const char *machine) { _cleanup_free_ char *e = NULL; sd_bus *bus; char *p; @@ -1362,7 +1370,8 @@ _public_ sd_bus *sd_bus_unref(sd_bus *bus) { * the messages and thus implicitly also kill our own * last references */ - bus_reset_queues(bus); + if (q) + bus_reset_queues(bus); } i = REFCNT_DEC(bus->n_ref); @@ -1995,6 +2004,11 @@ _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) { assert_return(BUS_IS_OPEN(bus->state) || bus->state == BUS_CLOSING, -ENOTCONN); assert_return(!bus_pid_changed(bus), -ECHILD); + if (bus->track_queue) { + *timeout_usec = 0; + return 1; + } + if (bus->state == BUS_CLOSING) { *timeout_usec = 0; return 1; @@ -2277,6 +2291,16 @@ finish: return r; } +static int dispatch_track(sd_bus *bus) { + assert(bus); + + if (!bus->track_queue) + return 0; + + bus_track_dispatch(bus->track_queue); + return 1; +} + static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **ret) { _cleanup_bus_message_unref_ sd_bus_message *m = NULL; int r; @@ -2292,6 +2316,10 @@ static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd if (r != 0) goto null_message; + r = dispatch_track(bus); + if (r != 0) + goto null_message; + r = dispatch_rqueue(bus, hint_priority, priority, &m); if (r < 0) return r; @@ -2380,10 +2408,10 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) { /* Then, synthesize a Disconnected message */ r = sd_bus_message_new_signal( bus, + &m, "/org/freedesktop/DBus/Local", "org.freedesktop.DBus.Local", - "Disconnected", - &m); + "Disconnected"); if (r < 0) return r; @@ -2817,7 +2845,7 @@ static int attach_io_events(sd_bus *bus) { return 0; if (!bus->input_io_event_source) { - r = sd_event_add_io(bus->event, bus->input_fd, 0, io_callback, bus, &bus->input_io_event_source); + r = sd_event_add_io(bus->event, &bus->input_io_event_source, bus->input_fd, 0, io_callback, bus); if (r < 0) return r; @@ -2836,7 +2864,7 @@ static int attach_io_events(sd_bus *bus) { assert(bus->output_fd >= 0); if (!bus->output_io_event_source) { - r = sd_event_add_io(bus->event, bus->output_fd, 0, io_callback, bus, &bus->output_io_event_source); + r = sd_event_add_io(bus->event, &bus->output_io_event_source, bus->output_fd, 0, io_callback, bus); if (r < 0) return r; @@ -2885,7 +2913,7 @@ _public_ int sd_bus_attach_event(sd_bus *bus, sd_event *event, int priority) { bus->event_priority = priority; - r = sd_event_add_monotonic(bus->event, 0, 0, time_callback, bus, &bus->time_event_source); + r = sd_event_add_monotonic(bus->event, &bus->time_event_source, 0, 0, time_callback, bus); if (r < 0) goto fail; @@ -2893,7 +2921,7 @@ _public_ int sd_bus_attach_event(sd_bus *bus, sd_event *event, int priority) { if (r < 0) goto fail; - r = sd_event_add_exit(bus->event, quit_callback, bus, &bus->quit_event_source); + r = sd_event_add_exit(bus->event, &bus->quit_event_source, quit_callback, bus); if (r < 0) goto fail; @@ -3036,76 +3064,46 @@ _public_ int sd_bus_get_tid(sd_bus *b, pid_t *tid) { return -ENXIO; } -_public_ char *sd_bus_label_escape(const char *s) { - char *r, *t; - const char *f; - - assert_return(s, NULL); - - /* Escapes all chars that D-Bus' object path cannot deal - * with. Can be reversed with bus_path_unescape(). We special - * case the empty string. */ - - if (*s == 0) - return strdup("_"); - - r = new(char, strlen(s)*3 + 1); - if (!r) - return NULL; - - for (f = s, t = r; *f; f++) { +_public_ int sd_bus_path_encode(const char *prefix, const char *external_id, char **ret_path) { + _cleanup_free_ char *e = NULL; + char *ret; - /* Escape everything that is not a-zA-Z0-9. We also - * escape 0-9 if it's the first character */ + assert_return(object_path_is_valid(prefix), -EINVAL); + assert_return(external_id, -EINVAL); + assert_return(ret_path, -EINVAL); - if (!(*f >= 'A' && *f <= 'Z') && - !(*f >= 'a' && *f <= 'z') && - !(f > s && *f >= '0' && *f <= '9')) { - *(t++) = '_'; - *(t++) = hexchar(*f >> 4); - *(t++) = hexchar(*f); - } else - *(t++) = *f; - } + e = bus_label_escape(external_id); + if (!e) + return -ENOMEM; - *t = 0; + ret = strjoin(prefix, "/", e, NULL); + if (!ret) + return -ENOMEM; - return r; + *ret_path = ret; + return 0; } -_public_ char *sd_bus_label_unescape(const char *f) { - char *r, *t; - - assert_return(f, NULL); - - /* Special case for the empty string */ - if (streq(f, "_")) - return strdup(""); - - r = new(char, strlen(f) + 1); - if (!r) - return NULL; - - for (t = r; *f; f++) { +_public_ int sd_bus_path_decode(const char *path, const char *prefix, char **external_id) { + const char *e; + char *ret; - if (*f == '_') { - int a, b; + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(object_path_is_valid(prefix), -EINVAL); + assert_return(external_id, -EINVAL); - if ((a = unhexchar(f[1])) < 0 || - (b = unhexchar(f[2])) < 0) { - /* Invalid escape code, let's take it literal then */ - *(t++) = '_'; - } else { - *(t++) = (char) ((a << 4) | b); - f += 2; - } - } else - *(t++) = *f; + e = object_path_startswith(path, prefix); + if (!e) { + *external_id = NULL; + return 0; } - *t = 0; + ret = bus_label_unescape(e); + if (!ret) + return -ENOMEM; - return r; + *external_id = ret; + return 1; } _public_ int sd_bus_get_peer_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {