X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fsd-bus.c;h=cebb07319af1916875c5ff6a76c03421cc572661;hp=795007acc4ae52ccb8199d9faea7efe2aa9e4f33;hb=9db76355212de5eb7985829d352183d3bdfb56d5;hpb=753eff037ee99d2c5ecbf3c3228c78d616cbb310 diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 795007acc..cebb07319 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -2089,18 +2089,125 @@ 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; return 1; } - return c->vtable->method.handler(bus, m, u); + if (c->vtable->method.handler) + return c->vtable->method.handler(bus, m, u); + + /* If the method callback is NULL, make this a successful NOP */ + r = sd_bus_reply_method_return(bus, m, NULL); + if (r < 0) + return r; + + return 1; +} + +static int invoke_property_get( + sd_bus *bus, + const sd_bus_vtable *v, + const char *path, + const char *interface, + const char *property, + sd_bus_message *m, + sd_bus_error *error, + void *userdata) { + + int r; + void *p; + + assert(bus); + assert(v); + + if (v->property.get) + return v->property.get(bus, path, interface, property, m, error, userdata); + + /* 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: + case SD_BUS_TYPE_OBJECT_PATH: + case SD_BUS_TYPE_SIGNATURE: + p = *(char**) userdata; + break; + + default: + p = userdata; + break; + } + + r = sd_bus_message_append_basic(m, v->property.signature[0], p); + if (r < 0) + return r; + + 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( @@ -2140,12 +2247,9 @@ static int property_get_set_callbacks_run( if (r < 0) return r; - if (c->vtable->property.get) { - r = c->vtable->property.get(bus, m->path, c->interface, c->member, reply, &error, u); - if (r < 0) - return r; - } else - assert_not_reached("automatic properties not supported yet"); + r = invoke_property_get(bus, c->vtable, m->path, c->interface, c->member, reply, &error, u); + if (r < 0) + return r; if (sd_bus_error_is_set(&error)) { r = sd_bus_reply_method_error(bus, m, &error); @@ -2167,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)) { @@ -2226,7 +2327,7 @@ static int vtable_append_all_properties( if (r < 0) return r; - r = v->property.get(bus, path, c->interface, v->property.member, reply, error, vtable_property_convert_userdata(v, userdata)); + r = invoke_property_get(bus, v, path, c->interface, v->property.member, reply, error, vtable_property_convert_userdata(v, userdata)); if (r < 0) return r; @@ -2499,6 +2600,7 @@ static int object_manager_serialize_vtable( static int object_manager_serialize_path( sd_bus *bus, sd_bus_message *reply, + const char *prefix, const char *path, bool require_fallback, sd_bus_error *error) { @@ -2509,10 +2611,11 @@ static int object_manager_serialize_path( assert(bus); assert(reply); + assert(prefix); assert(path); assert(error); - n = hashmap_get(bus->nodes, path); + n = hashmap_get(bus->nodes, prefix); if (!n) return 0; @@ -2566,7 +2669,7 @@ static int object_manager_serialize_path_and_fallbacks( assert(error); /* First, add all vtables registered for this path */ - r = object_manager_serialize_path(bus, reply, path, false, error); + r = object_manager_serialize_path(bus, reply, path, path, false, error); if (r < 0) return r; if (sd_bus_error_is_set(error)) @@ -2587,7 +2690,7 @@ static int object_manager_serialize_path_and_fallbacks( *e = 0; - r = object_manager_serialize_path(bus, reply, p, true, error); + r = object_manager_serialize_path(bus, reply, p, path, true, error); if (r < 0) return r; @@ -2687,7 +2790,13 @@ static int process_get_managed_objects( return 1; } -static int object_find_and_run(sd_bus *bus, sd_bus_message *m, const char *p, bool require_fallback, bool *found_object) { +static int object_find_and_run( + sd_bus *bus, + sd_bus_message *m, + const char *p, + bool require_fallback, + bool *found_object) { + struct node *n; struct vtable_member vtable_key, *v; int r; @@ -3390,7 +3499,6 @@ int sd_bus_emit_signal( const char *types, ...) { _cleanup_bus_message_unref_ sd_bus_message *m = NULL; - va_list ap; int r; if (!bus) @@ -3404,11 +3512,15 @@ int sd_bus_emit_signal( if (r < 0) return r; - va_start(ap, types); - r = bus_message_append_ap(m, types, ap); - va_end(ap); - if (r < 0) - return r; + if (!isempty(types)) { + va_list ap; + + va_start(ap, types); + r = bus_message_append_ap(m, types, ap); + va_end(ap); + if (r < 0) + return r; + } return sd_bus_send(bus, m, NULL); } @@ -3424,7 +3536,6 @@ int sd_bus_call_method( const char *types, ...) { _cleanup_bus_message_unref_ sd_bus_message *m = NULL; - va_list ap; int r; if (!bus) @@ -3439,11 +3550,15 @@ int sd_bus_call_method( if (r < 0) return r; - va_start(ap, types); - r = bus_message_append_ap(m, types, ap); - va_end(ap); - if (r < 0) - return r; + if (!isempty(types)) { + va_list ap; + + va_start(ap, types); + r = bus_message_append_ap(m, types, ap); + va_end(ap); + if (r < 0) + return r; + } return sd_bus_send_with_reply_and_block(bus, m, 0, error, reply); } @@ -3454,7 +3569,6 @@ int sd_bus_reply_method_return( const char *types, ...) { _cleanup_bus_message_unref_ sd_bus_message *m = NULL; - va_list ap; int r; if (!bus) @@ -3477,11 +3591,15 @@ int sd_bus_reply_method_return( if (r < 0) return r; - va_start(ap, types); - r = bus_message_append_ap(m, types, ap); - va_end(ap); - if (r < 0) - return r; + if (!isempty(types)) { + va_list ap; + + va_start(ap, types); + r = bus_message_append_ap(m, types, ap); + va_end(ap); + if (r < 0) + return r; + } return sd_bus_send(bus, m, NULL); } @@ -3571,7 +3689,7 @@ static void free_node_vtable(sd_bus *bus, struct node_vtable *w) { if (w->interface && w->node && w->vtable) { const sd_bus_vtable *v; - for (v = w->vtable; v->type != _SD_BUS_VTABLE_END; w++) { + for (v = w->vtable; v->type != _SD_BUS_VTABLE_END; v++) { struct vtable_member *x = NULL; switch (v->type) { @@ -3705,9 +3823,9 @@ 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) || - !v->method.handler || + !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; goto fail; @@ -3734,12 +3852,21 @@ 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) || !signature_is_single(v->property.signature, false) || + !(v->property.get || bus_type_is_basic(v->property.signature[0])) || v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY || (v->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY && !(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))) { r = -EINVAL; @@ -3771,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; } @@ -3792,7 +3919,7 @@ fail: free_node_vtable(bus, c); bus_node_gc(bus, n); - return 0; + return r; } static int remove_object_vtable_internal( @@ -3977,18 +4104,16 @@ static int emit_properties_changed_on_interface( if (streq(c->interface, interface)) break; - - r = node_vtable_get_userdata(bus, path, c, &u); - if (r < 0) - return r; - if (r > 0) - break; } if (!c) return 0; - r = sd_bus_message_new_signal(bus, path, "org.freedesktop.DBus", "PropertiesChanged", &m); + r = node_vtable_get_userdata(bus, path, c, &u); + if (r <= 0) + return r; + + r = sd_bus_message_new_signal(bus, path, "org.freedesktop.DBus.Properties", "PropertiesChanged", &m); if (r < 0) return r; @@ -4025,7 +4150,7 @@ static int emit_properties_changed_on_interface( if (r < 0) return r; - r = sd_bus_message_append(m, "s", *n); + r = sd_bus_message_append(m, "s", *property); if (r < 0) return r; @@ -4033,7 +4158,7 @@ static int emit_properties_changed_on_interface( if (r < 0) return r; - r = v->vtable->property.get(bus, m->path, interface, *property, m, &error, vtable_property_convert_userdata(v->vtable, u)); + r = invoke_property_get(bus, v->vtable, m->path, interface, *property, m, &error, vtable_property_convert_userdata(v->vtable, u)); if (r < 0) return r;