chiark / gitweb /
bus: add sd_bus_message_append_strv() to easily add a NULL terminated string array...
[elogind.git] / src / libsystemd-bus / bus-message.c
index 55c2d6288542e903205b38cfaa7999c9b7b22bf8..18c2d1c19dc75437fe9865c5cf4dd0d712b6fdc2 100644 (file)
@@ -65,8 +65,8 @@ static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
                 if (!part->sealed)
                         bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped);
                 else {
-                        if (part->size > 0)
-                                assert_se(munmap(part->data, PAGE_ALIGN(part->size)) == 0);
+                        if (part->mapped > 0)
+                                assert_se(munmap(part->data, part->mapped) == 0);
 
                         close_nointr_nofail(part->memfd);
                 }
@@ -125,8 +125,12 @@ static void message_free(sd_bus_message *m) {
         if (m->free_kdbus)
                 free(m->kdbus);
 
-        if (m->release_kdbus)
-                ioctl(m->bus->input_fd, KDBUS_CMD_MSG_RELEASE, m->kdbus);
+        if (m->release_kdbus) {
+                uint64_t off;
+
+                off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
+                ioctl(m->bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
+        }
 
         if (m->bus)
                 sd_bus_unref(m->bus);
@@ -492,9 +496,13 @@ int sd_bus_message_new_method_call(
         sd_bus_message *t;
         int r;
 
-        if (!path)
+        if (destination && !service_name_is_valid(destination))
                 return -EINVAL;
-        if (!member)
+        if (!object_path_is_valid(path))
+                return -EINVAL;
+        if (interface && !interface_name_is_valid(interface))
+                return -EINVAL;
+        if (!member_name_is_valid(member))
                 return -EINVAL;
         if (!m)
                 return -EINVAL;
@@ -623,6 +631,57 @@ fail:
         return r;
 }
 
+int sd_bus_message_new_method_errorf(
+                sd_bus *bus,
+                sd_bus_message *call,
+                sd_bus_message **m,
+                const char *name,
+                const char *format,
+                ...) {
+
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        sd_bus_message *t;
+        va_list ap;
+        int r;
+
+        if (!name)
+                return -EINVAL;
+        if (!m)
+                return -EINVAL;
+
+        r = message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_ERROR, &t);
+        if (r < 0)
+                return r;
+
+        r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, name, &t->error.name);
+        if (r < 0)
+                goto fail;
+
+        if (format) {
+                _cleanup_free_ char *message = NULL;
+
+                va_start(ap, format);
+                r = vasprintf(&message, format, ap);
+                va_end(ap);
+
+                if (r < 0) {
+                        r = -ENOMEM;
+                        goto fail;
+                }
+
+                r = message_append_basic(t, SD_BUS_TYPE_STRING, message, (const void**) &t->error.message);
+                if (r < 0)
+                        goto fail;
+        }
+
+        *m = t;
+        return 0;
+
+fail:
+        message_free(t);
+        return r;
+}
+
 int bus_message_new_synthetic_error(
                 sd_bus *bus,
                 uint64_t serial,
@@ -652,6 +711,16 @@ int bus_message_new_synthetic_error(
                         goto fail;
         }
 
+        r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
+        if (r < 0)
+                goto fail;
+
+        if (e->message) {
+                r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
+                if (r < 0)
+                        goto fail;
+        }
+
         *m = t;
         return 0;
 
@@ -1212,8 +1281,9 @@ static int part_make_space(
 
                         part->mapped = psz;
                         part->data = n;
-                        part->munmap_this = true;
                 }
+
+                part->munmap_this = true;
         } else {
                 n = realloc(part->data, sz);
                 if (!n) {
@@ -1244,7 +1314,6 @@ static void message_extend_containers(sd_bus_message *m, size_t expand) {
         for (c = m->containers; c < m->containers + m->n_containers; c++)
                 if (c->array_size)
                         *c->array_size += expand;
-
 }
 
 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
@@ -1554,7 +1623,7 @@ static int bus_message_open_array(
         assert(contents);
         assert(array_size);
 
-        if (!signature_is_single(contents))
+        if (!signature_is_single(contents, true))
                 return -EINVAL;
 
         alignment = bus_type_get_alignment(contents[0]);
@@ -1625,7 +1694,7 @@ static int bus_message_open_variant(
         assert(c);
         assert(contents);
 
-        if (!signature_is_single(contents))
+        if (!signature_is_single(contents, false))
                 return -EINVAL;
 
         if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
@@ -2235,14 +2304,10 @@ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
         void *a;
         int r;
 
-        if (!m)
-                return -EINVAL;
-        if (!memfd)
-                return -EINVAL;
-        if (m->sealed)
-                return -EPERM;
-        if (m->poisoned)
-                return -ESTALE;
+        assert_return(m, -EINVAL);
+        assert_return(memfd, -EINVAL);
+        assert_return(!m->sealed, -EPERM);
+        assert_return(!m->poisoned, -ESTALE);
 
         r = sd_memfd_set_sealed(memfd, true);
         if (r < 0)
@@ -2307,6 +2372,27 @@ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
         return 0;
 }
 
+int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
+        char **i;
+        int r;
+
+        assert_return(m, -EINVAL);
+        assert_return(!m->sealed, -EPERM);
+        assert_return(!m->poisoned, -ESTALE);
+
+        r = sd_bus_message_open_container(m, 'a', "s");
+        if (r < 0)
+                return r;
+
+        STRV_FOREACH(i, l) {
+                r = sd_bus_message_append_basic(m, 's', *i);
+                if (r < 0)
+                        return r;
+        }
+
+        return sd_bus_message_close_container(m);
+}
+
 int bus_body_part_map(struct bus_body_part *part) {
         void *p;
         size_t psz;
@@ -2700,7 +2786,7 @@ static int bus_message_enter_array(
         assert(contents);
         assert(array_size);
 
-        if (!signature_is_single(contents))
+        if (!signature_is_single(contents, true))
                 return -EINVAL;
 
         alignment = bus_type_get_alignment(contents[0]);
@@ -2754,7 +2840,7 @@ static int bus_message_enter_variant(
         assert(c);
         assert(contents);
 
-        if (!signature_is_single(contents))
+        if (!signature_is_single(contents, false))
                 return -EINVAL;
 
         if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
@@ -4286,3 +4372,16 @@ int bus_message_to_errno(sd_bus_message *m) {
 
         return bus_error_to_errno(&m->error);
 }
+
+int sd_bus_message_get_signature(sd_bus_message *m, int complete, const char **signature) {
+        struct bus_container *c;
+
+        if (!m)
+                return -EINVAL;
+        if (!signature)
+                return -EINVAL;
+
+        c = complete ? &m->root_container : message_get_container(m);
+        *signature = c->signature ?: "";
+        return 0;
+}