diff options
author | Lennart Poettering <lennart@poettering.net> | 2013-10-11 20:02:16 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2013-10-11 20:03:19 +0200 |
commit | 9db76355212de5eb7985829d352183d3bdfb56d5 (patch) | |
tree | 5b0c1f793c9db122d42f2bf5078b7425237dad5f /src | |
parent | 43a43f5016eb9404afdd6719b18f604a484535ec (diff) |
bus: if a a Set() vtable callback of a writable is left NULL, try to do the right thing automatically
Diffstat (limited to 'src')
-rw-r--r-- | src/libsystemd-bus/sd-bus.c | 90 | ||||
-rw-r--r-- | src/libsystemd-bus/test-bus-objects.c | 20 | ||||
-rw-r--r-- | src/systemd/sd-bus.h | 3 |
3 files changed, 92 insertions, 21 deletions
diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 3fd5186763..cebb07319a 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 637e0511b2..1c23c2136a 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 9268247729..2c12cf0f7d 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" |