From 9db76355212de5eb7985829d352183d3bdfb56d5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Oct 2013 20:02:16 +0200 Subject: [PATCH] bus: if a a Set() vtable callback of a writable is left NULL, try to do the right thing automatically --- TODO | 2 + src/libsystemd-bus/sd-bus.c | 90 +++++++++++++++++++++++---- src/libsystemd-bus/test-bus-objects.c | 20 ++++-- src/systemd/sd-bus.h | 3 - 4 files changed, 94 insertions(+), 21 deletions(-) diff --git a/TODO b/TODO index 6847217cb..4a498b909 100644 --- a/TODO +++ b/TODO @@ -52,6 +52,8 @@ CGroup Rework Completion: Features: +* Add a new Distribute=$NUMBER key to socket units that makes use of SO_REUSEPORT to distribute network traffic on $NUMBER instances + * tmpfiles: when applying ownership to /run/log/journal also do this for the journal fails contained in it * rework list.h to use typeof() and thus simplify most linked list macros by not requring the type to be specified diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 3fd518676..cebb07319 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -2089,11 +2089,11 @@ static int method_callbacks_run( if (r < 0) return r; - if (!streq(c->vtable->method.signature, signature)) { + if (!streq(strempty(c->vtable->method.signature), signature)) { r = sd_bus_reply_method_errorf(bus, m, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid arguments '%s' to call %s:%s, expecting '%s'.", - signature, c->interface, c->member, c->vtable->method.signature); + signature, c->interface, c->member, strempty(c->vtable->method.signature)); if (r < 0) return r; @@ -2132,6 +2132,8 @@ static int invoke_property_get( /* Automatic handling if no callback is defined. */ + assert(bus_type_is_basic(v->property.signature[0])); + switch (v->property.signature[0]) { case SD_BUS_TYPE_STRING: @@ -2142,6 +2144,7 @@ static int invoke_property_get( default: p = userdata; + break; } r = sd_bus_message_append_basic(m, v->property.signature[0], p); @@ -2151,6 +2154,62 @@ static int invoke_property_get( return 1; } +static int invoke_property_set( + sd_bus *bus, + const sd_bus_vtable *v, + const char *path, + const char *interface, + const char *property, + sd_bus_message *value, + sd_bus_error *error, + void *userdata) { + + int r; + + assert(bus); + assert(v); + + if (v->property.set) + return v->property.set(bus, path, interface, property, value, error, userdata); + + /* Automatic handling if no callback is defined. */ + + assert(signature_is_single(v->property.signature, false)); + assert(bus_type_is_basic(v->property.signature[0])); + + switch (v->property.signature[0]) { + + case SD_BUS_TYPE_STRING: + case SD_BUS_TYPE_OBJECT_PATH: + case SD_BUS_TYPE_SIGNATURE: { + const char *p; + char *n; + + r = sd_bus_message_read_basic(value, v->property.signature[0], &p); + if (r < 0) + return r; + + n = strdup(p); + if (!n) + return -ENOMEM; + + free(*(char**) userdata); + *(char**) userdata = n; + + break; + } + + default: + r = sd_bus_message_read_basic(value, v->property.signature[0], userdata); + if (r < 0) + return r; + + break; + } + + return 1; +} + static int property_get_set_callbacks_run( sd_bus *bus, sd_bus_message *m, @@ -2212,12 +2271,9 @@ static int property_get_set_callbacks_run( if (r < 0) return r; - if (c->vtable->property.set) { - r = c->vtable->property.set(bus, m->path, c->interface, c->member, m, &error, u); - if (r < 0) - return r; - } else - assert_not_reached("automatic properties not supported yet"); + r = invoke_property_set(bus, c->vtable, m->path, c->interface, c->member, m, &error, u); + if (r < 0) + return r; } if (sd_bus_error_is_set(&error)) { @@ -3767,8 +3823,8 @@ static int add_object_vtable_internal( struct vtable_member *m; if (!member_name_is_valid(v->method.member) || - !signature_is_valid(v->method.signature, false) || - !signature_is_valid(v->method.result, false) || + !signature_is_valid(strempty(v->method.signature), false) || + !signature_is_valid(strempty(v->method.result), false) || !(v->method.handler || (isempty(v->method.signature) && isempty(v->method.result))) || v->flags & (SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY)) { r = -EINVAL; @@ -3796,8 +3852,16 @@ static int add_object_vtable_internal( break; } - case _SD_BUS_VTABLE_PROPERTY: - case _SD_BUS_VTABLE_WRITABLE_PROPERTY: { + case _SD_BUS_VTABLE_WRITABLE_PROPERTY: + + if (!(v->property.set || bus_type_is_basic(v->property.signature[0]))) { + r = -EINVAL; + goto fail; + } + + /* Fall through */ + + case _SD_BUS_VTABLE_PROPERTY: { struct vtable_member *m; if (!member_name_is_valid(v->property.member) || @@ -3834,7 +3898,7 @@ static int add_object_vtable_internal( case _SD_BUS_VTABLE_SIGNAL: if (!member_name_is_valid(v->signal.member) || - !signature_is_single(v->signal.signature, false)) { + !signature_is_single(strempty(v->signal.signature), false)) { r = -EINVAL; goto fail; } diff --git a/src/libsystemd-bus/test-bus-objects.c b/src/libsystemd-bus/test-bus-objects.c index 637e0511b..1c23c2136 100644 --- a/src/libsystemd-bus/test-bus-objects.c +++ b/src/libsystemd-bus/test-bus-objects.c @@ -38,7 +38,6 @@ * * Add in: * - * automatic properties for Set() * node hierarchy updates during dispatching * emit_interfaces_added/emit_interfaces_removed * @@ -48,7 +47,7 @@ struct context { int fds[2]; bool quit; char *something; - const char *automatic_string_property; + char *automatic_string_property; uint32_t automatic_integer_property; }; @@ -153,8 +152,8 @@ static const sd_bus_vtable vtable[] = { SD_BUS_METHOD("AlterSomething", "s", "s", something_handler, 0), SD_BUS_METHOD("Exit", "", "", exit_handler, 0), SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0), - SD_BUS_PROPERTY("AutomaticStringProperty", "s", NULL, offsetof(struct context, automatic_string_property), 0), - SD_BUS_PROPERTY("AutomaticIntegerProperty", "u", NULL, offsetof(struct context, automatic_integer_property), 0), + SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL, offsetof(struct context, automatic_string_property), 0), + SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL, offsetof(struct context, automatic_integer_property), 0), SD_BUS_METHOD("NoOperation", "", "", NULL, 0), SD_BUS_VTABLE_END }; @@ -288,6 +287,16 @@ static int client(struct context *c) { sd_bus_message_unref(reply); reply = NULL; + r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticIntegerProperty", &error, "u", 815); + assert_se(r >= 0); + + assert_se(c->automatic_integer_property == 815); + + r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticStringProperty", &error, "s", "Du Dödel, Du!"); + assert_se(r >= 0); + + assert_se(streq(c->automatic_string_property, "Du Dödel, Du!")); + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); assert_se(r >= 0); @@ -393,7 +402,7 @@ int main(int argc, char *argv[]) { zero(c); c.automatic_integer_property = 4711; - c.automatic_string_property = "dudeldu"; + assert_se(c.automatic_string_property = strdup("dudeldu")); assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0); @@ -414,6 +423,7 @@ int main(int argc, char *argv[]) { return PTR_TO_INT(p); free(c.something); + free(c.automatic_string_property); return EXIT_SUCCESS; } diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 926824772..2c12cf0f7 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -57,12 +57,9 @@ typedef struct { /* Callbacks */ typedef int (*sd_bus_message_handler_t)(sd_bus *bus, sd_bus_message *m, void *userdata); - typedef int (*sd_bus_property_get_t) (sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata); typedef int (*sd_bus_property_set_t) (sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, sd_bus_error *error, void *userdata); - typedef int (*sd_bus_object_find_t) (sd_bus *bus, const char *path, const char *interface, void **found, void *userdata); - typedef int (*sd_bus_node_enumerator_t) (sd_bus *bus, const char *path, char ***nodes, void *userdata); #include "sd-bus-protocol.h" -- 2.30.2