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"
33 #include "bus-message.h"
34 #include "bus-internal.h"
36 #include "bus-signature.h"
37 #include "bus-gvariant.h"
39 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
41 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
46 if (old_base == new_base)
49 if ((uint8_t*) p < (uint8_t*) old_base)
52 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
55 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
58 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
62 if (part->memfd >= 0) {
63 /* If we can reuse the memfd, try that. For that it
64 * can't be sealed yet. */
67 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped);
70 assert_se(munmap(part->data, part->mapped) == 0);
72 close_nointr_nofail(part->memfd);
75 } else if (part->munmap_this)
76 munmap(part->data, part->mapped);
77 else if (part->free_this)
84 static void message_reset_parts(sd_bus_message *m) {
85 struct bus_body_part *part;
90 while (m->n_body_parts > 0) {
91 struct bus_body_part *next = part->next;
92 message_free_part(m, part);
99 m->cached_rindex_part = NULL;
100 m->cached_rindex_part_begin = 0;
103 static void message_reset_containers(sd_bus_message *m) {
108 for (i = 0; i < m->n_containers; i++) {
109 free(m->containers[i].signature);
110 free(m->containers[i].offsets);
114 m->containers = NULL;
117 m->root_container.index = 0;
120 static void message_free(sd_bus_message *m) {
126 message_reset_parts(m);
131 if (m->release_kdbus) {
134 off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
135 ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &off);
139 sd_bus_unref(m->bus);
142 close_many(m->fds, m->n_fds);
146 if (m->iovec != m->iovec_fixed)
149 message_reset_containers(m);
150 free(m->root_container.signature);
151 free(m->root_container.offsets);
153 free(m->peeked_signature);
155 bus_creds_done(&m->creds);
159 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
161 size_t old_size, new_size, start;
168 old_size = sizeof(struct bus_header) + m->header->fields_size;
169 start = ALIGN_TO(old_size, align);
170 new_size = start + sz;
172 if (old_size == new_size)
173 return (uint8_t*) m->header + old_size;
175 if (new_size > (size_t) ((uint32_t) -1))
178 if (m->free_header) {
179 np = realloc(m->header, ALIGN8(new_size));
183 /* Initially, the header is allocated as part of of
184 * the sd_bus_message itself, let's replace it by
187 np = malloc(ALIGN8(new_size));
191 memcpy(np, m->header, sizeof(struct bus_header));
194 /* Zero out padding */
195 if (start > old_size)
196 memset((uint8_t*) np + old_size, 0, start - old_size);
200 m->header->fields_size = new_size - sizeof(struct bus_header);
202 /* Adjust quick access pointers */
203 m->path = adjust_pointer(m->path, op, old_size, m->header);
204 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
205 m->member = adjust_pointer(m->member, op, old_size, m->header);
206 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
207 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
208 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
210 m->free_header = true;
213 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
216 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
219 return (uint8_t*) np + start;
226 static int message_append_field_string(
238 /* dbus1 doesn't allow strings over 32bit, let's enforce this
239 * globally, to not risk convertability */
241 if (l > (size_t) (uint32_t) -1)
244 /* Signature "(yv)" where the variant contains "s" */
246 if (BUS_MESSAGE_IS_GVARIANT(m)) {
248 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
249 p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
261 *ret = (char*) p + 8;
264 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
265 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
274 ((uint32_t*) p)[1] = l;
275 memcpy(p + 8, s, l + 1);
278 *ret = (char*) p + 8;
284 static int message_append_field_signature(
295 /* dbus1 doesn't allow signatures over 32bit, let's enforce
296 * this globally, to not risk convertability */
301 /* Signature "(yv)" where the variant contains "g" */
303 if (BUS_MESSAGE_IS_GVARIANT(m))
304 /* For gvariant the serialization is the same as for normal strings */
305 return message_append_field_string(m, h, 'g', s, ret);
307 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
308 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
314 p[2] = SD_BUS_TYPE_SIGNATURE;
317 memcpy(p + 5, s, l + 1);
320 *ret = (const char*) p + 5;
326 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
331 if (BUS_MESSAGE_IS_GVARIANT(m)) {
332 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
334 p = message_extend_fields(m, 8, 1 + 7 + 4 + 1 + 1, true);
340 *((uint32_t*) (p + 8)) = x;
344 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
345 p = message_extend_fields(m, 8, 4 + 4, false);
351 p[2] = SD_BUS_TYPE_UINT32;
354 ((uint32_t*) p)[1] = x;
360 int bus_message_from_header(
366 const struct ucred *ucred,
369 sd_bus_message **ret) {
372 struct bus_header *h;
375 assert(buffer || length <= 0);
376 assert(fds || n_fds <= 0);
379 if (length < sizeof(struct bus_header))
383 if (h->version != 1 &&
390 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
393 if (h->endian != BUS_LITTLE_ENDIAN &&
394 h->endian != BUS_BIG_ENDIAN)
397 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
400 label_sz = strlen(label);
415 m->creds.uid = ucred->uid;
416 m->creds.pid = ucred->pid;
417 m->creds.gid = ucred->gid;
418 m->creds.mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID;
422 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
423 memcpy(m->creds.label, label, label_sz + 1);
425 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
429 m->bus = sd_bus_ref(bus);
435 int bus_message_from_malloc(
441 const struct ucred *ucred,
443 sd_bus_message **ret) {
449 r = bus_message_from_header(bus, buffer, length, fds, n_fds, ucred, label, 0, &m);
453 if (length != BUS_MESSAGE_SIZE(m)) {
458 sz = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
461 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
463 m->body.sealed = true;
468 m->iovec = m->iovec_fixed;
469 m->iovec[0].iov_base = buffer;
470 m->iovec[0].iov_len = length;
472 r = bus_message_parse_fields(m);
476 /* We take possession of the memory and fds now */
477 m->free_header = true;
488 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
491 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
496 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
497 m->header->endian = BUS_NATIVE_ENDIAN;
498 m->header->type = type;
499 m->header->version = bus ? bus->message_version : 1;
500 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
501 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
504 m->bus = sd_bus_ref(bus);
509 _public_ int sd_bus_message_new_signal(
512 const char *interface,
514 sd_bus_message **m) {
519 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
520 assert_return(object_path_is_valid(path), -EINVAL);
521 assert_return(interface_name_is_valid(interface), -EINVAL);
522 assert_return(member_name_is_valid(member), -EINVAL);
523 assert_return(m, -EINVAL);
525 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
529 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
531 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
534 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
537 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
545 sd_bus_message_unref(t);
549 _public_ int sd_bus_message_new_method_call(
551 const char *destination,
553 const char *interface,
555 sd_bus_message **m) {
560 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
561 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
562 assert_return(object_path_is_valid(path), -EINVAL);
563 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
564 assert_return(member_name_is_valid(member), -EINVAL);
565 assert_return(m, -EINVAL);
567 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
571 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
574 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
579 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
585 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
598 static int message_new_reply(
599 sd_bus_message *call,
601 sd_bus_message **m) {
606 assert_return(call, -EINVAL);
607 assert_return(call->sealed, -EPERM);
608 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
609 assert_return(!call->bus || call->bus->state != BUS_UNSET, -ENOTCONN);
610 assert_return(m, -EINVAL);
612 t = message_new(call->bus, type);
616 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
617 t->reply_serial = BUS_MESSAGE_SERIAL(call);
619 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
624 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
629 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
630 t->enforced_reply_signature = call->enforced_reply_signature;
640 _public_ int sd_bus_message_new_method_return(
641 sd_bus_message *call,
642 sd_bus_message **m) {
644 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
647 _public_ int sd_bus_message_new_method_error(
648 sd_bus_message *call,
649 const sd_bus_error *e,
650 sd_bus_message **m) {
655 assert_return(sd_bus_error_is_set(e), -EINVAL);
656 assert_return(m, -EINVAL);
658 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
662 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
667 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
672 t->error._need_free = -1;
682 _public_ int sd_bus_message_new_method_errorf(
683 sd_bus_message *call,
689 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
692 assert_return(name, -EINVAL);
693 assert_return(m, -EINVAL);
695 va_start(ap, format);
696 bus_error_setfv(&error, name, format, ap);
699 return sd_bus_message_new_method_error(call, &error, m);
702 _public_ int sd_bus_message_new_method_errno(
703 sd_bus_message *call,
705 const sd_bus_error *p,
706 sd_bus_message **m) {
708 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
710 if (sd_bus_error_is_set(p))
711 return sd_bus_message_new_method_error(call, p, m);
713 sd_bus_error_set_errno(&berror, error);
715 return sd_bus_message_new_method_error(call, &berror, m);
718 _public_ int sd_bus_message_new_method_errnof(
719 sd_bus_message *call,
725 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
728 va_start(ap, format);
729 bus_error_set_errnofv(&berror, error, format, ap);
732 return sd_bus_message_new_method_error(call, &berror, m);
735 int bus_message_new_synthetic_error(
738 const sd_bus_error *e,
739 sd_bus_message **m) {
744 assert(sd_bus_error_is_set(e));
747 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
751 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
752 t->reply_serial = serial;
754 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
758 if (bus && bus->unique_name) {
759 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
764 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
769 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
774 t->error._need_free = -1;
784 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
785 assert_return(m, NULL);
787 assert(m->n_ref > 0);
793 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
794 assert_return(m, NULL);
796 assert(m->n_ref > 0);
805 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
806 assert_return(m, -EINVAL);
807 assert_return(type, -EINVAL);
809 *type = m->header->type;
813 _public_ int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
814 assert_return(m, -EINVAL);
815 assert_return(serial, -EINVAL);
816 assert_return(m->header->serial != 0, -ENOENT);
818 *serial = BUS_MESSAGE_SERIAL(m);
822 _public_ int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
823 assert_return(m, -EINVAL);
824 assert_return(serial, -EINVAL);
825 assert_return(m->reply_serial != 0, -ENOENT);
827 *serial = m->reply_serial;
831 _public_ int sd_bus_message_get_no_reply(sd_bus_message *m) {
832 assert_return(m, -EINVAL);
834 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL ? !!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
837 _public_ int sd_bus_message_get_no_auto_start(sd_bus_message *m) {
838 assert_return(m, -EINVAL);
840 return !!(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
843 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
844 assert_return(m, NULL);
849 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
850 assert_return(m, NULL);
855 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
856 assert_return(m, NULL);
861 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
862 assert_return(m, NULL);
864 return m->destination;
867 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
868 assert_return(m, NULL);
873 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
874 assert_return(m, NULL);
875 assert_return(sd_bus_error_is_set(&m->error), NULL);
880 _public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
881 assert_return(m, -EINVAL);
882 assert_return(usec, -EINVAL);
883 assert_return(m->monotonic > 0, -ENODATA);
885 *usec = m->monotonic;
889 _public_ int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
890 assert_return(m, -EINVAL);
891 assert_return(usec, -EINVAL);
892 assert_return(m->realtime > 0, -ENODATA);
898 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
899 assert_return(m, NULL);
901 if (m->creds.mask == 0)
907 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
908 const char *interface,
909 const char *member) {
910 assert_return(m, -EINVAL);
912 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
915 if (interface && (!m->interface || !streq(m->interface, interface)))
918 if (member && (!m->member || !streq(m->member, member)))
924 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
925 const char *interface,
926 const char *member) {
927 assert_return(m, -EINVAL);
929 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
932 if (interface && (!m->interface || !streq(m->interface, interface)))
935 if (member && (!m->member || !streq(m->member, member)))
941 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
942 assert_return(m, -EINVAL);
944 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
947 if (name && (!m->error.name || !streq(m->error.name, name)))
953 _public_ int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
954 assert_return(m, -EINVAL);
955 assert_return(!m->sealed, -EPERM);
956 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
959 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
961 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
966 _public_ int sd_bus_message_set_no_auto_start(sd_bus_message *m, int b) {
967 assert_return(m, -EINVAL);
968 assert_return(!m->sealed, -EPERM);
971 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
973 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
978 static struct bus_container *message_get_container(sd_bus_message *m) {
981 if (m->n_containers == 0)
982 return &m->root_container;
984 assert(m->containers);
985 return m->containers + m->n_containers - 1;
988 struct bus_body_part *message_append_part(sd_bus_message *m) {
989 struct bus_body_part *part;
996 if (m->n_body_parts <= 0) {
1000 assert(m->body_end);
1002 part = new0(struct bus_body_part, 1);
1008 m->body_end->next = part;
1018 static void part_zero(struct bus_body_part *part, size_t sz) {
1023 /* All other fields can be left in their defaults */
1024 assert(!part->data);
1025 assert(part->memfd < 0);
1028 part->is_zero = true;
1029 part->sealed = true;
1032 static int part_make_space(
1033 struct sd_bus_message *m,
1034 struct bus_body_part *part,
1043 assert(!part->sealed);
1048 if (!part->data && part->memfd < 0)
1049 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped);
1051 if (part->memfd >= 0) {
1054 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &u);
1060 if (!part->data || sz > part->mapped) {
1061 size_t psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1063 if (part->mapped <= 0)
1064 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1066 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1068 if (n == MAP_FAILED) {
1077 part->munmap_this = true;
1079 n = realloc(part->data, MAX(sz, 1u));
1086 part->free_this = true;
1090 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1096 static int message_add_offset(sd_bus_message *m, size_t offset) {
1097 struct bus_container *c;
1100 assert(BUS_MESSAGE_IS_GVARIANT(m));
1102 /* Add offset to current container, unless this is the first
1103 * item in it, which will have the 0 offset, which we can
1105 c = message_get_container(m);
1107 if (!c->need_offsets)
1110 if (!GREEDY_REALLOC(c->offsets, c->n_offsets_allocated, c->n_offsets + 1))
1113 c->offsets[c->n_offsets++] = offset;
1117 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1118 struct bus_container *c;
1125 /* Update counters */
1126 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1129 *c->array_size += expand;
1133 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1134 struct bus_body_part *part = NULL;
1135 size_t start_body, end_body, padding, start_part, end_part, added;
1147 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1148 end_body = start_body + sz;
1150 padding = start_body - m->header->body_size;
1151 added = padding + sz;
1153 /* Check for 32bit overflows */
1154 if (end_body > (size_t) ((uint32_t) -1)) {
1160 m->n_body_parts <= 0 ||
1161 m->body_end->sealed ||
1162 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1166 part = message_append_part(m);
1170 part_zero(part, padding);
1173 part = message_append_part(m);
1177 r = part_make_space(m, part, sz, &p);
1181 struct bus_container *c;
1189 start_part = ALIGN_TO(part->size, align);
1190 end_part = start_part + sz;
1192 r = part_make_space(m, part, end_part, &p);
1197 memset(p, 0, padding);
1198 p = (uint8_t*) p + padding;
1201 /* Readjust pointers */
1202 for (c = m->containers; c < m->containers + m->n_containers; c++)
1203 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1205 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1208 m->header->body_size = end_body;
1209 message_extend_containers(m, added);
1212 r = message_add_offset(m, end_body);
1222 static int message_push_fd(sd_bus_message *m, int fd) {
1233 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1237 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1240 close_nointr_nofail(copy);
1245 m->fds[m->n_fds] = copy;
1251 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1252 _cleanup_close_ int fd = -1;
1253 struct bus_container *c;
1257 assert_return(m, -EINVAL);
1258 assert_return(!m->sealed, -EPERM);
1259 assert_return(bus_type_is_basic(type), -EINVAL);
1260 assert_return(!m->poisoned, -ESTALE);
1262 c = message_get_container(m);
1264 if (c->signature && c->signature[c->index]) {
1265 /* Container signature is already set */
1267 if (c->signature[c->index] != type)
1272 /* Maybe we can append to the signature? But only if this is the top-level container*/
1273 if (c->enclosing != 0)
1276 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1283 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1289 case SD_BUS_TYPE_SIGNATURE:
1290 case SD_BUS_TYPE_STRING:
1293 /* Fall through... */
1294 case SD_BUS_TYPE_OBJECT_PATH:
1302 case SD_BUS_TYPE_BOOLEAN:
1304 u8 = p && *(int*) p;
1310 case SD_BUS_TYPE_UNIX_FD:
1315 fd = message_push_fd(m, *(int*) p);
1326 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1327 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1334 a = message_extend_body(m, align, sz, true);
1341 *stored = (const uint8_t*) a;
1348 case SD_BUS_TYPE_STRING:
1349 /* To make things easy we'll serialize a NULL string
1350 * into the empty string */
1353 /* Fall through... */
1354 case SD_BUS_TYPE_OBJECT_PATH:
1360 sz = 4 + strlen(p) + 1;
1363 case SD_BUS_TYPE_SIGNATURE:
1368 sz = 1 + strlen(p) + 1;
1371 case SD_BUS_TYPE_BOOLEAN:
1373 u32 = p && *(int*) p;
1379 case SD_BUS_TYPE_UNIX_FD:
1384 fd = message_push_fd(m, *(int*) p);
1395 align = bus_type_get_alignment(type);
1396 sz = bus_type_get_size(type);
1403 a = message_extend_body(m, align, sz, false);
1407 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1408 *(uint32_t*) a = sz - 5;
1409 memcpy((uint8_t*) a + 4, p, sz - 4);
1412 *stored = (const uint8_t*) a + 4;
1414 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1415 *(uint8_t*) a = sz - 1;
1416 memcpy((uint8_t*) a + 1, p, sz - 1);
1419 *stored = (const uint8_t*) a + 1;
1428 if (type == SD_BUS_TYPE_UNIX_FD)
1431 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1438 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1439 return message_append_basic(m, type, p, NULL);
1442 _public_ int sd_bus_message_append_string_space(
1447 struct bus_container *c;
1450 assert_return(m, -EINVAL);
1451 assert_return(s, -EINVAL);
1452 assert_return(!m->sealed, -EPERM);
1453 assert_return(!m->poisoned, -ESTALE);
1455 c = message_get_container(m);
1457 if (c->signature && c->signature[c->index]) {
1458 /* Container signature is already set */
1460 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1465 /* Maybe we can append to the signature? But only if this is the top-level container*/
1466 if (c->enclosing != 0)
1469 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1476 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1477 a = message_extend_body(m, 1, size + 1, true);
1483 a = message_extend_body(m, 4, 4 + size + 1, false);
1487 *(uint32_t*) a = size;
1493 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1499 _public_ int sd_bus_message_append_string_iovec(
1501 const struct iovec *iov,
1509 assert_return(m, -EINVAL);
1510 assert_return(!m->sealed, -EPERM);
1511 assert_return(iov || n == 0, -EINVAL);
1512 assert_return(!m->poisoned, -ESTALE);
1514 size = IOVEC_TOTAL_SIZE(iov, n);
1516 r = sd_bus_message_append_string_space(m, size, &p);
1520 for (i = 0; i < n; i++) {
1522 if (iov[i].iov_base)
1523 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1525 memset(p, ' ', iov[i].iov_len);
1527 p += iov[i].iov_len;
1533 static int bus_message_open_array(
1535 struct bus_container *c,
1536 const char *contents,
1537 uint32_t **array_size,
1539 bool *need_offsets) {
1549 assert(need_offsets);
1551 if (!signature_is_single(contents, true))
1554 if (c->signature && c->signature[c->index]) {
1556 /* Verify the existing signature */
1558 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1561 if (!startswith(c->signature + c->index + 1, contents))
1564 nindex = c->index + 1 + strlen(contents);
1568 if (c->enclosing != 0)
1571 /* Extend the existing signature */
1573 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1579 nindex = e - c->signature;
1582 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1583 alignment = bus_gvariant_get_alignment(contents);
1587 /* Add alignment padding and add to offset list */
1588 if (!message_extend_body(m, alignment, 0, false))
1591 r = bus_gvariant_is_fixed_size(contents);
1595 *begin = m->header->body_size;
1596 *need_offsets = r == 0;
1600 struct bus_body_part *o;
1602 alignment = bus_type_get_alignment(contents[0]);
1606 a = message_extend_body(m, 4, 4, false);
1611 op = m->body_end->data;
1612 os = m->body_end->size;
1614 /* Add alignment between size and first element */
1615 if (!message_extend_body(m, alignment, 0, false))
1618 /* location of array size might have changed so let's readjust a */
1619 if (o == m->body_end)
1620 a = adjust_pointer(a, op, os, m->body_end->data);
1626 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1632 static int bus_message_open_variant(
1634 struct bus_container *c,
1635 const char *contents) {
1641 if (!signature_is_single(contents, false))
1644 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1647 if (c->signature && c->signature[c->index]) {
1649 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1655 if (c->enclosing != 0)
1658 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1665 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1666 /* Variants are always aligned to 8 */
1668 if (!message_extend_body(m, 8, 0, false))
1675 l = strlen(contents);
1676 a = message_extend_body(m, 1, 1 + l + 1, false);
1681 memcpy((uint8_t*) a + 1, contents, l + 1);
1684 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1690 static int bus_message_open_struct(
1692 struct bus_container *c,
1693 const char *contents,
1695 bool *need_offsets) {
1704 assert(need_offsets);
1706 if (!signature_is_valid(contents, false))
1709 if (c->signature && c->signature[c->index]) {
1712 l = strlen(contents);
1714 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1715 !startswith(c->signature + c->index + 1, contents) ||
1716 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1719 nindex = c->index + 1 + l + 1;
1723 if (c->enclosing != 0)
1726 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1732 nindex = e - c->signature;
1735 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1738 alignment = bus_gvariant_get_alignment(contents);
1742 if (!message_extend_body(m, alignment, 0, false))
1745 r = bus_gvariant_is_fixed_size(contents);
1749 *begin = m->header->body_size;
1750 *need_offsets = r == 0;
1752 /* Align contents to 8 byte boundary */
1753 if (!message_extend_body(m, 8, 0, false))
1757 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1763 static int bus_message_open_dict_entry(
1765 struct bus_container *c,
1766 const char *contents,
1768 bool *need_offsets) {
1776 assert(need_offsets);
1778 if (!signature_is_pair(contents))
1781 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1784 if (c->signature && c->signature[c->index]) {
1787 l = strlen(contents);
1789 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1790 !startswith(c->signature + c->index + 1, contents) ||
1791 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1796 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1799 alignment = bus_gvariant_get_alignment(contents);
1803 if (!message_extend_body(m, alignment, 0, false))
1806 r = bus_gvariant_is_fixed_size(contents);
1810 *begin = m->header->body_size;
1811 *need_offsets = r == 0;
1813 /* Align contents to 8 byte boundary */
1814 if (!message_extend_body(m, 8, 0, false))
1821 _public_ int sd_bus_message_open_container(
1824 const char *contents) {
1826 struct bus_container *c, *w;
1827 uint32_t *array_size = NULL;
1829 size_t before, begin;
1830 bool need_offsets = false;
1833 assert_return(m, -EINVAL);
1834 assert_return(!m->sealed, -EPERM);
1835 assert_return(contents, -EINVAL);
1836 assert_return(!m->poisoned, -ESTALE);
1838 /* Make sure we have space for one more container */
1839 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1847 c = message_get_container(m);
1849 signature = strdup(contents);
1855 /* Save old index in the parent container, in case we have to
1856 * abort this container */
1857 c->saved_index = c->index;
1858 before = m->header->body_size;
1860 if (type == SD_BUS_TYPE_ARRAY)
1861 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1862 else if (type == SD_BUS_TYPE_VARIANT)
1863 r = bus_message_open_variant(m, c, contents);
1864 else if (type == SD_BUS_TYPE_STRUCT)
1865 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1866 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1867 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1876 /* OK, let's fill it in */
1877 w += m->n_containers++;
1878 w->enclosing = type;
1879 w->signature = signature;
1881 w->array_size = array_size;
1884 w->n_offsets = w->n_offsets_allocated = 0;
1886 w->need_offsets = need_offsets;
1891 static size_t determine_word_size(size_t sz, size_t extra) {
1892 if (sz <= 0 && extra == 0)
1894 else if (sz + extra <= 0xFF)
1896 else if (sz + extra*2 <= 0xFFFF)
1898 else if (sz + extra*4 <= 0xFFFFFFFF)
1904 static size_t read_word_le(void *p, size_t sz) {
1914 return *(uint8_t*) p;
1919 return le16toh(x.u16);
1921 return le32toh(x.u32);
1923 return le64toh(x.u64);
1925 assert_not_reached("unknown word width");
1928 static void write_word_le(void *p, size_t sz, size_t value) {
1936 assert(sz == 8 || (value < (1ULL << (sz*8))));
1939 *(uint8_t*) p = value;
1942 x.u16 = htole16((uint16_t) value);
1944 x.u32 = htole32((uint32_t) value);
1946 x.u64 = htole64((uint64_t) value);
1948 assert_not_reached("unknown word width");
1953 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1958 if (!BUS_MESSAGE_IS_GVARIANT(m))
1961 if (c->need_offsets) {
1962 size_t payload, sz, i;
1965 /* Variable-width arrays */
1967 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
1968 sz = determine_word_size(payload, c->n_offsets);
1970 a = message_extend_body(m, 1, sz * c->n_offsets, true);
1974 for (i = 0; i < c->n_offsets; i++)
1975 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
1979 /* Fixed-width or empty arrays */
1981 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
1989 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
1996 if (!BUS_MESSAGE_IS_GVARIANT(m))
1999 l = strlen(c->signature);
2001 a = message_extend_body(m, 1, 1 + l, true);
2006 memcpy(a+1, c->signature, l);
2011 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2012 size_t n_variable = 0;
2021 if (!BUS_MESSAGE_IS_GVARIANT(m))
2028 r = signature_element_length(p, &n);
2037 r = bus_gvariant_is_fixed_size(t);
2042 assert(i <= c->n_offsets);
2044 /* We need to add an offset for each item that has a
2045 * variable size and that is not the last one in the
2047 if (r == 0 && p[n] != 0)
2054 assert(i == c->n_offsets);
2056 if (n_variable <= 0) {
2057 a = message_extend_body(m, 1, 0, add_offset);
2064 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2066 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2068 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2073 for (i = 0, j = 0; i < c->n_offsets; i++) {
2077 r = signature_element_length(p, &n);
2088 r = bus_gvariant_is_fixed_size(t);
2091 if (r > 0 || p[0] == 0)
2095 k = n_variable - 1 - j;
2097 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2106 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2107 struct bus_container *c;
2110 assert_return(m, -EINVAL);
2111 assert_return(!m->sealed, -EPERM);
2112 assert_return(m->n_containers > 0, -EINVAL);
2113 assert_return(!m->poisoned, -ESTALE);
2115 c = message_get_container(m);
2117 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2118 if (c->signature && c->signature[c->index] != 0)
2123 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2124 r = bus_message_close_array(m, c);
2125 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2126 r = bus_message_close_variant(m, c);
2127 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2128 r = bus_message_close_struct(m, c, true);
2130 assert_not_reached("Unknown container type");
2144 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2151 stack[*i].types = types;
2152 stack[*i].n_struct = n_struct;
2153 stack[*i].n_array = n_array;
2159 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2170 *types = stack[*i].types;
2171 *n_struct = stack[*i].n_struct;
2172 *n_array = stack[*i].n_array;
2177 int bus_message_append_ap(
2182 unsigned n_array, n_struct;
2183 TypeStack stack[BUS_CONTAINER_DEPTH];
2184 unsigned stack_ptr = 0;
2192 n_array = (unsigned) -1;
2193 n_struct = strlen(types);
2198 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2199 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2205 r = sd_bus_message_close_container(m);
2213 if (n_array != (unsigned) -1)
2222 case SD_BUS_TYPE_BYTE: {
2225 x = (uint8_t) va_arg(ap, int);
2226 r = sd_bus_message_append_basic(m, *t, &x);
2230 case SD_BUS_TYPE_BOOLEAN:
2231 case SD_BUS_TYPE_INT32:
2232 case SD_BUS_TYPE_UINT32:
2233 case SD_BUS_TYPE_UNIX_FD: {
2236 /* We assume a boolean is the same as int32_t */
2237 assert_cc(sizeof(int32_t) == sizeof(int));
2239 x = va_arg(ap, uint32_t);
2240 r = sd_bus_message_append_basic(m, *t, &x);
2244 case SD_BUS_TYPE_INT16:
2245 case SD_BUS_TYPE_UINT16: {
2248 x = (uint16_t) va_arg(ap, int);
2249 r = sd_bus_message_append_basic(m, *t, &x);
2253 case SD_BUS_TYPE_INT64:
2254 case SD_BUS_TYPE_UINT64:
2255 case SD_BUS_TYPE_DOUBLE: {
2258 x = va_arg(ap, uint64_t);
2259 r = sd_bus_message_append_basic(m, *t, &x);
2263 case SD_BUS_TYPE_STRING:
2264 case SD_BUS_TYPE_OBJECT_PATH:
2265 case SD_BUS_TYPE_SIGNATURE: {
2268 x = va_arg(ap, const char*);
2269 r = sd_bus_message_append_basic(m, *t, x);
2273 case SD_BUS_TYPE_ARRAY: {
2276 r = signature_element_length(t + 1, &k);
2282 memcpy(s, t + 1, k);
2285 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2290 if (n_array == (unsigned) -1) {
2295 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2301 n_array = va_arg(ap, unsigned);
2306 case SD_BUS_TYPE_VARIANT: {
2309 s = va_arg(ap, const char*);
2313 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2317 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2322 n_struct = strlen(s);
2323 n_array = (unsigned) -1;
2328 case SD_BUS_TYPE_STRUCT_BEGIN:
2329 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2332 r = signature_element_length(t, &k);
2339 memcpy(s, t + 1, k - 2);
2342 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2347 if (n_array == (unsigned) -1) {
2352 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2358 n_array = (unsigned) -1;
2374 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2378 assert_return(m, -EINVAL);
2379 assert_return(types, -EINVAL);
2380 assert_return(!m->sealed, -EPERM);
2381 assert_return(!m->poisoned, -ESTALE);
2383 va_start(ap, types);
2384 r = bus_message_append_ap(m, types, ap);
2390 _public_ int sd_bus_message_append_array_space(
2400 assert_return(m, -EINVAL);
2401 assert_return(!m->sealed, -EPERM);
2402 assert_return(bus_type_is_trivial(type), -EINVAL);
2403 assert_return(ptr || size == 0, -EINVAL);
2404 assert_return(!m->poisoned, -ESTALE);
2406 align = bus_type_get_alignment(type);
2407 sz = bus_type_get_size(type);
2409 assert_se(align > 0);
2415 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2419 a = message_extend_body(m, align, size, false);
2423 r = sd_bus_message_close_container(m);
2431 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2438 assert_return(m, -EINVAL);
2439 assert_return(!m->sealed, -EPERM);
2440 assert_return(bus_type_is_trivial(type), -EINVAL);
2441 assert_return(ptr || size == 0, -EINVAL);
2442 assert_return(!m->poisoned, -ESTALE);
2444 r = sd_bus_message_append_array_space(m, type, size, &p);
2449 memcpy(p, ptr, size);
2454 _public_ int sd_bus_message_append_array_iovec(
2457 const struct iovec *iov,
2465 assert_return(m, -EINVAL);
2466 assert_return(!m->sealed, -EPERM);
2467 assert_return(bus_type_is_trivial(type), -EINVAL);
2468 assert_return(iov || n == 0, -EINVAL);
2469 assert_return(!m->poisoned, -ESTALE);
2471 size = IOVEC_TOTAL_SIZE(iov, n);
2473 r = sd_bus_message_append_array_space(m, type, size, &p);
2477 for (i = 0; i < n; i++) {
2479 if (iov[i].iov_base)
2480 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2482 memset(p, 0, iov[i].iov_len);
2484 p = (uint8_t*) p + iov[i].iov_len;
2490 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2493 _cleanup_close_ int copy_fd = -1;
2494 struct bus_body_part *part;
2506 if (!bus_type_is_trivial(type))
2511 r = sd_memfd_set_sealed(memfd, true);
2515 copy_fd = sd_memfd_dup_fd(memfd);
2519 r = sd_memfd_get_size(memfd, &size);
2523 align = bus_type_get_alignment(type);
2524 sz = bus_type_get_size(type);
2526 assert_se(align > 0);
2532 if (size > (uint64_t) (uint32_t) -1)
2535 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2539 a = message_extend_body(m, align, 0, false);
2543 part = message_append_part(m);
2547 part->memfd = copy_fd;
2548 part->sealed = true;
2552 message_extend_containers(m, size);
2553 m->header->body_size += size;
2555 return sd_bus_message_close_container(m);
2558 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
2559 _cleanup_close_ int copy_fd = -1;
2560 struct bus_body_part *part;
2561 struct bus_container *c;
2566 assert_return(m, -EINVAL);
2567 assert_return(memfd, -EINVAL);
2568 assert_return(!m->sealed, -EPERM);
2569 assert_return(!m->poisoned, -ESTALE);
2571 r = sd_memfd_set_sealed(memfd, true);
2575 copy_fd = sd_memfd_dup_fd(memfd);
2579 r = sd_memfd_get_size(memfd, &size);
2583 /* We require this to be NUL terminated */
2587 if (size > (uint64_t) (uint32_t) -1)
2590 c = message_get_container(m);
2591 if (c->signature && c->signature[c->index]) {
2592 /* Container signature is already set */
2594 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2599 /* Maybe we can append to the signature? But only if this is the top-level container*/
2600 if (c->enclosing != 0)
2603 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2610 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2611 a = message_extend_body(m, 4, 4, false);
2615 *(uint32_t*) a = size - 1;
2618 part = message_append_part(m);
2622 part->memfd = copy_fd;
2623 part->sealed = true;
2627 m->header->body_size += size;
2628 message_extend_containers(m, size);
2630 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2631 r = message_add_offset(m, m->header->body_size);
2638 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2644 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2648 assert_return(m, -EINVAL);
2649 assert_return(!m->sealed, -EPERM);
2650 assert_return(!m->poisoned, -ESTALE);
2652 r = sd_bus_message_open_container(m, 'a', "s");
2656 STRV_FOREACH(i, l) {
2657 r = sd_bus_message_append_basic(m, 's', *i);
2662 return sd_bus_message_close_container(m);
2665 static int bus_message_close_header(sd_bus_message *m) {
2671 if (!BUS_MESSAGE_IS_GVARIANT(m))
2674 if (m->n_header_offsets < 1)
2677 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2679 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2681 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2685 for (i = 0; i < m->n_header_offsets; i++)
2686 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2691 int bus_message_seal(sd_bus_message *m, uint64_t serial) {
2692 struct bus_body_part *part;
2702 if (m->n_containers > 0)
2708 /* In vtables the return signature of method calls is listed,
2709 * let's check if they match if this is a response */
2710 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2711 m->enforced_reply_signature &&
2712 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2715 /* If gvariant marshalling is used we need to close the body structure */
2716 r = bus_message_close_struct(m, &m->root_container, false);
2720 /* If there's a non-trivial signature set, then add it in here */
2721 if (!isempty(m->root_container.signature)) {
2722 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2728 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2733 r = bus_message_close_header(m);
2737 m->header->serial = serial;
2739 /* Add padding at the end of the fields part, since we know
2740 * the body needs to start at an 8 byte alignment. We made
2741 * sure we allocated enough space for this, so all we need to
2742 * do here is to zero it out. */
2743 l = BUS_MESSAGE_FIELDS_SIZE(m);
2746 memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
2748 /* If this is something we can send as memfd, then let's seal
2749 the memfd now. Note that we can send memfds as payload only
2750 for directed messages, and not for broadcasts. */
2751 if (m->destination && m->bus && m->bus->use_memfd) {
2752 MESSAGE_FOREACH_PART(part, i, m)
2753 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2754 bus_body_part_unmap(part);
2756 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
2757 part->sealed = true;
2761 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2762 m->root_container.index = 0;
2763 m->root_container.offset_index = 0;
2764 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2771 int bus_body_part_map(struct bus_body_part *part) {
2780 if (part->size <= 0)
2783 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2784 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2785 static const uint8_t zeroes[7] = { };
2786 part->data = (void*) zeroes;
2790 psz = PAGE_ALIGN(part->size);
2792 if (part->memfd >= 0)
2793 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2794 else if (part->is_zero)
2795 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2799 if (p == MAP_FAILED)
2804 part->munmap_this = true;
2809 void bus_body_part_unmap(struct bus_body_part *part) {
2813 if (part->memfd < 0)
2819 if (!part->munmap_this)
2822 assert_se(munmap(part->data, part->mapped) == 0);
2826 part->munmap_this = false;
2831 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2832 size_t k, start, end;
2837 start = ALIGN_TO((size_t) *rindex, align);
2838 end = start + nbytes;
2843 /* Verify that padding is 0 */
2844 for (k = *rindex; k < start; k++)
2845 if (((const uint8_t*) p)[k] != 0)
2849 *r = (uint8_t*) p + start;
2856 static bool message_end_of_signature(sd_bus_message *m) {
2857 struct bus_container *c;
2861 c = message_get_container(m);
2862 return !c->signature || c->signature[c->index] == 0;
2865 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2866 struct bus_container *c;
2870 c = message_get_container(m);
2871 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2874 if (BUS_MESSAGE_IS_GVARIANT(m))
2875 return index >= c->end;
2877 assert(c->array_size);
2878 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2882 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2883 assert_return(m, -EINVAL);
2884 assert_return(m->sealed, -EPERM);
2886 if (complete && m->n_containers > 0)
2889 if (message_end_of_signature(m))
2892 if (message_end_of_array(m, m->rindex))
2898 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2899 struct bus_body_part *part;
2905 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2906 part = m->cached_rindex_part;
2907 begin = m->cached_rindex_part_begin;
2917 if (index + sz <= begin + part->size) {
2919 r = bus_body_part_map(part);
2924 *p = (uint8_t*) part->data + index - begin;
2926 m->cached_rindex_part = part;
2927 m->cached_rindex_part_begin = begin;
2932 begin += part->size;
2939 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2946 if (!BUS_MESSAGE_IS_GVARIANT(m))
2949 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2952 sz = bus_gvariant_get_size(c->signature);
2956 if (c->offset_index+1 >= c->n_offsets)
2959 /* Variable-size array */
2961 alignment = bus_gvariant_get_alignment(c->signature);
2962 assert(alignment > 0);
2964 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
2965 c->item_size = c->offsets[c->offset_index+1] - *rindex;
2967 /* Fixed-size array */
2974 } else if (c->enclosing == 0 ||
2975 c->enclosing == SD_BUS_TYPE_STRUCT ||
2976 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
2981 if (c->offset_index+1 >= c->n_offsets)
2984 r = signature_element_length(c->signature + c->index, &n);
2988 r = signature_element_length(c->signature + c->index + n, &j);
2993 memcpy(t, c->signature + c->index + n, j);
2996 alignment = bus_gvariant_get_alignment(t);
2999 assert(alignment > 0);
3001 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3002 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3006 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3009 assert_not_reached("Unknown container type");
3014 /* Reached the end */
3021 static int message_peek_body(
3028 size_t k, start, end, padding;
3029 struct bus_body_part *part;
3036 if (message_end_of_array(m, *rindex))
3039 start = ALIGN_TO((size_t) *rindex, align);
3040 padding = start - *rindex;
3041 end = start + nbytes;
3043 if (end > BUS_MESSAGE_BODY_SIZE(m))
3046 part = find_part(m, *rindex, padding, (void**) &q);
3051 /* Verify padding */
3052 for (k = 0; k < padding; k++)
3057 part = find_part(m, start, nbytes, (void**) &q);
3069 static bool validate_nul(const char *s, size_t l) {
3071 /* Check for NUL chars in the string */
3072 if (memchr(s, 0, l))
3075 /* Check for NUL termination */
3082 static bool validate_string(const char *s, size_t l) {
3084 if (!validate_nul(s, l))
3087 /* Check if valid UTF8 */
3088 if (!utf8_is_valid(s))
3094 static bool validate_signature(const char *s, size_t l) {
3096 if (!validate_nul(s, l))
3099 /* Check if valid signature */
3100 if (!signature_is_valid(s, true))
3106 static bool validate_object_path(const char *s, size_t l) {
3108 if (!validate_nul(s, l))
3111 if (!object_path_is_valid(s))
3117 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3118 struct bus_container *c;
3123 assert_return(m, -EINVAL);
3124 assert_return(m->sealed, -EPERM);
3125 assert_return(bus_type_is_basic(type), -EINVAL);
3127 if (message_end_of_signature(m))
3130 if (message_end_of_array(m, m->rindex))
3133 c = message_get_container(m);
3134 if (c->signature[c->index] != type)
3139 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3141 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3144 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3148 if (type == SD_BUS_TYPE_STRING)
3149 ok = validate_string(q, c->item_size-1);
3150 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3151 ok = validate_object_path(q, c->item_size-1);
3153 ok = validate_signature(q, c->item_size-1);
3159 *(const char**) p = q;
3163 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3165 if ((size_t) sz != c->item_size)
3168 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3171 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3177 case SD_BUS_TYPE_BYTE:
3179 *(uint8_t*) p = *(uint8_t*) q;
3182 case SD_BUS_TYPE_BOOLEAN:
3184 *(int*) p = !!*(uint8_t*) q;
3187 case SD_BUS_TYPE_INT16:
3188 case SD_BUS_TYPE_UINT16:
3190 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3193 case SD_BUS_TYPE_INT32:
3194 case SD_BUS_TYPE_UINT32:
3196 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3199 case SD_BUS_TYPE_INT64:
3200 case SD_BUS_TYPE_UINT64:
3201 case SD_BUS_TYPE_DOUBLE:
3203 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3206 case SD_BUS_TYPE_UNIX_FD: {
3209 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3214 *(int*) p = m->fds[j];
3220 assert_not_reached("unexpected type");
3224 r = container_next_item(m, c, &rindex);
3231 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3235 r = message_peek_body(m, &rindex, 4, 4, &q);
3239 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3240 r = message_peek_body(m, &rindex, 1, l+1, &q);
3246 if (type == SD_BUS_TYPE_OBJECT_PATH)
3247 ok = validate_object_path(q, l);
3249 ok = validate_string(q, l);
3254 *(const char**) p = q;
3256 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3259 r = message_peek_body(m, &rindex, 1, 1, &q);
3264 r = message_peek_body(m, &rindex, 1, l+1, &q);
3270 if (!validate_signature(q, l))
3274 *(const char**) p = q;
3279 align = bus_type_get_alignment(type);
3282 sz = bus_type_get_size(type);
3285 r = message_peek_body(m, &rindex, align, sz, &q);
3291 case SD_BUS_TYPE_BYTE:
3293 *(uint8_t*) p = *(uint8_t*) q;
3296 case SD_BUS_TYPE_BOOLEAN:
3298 *(int*) p = !!*(uint32_t*) q;
3301 case SD_BUS_TYPE_INT16:
3302 case SD_BUS_TYPE_UINT16:
3304 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3307 case SD_BUS_TYPE_INT32:
3308 case SD_BUS_TYPE_UINT32:
3310 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3313 case SD_BUS_TYPE_INT64:
3314 case SD_BUS_TYPE_UINT64:
3315 case SD_BUS_TYPE_DOUBLE:
3317 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3320 case SD_BUS_TYPE_UNIX_FD: {
3323 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3328 *(int*) p = m->fds[j];
3333 assert_not_reached("Unknown basic type...");
3340 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3346 static int bus_message_enter_array(
3348 struct bus_container *c,
3349 const char *contents,
3350 uint32_t **array_size,
3353 size_t *n_offsets) {
3367 if (!signature_is_single(contents, true))
3370 if (!c->signature || c->signature[c->index] == 0)
3373 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3376 if (!startswith(c->signature + c->index + 1, contents))
3381 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3384 r = message_peek_body(m, &rindex, 4, 4, &q);
3388 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3391 alignment = bus_type_get_alignment(contents[0]);
3395 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3401 *array_size = (uint32_t*) q;
3403 } else if (c->item_size <= 0) {
3405 /* gvariant: empty array */
3410 } else if (bus_gvariant_is_fixed_size(contents)) {
3412 /* gvariant: fixed length array */
3413 *item_size = bus_gvariant_get_size(contents);
3418 size_t where, p = 0, framing, sz;
3421 /* gvariant: variable length array */
3422 sz = determine_word_size(c->item_size, 0);
3424 where = rindex + c->item_size - sz;
3425 r = message_peek_body(m, &where, 1, sz, &q);
3431 framing = read_word_le(q, sz);
3432 if (framing > c->item_size - sz)
3434 if ((c->item_size - framing) % sz != 0)
3437 *n_offsets = (c->item_size - framing) / sz;
3439 where = rindex + framing;
3440 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3446 *offsets = new(size_t, *n_offsets);
3450 for (i = 0; i < *n_offsets; i++) {
3453 x = read_word_le((uint8_t*) q + i * sz, sz);
3454 if (x > c->item_size - sz)
3459 (*offsets)[i] = rindex + x;
3463 *item_size = (*offsets)[0] - rindex;
3468 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3469 c->index += 1 + strlen(contents);
3474 static int bus_message_enter_variant(
3476 struct bus_container *c,
3477 const char *contents,
3478 size_t *item_size) {
3490 if (!signature_is_single(contents, false))
3493 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3496 if (!c->signature || c->signature[c->index] == 0)
3499 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3504 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3507 k = strlen(contents);
3508 if (1+k > c->item_size)
3511 where = rindex + c->item_size - (1+k);
3512 r = message_peek_body(m, &where, 1, 1+k, &q);
3518 if (*(char*) q != 0)
3521 if (memcmp((uint8_t*) q+1, contents, k))
3524 *item_size = c->item_size - (1+k);
3527 r = message_peek_body(m, &rindex, 1, 1, &q);
3534 r = message_peek_body(m, &rindex, 1, l+1, &q);
3540 if (!validate_signature(q, l))
3543 if (!streq(q, contents))
3549 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3555 static int build_struct_offsets(
3557 const char *signature,
3561 size_t *n_offsets) {
3563 unsigned n_variable = 0, n_total = 0, v;
3564 size_t previous = 0, where;
3576 sz = determine_word_size(size, 0);
3578 /* First, loop over signature and count variable elements and
3579 * elements in general. We use this to know how large the
3580 * offset array is at the end of the structure. Note that
3581 * GVariant only stores offsets for all variable size elements
3582 * that are not the last item. */
3588 r = signature_element_length(p, &n);
3597 r = bus_gvariant_is_fixed_size(t);
3602 if (r == 0 && p[n] != 0) /* except the last item */
3609 if (size < n_variable * sz)
3612 where = m->rindex + size - (n_variable * sz);
3613 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3621 *offsets = new(size_t, n_total);
3627 /* Second, loop again and build an offset table */
3633 r = signature_element_length(p, &n);
3642 k = bus_gvariant_get_size(t);
3650 x = read_word_le((uint8_t*) q + v*sz, sz);
3653 if (m->rindex + x < previous)
3656 /* The last item's end
3657 * is determined from
3660 x = size - (n_variable * sz);
3662 offset = m->rindex + x;
3668 align = bus_gvariant_get_alignment(t);
3671 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3675 previous = (*offsets)[(*n_offsets)++] = offset;
3680 assert(*n_offsets == n_total);
3682 *item_size = (*offsets)[0] - m->rindex;
3686 static int enter_struct_or_dict_entry(
3688 struct bus_container *c,
3689 const char *contents,
3692 size_t *n_offsets) {
3703 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3706 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3710 } else if (c->item_size <= 0) {
3712 /* gvariant empty struct */
3717 /* gvariant with contents */
3718 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3723 static int bus_message_enter_struct(
3725 struct bus_container *c,
3726 const char *contents,
3729 size_t *n_offsets) {
3741 if (!signature_is_valid(contents, false))
3744 if (!c->signature || c->signature[c->index] == 0)
3747 l = strlen(contents);
3749 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3750 !startswith(c->signature + c->index + 1, contents) ||
3751 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3754 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3758 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3759 c->index += 1 + l + 1;
3764 static int bus_message_enter_dict_entry(
3766 struct bus_container *c,
3767 const char *contents,
3770 size_t *n_offsets) {
3779 if (!signature_is_pair(contents))
3782 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3785 if (!c->signature || c->signature[c->index] == 0)
3788 l = strlen(contents);
3790 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3791 !startswith(c->signature + c->index + 1, contents) ||
3792 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3795 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3799 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3800 c->index += 1 + l + 1;
3805 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3807 const char *contents) {
3808 struct bus_container *c, *w;
3809 uint32_t *array_size = NULL;
3812 size_t *offsets = NULL;
3813 size_t n_offsets = 0, item_size = 0;
3816 assert_return(m, -EINVAL);
3817 assert_return(m->sealed, -EPERM);
3818 assert_return(type != 0 || !contents, -EINVAL);
3820 if (type == 0 || !contents) {
3824 /* Allow entering into anonymous containers */
3825 r = sd_bus_message_peek_type(m, &tt, &cc);
3829 if (type != 0 && type != tt)
3832 if (contents && !streq(contents, cc))
3840 * We enforce a global limit on container depth, that is much
3841 * higher than the 32 structs and 32 arrays the specification
3842 * mandates. This is simpler to implement for us, and we need
3843 * this only to ensure our container array doesn't grow
3844 * without bounds. We are happy to return any data from a
3845 * message as long as the data itself is valid, even if the
3846 * overall message might be not.
3848 * Note that the message signature is validated when
3849 * parsing the headers, and that validation does check the
3852 * Note that the specification defines no limits on the depth
3853 * of stacked variants, but we do.
3855 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3858 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
3863 if (message_end_of_signature(m))
3866 if (message_end_of_array(m, m->rindex))
3869 c = message_get_container(m);
3871 signature = strdup(contents);
3875 c->saved_index = c->index;
3878 if (type == SD_BUS_TYPE_ARRAY)
3879 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3880 else if (type == SD_BUS_TYPE_VARIANT)
3881 r = bus_message_enter_variant(m, c, contents, &item_size);
3882 else if (type == SD_BUS_TYPE_STRUCT)
3883 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3884 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3885 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3895 /* OK, let's fill it in */
3896 w += m->n_containers++;
3897 w->enclosing = type;
3898 w->signature = signature;
3902 w->begin = m->rindex;
3903 w->end = m->rindex + c->item_size;
3905 w->array_size = array_size;
3906 w->item_size = item_size;
3907 w->offsets = offsets;
3908 w->n_offsets = n_offsets;
3909 w->offset_index = 0;
3914 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3915 struct bus_container *c;
3918 assert_return(m, -EINVAL);
3919 assert_return(m->sealed, -EPERM);
3920 assert_return(m->n_containers > 0, -ENXIO);
3922 c = message_get_container(m);
3924 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3925 if (c->signature && c->signature[c->index] != 0)
3929 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3930 if (m->rindex < c->end)
3933 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3936 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3937 if (c->begin + l != m->rindex)
3945 c = message_get_container(m);
3947 r = container_next_item(m, c, &m->rindex);
3954 static void message_quit_container(sd_bus_message *m) {
3955 struct bus_container *c;
3959 assert(m->n_containers > 0);
3961 c = message_get_container(m);
3964 assert(m->rindex >= c->before);
3965 m->rindex = c->before;
3967 /* Free container */
3972 /* Correct index of new top-level container */
3973 c = message_get_container(m);
3974 c->index = c->saved_index;
3977 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
3978 struct bus_container *c;
3981 assert_return(m, -EINVAL);
3982 assert_return(m->sealed, -EPERM);
3984 if (message_end_of_signature(m))
3987 if (message_end_of_array(m, m->rindex))
3990 c = message_get_container(m);
3992 if (bus_type_is_basic(c->signature[c->index])) {
3996 *type = c->signature[c->index];
4000 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4006 r = signature_element_length(c->signature+c->index+1, &l);
4012 sig = strndup(c->signature + c->index + 1, l);
4016 free(m->peeked_signature);
4017 m->peeked_signature = sig;
4023 *type = SD_BUS_TYPE_ARRAY;
4028 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4029 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4035 r = signature_element_length(c->signature+c->index, &l);
4040 sig = strndup(c->signature + c->index + 1, l - 2);
4044 free(m->peeked_signature);
4045 m->peeked_signature = sig;
4051 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4056 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4060 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4063 if (c->item_size < 2)
4066 /* Look for the NUL delimiter that
4067 separates the payload from the
4068 signature. Since the body might be
4069 in a different part that then the
4070 signature we map byte by byte. */
4072 for (k = 2; k <= c->item_size; k++) {
4075 where = m->rindex + c->item_size - k;
4076 r = message_peek_body(m, &where, 1, k, &q);
4082 if (*(char*) q == 0)
4086 if (k > c->item_size)
4089 free(m->peeked_signature);
4090 m->peeked_signature = strndup((char*) q + 1, k - 1);
4091 if (!m->peeked_signature)
4094 if (!signature_is_valid(m->peeked_signature, true))
4097 *contents = m->peeked_signature;
4102 r = message_peek_body(m, &rindex, 1, 1, &q);
4109 r = message_peek_body(m, &rindex, 1, l+1, &q);
4115 if (!validate_signature(q, l))
4123 *type = SD_BUS_TYPE_VARIANT;
4138 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4139 struct bus_container *c;
4141 assert_return(m, -EINVAL);
4142 assert_return(m->sealed, -EPERM);
4145 message_reset_containers(m);
4148 c = message_get_container(m);
4150 c = message_get_container(m);
4152 c->offset_index = 0;
4154 m->rindex = c->begin;
4157 return !isempty(c->signature);
4160 static int message_read_ap(
4165 unsigned n_array, n_struct;
4166 TypeStack stack[BUS_CONTAINER_DEPTH];
4167 unsigned stack_ptr = 0;
4168 unsigned n_loop = 0;
4176 /* Ideally, we'd just call ourselves recursively on every
4177 * complex type. However, the state of a va_list that is
4178 * passed to a function is undefined after that function
4179 * returns. This means we need to docode the va_list linearly
4180 * in a single stackframe. We hence implement our own
4181 * home-grown stack in an array. */
4183 n_array = (unsigned) -1; /* lenght of current array entries */
4184 n_struct = strlen(types); /* length of current struct contents signature */
4191 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4192 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4198 r = sd_bus_message_exit_container(m);
4206 if (n_array != (unsigned) -1)
4215 case SD_BUS_TYPE_BYTE:
4216 case SD_BUS_TYPE_BOOLEAN:
4217 case SD_BUS_TYPE_INT16:
4218 case SD_BUS_TYPE_UINT16:
4219 case SD_BUS_TYPE_INT32:
4220 case SD_BUS_TYPE_UINT32:
4221 case SD_BUS_TYPE_INT64:
4222 case SD_BUS_TYPE_UINT64:
4223 case SD_BUS_TYPE_DOUBLE:
4224 case SD_BUS_TYPE_STRING:
4225 case SD_BUS_TYPE_OBJECT_PATH:
4226 case SD_BUS_TYPE_SIGNATURE:
4227 case SD_BUS_TYPE_UNIX_FD: {
4230 p = va_arg(ap, void*);
4231 r = sd_bus_message_read_basic(m, *t, p);
4244 case SD_BUS_TYPE_ARRAY: {
4247 r = signature_element_length(t + 1, &k);
4253 memcpy(s, t + 1, k);
4256 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4267 if (n_array == (unsigned) -1) {
4272 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4278 n_array = va_arg(ap, unsigned);
4283 case SD_BUS_TYPE_VARIANT: {
4286 s = va_arg(ap, const char *);
4290 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4300 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4305 n_struct = strlen(s);
4306 n_array = (unsigned) -1;
4311 case SD_BUS_TYPE_STRUCT_BEGIN:
4312 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4315 r = signature_element_length(t, &k);
4321 memcpy(s, t + 1, k - 2);
4324 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4334 if (n_array == (unsigned) -1) {
4339 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4345 n_array = (unsigned) -1;
4358 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4362 assert_return(m, -EINVAL);
4363 assert_return(m->sealed, -EPERM);
4364 assert_return(types, -EINVAL);
4366 va_start(ap, types);
4367 r = message_read_ap(m, types, ap);
4373 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4376 assert_return(m, -EINVAL);
4377 assert_return(m->sealed, -EPERM);
4378 assert_return(types, -EINVAL);
4385 case SD_BUS_TYPE_BYTE:
4386 case SD_BUS_TYPE_BOOLEAN:
4387 case SD_BUS_TYPE_INT16:
4388 case SD_BUS_TYPE_UINT16:
4389 case SD_BUS_TYPE_INT32:
4390 case SD_BUS_TYPE_UINT32:
4391 case SD_BUS_TYPE_INT64:
4392 case SD_BUS_TYPE_UINT64:
4393 case SD_BUS_TYPE_DOUBLE:
4394 case SD_BUS_TYPE_STRING:
4395 case SD_BUS_TYPE_OBJECT_PATH:
4396 case SD_BUS_TYPE_SIGNATURE:
4397 case SD_BUS_TYPE_UNIX_FD:
4399 r = sd_bus_message_read_basic(m, *types, NULL);
4403 r = sd_bus_message_skip(m, types + 1);
4409 case SD_BUS_TYPE_ARRAY: {
4412 r = signature_element_length(types + 1, &k);
4418 memcpy(s, types+1, k);
4421 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4426 r = sd_bus_message_skip(m, s);
4433 r = sd_bus_message_exit_container(m);
4438 r = sd_bus_message_skip(m, types + 1 + k);
4445 case SD_BUS_TYPE_VARIANT: {
4446 const char *contents;
4449 r = sd_bus_message_peek_type(m, &x, &contents);
4453 if (x != SD_BUS_TYPE_VARIANT)
4456 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4460 r = sd_bus_message_skip(m, contents);
4465 r = sd_bus_message_exit_container(m);
4469 r = sd_bus_message_skip(m, types + 1);
4476 case SD_BUS_TYPE_STRUCT_BEGIN:
4477 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4480 r = signature_element_length(types, &k);
4486 memcpy(s, types+1, k-2);
4489 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4493 r = sd_bus_message_skip(m, s);
4498 r = sd_bus_message_exit_container(m);
4503 r = sd_bus_message_skip(m, types + k);
4515 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4519 struct bus_container *c;
4525 assert_return(m, -EINVAL);
4526 assert_return(m->sealed, -EPERM);
4527 assert_return(bus_type_is_trivial(type), -EINVAL);
4528 assert_return(ptr, -EINVAL);
4529 assert_return(size, -EINVAL);
4530 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4532 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4536 c = message_get_container(m);
4538 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4539 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4545 align = bus_type_get_alignment(type);
4549 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4553 /* Zero length array, let's return some aligned
4554 * pointer that is not NULL */
4555 p = (uint8_t*) NULL + align;
4557 r = message_peek_body(m, &m->rindex, align, sz, &p);
4566 r = sd_bus_message_exit_container(m);
4570 *ptr = (const void*) p;
4576 message_quit_container(m);
4580 static int message_peek_fields(
4591 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4594 static int message_peek_field_uint32(
4606 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4609 /* identical for gvariant and dbus1 */
4611 r = message_peek_fields(m, ri, 4, 4, &q);
4616 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4621 static int message_peek_field_string(
4623 bool (*validate)(const char *p),
4635 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4640 r = message_peek_fields(m, ri, 1, item_size, &q);
4646 r = message_peek_field_uint32(m, ri, 4, &l);
4650 r = message_peek_fields(m, ri, 1, l+1, &q);
4656 if (!validate_nul(q, l))
4662 if (!validate_string(q, l))
4672 static int message_peek_field_signature(
4685 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4690 r = message_peek_fields(m, ri, 1, item_size, &q);
4696 r = message_peek_fields(m, ri, 1, 1, &q);
4701 r = message_peek_fields(m, ri, 1, l+1, &q);
4706 if (!validate_signature(q, l))
4715 static int message_skip_fields(
4718 uint32_t array_size,
4719 const char **signature) {
4721 size_t original_index;
4727 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4729 original_index = *ri;
4735 if (array_size != (uint32_t) -1 &&
4736 array_size <= *ri - original_index)
4743 if (t == SD_BUS_TYPE_STRING) {
4745 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4751 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4753 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4759 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4761 r = message_peek_field_signature(m, ri, 0, NULL);
4767 } else if (bus_type_is_basic(t)) {
4770 align = bus_type_get_alignment(t);
4771 k = bus_type_get_size(t);
4772 assert(align > 0 && k > 0);
4774 r = message_peek_fields(m, ri, align, k, NULL);
4780 } else if (t == SD_BUS_TYPE_ARRAY) {
4782 r = signature_element_length(*signature+1, &l);
4792 strncpy(sig, *signature + 1, l-1);
4795 alignment = bus_type_get_alignment(sig[0]);
4799 r = message_peek_field_uint32(m, ri, 0, &nas);
4802 if (nas > BUS_ARRAY_MAX_SIZE)
4805 r = message_peek_fields(m, ri, alignment, 0, NULL);
4809 r = message_skip_fields(m, ri, nas, (const char**) &s);
4814 (*signature) += 1 + l;
4816 } else if (t == SD_BUS_TYPE_VARIANT) {
4819 r = message_peek_field_signature(m, ri, 0, &s);
4823 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4829 } else if (t == SD_BUS_TYPE_STRUCT ||
4830 t == SD_BUS_TYPE_DICT_ENTRY) {
4832 r = signature_element_length(*signature, &l);
4839 strncpy(sig, *signature + 1, l-1);
4842 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4853 int bus_message_parse_fields(sd_bus_message *m) {
4856 uint32_t unix_fds = 0;
4857 void *offsets = NULL;
4858 unsigned n_offsets = 0;
4864 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4867 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4871 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4872 r = message_peek_fields(m, &ri, 1, sz, &q);
4876 framing = read_word_le(q, sz);
4877 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4879 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4883 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4887 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4892 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4893 _cleanup_free_ char *sig = NULL;
4894 const char *signature;
4896 size_t item_size = (size_t) -1;
4898 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4905 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4908 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4912 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4917 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4922 where = ri = ALIGN_TO(ri, 8);
4923 item_size = end - ri;
4924 r = message_peek_fields(m, &where, 1, item_size, &q);
4928 b = memrchr(q, 0, item_size);
4932 sig = strndup(b+1, item_size - (b+1-(char*) q));
4937 item_size = b - (char*) q;
4939 r = message_peek_field_signature(m, &ri, 0, &signature);
4945 case _BUS_MESSAGE_HEADER_INVALID:
4948 case BUS_MESSAGE_HEADER_PATH:
4953 if (!streq(signature, "o"))
4956 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
4959 case BUS_MESSAGE_HEADER_INTERFACE:
4964 if (!streq(signature, "s"))
4967 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
4970 case BUS_MESSAGE_HEADER_MEMBER:
4975 if (!streq(signature, "s"))
4978 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
4981 case BUS_MESSAGE_HEADER_ERROR_NAME:
4986 if (!streq(signature, "s"))
4989 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
4991 m->error._need_free = -1;
4995 case BUS_MESSAGE_HEADER_DESTINATION:
5000 if (!streq(signature, "s"))
5003 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5006 case BUS_MESSAGE_HEADER_SENDER:
5011 if (!streq(signature, "s"))
5014 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5016 if (r >= 0 && m->sender[0] == ':' && m->bus && m->bus->bus_client && !m->bus->is_kernel) {
5017 m->creds.unique_name = (char*) m->sender;
5018 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5024 case BUS_MESSAGE_HEADER_SIGNATURE: {
5028 if (m->root_container.signature)
5031 if (!streq(signature, "g"))
5034 r = message_peek_field_signature(m, &ri, item_size, &s);
5042 free(m->root_container.signature);
5043 m->root_container.signature = c;
5047 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5048 if (m->reply_serial != 0)
5051 if (!streq(signature, "u"))
5054 r = message_peek_field_uint32(m, &ri, item_size, &m->reply_serial);
5058 if (m->reply_serial == 0)
5063 case BUS_MESSAGE_HEADER_UNIX_FDS:
5067 if (!streq(signature, "u"))
5070 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5080 if (!BUS_MESSAGE_IS_GVARIANT(m))
5081 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5090 if (m->n_fds != unix_fds)
5093 if (isempty(m->root_container.signature) != (BUS_MESSAGE_BODY_SIZE(m) == 0))
5096 switch (m->header->type) {
5098 case SD_BUS_MESSAGE_SIGNAL:
5099 if (!m->path || !m->interface || !m->member)
5103 case SD_BUS_MESSAGE_METHOD_CALL:
5105 if (!m->path || !m->member)
5110 case SD_BUS_MESSAGE_METHOD_RETURN:
5112 if (m->reply_serial == 0)
5116 case SD_BUS_MESSAGE_METHOD_ERROR:
5118 if (m->reply_serial == 0 || !m->error.name)
5123 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5125 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5126 r = build_struct_offsets(
5128 m->root_container.signature,
5129 BUS_MESSAGE_BODY_SIZE(m),
5130 &m->root_container.item_size,
5131 &m->root_container.offsets,
5132 &m->root_container.n_offsets);
5137 /* Try to read the error message, but if we can't it's a non-issue */
5138 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5139 sd_bus_message_read(m, "s", &m->error.message);
5144 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5145 assert_return(m, -EINVAL);
5146 assert_return(destination, -EINVAL);
5147 assert_return(!m->sealed, -EPERM);
5148 assert_return(!m->destination, -EEXIST);
5150 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5153 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5157 struct bus_body_part *part;
5163 total = BUS_MESSAGE_SIZE(m);
5169 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5170 MESSAGE_FOREACH_PART(part, i, m)
5171 e = mempcpy(e, part->data, part->size);
5173 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5181 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5187 r = sd_bus_message_enter_container(m, 'a', "s");
5194 r = sd_bus_message_read_basic(m, 's', &s);
5200 r = strv_extend(l, s);
5205 r = sd_bus_message_exit_container(m);
5212 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5216 assert_return(m, -EINVAL);
5217 assert_return(m->sealed, -EPERM);
5218 assert_return(l, -EINVAL);
5220 r = bus_message_read_strv_extend(m, &strv);
5230 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5232 const char *t = NULL;
5237 r = sd_bus_message_rewind(m, true);
5241 for (j = 0; j <= i; j++) {
5244 r = sd_bus_message_peek_type(m, &type, NULL);
5248 if (type != SD_BUS_TYPE_STRING &&
5249 type != SD_BUS_TYPE_OBJECT_PATH &&
5250 type != SD_BUS_TYPE_SIGNATURE)
5253 r = sd_bus_message_read_basic(m, type, &t);
5261 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5267 if (size < sizeof(struct bus_header))
5270 full = sizeof(struct bus_header) +
5271 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5273 return size >= full;
5276 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5282 if (h->endian == BUS_NATIVE_ENDIAN) {
5283 fs = h->fields_size;
5285 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5286 fs = bswap_32(h->fields_size);
5287 bs = bswap_32(h->body_size);
5291 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5295 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5296 assert_return(m, -EINVAL);
5298 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5301 return sd_bus_error_get_errno(&m->error);
5304 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5305 struct bus_container *c;
5307 assert_return(m, NULL);
5309 c = complete ? &m->root_container : message_get_container(m);
5310 return c->signature ?: "";
5313 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5314 bool done_something = false;
5317 assert_return(m, -EINVAL);
5318 assert_return(source, -EINVAL);
5319 assert_return(!m->sealed, -EPERM);
5320 assert_return(source->sealed, -EPERM);
5323 const char *contents;
5338 r = sd_bus_message_peek_type(source, &type, &contents);
5344 done_something = true;
5346 if (bus_type_is_container(type) > 0) {
5348 r = sd_bus_message_enter_container(source, type, contents);
5352 r = sd_bus_message_open_container(m, type, contents);
5356 r = sd_bus_message_copy(m, source, true);
5360 r = sd_bus_message_close_container(m);
5364 r = sd_bus_message_exit_container(source);
5371 r = sd_bus_message_read_basic(source, type, &basic);
5377 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5378 type == SD_BUS_TYPE_SIGNATURE ||
5379 type == SD_BUS_TYPE_STRING)
5380 r = sd_bus_message_append_basic(m, type, basic.string);
5382 r = sd_bus_message_append_basic(m, type, &basic);
5389 return done_something;
5392 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5397 assert_return(m, -EINVAL);
5398 assert_return(m->sealed, -EPERM);
5399 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5400 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5401 assert_return(type || contents, -EINVAL);
5402 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5404 r = sd_bus_message_peek_type(m, &t, &c);
5408 if (type != 0 && type != t)
5411 if (contents && !streq_ptr(contents, c))
5417 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5418 assert_return(m, NULL);