1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include "time-util.h"
30 #include "cgroup-util.h"
31 #include "memfd-util.h"
34 #include "bus-message.h"
35 #include "bus-internal.h"
37 #include "bus-signature.h"
38 #include "bus-gvariant.h"
41 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
43 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
48 if (old_base == new_base)
51 if ((uint8_t*) p < (uint8_t*) old_base)
54 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
57 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
60 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
64 if (part->memfd >= 0) {
65 /* If we can reuse the memfd, try that. For that it
66 * can't be sealed yet. */
69 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
72 assert_se(munmap(part->data, part->mapped) == 0);
74 safe_close(part->memfd);
77 } else if (part->munmap_this)
78 munmap(part->data, part->mapped);
79 else if (part->free_this)
86 static void message_reset_parts(sd_bus_message *m) {
87 struct bus_body_part *part;
92 while (m->n_body_parts > 0) {
93 struct bus_body_part *next = part->next;
94 message_free_part(m, part);
101 m->cached_rindex_part = NULL;
102 m->cached_rindex_part_begin = 0;
105 static void message_reset_containers(sd_bus_message *m) {
110 for (i = 0; i < m->n_containers; i++) {
111 free(m->containers[i].signature);
112 free(m->containers[i].offsets);
116 m->containers = NULL;
118 m->n_containers = m->containers_allocated = 0;
119 m->root_container.index = 0;
122 static void message_free(sd_bus_message *m) {
128 message_reset_parts(m);
130 if (m->release_kdbus) {
131 struct kdbus_cmd_free cmd_free;
134 cmd_free.offset = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
135 (void) ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &cmd_free);
141 sd_bus_unref(m->bus);
144 close_many(m->fds, m->n_fds);
148 if (m->iovec != m->iovec_fixed)
151 if (m->destination_ptr) {
152 free(m->destination_ptr);
153 m->destination_ptr = NULL;
156 message_reset_containers(m);
157 free(m->root_container.signature);
158 free(m->root_container.offsets);
160 free(m->root_container.peeked_signature);
162 bus_creds_done(&m->creds);
166 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
168 size_t old_size, new_size, start;
175 old_size = sizeof(struct bus_header) + m->header->fields_size;
176 start = ALIGN_TO(old_size, align);
177 new_size = start + sz;
179 if (old_size == new_size)
180 return (uint8_t*) m->header + old_size;
182 if (new_size > (size_t) ((uint32_t) -1))
185 if (m->free_header) {
186 np = realloc(m->header, ALIGN8(new_size));
190 /* Initially, the header is allocated as part of of
191 * the sd_bus_message itself, let's replace it by
194 np = malloc(ALIGN8(new_size));
198 memcpy(np, m->header, sizeof(struct bus_header));
201 /* Zero out padding */
202 if (start > old_size)
203 memzero((uint8_t*) np + old_size, start - old_size);
207 m->header->fields_size = new_size - sizeof(struct bus_header);
209 /* Adjust quick access pointers */
210 m->path = adjust_pointer(m->path, op, old_size, m->header);
211 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
212 m->member = adjust_pointer(m->member, op, old_size, m->header);
213 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
214 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
215 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
217 m->free_header = true;
220 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
223 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
226 return (uint8_t*) np + start;
233 static int message_append_field_string(
245 /* dbus1 doesn't allow strings over 32bit, let's enforce this
246 * globally, to not risk convertability */
248 if (l > (size_t) (uint32_t) -1)
251 /* Signature "(yv)" where the variant contains "s" */
253 if (BUS_MESSAGE_IS_GVARIANT(m)) {
255 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
256 p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
268 *ret = (char*) p + 8;
271 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
272 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
281 ((uint32_t*) p)[1] = l;
282 memcpy(p + 8, s, l + 1);
285 *ret = (char*) p + 8;
291 static int message_append_field_signature(
302 /* dbus1 doesn't allow signatures over 32bit, let's enforce
303 * this globally, to not risk convertability */
308 /* Signature "(yv)" where the variant contains "g" */
310 if (BUS_MESSAGE_IS_GVARIANT(m))
311 /* For gvariant the serialization is the same as for normal strings */
312 return message_append_field_string(m, h, 'g', s, ret);
314 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
315 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
321 p[2] = SD_BUS_TYPE_SIGNATURE;
324 memcpy(p + 5, s, l + 1);
327 *ret = (const char*) p + 5;
333 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
338 if (BUS_MESSAGE_IS_GVARIANT(m)) {
339 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
341 p = message_extend_fields(m, 8, 1 + 7 + 4 + 1 + 1, true);
347 *((uint32_t*) (p + 8)) = x;
351 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
352 p = message_extend_fields(m, 8, 4 + 4, false);
358 p[2] = SD_BUS_TYPE_UINT32;
361 ((uint32_t*) p)[1] = x;
367 int bus_message_from_header(
373 const struct ucred *ucred,
376 sd_bus_message **ret) {
379 struct bus_header *h;
383 assert(buffer || length <= 0);
384 assert(fds || n_fds <= 0);
387 if (length < sizeof(struct bus_header))
391 if (h->version != 1 &&
398 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
401 if (h->endian != BUS_LITTLE_ENDIAN &&
402 h->endian != BUS_BIG_ENDIAN)
405 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
408 label_sz = strlen(label);
423 m->creds.uid = ucred->uid;
424 m->creds.pid = ucred->pid;
425 m->creds.gid = ucred->gid;
426 m->creds.mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID;
430 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
431 memcpy(m->creds.label, label, label_sz + 1);
433 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
436 m->bus = sd_bus_ref(bus);
442 int bus_message_from_malloc(
448 const struct ucred *ucred,
450 sd_bus_message **ret) {
456 r = bus_message_from_header(bus, buffer, length, fds, n_fds, ucred, label, 0, &m);
460 if (length != BUS_MESSAGE_SIZE(m)) {
465 sz = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
468 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
470 m->body.sealed = true;
475 m->iovec = m->iovec_fixed;
476 m->iovec[0].iov_base = buffer;
477 m->iovec[0].iov_len = length;
479 r = bus_message_parse_fields(m);
483 /* We take possession of the memory and fds now */
484 m->free_header = true;
495 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
500 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
505 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
506 m->header->endian = BUS_NATIVE_ENDIAN;
507 m->header->type = type;
508 m->header->version = bus ? bus->message_version : 1;
509 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
510 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
511 m->bus = sd_bus_ref(bus);
516 _public_ int sd_bus_message_new_signal(
520 const char *interface,
521 const char *member) {
526 assert_return(bus, -ENOTCONN);
527 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
528 assert_return(object_path_is_valid(path), -EINVAL);
529 assert_return(interface_name_is_valid(interface), -EINVAL);
530 assert_return(member_name_is_valid(member), -EINVAL);
531 assert_return(m, -EINVAL);
533 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
537 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
539 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
542 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
545 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
553 sd_bus_message_unref(t);
557 _public_ int sd_bus_message_new_method_call(
560 const char *destination,
562 const char *interface,
563 const char *member) {
568 assert_return(bus, -ENOTCONN);
569 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
570 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
571 assert_return(object_path_is_valid(path), -EINVAL);
572 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
573 assert_return(member_name_is_valid(member), -EINVAL);
574 assert_return(m, -EINVAL);
576 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
580 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
583 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
588 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
594 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
607 static int message_new_reply(
608 sd_bus_message *call,
610 sd_bus_message **m) {
615 assert_return(call, -EINVAL);
616 assert_return(call->sealed, -EPERM);
617 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
618 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
619 assert_return(m, -EINVAL);
621 t = message_new(call->bus, type);
625 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
626 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
628 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
633 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
638 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
639 t->enforced_reply_signature = call->enforced_reply_signature;
649 _public_ int sd_bus_message_new_method_return(
650 sd_bus_message *call,
651 sd_bus_message **m) {
653 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
656 _public_ int sd_bus_message_new_method_error(
657 sd_bus_message *call,
659 const sd_bus_error *e) {
664 assert_return(sd_bus_error_is_set(e), -EINVAL);
665 assert_return(m, -EINVAL);
667 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
671 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
676 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
681 t->error._need_free = -1;
691 _public_ int sd_bus_message_new_method_errorf(
692 sd_bus_message *call,
698 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
701 assert_return(name, -EINVAL);
702 assert_return(m, -EINVAL);
704 va_start(ap, format);
705 bus_error_setfv(&error, name, format, ap);
708 return sd_bus_message_new_method_error(call, m, &error);
711 _public_ int sd_bus_message_new_method_errno(
712 sd_bus_message *call,
715 const sd_bus_error *p) {
717 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
719 if (sd_bus_error_is_set(p))
720 return sd_bus_message_new_method_error(call, m, p);
722 sd_bus_error_set_errno(&berror, error);
724 return sd_bus_message_new_method_error(call, m, &berror);
727 _public_ int sd_bus_message_new_method_errnof(
728 sd_bus_message *call,
734 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
737 va_start(ap, format);
738 bus_error_set_errnofv(&berror, error, format, ap);
741 return sd_bus_message_new_method_error(call, m, &berror);
744 int bus_message_new_synthetic_error(
747 const sd_bus_error *e,
748 sd_bus_message **m) {
754 assert(sd_bus_error_is_set(e));
757 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
761 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
762 t->reply_cookie = cookie;
764 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
768 if (bus && bus->unique_name) {
769 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
774 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
779 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
784 t->error._need_free = -1;
794 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
795 assert_return(m, NULL);
797 assert(m->n_ref > 0);
803 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
808 assert(m->n_ref > 0);
818 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
819 assert_return(m, -EINVAL);
820 assert_return(type, -EINVAL);
822 *type = m->header->type;
826 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
827 assert_return(m, -EINVAL);
828 assert_return(cookie, -EINVAL);
829 assert_return(m->header->serial != 0, -ENODATA);
831 *cookie = BUS_MESSAGE_COOKIE(m);
835 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
836 assert_return(m, -EINVAL);
837 assert_return(cookie, -EINVAL);
838 assert_return(m->reply_cookie != 0, -ENODATA);
840 *cookie = m->reply_cookie;
844 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
845 assert_return(m, -EINVAL);
847 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
848 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
851 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
852 assert_return(m, -EINVAL);
854 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
857 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
858 assert_return(m, -EINVAL);
860 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
861 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
864 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
865 assert_return(m, NULL);
870 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
871 assert_return(m, NULL);
876 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
877 assert_return(m, NULL);
882 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
883 assert_return(m, NULL);
885 return m->destination;
888 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
889 assert_return(m, NULL);
894 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
895 assert_return(m, NULL);
896 assert_return(sd_bus_error_is_set(&m->error), NULL);
901 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
902 assert_return(m, -EINVAL);
903 assert_return(usec, -EINVAL);
905 if (m->monotonic <= 0)
908 *usec = m->monotonic;
912 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
913 assert_return(m, -EINVAL);
914 assert_return(usec, -EINVAL);
916 if (m->realtime <= 0)
923 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
924 assert_return(m, -EINVAL);
925 assert_return(seqnum, -EINVAL);
934 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
935 assert_return(m, NULL);
937 if (m->creds.mask == 0)
943 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
944 const char *interface,
945 const char *member) {
946 assert_return(m, -EINVAL);
948 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
951 if (interface && (!m->interface || !streq(m->interface, interface)))
954 if (member && (!m->member || !streq(m->member, member)))
960 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
961 const char *interface,
962 const char *member) {
963 assert_return(m, -EINVAL);
965 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
968 if (interface && (!m->interface || !streq(m->interface, interface)))
971 if (member && (!m->member || !streq(m->member, member)))
977 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
978 assert_return(m, -EINVAL);
980 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
983 if (name && (!m->error.name || !streq(m->error.name, name)))
989 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
990 assert_return(m, -EINVAL);
991 assert_return(!m->sealed, -EPERM);
992 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
995 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
997 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1002 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1003 assert_return(m, -EINVAL);
1004 assert_return(!m->sealed, -EPERM);
1007 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1009 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1014 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1015 assert_return(m, -EINVAL);
1016 assert_return(!m->sealed, -EPERM);
1019 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1021 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1026 static struct bus_container *message_get_container(sd_bus_message *m) {
1029 if (m->n_containers == 0)
1030 return &m->root_container;
1032 assert(m->containers);
1033 return m->containers + m->n_containers - 1;
1036 struct bus_body_part *message_append_part(sd_bus_message *m) {
1037 struct bus_body_part *part;
1044 if (m->n_body_parts <= 0) {
1048 assert(m->body_end);
1050 part = new0(struct bus_body_part, 1);
1056 m->body_end->next = part;
1066 static void part_zero(struct bus_body_part *part, size_t sz) {
1071 /* All other fields can be left in their defaults */
1072 assert(!part->data);
1073 assert(part->memfd < 0);
1076 part->is_zero = true;
1077 part->sealed = true;
1080 static int part_make_space(
1081 struct sd_bus_message *m,
1082 struct bus_body_part *part,
1091 assert(!part->sealed);
1096 if (!part->data && part->memfd < 0)
1097 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1099 if (part->memfd >= 0) {
1101 if (part->allocated == 0 || sz > part->allocated) {
1102 uint64_t new_allocated;
1104 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1105 r = memfd_set_size(part->memfd, new_allocated);
1111 part->allocated = new_allocated;
1114 if (!part->data || sz > part->mapped) {
1117 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1118 if (part->mapped <= 0)
1119 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1121 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1123 if (n == MAP_FAILED) {
1132 part->munmap_this = true;
1134 if (part->allocated == 0 || sz > part->allocated) {
1135 size_t new_allocated;
1137 new_allocated = sz > 0 ? 2 * sz : 64;
1138 n = realloc(part->data, new_allocated);
1145 part->allocated = new_allocated;
1146 part->free_this = true;
1151 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1157 static int message_add_offset(sd_bus_message *m, size_t offset) {
1158 struct bus_container *c;
1161 assert(BUS_MESSAGE_IS_GVARIANT(m));
1163 /* Add offset to current container, unless this is the first
1164 * item in it, which will have the 0 offset, which we can
1166 c = message_get_container(m);
1168 if (!c->need_offsets)
1171 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1174 c->offsets[c->n_offsets++] = offset;
1178 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1179 struct bus_container *c;
1186 /* Update counters */
1187 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1190 *c->array_size += expand;
1194 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1195 size_t start_body, end_body, padding, added;
1206 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1207 end_body = start_body + sz;
1209 padding = start_body - m->header->body_size;
1210 added = padding + sz;
1212 /* Check for 32bit overflows */
1213 if (end_body > (size_t) ((uint32_t) -1)) {
1219 struct bus_body_part *part = NULL;
1223 m->n_body_parts <= 0 ||
1224 m->body_end->sealed ||
1225 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1229 part = message_append_part(m);
1233 part_zero(part, padding);
1236 part = message_append_part(m);
1240 r = part_make_space(m, part, sz, &p);
1244 struct bus_container *c;
1246 size_t os, start_part, end_part;
1252 start_part = ALIGN_TO(part->size, align);
1253 end_part = start_part + sz;
1255 r = part_make_space(m, part, end_part, &p);
1260 memzero(p, padding);
1261 p = (uint8_t*) p + padding;
1264 /* Readjust pointers */
1265 for (c = m->containers; c < m->containers + m->n_containers; c++)
1266 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1268 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1271 /* Return something that is not NULL and is aligned */
1272 p = (uint8_t *) NULL + align;
1274 m->header->body_size = end_body;
1275 message_extend_containers(m, added);
1278 r = message_add_offset(m, end_body);
1288 static int message_push_fd(sd_bus_message *m, int fd) {
1299 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1303 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1311 m->fds[m->n_fds] = copy;
1317 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1318 _cleanup_close_ int fd = -1;
1319 struct bus_container *c;
1323 assert_return(m, -EINVAL);
1324 assert_return(!m->sealed, -EPERM);
1325 assert_return(bus_type_is_basic(type), -EINVAL);
1326 assert_return(!m->poisoned, -ESTALE);
1328 c = message_get_container(m);
1330 if (c->signature && c->signature[c->index]) {
1331 /* Container signature is already set */
1333 if (c->signature[c->index] != type)
1338 /* Maybe we can append to the signature? But only if this is the top-level container*/
1339 if (c->enclosing != 0)
1342 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1349 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1355 case SD_BUS_TYPE_SIGNATURE:
1356 case SD_BUS_TYPE_STRING:
1359 /* Fall through... */
1360 case SD_BUS_TYPE_OBJECT_PATH:
1368 case SD_BUS_TYPE_BOOLEAN:
1370 u8 = p && *(int*) p;
1376 case SD_BUS_TYPE_UNIX_FD:
1381 fd = message_push_fd(m, *(int*) p);
1392 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1393 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1400 a = message_extend_body(m, align, sz, true);
1407 *stored = (const uint8_t*) a;
1414 case SD_BUS_TYPE_STRING:
1415 /* To make things easy we'll serialize a NULL string
1416 * into the empty string */
1419 /* Fall through... */
1420 case SD_BUS_TYPE_OBJECT_PATH:
1426 sz = 4 + strlen(p) + 1;
1429 case SD_BUS_TYPE_SIGNATURE:
1434 sz = 1 + strlen(p) + 1;
1437 case SD_BUS_TYPE_BOOLEAN:
1439 u32 = p && *(int*) p;
1445 case SD_BUS_TYPE_UNIX_FD:
1450 fd = message_push_fd(m, *(int*) p);
1461 align = bus_type_get_alignment(type);
1462 sz = bus_type_get_size(type);
1469 a = message_extend_body(m, align, sz, false);
1473 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1474 *(uint32_t*) a = sz - 5;
1475 memcpy((uint8_t*) a + 4, p, sz - 4);
1478 *stored = (const uint8_t*) a + 4;
1480 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1481 *(uint8_t*) a = sz - 2;
1482 memcpy((uint8_t*) a + 1, p, sz - 1);
1485 *stored = (const uint8_t*) a + 1;
1494 if (type == SD_BUS_TYPE_UNIX_FD)
1497 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1504 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1505 return message_append_basic(m, type, p, NULL);
1508 _public_ int sd_bus_message_append_string_space(
1513 struct bus_container *c;
1516 assert_return(m, -EINVAL);
1517 assert_return(s, -EINVAL);
1518 assert_return(!m->sealed, -EPERM);
1519 assert_return(!m->poisoned, -ESTALE);
1521 c = message_get_container(m);
1523 if (c->signature && c->signature[c->index]) {
1524 /* Container signature is already set */
1526 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1531 /* Maybe we can append to the signature? But only if this is the top-level container*/
1532 if (c->enclosing != 0)
1535 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1542 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1543 a = message_extend_body(m, 1, size + 1, true);
1549 a = message_extend_body(m, 4, 4 + size + 1, false);
1553 *(uint32_t*) a = size;
1559 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1565 _public_ int sd_bus_message_append_string_iovec(
1567 const struct iovec *iov,
1575 assert_return(m, -EINVAL);
1576 assert_return(!m->sealed, -EPERM);
1577 assert_return(iov || n == 0, -EINVAL);
1578 assert_return(!m->poisoned, -ESTALE);
1580 size = IOVEC_TOTAL_SIZE(iov, n);
1582 r = sd_bus_message_append_string_space(m, size, &p);
1586 for (i = 0; i < n; i++) {
1588 if (iov[i].iov_base)
1589 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1591 memset(p, ' ', iov[i].iov_len);
1593 p += iov[i].iov_len;
1599 static int bus_message_open_array(
1601 struct bus_container *c,
1602 const char *contents,
1603 uint32_t **array_size,
1605 bool *need_offsets) {
1615 assert(need_offsets);
1617 if (!signature_is_single(contents, true))
1620 if (c->signature && c->signature[c->index]) {
1622 /* Verify the existing signature */
1624 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1627 if (!startswith(c->signature + c->index + 1, contents))
1630 nindex = c->index + 1 + strlen(contents);
1634 if (c->enclosing != 0)
1637 /* Extend the existing signature */
1639 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1645 nindex = e - c->signature;
1648 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1649 alignment = bus_gvariant_get_alignment(contents);
1653 /* Add alignment padding and add to offset list */
1654 if (!message_extend_body(m, alignment, 0, false))
1657 r = bus_gvariant_is_fixed_size(contents);
1661 *begin = m->header->body_size;
1662 *need_offsets = r == 0;
1666 struct bus_body_part *o;
1668 alignment = bus_type_get_alignment(contents[0]);
1672 a = message_extend_body(m, 4, 4, false);
1677 op = m->body_end->data;
1678 os = m->body_end->size;
1680 /* Add alignment between size and first element */
1681 if (!message_extend_body(m, alignment, 0, false))
1684 /* location of array size might have changed so let's readjust a */
1685 if (o == m->body_end)
1686 a = adjust_pointer(a, op, os, m->body_end->data);
1692 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1698 static int bus_message_open_variant(
1700 struct bus_container *c,
1701 const char *contents) {
1707 if (!signature_is_single(contents, false))
1710 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1713 if (c->signature && c->signature[c->index]) {
1715 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1721 if (c->enclosing != 0)
1724 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1731 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1732 /* Variants are always aligned to 8 */
1734 if (!message_extend_body(m, 8, 0, false))
1741 l = strlen(contents);
1742 a = message_extend_body(m, 1, 1 + l + 1, false);
1747 memcpy((uint8_t*) a + 1, contents, l + 1);
1750 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1756 static int bus_message_open_struct(
1758 struct bus_container *c,
1759 const char *contents,
1761 bool *need_offsets) {
1770 assert(need_offsets);
1772 if (!signature_is_valid(contents, false))
1775 if (c->signature && c->signature[c->index]) {
1778 l = strlen(contents);
1780 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1781 !startswith(c->signature + c->index + 1, contents) ||
1782 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1785 nindex = c->index + 1 + l + 1;
1789 if (c->enclosing != 0)
1792 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1798 nindex = e - c->signature;
1801 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1804 alignment = bus_gvariant_get_alignment(contents);
1808 if (!message_extend_body(m, alignment, 0, false))
1811 r = bus_gvariant_is_fixed_size(contents);
1815 *begin = m->header->body_size;
1816 *need_offsets = r == 0;
1818 /* Align contents to 8 byte boundary */
1819 if (!message_extend_body(m, 8, 0, false))
1823 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1829 static int bus_message_open_dict_entry(
1831 struct bus_container *c,
1832 const char *contents,
1834 bool *need_offsets) {
1842 assert(need_offsets);
1844 if (!signature_is_pair(contents))
1847 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1850 if (c->signature && c->signature[c->index]) {
1853 l = strlen(contents);
1855 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1856 !startswith(c->signature + c->index + 1, contents) ||
1857 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1862 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1865 alignment = bus_gvariant_get_alignment(contents);
1869 if (!message_extend_body(m, alignment, 0, false))
1872 r = bus_gvariant_is_fixed_size(contents);
1876 *begin = m->header->body_size;
1877 *need_offsets = r == 0;
1879 /* Align contents to 8 byte boundary */
1880 if (!message_extend_body(m, 8, 0, false))
1887 _public_ int sd_bus_message_open_container(
1890 const char *contents) {
1892 struct bus_container *c, *w;
1893 uint32_t *array_size = NULL;
1895 size_t before, begin = 0;
1896 bool need_offsets = false;
1899 assert_return(m, -EINVAL);
1900 assert_return(!m->sealed, -EPERM);
1901 assert_return(contents, -EINVAL);
1902 assert_return(!m->poisoned, -ESTALE);
1904 /* Make sure we have space for one more container */
1905 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1910 c = message_get_container(m);
1912 signature = strdup(contents);
1918 /* Save old index in the parent container, in case we have to
1919 * abort this container */
1920 c->saved_index = c->index;
1921 before = m->header->body_size;
1923 if (type == SD_BUS_TYPE_ARRAY)
1924 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1925 else if (type == SD_BUS_TYPE_VARIANT)
1926 r = bus_message_open_variant(m, c, contents);
1927 else if (type == SD_BUS_TYPE_STRUCT)
1928 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1929 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1930 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1939 /* OK, let's fill it in */
1940 w = m->containers + m->n_containers++;
1941 w->enclosing = type;
1942 w->signature = signature;
1944 w->array_size = array_size;
1947 w->n_offsets = w->offsets_allocated = 0;
1949 w->need_offsets = need_offsets;
1954 static size_t determine_word_size(size_t sz, size_t extra) {
1955 if (sz + extra <= 0xFF)
1957 else if (sz + extra*2 <= 0xFFFF)
1959 else if (sz + extra*4 <= 0xFFFFFFFF)
1965 static size_t read_word_le(void *p, size_t sz) {
1975 return *(uint8_t*) p;
1980 return le16toh(x.u16);
1982 return le32toh(x.u32);
1984 return le64toh(x.u64);
1986 assert_not_reached("unknown word width");
1989 static void write_word_le(void *p, size_t sz, size_t value) {
1997 assert(sz == 8 || (value < (1ULL << (sz*8))));
2000 *(uint8_t*) p = value;
2003 x.u16 = htole16((uint16_t) value);
2005 x.u32 = htole32((uint32_t) value);
2007 x.u64 = htole64((uint64_t) value);
2009 assert_not_reached("unknown word width");
2014 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2019 if (!BUS_MESSAGE_IS_GVARIANT(m))
2022 if (c->need_offsets) {
2023 size_t payload, sz, i;
2026 /* Variable-width arrays */
2028 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2029 sz = determine_word_size(payload, c->n_offsets);
2031 a = message_extend_body(m, 1, sz * c->n_offsets, true);
2035 for (i = 0; i < c->n_offsets; i++)
2036 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2040 /* Fixed-width or empty arrays */
2042 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
2050 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2057 if (!BUS_MESSAGE_IS_GVARIANT(m))
2060 l = strlen(c->signature);
2062 a = message_extend_body(m, 1, 1 + l, true);
2067 memcpy(a+1, c->signature, l);
2072 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2073 size_t n_variable = 0;
2082 if (!BUS_MESSAGE_IS_GVARIANT(m))
2085 p = strempty(c->signature);
2089 r = signature_element_length(p, &n);
2098 r = bus_gvariant_is_fixed_size(t);
2103 assert(!c->need_offsets || i <= c->n_offsets);
2105 /* We need to add an offset for each item that has a
2106 * variable size and that is not the last one in the
2108 if (r == 0 && p[n] != 0)
2115 assert(!c->need_offsets || i == c->n_offsets);
2116 assert(c->need_offsets || n_variable == 0);
2118 if (n_variable <= 0) {
2119 a = message_extend_body(m, 1, 0, add_offset);
2126 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2128 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2130 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2134 p = strempty(c->signature);
2135 for (i = 0, j = 0; i < c->n_offsets; i++) {
2139 r = signature_element_length(p, &n);
2150 r = bus_gvariant_is_fixed_size(t);
2153 if (r > 0 || p[0] == 0)
2157 k = n_variable - 1 - j;
2159 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2168 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2169 struct bus_container *c;
2172 assert_return(m, -EINVAL);
2173 assert_return(!m->sealed, -EPERM);
2174 assert_return(m->n_containers > 0, -EINVAL);
2175 assert_return(!m->poisoned, -ESTALE);
2177 c = message_get_container(m);
2179 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2180 if (c->signature && c->signature[c->index] != 0)
2185 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2186 r = bus_message_close_array(m, c);
2187 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2188 r = bus_message_close_variant(m, c);
2189 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2190 r = bus_message_close_struct(m, c, true);
2192 assert_not_reached("Unknown container type");
2206 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2213 stack[*i].types = types;
2214 stack[*i].n_struct = n_struct;
2215 stack[*i].n_array = n_array;
2221 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2232 *types = stack[*i].types;
2233 *n_struct = stack[*i].n_struct;
2234 *n_array = stack[*i].n_array;
2239 int bus_message_append_ap(
2244 unsigned n_array, n_struct;
2245 TypeStack stack[BUS_CONTAINER_DEPTH];
2246 unsigned stack_ptr = 0;
2254 n_array = (unsigned) -1;
2255 n_struct = strlen(types);
2260 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2261 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2267 r = sd_bus_message_close_container(m);
2275 if (n_array != (unsigned) -1)
2284 case SD_BUS_TYPE_BYTE: {
2287 x = (uint8_t) va_arg(ap, int);
2288 r = sd_bus_message_append_basic(m, *t, &x);
2292 case SD_BUS_TYPE_BOOLEAN:
2293 case SD_BUS_TYPE_INT32:
2294 case SD_BUS_TYPE_UINT32:
2295 case SD_BUS_TYPE_UNIX_FD: {
2298 /* We assume a boolean is the same as int32_t */
2299 assert_cc(sizeof(int32_t) == sizeof(int));
2301 x = va_arg(ap, uint32_t);
2302 r = sd_bus_message_append_basic(m, *t, &x);
2306 case SD_BUS_TYPE_INT16:
2307 case SD_BUS_TYPE_UINT16: {
2310 x = (uint16_t) va_arg(ap, int);
2311 r = sd_bus_message_append_basic(m, *t, &x);
2315 case SD_BUS_TYPE_INT64:
2316 case SD_BUS_TYPE_UINT64:
2317 case SD_BUS_TYPE_DOUBLE: {
2320 x = va_arg(ap, uint64_t);
2321 r = sd_bus_message_append_basic(m, *t, &x);
2325 case SD_BUS_TYPE_STRING:
2326 case SD_BUS_TYPE_OBJECT_PATH:
2327 case SD_BUS_TYPE_SIGNATURE: {
2330 x = va_arg(ap, const char*);
2331 r = sd_bus_message_append_basic(m, *t, x);
2335 case SD_BUS_TYPE_ARRAY: {
2338 r = signature_element_length(t + 1, &k);
2344 memcpy(s, t + 1, k);
2347 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2352 if (n_array == (unsigned) -1) {
2357 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2363 n_array = va_arg(ap, unsigned);
2368 case SD_BUS_TYPE_VARIANT: {
2371 s = va_arg(ap, const char*);
2375 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2379 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2384 n_struct = strlen(s);
2385 n_array = (unsigned) -1;
2390 case SD_BUS_TYPE_STRUCT_BEGIN:
2391 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2394 r = signature_element_length(t, &k);
2401 memcpy(s, t + 1, k - 2);
2404 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2409 if (n_array == (unsigned) -1) {
2414 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2420 n_array = (unsigned) -1;
2436 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2440 assert_return(m, -EINVAL);
2441 assert_return(types, -EINVAL);
2442 assert_return(!m->sealed, -EPERM);
2443 assert_return(!m->poisoned, -ESTALE);
2445 va_start(ap, types);
2446 r = bus_message_append_ap(m, types, ap);
2452 _public_ int sd_bus_message_append_array_space(
2462 assert_return(m, -EINVAL);
2463 assert_return(!m->sealed, -EPERM);
2464 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2465 assert_return(ptr || size == 0, -EINVAL);
2466 assert_return(!m->poisoned, -ESTALE);
2468 /* alignment and size of the trivial types (except bool) is
2469 * identical for gvariant and dbus1 marshalling */
2470 align = bus_type_get_alignment(type);
2471 sz = bus_type_get_size(type);
2473 assert_se(align > 0);
2479 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2483 a = message_extend_body(m, align, size, false);
2487 r = sd_bus_message_close_container(m);
2495 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2502 assert_return(m, -EINVAL);
2503 assert_return(!m->sealed, -EPERM);
2504 assert_return(bus_type_is_trivial(type), -EINVAL);
2505 assert_return(ptr || size == 0, -EINVAL);
2506 assert_return(!m->poisoned, -ESTALE);
2508 r = sd_bus_message_append_array_space(m, type, size, &p);
2513 memcpy(p, ptr, size);
2518 _public_ int sd_bus_message_append_array_iovec(
2521 const struct iovec *iov,
2529 assert_return(m, -EINVAL);
2530 assert_return(!m->sealed, -EPERM);
2531 assert_return(bus_type_is_trivial(type), -EINVAL);
2532 assert_return(iov || n == 0, -EINVAL);
2533 assert_return(!m->poisoned, -ESTALE);
2535 size = IOVEC_TOTAL_SIZE(iov, n);
2537 r = sd_bus_message_append_array_space(m, type, size, &p);
2541 for (i = 0; i < n; i++) {
2543 if (iov[i].iov_base)
2544 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2546 memzero(p, iov[i].iov_len);
2548 p = (uint8_t*) p + iov[i].iov_len;
2554 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2557 _cleanup_close_ int copy_fd = -1;
2558 struct bus_body_part *part;
2570 if (!bus_type_is_trivial(type))
2575 r = memfd_set_sealed(memfd);
2579 copy_fd = dup(memfd);
2583 r = memfd_get_size(memfd, &size);
2587 align = bus_type_get_alignment(type);
2588 sz = bus_type_get_size(type);
2590 assert_se(align > 0);
2596 if (size > (uint64_t) (uint32_t) -1)
2599 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2603 a = message_extend_body(m, align, 0, false);
2607 part = message_append_part(m);
2611 part->memfd = copy_fd;
2612 part->sealed = true;
2616 m->header->body_size += size;
2617 message_extend_containers(m, size);
2619 return sd_bus_message_close_container(m);
2622 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) {
2623 _cleanup_close_ int copy_fd = -1;
2624 struct bus_body_part *part;
2625 struct bus_container *c;
2630 assert_return(m, -EINVAL);
2631 assert_return(memfd >= 0, -EINVAL);
2632 assert_return(!m->sealed, -EPERM);
2633 assert_return(!m->poisoned, -ESTALE);
2635 r = memfd_set_sealed(memfd);
2639 copy_fd = dup(memfd);
2643 r = memfd_get_size(memfd, &size);
2647 /* We require this to be NUL terminated */
2651 if (size > (uint64_t) (uint32_t) -1)
2654 c = message_get_container(m);
2655 if (c->signature && c->signature[c->index]) {
2656 /* Container signature is already set */
2658 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2663 /* Maybe we can append to the signature? But only if this is the top-level container*/
2664 if (c->enclosing != 0)
2667 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2674 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2675 a = message_extend_body(m, 4, 4, false);
2679 *(uint32_t*) a = size - 1;
2682 part = message_append_part(m);
2686 part->memfd = copy_fd;
2687 part->sealed = true;
2691 m->header->body_size += size;
2692 message_extend_containers(m, size);
2694 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2695 r = message_add_offset(m, m->header->body_size);
2702 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2708 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2712 assert_return(m, -EINVAL);
2713 assert_return(!m->sealed, -EPERM);
2714 assert_return(!m->poisoned, -ESTALE);
2716 r = sd_bus_message_open_container(m, 'a', "s");
2720 STRV_FOREACH(i, l) {
2721 r = sd_bus_message_append_basic(m, 's', *i);
2726 return sd_bus_message_close_container(m);
2729 static int bus_message_close_header(sd_bus_message *m) {
2735 if (!BUS_MESSAGE_IS_GVARIANT(m))
2738 if (m->n_header_offsets < 1)
2741 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2743 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2745 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2749 for (i = 0; i < m->n_header_offsets; i++)
2750 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2755 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2756 struct bus_body_part *part;
2766 if (m->n_containers > 0)
2772 /* In vtables the return signature of method calls is listed,
2773 * let's check if they match if this is a response */
2774 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2775 m->enforced_reply_signature &&
2776 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2779 /* If gvariant marshalling is used we need to close the body structure */
2780 r = bus_message_close_struct(m, &m->root_container, false);
2784 /* If there's a non-trivial signature set, then add it in here */
2785 if (!isempty(m->root_container.signature)) {
2786 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2792 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2797 r = bus_message_close_header(m);
2801 m->header->serial = (uint32_t) cookie;
2802 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2804 /* Add padding at the end of the fields part, since we know
2805 * the body needs to start at an 8 byte alignment. We made
2806 * sure we allocated enough space for this, so all we need to
2807 * do here is to zero it out. */
2808 l = BUS_MESSAGE_FIELDS_SIZE(m);
2811 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, a);
2813 /* If this is something we can send as memfd, then let's seal
2814 the memfd now. Note that we can send memfds as payload only
2815 for directed messages, and not for broadcasts. */
2816 if (m->destination && m->bus->use_memfd) {
2817 MESSAGE_FOREACH_PART(part, i, m)
2818 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2821 /* Try to seal it if that makes
2822 * sense. First, unmap our own map to
2823 * make sure we don't keep it busy. */
2824 bus_body_part_unmap(part);
2826 /* Then, sync up real memfd size */
2828 r = memfd_set_size(part->memfd, sz);
2832 /* Finally, try to seal */
2833 if (memfd_set_sealed(part->memfd) >= 0)
2834 part->sealed = true;
2838 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2839 m->root_container.index = 0;
2840 m->root_container.offset_index = 0;
2841 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2848 int bus_body_part_map(struct bus_body_part *part) {
2857 if (part->size <= 0)
2860 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2861 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2862 static const uint8_t zeroes[7] = { };
2863 part->data = (void*) zeroes;
2867 psz = PAGE_ALIGN(part->size);
2869 if (part->memfd >= 0)
2870 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, 0);
2871 else if (part->is_zero)
2872 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2876 if (p == MAP_FAILED)
2881 part->munmap_this = true;
2886 void bus_body_part_unmap(struct bus_body_part *part) {
2890 if (part->memfd < 0)
2896 if (!part->munmap_this)
2899 assert_se(munmap(part->data, part->mapped) == 0);
2903 part->munmap_this = false;
2908 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2909 size_t k, start, end;
2914 start = ALIGN_TO((size_t) *rindex, align);
2915 end = start + nbytes;
2920 /* Verify that padding is 0 */
2921 for (k = *rindex; k < start; k++)
2922 if (((const uint8_t*) p)[k] != 0)
2926 *r = (uint8_t*) p + start;
2933 static bool message_end_of_signature(sd_bus_message *m) {
2934 struct bus_container *c;
2938 c = message_get_container(m);
2939 return !c->signature || c->signature[c->index] == 0;
2942 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2943 struct bus_container *c;
2947 c = message_get_container(m);
2948 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2951 if (BUS_MESSAGE_IS_GVARIANT(m))
2952 return index >= c->end;
2954 assert(c->array_size);
2955 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2959 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2960 assert_return(m, -EINVAL);
2961 assert_return(m->sealed, -EPERM);
2963 if (complete && m->n_containers > 0)
2966 if (message_end_of_signature(m))
2969 if (message_end_of_array(m, m->rindex))
2975 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2976 struct bus_body_part *part;
2982 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2983 part = m->cached_rindex_part;
2984 begin = m->cached_rindex_part_begin;
2994 if (index + sz <= begin + part->size) {
2996 r = bus_body_part_map(part);
3001 *p = (uint8_t*) part->data + index - begin;
3003 m->cached_rindex_part = part;
3004 m->cached_rindex_part_begin = begin;
3009 begin += part->size;
3016 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3023 if (!BUS_MESSAGE_IS_GVARIANT(m))
3026 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3029 sz = bus_gvariant_get_size(c->signature);
3033 if (c->offset_index+1 >= c->n_offsets)
3036 /* Variable-size array */
3038 alignment = bus_gvariant_get_alignment(c->signature);
3039 assert(alignment > 0);
3041 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3042 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3045 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3048 /* Fixed-size array */
3049 *rindex = c->begin + (c->offset_index+1) * sz;
3055 } else if (c->enclosing == 0 ||
3056 c->enclosing == SD_BUS_TYPE_STRUCT ||
3057 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3062 if (c->offset_index+1 >= c->n_offsets)
3065 r = signature_element_length(c->signature + c->index, &n);
3069 r = signature_element_length(c->signature + c->index + n, &j);
3074 memcpy(t, c->signature + c->index + n, j);
3077 alignment = bus_gvariant_get_alignment(t);
3080 assert(alignment > 0);
3082 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3083 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3087 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3090 assert_not_reached("Unknown container type");
3095 /* Reached the end */
3102 static int message_peek_body(
3109 size_t k, start, end, padding;
3110 struct bus_body_part *part;
3117 start = ALIGN_TO((size_t) *rindex, align);
3118 padding = start - *rindex;
3119 end = start + nbytes;
3121 if (end > BUS_MESSAGE_BODY_SIZE(m))
3124 part = find_part(m, *rindex, padding, (void**) &q);
3129 /* Verify padding */
3130 for (k = 0; k < padding; k++)
3135 part = find_part(m, start, nbytes, (void**) &q);
3136 if (!part || (nbytes > 0 && !q))
3147 static bool validate_nul(const char *s, size_t l) {
3149 /* Check for NUL chars in the string */
3150 if (memchr(s, 0, l))
3153 /* Check for NUL termination */
3160 static bool validate_string(const char *s, size_t l) {
3162 if (!validate_nul(s, l))
3165 /* Check if valid UTF8 */
3166 if (!utf8_is_valid(s))
3172 static bool validate_signature(const char *s, size_t l) {
3174 if (!validate_nul(s, l))
3177 /* Check if valid signature */
3178 if (!signature_is_valid(s, true))
3184 static bool validate_object_path(const char *s, size_t l) {
3186 if (!validate_nul(s, l))
3189 if (!object_path_is_valid(s))
3195 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3196 struct bus_container *c;
3201 assert_return(m, -EINVAL);
3202 assert_return(m->sealed, -EPERM);
3203 assert_return(bus_type_is_basic(type), -EINVAL);
3205 if (message_end_of_signature(m))
3208 if (message_end_of_array(m, m->rindex))
3211 c = message_get_container(m);
3212 if (c->signature[c->index] != type)
3217 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3219 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3222 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3226 if (type == SD_BUS_TYPE_STRING)
3227 ok = validate_string(q, c->item_size-1);
3228 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3229 ok = validate_object_path(q, c->item_size-1);
3231 ok = validate_signature(q, c->item_size-1);
3237 *(const char**) p = q;
3241 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3243 if ((size_t) sz != c->item_size)
3246 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3249 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3255 case SD_BUS_TYPE_BYTE:
3257 *(uint8_t*) p = *(uint8_t*) q;
3260 case SD_BUS_TYPE_BOOLEAN:
3262 *(int*) p = !!*(uint8_t*) q;
3265 case SD_BUS_TYPE_INT16:
3266 case SD_BUS_TYPE_UINT16:
3268 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3271 case SD_BUS_TYPE_INT32:
3272 case SD_BUS_TYPE_UINT32:
3274 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3277 case SD_BUS_TYPE_INT64:
3278 case SD_BUS_TYPE_UINT64:
3279 case SD_BUS_TYPE_DOUBLE:
3281 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3284 case SD_BUS_TYPE_UNIX_FD: {
3287 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3292 *(int*) p = m->fds[j];
3298 assert_not_reached("unexpected type");
3302 r = container_next_item(m, c, &rindex);
3309 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3313 r = message_peek_body(m, &rindex, 4, 4, &q);
3317 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3318 r = message_peek_body(m, &rindex, 1, l+1, &q);
3322 if (type == SD_BUS_TYPE_OBJECT_PATH)
3323 ok = validate_object_path(q, l);
3325 ok = validate_string(q, l);
3330 *(const char**) p = q;
3332 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3335 r = message_peek_body(m, &rindex, 1, 1, &q);
3340 r = message_peek_body(m, &rindex, 1, l+1, &q);
3344 if (!validate_signature(q, l))
3348 *(const char**) p = q;
3353 align = bus_type_get_alignment(type);
3356 sz = bus_type_get_size(type);
3359 r = message_peek_body(m, &rindex, align, sz, &q);
3365 case SD_BUS_TYPE_BYTE:
3367 *(uint8_t*) p = *(uint8_t*) q;
3370 case SD_BUS_TYPE_BOOLEAN:
3372 *(int*) p = !!*(uint32_t*) q;
3375 case SD_BUS_TYPE_INT16:
3376 case SD_BUS_TYPE_UINT16:
3378 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3381 case SD_BUS_TYPE_INT32:
3382 case SD_BUS_TYPE_UINT32:
3384 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3387 case SD_BUS_TYPE_INT64:
3388 case SD_BUS_TYPE_UINT64:
3389 case SD_BUS_TYPE_DOUBLE:
3391 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3394 case SD_BUS_TYPE_UNIX_FD: {
3397 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3402 *(int*) p = m->fds[j];
3407 assert_not_reached("Unknown basic type...");
3414 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3420 static int bus_message_enter_array(
3422 struct bus_container *c,
3423 const char *contents,
3424 uint32_t **array_size,
3427 size_t *n_offsets) {
3441 if (!signature_is_single(contents, true))
3444 if (!c->signature || c->signature[c->index] == 0)
3447 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3450 if (!startswith(c->signature + c->index + 1, contents))
3455 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3458 r = message_peek_body(m, &rindex, 4, 4, &q);
3462 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3465 alignment = bus_type_get_alignment(contents[0]);
3469 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3473 *array_size = (uint32_t*) q;
3475 } else if (c->item_size <= 0) {
3477 /* gvariant: empty array */
3482 } else if (bus_gvariant_is_fixed_size(contents)) {
3484 /* gvariant: fixed length array */
3485 *item_size = bus_gvariant_get_size(contents);
3490 size_t where, p = 0, framing, sz;
3493 /* gvariant: variable length array */
3494 sz = determine_word_size(c->item_size, 0);
3496 where = rindex + c->item_size - sz;
3497 r = message_peek_body(m, &where, 1, sz, &q);
3501 framing = read_word_le(q, sz);
3502 if (framing > c->item_size - sz)
3504 if ((c->item_size - framing) % sz != 0)
3507 *n_offsets = (c->item_size - framing) / sz;
3509 where = rindex + framing;
3510 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3514 *offsets = new(size_t, *n_offsets);
3518 for (i = 0; i < *n_offsets; i++) {
3521 x = read_word_le((uint8_t*) q + i * sz, sz);
3522 if (x > c->item_size - sz)
3527 (*offsets)[i] = rindex + x;
3531 *item_size = (*offsets)[0] - rindex;
3536 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3537 c->index += 1 + strlen(contents);
3542 static int bus_message_enter_variant(
3544 struct bus_container *c,
3545 const char *contents,
3546 size_t *item_size) {
3558 if (!signature_is_single(contents, false))
3561 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3564 if (!c->signature || c->signature[c->index] == 0)
3567 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3572 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3575 k = strlen(contents);
3576 if (1+k > c->item_size)
3579 where = rindex + c->item_size - (1+k);
3580 r = message_peek_body(m, &where, 1, 1+k, &q);
3584 if (*(char*) q != 0)
3587 if (memcmp((uint8_t*) q+1, contents, k))
3590 *item_size = c->item_size - (1+k);
3593 r = message_peek_body(m, &rindex, 1, 1, &q);
3598 r = message_peek_body(m, &rindex, 1, l+1, &q);
3602 if (!validate_signature(q, l))
3605 if (!streq(q, contents))
3611 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3617 static int build_struct_offsets(
3619 const char *signature,
3623 size_t *n_offsets) {
3625 unsigned n_variable = 0, n_total = 0, v;
3626 size_t previous = 0, where;
3637 if (isempty(signature)) {
3644 sz = determine_word_size(size, 0);
3648 /* First, loop over signature and count variable elements and
3649 * elements in general. We use this to know how large the
3650 * offset array is at the end of the structure. Note that
3651 * GVariant only stores offsets for all variable size elements
3652 * that are not the last item. */
3658 r = signature_element_length(p, &n);
3667 r = bus_gvariant_is_fixed_size(t);
3672 if (r == 0 && p[n] != 0) /* except the last item */
3679 if (size < n_variable * sz)
3682 where = m->rindex + size - (n_variable * sz);
3683 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3689 *offsets = new(size_t, n_total);
3695 /* Second, loop again and build an offset table */
3701 r = signature_element_length(p, &n);
3710 k = bus_gvariant_get_size(t);
3718 x = read_word_le((uint8_t*) q + v*sz, sz);
3721 if (m->rindex + x < previous)
3724 /* The last item's end
3725 * is determined from
3728 x = size - (n_variable * sz);
3730 offset = m->rindex + x;
3736 align = bus_gvariant_get_alignment(t);
3739 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3743 previous = (*offsets)[(*n_offsets)++] = offset;
3748 assert(*n_offsets == n_total);
3750 *item_size = (*offsets)[0] - m->rindex;
3754 static int enter_struct_or_dict_entry(
3756 struct bus_container *c,
3757 const char *contents,
3760 size_t *n_offsets) {
3771 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3774 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3778 } else if (c->item_size <= 0) {
3780 /* gvariant empty struct */
3785 /* gvariant with contents */
3786 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3791 static int bus_message_enter_struct(
3793 struct bus_container *c,
3794 const char *contents,
3797 size_t *n_offsets) {
3809 if (!signature_is_valid(contents, false))
3812 if (!c->signature || c->signature[c->index] == 0)
3815 l = strlen(contents);
3817 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3818 !startswith(c->signature + c->index + 1, contents) ||
3819 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3822 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3826 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3827 c->index += 1 + l + 1;
3832 static int bus_message_enter_dict_entry(
3834 struct bus_container *c,
3835 const char *contents,
3838 size_t *n_offsets) {
3847 if (!signature_is_pair(contents))
3850 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3853 if (!c->signature || c->signature[c->index] == 0)
3856 l = strlen(contents);
3858 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3859 !startswith(c->signature + c->index + 1, contents) ||
3860 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3863 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3867 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3868 c->index += 1 + l + 1;
3873 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3875 const char *contents) {
3876 struct bus_container *c, *w;
3877 uint32_t *array_size = NULL;
3880 size_t *offsets = NULL;
3881 size_t n_offsets = 0, item_size = 0;
3884 assert_return(m, -EINVAL);
3885 assert_return(m->sealed, -EPERM);
3886 assert_return(type != 0 || !contents, -EINVAL);
3888 if (type == 0 || !contents) {
3892 /* Allow entering into anonymous containers */
3893 r = sd_bus_message_peek_type(m, &tt, &cc);
3897 if (type != 0 && type != tt)
3900 if (contents && !streq(contents, cc))
3908 * We enforce a global limit on container depth, that is much
3909 * higher than the 32 structs and 32 arrays the specification
3910 * mandates. This is simpler to implement for us, and we need
3911 * this only to ensure our container array doesn't grow
3912 * without bounds. We are happy to return any data from a
3913 * message as long as the data itself is valid, even if the
3914 * overall message might be not.
3916 * Note that the message signature is validated when
3917 * parsing the headers, and that validation does check the
3920 * Note that the specification defines no limits on the depth
3921 * of stacked variants, but we do.
3923 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3926 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3929 if (message_end_of_signature(m))
3932 if (message_end_of_array(m, m->rindex))
3935 c = message_get_container(m);
3937 signature = strdup(contents);
3941 c->saved_index = c->index;
3944 if (type == SD_BUS_TYPE_ARRAY)
3945 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3946 else if (type == SD_BUS_TYPE_VARIANT)
3947 r = bus_message_enter_variant(m, c, contents, &item_size);
3948 else if (type == SD_BUS_TYPE_STRUCT)
3949 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3950 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3951 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3961 /* OK, let's fill it in */
3962 w = m->containers + m->n_containers++;
3963 w->enclosing = type;
3964 w->signature = signature;
3965 w->peeked_signature = NULL;
3969 w->begin = m->rindex;
3970 w->end = m->rindex + c->item_size;
3972 w->array_size = array_size;
3973 w->item_size = item_size;
3974 w->offsets = offsets;
3975 w->n_offsets = n_offsets;
3976 w->offset_index = 0;
3981 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3982 struct bus_container *c;
3986 assert_return(m, -EINVAL);
3987 assert_return(m->sealed, -EPERM);
3988 assert_return(m->n_containers > 0, -ENXIO);
3990 c = message_get_container(m);
3992 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3993 if (c->signature && c->signature[c->index] != 0)
3997 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3998 if (m->rindex < c->end)
4001 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4004 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4005 if (c->begin + l != m->rindex)
4010 free(c->peeked_signature);
4014 c = message_get_container(m);
4017 c->index = c->saved_index;
4018 r = container_next_item(m, c, &m->rindex);
4026 static void message_quit_container(sd_bus_message *m) {
4027 struct bus_container *c;
4031 assert(m->n_containers > 0);
4033 c = message_get_container(m);
4036 assert(m->rindex >= c->before);
4037 m->rindex = c->before;
4039 /* Free container */
4044 /* Correct index of new top-level container */
4045 c = message_get_container(m);
4046 c->index = c->saved_index;
4049 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4050 struct bus_container *c;
4053 assert_return(m, -EINVAL);
4054 assert_return(m->sealed, -EPERM);
4056 if (message_end_of_signature(m))
4059 if (message_end_of_array(m, m->rindex))
4062 c = message_get_container(m);
4064 if (bus_type_is_basic(c->signature[c->index])) {
4068 *type = c->signature[c->index];
4072 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4078 r = signature_element_length(c->signature+c->index+1, &l);
4084 sig = strndup(c->signature + c->index + 1, l);
4088 free(c->peeked_signature);
4089 *contents = c->peeked_signature = sig;
4093 *type = SD_BUS_TYPE_ARRAY;
4098 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4099 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4105 r = signature_element_length(c->signature+c->index, &l);
4110 sig = strndup(c->signature + c->index + 1, l - 2);
4114 free(c->peeked_signature);
4115 *contents = c->peeked_signature = sig;
4119 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4124 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4128 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4131 if (c->item_size < 2)
4134 /* Look for the NUL delimiter that
4135 separates the payload from the
4136 signature. Since the body might be
4137 in a different part that then the
4138 signature we map byte by byte. */
4140 for (k = 2; k <= c->item_size; k++) {
4143 where = m->rindex + c->item_size - k;
4144 r = message_peek_body(m, &where, 1, k, &q);
4148 if (*(char*) q == 0)
4152 if (k > c->item_size)
4155 free(c->peeked_signature);
4156 c->peeked_signature = strndup((char*) q + 1, k - 1);
4157 if (!c->peeked_signature)
4160 if (!signature_is_valid(c->peeked_signature, true))
4163 *contents = c->peeked_signature;
4168 r = message_peek_body(m, &rindex, 1, 1, &q);
4173 r = message_peek_body(m, &rindex, 1, l+1, &q);
4177 if (!validate_signature(q, l))
4185 *type = SD_BUS_TYPE_VARIANT;
4200 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4201 struct bus_container *c;
4203 assert_return(m, -EINVAL);
4204 assert_return(m->sealed, -EPERM);
4207 message_reset_containers(m);
4210 c = message_get_container(m);
4212 c = message_get_container(m);
4214 c->offset_index = 0;
4216 m->rindex = c->begin;
4219 c->offset_index = 0;
4220 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4222 return !isempty(c->signature);
4225 static int message_read_ap(
4230 unsigned n_array, n_struct;
4231 TypeStack stack[BUS_CONTAINER_DEPTH];
4232 unsigned stack_ptr = 0;
4233 unsigned n_loop = 0;
4241 /* Ideally, we'd just call ourselves recursively on every
4242 * complex type. However, the state of a va_list that is
4243 * passed to a function is undefined after that function
4244 * returns. This means we need to docode the va_list linearly
4245 * in a single stackframe. We hence implement our own
4246 * home-grown stack in an array. */
4248 n_array = (unsigned) -1; /* length of current array entries */
4249 n_struct = strlen(types); /* length of current struct contents signature */
4256 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4257 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4263 r = sd_bus_message_exit_container(m);
4271 if (n_array != (unsigned) -1)
4280 case SD_BUS_TYPE_BYTE:
4281 case SD_BUS_TYPE_BOOLEAN:
4282 case SD_BUS_TYPE_INT16:
4283 case SD_BUS_TYPE_UINT16:
4284 case SD_BUS_TYPE_INT32:
4285 case SD_BUS_TYPE_UINT32:
4286 case SD_BUS_TYPE_INT64:
4287 case SD_BUS_TYPE_UINT64:
4288 case SD_BUS_TYPE_DOUBLE:
4289 case SD_BUS_TYPE_STRING:
4290 case SD_BUS_TYPE_OBJECT_PATH:
4291 case SD_BUS_TYPE_SIGNATURE:
4292 case SD_BUS_TYPE_UNIX_FD: {
4295 p = va_arg(ap, void*);
4296 r = sd_bus_message_read_basic(m, *t, p);
4309 case SD_BUS_TYPE_ARRAY: {
4312 r = signature_element_length(t + 1, &k);
4318 memcpy(s, t + 1, k);
4321 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4332 if (n_array == (unsigned) -1) {
4337 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4343 n_array = va_arg(ap, unsigned);
4348 case SD_BUS_TYPE_VARIANT: {
4351 s = va_arg(ap, const char *);
4355 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4365 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4370 n_struct = strlen(s);
4371 n_array = (unsigned) -1;
4376 case SD_BUS_TYPE_STRUCT_BEGIN:
4377 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4380 r = signature_element_length(t, &k);
4386 memcpy(s, t + 1, k - 2);
4389 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4399 if (n_array == (unsigned) -1) {
4404 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4410 n_array = (unsigned) -1;
4423 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4427 assert_return(m, -EINVAL);
4428 assert_return(m->sealed, -EPERM);
4429 assert_return(types, -EINVAL);
4431 va_start(ap, types);
4432 r = message_read_ap(m, types, ap);
4438 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4441 assert_return(m, -EINVAL);
4442 assert_return(m->sealed, -EPERM);
4443 assert_return(types, -EINVAL);
4450 case SD_BUS_TYPE_BYTE:
4451 case SD_BUS_TYPE_BOOLEAN:
4452 case SD_BUS_TYPE_INT16:
4453 case SD_BUS_TYPE_UINT16:
4454 case SD_BUS_TYPE_INT32:
4455 case SD_BUS_TYPE_UINT32:
4456 case SD_BUS_TYPE_INT64:
4457 case SD_BUS_TYPE_UINT64:
4458 case SD_BUS_TYPE_DOUBLE:
4459 case SD_BUS_TYPE_STRING:
4460 case SD_BUS_TYPE_OBJECT_PATH:
4461 case SD_BUS_TYPE_SIGNATURE:
4462 case SD_BUS_TYPE_UNIX_FD:
4464 r = sd_bus_message_read_basic(m, *types, NULL);
4468 r = sd_bus_message_skip(m, types + 1);
4474 case SD_BUS_TYPE_ARRAY: {
4477 r = signature_element_length(types + 1, &k);
4483 memcpy(s, types+1, k);
4486 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4491 r = sd_bus_message_skip(m, s);
4498 r = sd_bus_message_exit_container(m);
4503 r = sd_bus_message_skip(m, types + 1 + k);
4510 case SD_BUS_TYPE_VARIANT: {
4511 const char *contents;
4514 r = sd_bus_message_peek_type(m, &x, &contents);
4518 if (x != SD_BUS_TYPE_VARIANT)
4521 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4525 r = sd_bus_message_skip(m, contents);
4530 r = sd_bus_message_exit_container(m);
4534 r = sd_bus_message_skip(m, types + 1);
4541 case SD_BUS_TYPE_STRUCT_BEGIN:
4542 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4545 r = signature_element_length(types, &k);
4551 memcpy(s, types+1, k-2);
4554 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4558 r = sd_bus_message_skip(m, s);
4563 r = sd_bus_message_exit_container(m);
4568 r = sd_bus_message_skip(m, types + k);
4580 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4584 struct bus_container *c;
4590 assert_return(m, -EINVAL);
4591 assert_return(m->sealed, -EPERM);
4592 assert_return(bus_type_is_trivial(type), -EINVAL);
4593 assert_return(ptr, -EINVAL);
4594 assert_return(size, -EINVAL);
4595 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4597 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4601 c = message_get_container(m);
4603 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4604 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4608 sz = c->end - c->begin;
4610 align = bus_type_get_alignment(type);
4614 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4618 /* Zero length array, let's return some aligned
4619 * pointer that is not NULL */
4620 p = (uint8_t*) NULL + align;
4622 r = message_peek_body(m, &m->rindex, align, sz, &p);
4627 r = sd_bus_message_exit_container(m);
4631 *ptr = (const void*) p;
4637 message_quit_container(m);
4641 static int message_peek_fields(
4652 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4655 static int message_peek_field_uint32(
4667 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4670 /* identical for gvariant and dbus1 */
4672 r = message_peek_fields(m, ri, 4, 4, &q);
4677 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4682 static int message_peek_field_string(
4684 bool (*validate)(const char *p),
4696 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4701 r = message_peek_fields(m, ri, 1, item_size, &q);
4707 r = message_peek_field_uint32(m, ri, 4, &l);
4711 r = message_peek_fields(m, ri, 1, l+1, &q);
4717 if (!validate_nul(q, l))
4723 if (!validate_string(q, l))
4733 static int message_peek_field_signature(
4746 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4751 r = message_peek_fields(m, ri, 1, item_size, &q);
4757 r = message_peek_fields(m, ri, 1, 1, &q);
4762 r = message_peek_fields(m, ri, 1, l+1, &q);
4767 if (!validate_signature(q, l))
4776 static int message_skip_fields(
4779 uint32_t array_size,
4780 const char **signature) {
4782 size_t original_index;
4788 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4790 original_index = *ri;
4796 if (array_size != (uint32_t) -1 &&
4797 array_size <= *ri - original_index)
4804 if (t == SD_BUS_TYPE_STRING) {
4806 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4812 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4814 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4820 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4822 r = message_peek_field_signature(m, ri, 0, NULL);
4828 } else if (bus_type_is_basic(t)) {
4831 align = bus_type_get_alignment(t);
4832 k = bus_type_get_size(t);
4833 assert(align > 0 && k > 0);
4835 r = message_peek_fields(m, ri, align, k, NULL);
4841 } else if (t == SD_BUS_TYPE_ARRAY) {
4843 r = signature_element_length(*signature+1, &l);
4853 strncpy(sig, *signature + 1, l-1);
4856 alignment = bus_type_get_alignment(sig[0]);
4860 r = message_peek_field_uint32(m, ri, 0, &nas);
4863 if (nas > BUS_ARRAY_MAX_SIZE)
4866 r = message_peek_fields(m, ri, alignment, 0, NULL);
4870 r = message_skip_fields(m, ri, nas, (const char**) &s);
4875 (*signature) += 1 + l;
4877 } else if (t == SD_BUS_TYPE_VARIANT) {
4880 r = message_peek_field_signature(m, ri, 0, &s);
4884 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4890 } else if (t == SD_BUS_TYPE_STRUCT ||
4891 t == SD_BUS_TYPE_DICT_ENTRY) {
4893 r = signature_element_length(*signature, &l);
4900 strncpy(sig, *signature + 1, l-1);
4903 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4914 int bus_message_parse_fields(sd_bus_message *m) {
4917 uint32_t unix_fds = 0;
4918 bool unix_fds_set = false;
4919 void *offsets = NULL;
4920 unsigned n_offsets = 0;
4926 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4929 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4933 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4934 r = message_peek_fields(m, &ri, 1, sz, &q);
4938 framing = read_word_le(q, sz);
4939 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4941 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4945 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4949 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4954 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4955 _cleanup_free_ char *sig = NULL;
4956 const char *signature;
4958 size_t item_size = (size_t) -1;
4960 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4967 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4970 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4974 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4979 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4984 where = ri = ALIGN_TO(ri, 8);
4985 item_size = end - ri;
4986 r = message_peek_fields(m, &where, 1, item_size, &q);
4990 b = memrchr(q, 0, item_size);
4994 sig = strndup(b+1, item_size - (b+1-(char*) q));
4999 item_size = b - (char*) q;
5001 r = message_peek_field_signature(m, &ri, 0, &signature);
5007 case _BUS_MESSAGE_HEADER_INVALID:
5010 case BUS_MESSAGE_HEADER_PATH:
5015 if (!streq(signature, "o"))
5018 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5021 case BUS_MESSAGE_HEADER_INTERFACE:
5026 if (!streq(signature, "s"))
5029 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5032 case BUS_MESSAGE_HEADER_MEMBER:
5037 if (!streq(signature, "s"))
5040 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5043 case BUS_MESSAGE_HEADER_ERROR_NAME:
5048 if (!streq(signature, "s"))
5051 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5053 m->error._need_free = -1;
5057 case BUS_MESSAGE_HEADER_DESTINATION:
5062 if (!streq(signature, "s"))
5065 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5068 case BUS_MESSAGE_HEADER_SENDER:
5073 if (!streq(signature, "s"))
5076 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5078 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5079 m->creds.unique_name = (char*) m->sender;
5080 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5086 case BUS_MESSAGE_HEADER_SIGNATURE: {
5090 if (m->root_container.signature)
5093 if (!streq(signature, "g"))
5096 r = message_peek_field_signature(m, &ri, item_size, &s);
5104 free(m->root_container.signature);
5105 m->root_container.signature = c;
5109 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5112 if (m->reply_cookie != 0)
5115 if (!streq(signature, "u"))
5118 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5122 m->reply_cookie = serial;
5124 if (m->reply_cookie == 0)
5130 case BUS_MESSAGE_HEADER_UNIX_FDS:
5134 if (!streq(signature, "u"))
5137 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5141 unix_fds_set = true;
5145 if (!BUS_MESSAGE_IS_GVARIANT(m))
5146 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5155 if (m->n_fds != unix_fds)
5158 switch (m->header->type) {
5160 case SD_BUS_MESSAGE_SIGNAL:
5161 if (!m->path || !m->interface || !m->member)
5165 case SD_BUS_MESSAGE_METHOD_CALL:
5167 if (!m->path || !m->member)
5172 case SD_BUS_MESSAGE_METHOD_RETURN:
5174 if (m->reply_cookie == 0)
5178 case SD_BUS_MESSAGE_METHOD_ERROR:
5180 if (m->reply_cookie == 0 || !m->error.name)
5185 /* Refuse non-local messages that claim they are local */
5186 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5188 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5190 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5193 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5195 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5196 r = build_struct_offsets(
5198 m->root_container.signature,
5199 BUS_MESSAGE_BODY_SIZE(m),
5200 &m->root_container.item_size,
5201 &m->root_container.offsets,
5202 &m->root_container.n_offsets);
5207 /* Try to read the error message, but if we can't it's a non-issue */
5208 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5209 sd_bus_message_read(m, "s", &m->error.message);
5214 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5215 assert_return(m, -EINVAL);
5216 assert_return(destination, -EINVAL);
5217 assert_return(!m->sealed, -EPERM);
5218 assert_return(!m->destination, -EEXIST);
5220 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5223 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5227 struct bus_body_part *part;
5233 total = BUS_MESSAGE_SIZE(m);
5239 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5240 MESSAGE_FOREACH_PART(part, i, m)
5241 e = mempcpy(e, part->data, part->size);
5243 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5251 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5257 r = sd_bus_message_enter_container(m, 'a', "s");
5264 r = sd_bus_message_read_basic(m, 's', &s);
5270 r = strv_extend(l, s);
5275 r = sd_bus_message_exit_container(m);
5282 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5286 assert_return(m, -EINVAL);
5287 assert_return(m->sealed, -EPERM);
5288 assert_return(l, -EINVAL);
5290 r = bus_message_read_strv_extend(m, &strv);
5300 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5302 const char *t = NULL;
5307 r = sd_bus_message_rewind(m, true);
5311 for (j = 0; j <= i; j++) {
5314 r = sd_bus_message_peek_type(m, &type, NULL);
5318 if (type != SD_BUS_TYPE_STRING &&
5319 type != SD_BUS_TYPE_OBJECT_PATH &&
5320 type != SD_BUS_TYPE_SIGNATURE)
5323 r = sd_bus_message_read_basic(m, type, &t);
5331 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5337 if (size < sizeof(struct bus_header))
5340 full = sizeof(struct bus_header) +
5341 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5343 return size >= full;
5346 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5352 if (h->endian == BUS_NATIVE_ENDIAN) {
5353 fs = h->fields_size;
5355 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5356 fs = bswap_32(h->fields_size);
5357 bs = bswap_32(h->body_size);
5361 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5365 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5366 assert_return(m, EINVAL);
5368 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5371 return sd_bus_error_get_errno(&m->error);
5374 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5375 struct bus_container *c;
5377 assert_return(m, NULL);
5379 c = complete ? &m->root_container : message_get_container(m);
5380 return strempty(c->signature);
5383 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5384 assert_return(m, -EINVAL);
5386 return isempty(m->root_container.signature);
5389 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5390 bool done_something = false;
5393 assert_return(m, -EINVAL);
5394 assert_return(source, -EINVAL);
5395 assert_return(!m->sealed, -EPERM);
5396 assert_return(source->sealed, -EPERM);
5399 const char *contents;
5414 r = sd_bus_message_peek_type(source, &type, &contents);
5420 done_something = true;
5422 if (bus_type_is_container(type) > 0) {
5424 r = sd_bus_message_enter_container(source, type, contents);
5428 r = sd_bus_message_open_container(m, type, contents);
5432 r = sd_bus_message_copy(m, source, true);
5436 r = sd_bus_message_close_container(m);
5440 r = sd_bus_message_exit_container(source);
5447 r = sd_bus_message_read_basic(source, type, &basic);
5453 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5454 type == SD_BUS_TYPE_SIGNATURE ||
5455 type == SD_BUS_TYPE_STRING)
5456 r = sd_bus_message_append_basic(m, type, basic.string);
5458 r = sd_bus_message_append_basic(m, type, &basic);
5465 return done_something;
5468 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5473 assert_return(m, -EINVAL);
5474 assert_return(m->sealed, -EPERM);
5475 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5476 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5477 assert_return(type || contents, -EINVAL);
5478 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5480 r = sd_bus_message_peek_type(m, &t, &c);
5484 if (type != 0 && type != t)
5487 if (contents && !streq_ptr(contents, c))
5493 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5494 assert_return(m, NULL);
5499 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5500 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5508 switch ((*m)->header->type) {
5510 case SD_BUS_MESSAGE_SIGNAL:
5511 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5517 case SD_BUS_MESSAGE_METHOD_CALL:
5518 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5524 case SD_BUS_MESSAGE_METHOD_RETURN:
5525 case SD_BUS_MESSAGE_METHOD_ERROR:
5527 n = message_new(bus, (*m)->header->type);
5531 n->reply_cookie = (*m)->reply_cookie;
5532 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5536 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5537 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5541 n->error._need_free = -1;
5550 if ((*m)->destination && !n->destination) {
5551 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5556 if ((*m)->sender && !n->sender) {
5557 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5562 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5564 r = sd_bus_message_copy(n, *m, true);
5568 timeout = (*m)->timeout;
5569 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5570 timeout = BUS_DEFAULT_TIMEOUT;
5572 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5576 sd_bus_message_unref(*m);
5583 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5587 assert_return(!m->sealed, -EPERM);
5588 assert_return(!m->sender, -EPERM);
5590 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5593 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5594 assert_return(m, -EINVAL);
5595 assert_return(priority, -EINVAL);
5597 *priority = m->priority;
5601 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5602 assert_return(m, -EINVAL);
5603 assert_return(!m->sealed, -EPERM);
5605 m->priority = priority;