chiark / gitweb /
bus: support implicit serialization of strv string arrays within vtables
[elogind.git] / src / libsystemd-bus / bus-objects.c
index 90417fdca196493a4ea992416ea47492672e683a..92781e9adcc1ef2192c40c4657f9759b03632dd8 100644 (file)
@@ -312,7 +312,6 @@ static int invoke_property_get(
                 sd_bus_error *error,
                 void *userdata) {
 
-        int r;
         const void *p;
 
         assert(bus);
@@ -327,20 +326,22 @@ static int invoke_property_get(
 
         /* Automatic handling if no callback is defined. */
 
+        if (streq(v->x.property.signature, "as"))
+                return sd_bus_message_append_strv(m, *(char***) userdata);
+
         assert(signature_is_single(v->x.property.signature, false));
         assert(bus_type_is_basic(v->x.property.signature[0]));
 
         switch (v->x.property.signature[0]) {
 
         case SD_BUS_TYPE_STRING:
-                p = *(char**) userdata;
-                if (!p)
-                        p = "";
+        case SD_BUS_TYPE_SIGNATURE:
+                p = strempty(*(char**) userdata);
                 break;
 
         case SD_BUS_TYPE_OBJECT_PATH:
-        case SD_BUS_TYPE_SIGNATURE:
                 p = *(char**) userdata;
+                assert(p);
                 break;
 
         default:
@@ -348,11 +349,7 @@ static int invoke_property_get(
                 break;
         }
 
-        r = sd_bus_message_append_basic(m, v->x.property.signature[0], p);
-        if (r < 0)
-                return r;
-
-        return 1;
+        return sd_bus_message_append_basic(m, v->x.property.signature[0], p);
 }
 
 static int invoke_property_set(
@@ -586,7 +583,7 @@ static int property_get_all_callbacks_run(
 
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         struct node_vtable *c;
-        bool found_interface = false;
+        bool found_interface;
         int r;
 
         assert(bus);
@@ -601,6 +598,11 @@ static int property_get_all_callbacks_run(
         if (r < 0)
                 return r;
 
+        found_interface = !iface ||
+                streq(iface, "org.freedesktop.DBus.Properties") ||
+                streq(iface, "org.freedesktop.DBus.Peer") ||
+                streq(iface, "org.freedesktop.DBus.Introspectable");
+
         LIST_FOREACH(vtables, c, first) {
                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
                 void *u;
@@ -1583,7 +1585,7 @@ static int add_object_vtable_internal(
 
                         if (!member_name_is_valid(v->x.property.member) ||
                             !signature_is_single(v->x.property.signature, false) ||
-                            !(v->x.property.get || bus_type_is_basic(v->x.property.signature[0])) ||
+                            !(v->x.property.get || bus_type_is_basic(v->x.property.signature[0]) || streq(v->x.property.signature, "as")) ||
                             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;
@@ -1615,7 +1617,7 @@ static int add_object_vtable_internal(
                 case _SD_BUS_VTABLE_SIGNAL:
 
                         if (!member_name_is_valid(v->x.signal.member) ||
-                            !signature_is_single(strempty(v->x.signal.signature), false)) {
+                            !signature_is_valid(strempty(v->x.signal.signature), false)) {
                                 r = -EINVAL;
                                 goto fail;
                         }
@@ -1977,8 +1979,7 @@ int sd_bus_emit_properties_changed(
                 const char *interface,
                 const char *name, ...)  {
 
-        _cleanup_strv_free_ char **names = NULL;
-        va_list ap;
+        char **names;
 
         assert_return(bus, -EINVAL);
         assert_return(object_path_is_valid(path), -EINVAL);
@@ -1989,12 +1990,7 @@ int sd_bus_emit_properties_changed(
         if (!name)
                 return 0;
 
-        va_start(ap, name);
-        names = strv_new_ap(name, ap);
-        va_end(ap);
-
-        if (!names)
-                return -ENOMEM;
+        names = strv_from_stdarg_alloca(name);
 
         return sd_bus_emit_properties_changed_strv(bus, path, interface, names);
 }
@@ -2158,20 +2154,14 @@ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **inte
 }
 
 int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) {
-        _cleanup_strv_free_ char **interfaces = NULL;
-        va_list ap;
+        char **interfaces;
 
         assert_return(bus, -EINVAL);
         assert_return(object_path_is_valid(path), -EINVAL);
         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
-        va_start(ap, interface);
-        interfaces = strv_new_ap(interface, ap);
-        va_end(ap);
-
-        if (!interfaces)
-                return -ENOMEM;
+        interfaces = strv_from_stdarg_alloca(interface);
 
         return sd_bus_emit_interfaces_added_strv(bus, path, interfaces);
 }
@@ -2204,20 +2194,14 @@ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **in
 }
 
 int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) {
-        _cleanup_strv_free_ char **interfaces = NULL;
-        va_list ap;
+        char **interfaces;
 
         assert_return(bus, -EINVAL);
         assert_return(object_path_is_valid(path), -EINVAL);
         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
-        va_start(ap, interface);
-        interfaces = strv_new_ap(interface, ap);
-        va_end(ap);
-
-        if (!interfaces)
-                return -ENOMEM;
+        interfaces = strv_from_stdarg_alloca(interface);
 
         return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces);
 }