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) {
798 assert(m->n_ref > 0);
807 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
808 assert_return(m, -EINVAL);
809 assert_return(type, -EINVAL);
811 *type = m->header->type;
815 _public_ int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
816 assert_return(m, -EINVAL);
817 assert_return(serial, -EINVAL);
818 assert_return(m->header->serial != 0, -ENOENT);
820 *serial = BUS_MESSAGE_SERIAL(m);
824 _public_ int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
825 assert_return(m, -EINVAL);
826 assert_return(serial, -EINVAL);
827 assert_return(m->reply_serial != 0, -ENOENT);
829 *serial = m->reply_serial;
833 _public_ int sd_bus_message_get_no_reply(sd_bus_message *m) {
834 assert_return(m, -EINVAL);
836 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL ? !!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
839 _public_ int sd_bus_message_get_no_auto_start(sd_bus_message *m) {
840 assert_return(m, -EINVAL);
842 return !!(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
845 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
846 assert_return(m, NULL);
851 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
852 assert_return(m, NULL);
857 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
858 assert_return(m, NULL);
863 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
864 assert_return(m, NULL);
866 return m->destination;
869 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
870 assert_return(m, NULL);
875 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
876 assert_return(m, NULL);
877 assert_return(sd_bus_error_is_set(&m->error), NULL);
882 _public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
883 assert_return(m, -EINVAL);
884 assert_return(usec, -EINVAL);
885 assert_return(m->monotonic > 0, -ENODATA);
887 *usec = m->monotonic;
891 _public_ int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
892 assert_return(m, -EINVAL);
893 assert_return(usec, -EINVAL);
894 assert_return(m->realtime > 0, -ENODATA);
900 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
901 assert_return(m, NULL);
903 if (m->creds.mask == 0)
909 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
910 const char *interface,
911 const char *member) {
912 assert_return(m, -EINVAL);
914 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
917 if (interface && (!m->interface || !streq(m->interface, interface)))
920 if (member && (!m->member || !streq(m->member, member)))
926 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
927 const char *interface,
928 const char *member) {
929 assert_return(m, -EINVAL);
931 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
934 if (interface && (!m->interface || !streq(m->interface, interface)))
937 if (member && (!m->member || !streq(m->member, member)))
943 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
944 assert_return(m, -EINVAL);
946 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
949 if (name && (!m->error.name || !streq(m->error.name, name)))
955 _public_ int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
956 assert_return(m, -EINVAL);
957 assert_return(!m->sealed, -EPERM);
958 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
961 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
963 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
968 _public_ int sd_bus_message_set_no_auto_start(sd_bus_message *m, int b) {
969 assert_return(m, -EINVAL);
970 assert_return(!m->sealed, -EPERM);
973 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
975 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
980 static struct bus_container *message_get_container(sd_bus_message *m) {
983 if (m->n_containers == 0)
984 return &m->root_container;
986 assert(m->containers);
987 return m->containers + m->n_containers - 1;
990 struct bus_body_part *message_append_part(sd_bus_message *m) {
991 struct bus_body_part *part;
998 if (m->n_body_parts <= 0) {
1002 assert(m->body_end);
1004 part = new0(struct bus_body_part, 1);
1010 m->body_end->next = part;
1020 static void part_zero(struct bus_body_part *part, size_t sz) {
1025 /* All other fields can be left in their defaults */
1026 assert(!part->data);
1027 assert(part->memfd < 0);
1030 part->is_zero = true;
1031 part->sealed = true;
1034 static int part_make_space(
1035 struct sd_bus_message *m,
1036 struct bus_body_part *part,
1045 assert(!part->sealed);
1050 if (!part->data && part->memfd < 0)
1051 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped);
1053 if (part->memfd >= 0) {
1056 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &u);
1062 if (!part->data || sz > part->mapped) {
1063 size_t psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1065 if (part->mapped <= 0)
1066 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1068 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1070 if (n == MAP_FAILED) {
1079 part->munmap_this = true;
1081 n = realloc(part->data, MAX(sz, 1u));
1088 part->free_this = true;
1092 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1098 static int message_add_offset(sd_bus_message *m, size_t offset) {
1099 struct bus_container *c;
1102 assert(BUS_MESSAGE_IS_GVARIANT(m));
1104 /* Add offset to current container, unless this is the first
1105 * item in it, which will have the 0 offset, which we can
1107 c = message_get_container(m);
1109 if (!c->need_offsets)
1112 if (!GREEDY_REALLOC(c->offsets, c->n_offsets_allocated, c->n_offsets + 1))
1115 c->offsets[c->n_offsets++] = offset;
1119 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1120 struct bus_container *c;
1127 /* Update counters */
1128 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1131 *c->array_size += expand;
1135 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1136 size_t start_body, end_body, padding, 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 struct bus_body_part *part = NULL;
1164 m->n_body_parts <= 0 ||
1165 m->body_end->sealed ||
1166 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1170 part = message_append_part(m);
1174 part_zero(part, padding);
1177 part = message_append_part(m);
1181 r = part_make_space(m, part, sz, &p);
1185 struct bus_container *c;
1187 size_t os, start_part, end_part;
1193 start_part = ALIGN_TO(part->size, align);
1194 end_part = start_part + sz;
1196 r = part_make_space(m, part, end_part, &p);
1201 memset(p, 0, padding);
1202 p = (uint8_t*) p + padding;
1205 /* Readjust pointers */
1206 for (c = m->containers; c < m->containers + m->n_containers; c++)
1207 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1209 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1212 /* Return something that is not NULL and is aligned */
1213 p = (uint8_t *) NULL + align;
1215 m->header->body_size = end_body;
1216 message_extend_containers(m, added);
1219 r = message_add_offset(m, end_body);
1229 static int message_push_fd(sd_bus_message *m, int fd) {
1240 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1244 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1247 close_nointr_nofail(copy);
1252 m->fds[m->n_fds] = copy;
1258 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1259 _cleanup_close_ int fd = -1;
1260 struct bus_container *c;
1264 assert_return(m, -EINVAL);
1265 assert_return(!m->sealed, -EPERM);
1266 assert_return(bus_type_is_basic(type), -EINVAL);
1267 assert_return(!m->poisoned, -ESTALE);
1269 c = message_get_container(m);
1271 if (c->signature && c->signature[c->index]) {
1272 /* Container signature is already set */
1274 if (c->signature[c->index] != type)
1279 /* Maybe we can append to the signature? But only if this is the top-level container*/
1280 if (c->enclosing != 0)
1283 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1290 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1296 case SD_BUS_TYPE_SIGNATURE:
1297 case SD_BUS_TYPE_STRING:
1300 /* Fall through... */
1301 case SD_BUS_TYPE_OBJECT_PATH:
1309 case SD_BUS_TYPE_BOOLEAN:
1311 u8 = p && *(int*) p;
1317 case SD_BUS_TYPE_UNIX_FD:
1322 fd = message_push_fd(m, *(int*) p);
1333 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1334 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1341 a = message_extend_body(m, align, sz, true);
1348 *stored = (const uint8_t*) a;
1355 case SD_BUS_TYPE_STRING:
1356 /* To make things easy we'll serialize a NULL string
1357 * into the empty string */
1360 /* Fall through... */
1361 case SD_BUS_TYPE_OBJECT_PATH:
1367 sz = 4 + strlen(p) + 1;
1370 case SD_BUS_TYPE_SIGNATURE:
1375 sz = 1 + strlen(p) + 1;
1378 case SD_BUS_TYPE_BOOLEAN:
1380 u32 = p && *(int*) p;
1386 case SD_BUS_TYPE_UNIX_FD:
1391 fd = message_push_fd(m, *(int*) p);
1402 align = bus_type_get_alignment(type);
1403 sz = bus_type_get_size(type);
1410 a = message_extend_body(m, align, sz, false);
1414 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1415 *(uint32_t*) a = sz - 5;
1416 memcpy((uint8_t*) a + 4, p, sz - 4);
1419 *stored = (const uint8_t*) a + 4;
1421 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1422 *(uint8_t*) a = sz - 1;
1423 memcpy((uint8_t*) a + 1, p, sz - 1);
1426 *stored = (const uint8_t*) a + 1;
1435 if (type == SD_BUS_TYPE_UNIX_FD)
1438 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1445 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1446 return message_append_basic(m, type, p, NULL);
1449 _public_ int sd_bus_message_append_string_space(
1454 struct bus_container *c;
1457 assert_return(m, -EINVAL);
1458 assert_return(s, -EINVAL);
1459 assert_return(!m->sealed, -EPERM);
1460 assert_return(!m->poisoned, -ESTALE);
1462 c = message_get_container(m);
1464 if (c->signature && c->signature[c->index]) {
1465 /* Container signature is already set */
1467 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1472 /* Maybe we can append to the signature? But only if this is the top-level container*/
1473 if (c->enclosing != 0)
1476 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1483 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1484 a = message_extend_body(m, 1, size + 1, true);
1490 a = message_extend_body(m, 4, 4 + size + 1, false);
1494 *(uint32_t*) a = size;
1500 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1506 _public_ int sd_bus_message_append_string_iovec(
1508 const struct iovec *iov,
1516 assert_return(m, -EINVAL);
1517 assert_return(!m->sealed, -EPERM);
1518 assert_return(iov || n == 0, -EINVAL);
1519 assert_return(!m->poisoned, -ESTALE);
1521 size = IOVEC_TOTAL_SIZE(iov, n);
1523 r = sd_bus_message_append_string_space(m, size, &p);
1527 for (i = 0; i < n; i++) {
1529 if (iov[i].iov_base)
1530 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1532 memset(p, ' ', iov[i].iov_len);
1534 p += iov[i].iov_len;
1540 static int bus_message_open_array(
1542 struct bus_container *c,
1543 const char *contents,
1544 uint32_t **array_size,
1546 bool *need_offsets) {
1556 assert(need_offsets);
1558 if (!signature_is_single(contents, true))
1561 if (c->signature && c->signature[c->index]) {
1563 /* Verify the existing signature */
1565 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1568 if (!startswith(c->signature + c->index + 1, contents))
1571 nindex = c->index + 1 + strlen(contents);
1575 if (c->enclosing != 0)
1578 /* Extend the existing signature */
1580 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1586 nindex = e - c->signature;
1589 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1590 alignment = bus_gvariant_get_alignment(contents);
1594 /* Add alignment padding and add to offset list */
1595 if (!message_extend_body(m, alignment, 0, false))
1598 r = bus_gvariant_is_fixed_size(contents);
1602 *begin = m->header->body_size;
1603 *need_offsets = r == 0;
1607 struct bus_body_part *o;
1609 alignment = bus_type_get_alignment(contents[0]);
1613 a = message_extend_body(m, 4, 4, false);
1618 op = m->body_end->data;
1619 os = m->body_end->size;
1621 /* Add alignment between size and first element */
1622 if (!message_extend_body(m, alignment, 0, false))
1625 /* location of array size might have changed so let's readjust a */
1626 if (o == m->body_end)
1627 a = adjust_pointer(a, op, os, m->body_end->data);
1633 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1639 static int bus_message_open_variant(
1641 struct bus_container *c,
1642 const char *contents) {
1648 if (!signature_is_single(contents, false))
1651 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1654 if (c->signature && c->signature[c->index]) {
1656 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1662 if (c->enclosing != 0)
1665 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1672 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1673 /* Variants are always aligned to 8 */
1675 if (!message_extend_body(m, 8, 0, false))
1682 l = strlen(contents);
1683 a = message_extend_body(m, 1, 1 + l + 1, false);
1688 memcpy((uint8_t*) a + 1, contents, l + 1);
1691 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1697 static int bus_message_open_struct(
1699 struct bus_container *c,
1700 const char *contents,
1702 bool *need_offsets) {
1711 assert(need_offsets);
1713 if (!signature_is_valid(contents, false))
1716 if (c->signature && c->signature[c->index]) {
1719 l = strlen(contents);
1721 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1722 !startswith(c->signature + c->index + 1, contents) ||
1723 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1726 nindex = c->index + 1 + l + 1;
1730 if (c->enclosing != 0)
1733 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1739 nindex = e - c->signature;
1742 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1745 alignment = bus_gvariant_get_alignment(contents);
1749 if (!message_extend_body(m, alignment, 0, false))
1752 r = bus_gvariant_is_fixed_size(contents);
1756 *begin = m->header->body_size;
1757 *need_offsets = r == 0;
1759 /* Align contents to 8 byte boundary */
1760 if (!message_extend_body(m, 8, 0, false))
1764 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1770 static int bus_message_open_dict_entry(
1772 struct bus_container *c,
1773 const char *contents,
1775 bool *need_offsets) {
1783 assert(need_offsets);
1785 if (!signature_is_pair(contents))
1788 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1791 if (c->signature && c->signature[c->index]) {
1794 l = strlen(contents);
1796 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1797 !startswith(c->signature + c->index + 1, contents) ||
1798 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1803 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1806 alignment = bus_gvariant_get_alignment(contents);
1810 if (!message_extend_body(m, alignment, 0, false))
1813 r = bus_gvariant_is_fixed_size(contents);
1817 *begin = m->header->body_size;
1818 *need_offsets = r == 0;
1820 /* Align contents to 8 byte boundary */
1821 if (!message_extend_body(m, 8, 0, false))
1828 _public_ int sd_bus_message_open_container(
1831 const char *contents) {
1833 struct bus_container *c, *w;
1834 uint32_t *array_size = NULL;
1836 size_t before, begin;
1837 bool need_offsets = false;
1840 assert_return(m, -EINVAL);
1841 assert_return(!m->sealed, -EPERM);
1842 assert_return(contents, -EINVAL);
1843 assert_return(!m->poisoned, -ESTALE);
1845 /* Make sure we have space for one more container */
1846 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1854 c = message_get_container(m);
1856 signature = strdup(contents);
1862 /* Save old index in the parent container, in case we have to
1863 * abort this container */
1864 c->saved_index = c->index;
1865 before = m->header->body_size;
1867 if (type == SD_BUS_TYPE_ARRAY)
1868 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1869 else if (type == SD_BUS_TYPE_VARIANT)
1870 r = bus_message_open_variant(m, c, contents);
1871 else if (type == SD_BUS_TYPE_STRUCT)
1872 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1873 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1874 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1883 /* OK, let's fill it in */
1884 w += m->n_containers++;
1885 w->enclosing = type;
1886 w->signature = signature;
1888 w->array_size = array_size;
1891 w->n_offsets = w->n_offsets_allocated = 0;
1893 w->need_offsets = need_offsets;
1898 static size_t determine_word_size(size_t sz, size_t extra) {
1899 if (sz + extra <= 0xFF)
1901 else if (sz + extra*2 <= 0xFFFF)
1903 else if (sz + extra*4 <= 0xFFFFFFFF)
1909 static size_t read_word_le(void *p, size_t sz) {
1919 return *(uint8_t*) p;
1924 return le16toh(x.u16);
1926 return le32toh(x.u32);
1928 return le64toh(x.u64);
1930 assert_not_reached("unknown word width");
1933 static void write_word_le(void *p, size_t sz, size_t value) {
1941 assert(sz == 8 || (value < (1ULL << (sz*8))));
1944 *(uint8_t*) p = value;
1947 x.u16 = htole16((uint16_t) value);
1949 x.u32 = htole32((uint32_t) value);
1951 x.u64 = htole64((uint64_t) value);
1953 assert_not_reached("unknown word width");
1958 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1963 if (!BUS_MESSAGE_IS_GVARIANT(m))
1966 if (c->need_offsets) {
1967 size_t payload, sz, i;
1970 /* Variable-width arrays */
1972 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
1973 sz = determine_word_size(payload, c->n_offsets);
1975 a = message_extend_body(m, 1, sz * c->n_offsets, true);
1979 for (i = 0; i < c->n_offsets; i++)
1980 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
1984 /* Fixed-width or empty arrays */
1986 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
1994 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2001 if (!BUS_MESSAGE_IS_GVARIANT(m))
2004 l = strlen(c->signature);
2006 a = message_extend_body(m, 1, 1 + l, true);
2011 memcpy(a+1, c->signature, l);
2016 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2017 size_t n_variable = 0;
2026 if (!BUS_MESSAGE_IS_GVARIANT(m))
2029 p = strempty(c->signature);
2033 r = signature_element_length(p, &n);
2042 r = bus_gvariant_is_fixed_size(t);
2047 assert(i <= c->n_offsets);
2049 /* We need to add an offset for each item that has a
2050 * variable size and that is not the last one in the
2052 if (r == 0 && p[n] != 0)
2059 assert(i == c->n_offsets);
2061 if (n_variable <= 0) {
2062 a = message_extend_body(m, 1, 0, add_offset);
2069 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2071 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2073 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2077 p = strempty(c->signature);
2078 for (i = 0, j = 0; i < c->n_offsets; i++) {
2082 r = signature_element_length(p, &n);
2093 r = bus_gvariant_is_fixed_size(t);
2096 if (r > 0 || p[0] == 0)
2100 k = n_variable - 1 - j;
2102 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2111 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2112 struct bus_container *c;
2115 assert_return(m, -EINVAL);
2116 assert_return(!m->sealed, -EPERM);
2117 assert_return(m->n_containers > 0, -EINVAL);
2118 assert_return(!m->poisoned, -ESTALE);
2120 c = message_get_container(m);
2122 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2123 if (c->signature && c->signature[c->index] != 0)
2128 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2129 r = bus_message_close_array(m, c);
2130 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2131 r = bus_message_close_variant(m, c);
2132 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2133 r = bus_message_close_struct(m, c, true);
2135 assert_not_reached("Unknown container type");
2149 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2156 stack[*i].types = types;
2157 stack[*i].n_struct = n_struct;
2158 stack[*i].n_array = n_array;
2164 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2175 *types = stack[*i].types;
2176 *n_struct = stack[*i].n_struct;
2177 *n_array = stack[*i].n_array;
2182 int bus_message_append_ap(
2187 unsigned n_array, n_struct;
2188 TypeStack stack[BUS_CONTAINER_DEPTH];
2189 unsigned stack_ptr = 0;
2197 n_array = (unsigned) -1;
2198 n_struct = strlen(types);
2203 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2204 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2210 r = sd_bus_message_close_container(m);
2218 if (n_array != (unsigned) -1)
2227 case SD_BUS_TYPE_BYTE: {
2230 x = (uint8_t) va_arg(ap, int);
2231 r = sd_bus_message_append_basic(m, *t, &x);
2235 case SD_BUS_TYPE_BOOLEAN:
2236 case SD_BUS_TYPE_INT32:
2237 case SD_BUS_TYPE_UINT32:
2238 case SD_BUS_TYPE_UNIX_FD: {
2241 /* We assume a boolean is the same as int32_t */
2242 assert_cc(sizeof(int32_t) == sizeof(int));
2244 x = va_arg(ap, uint32_t);
2245 r = sd_bus_message_append_basic(m, *t, &x);
2249 case SD_BUS_TYPE_INT16:
2250 case SD_BUS_TYPE_UINT16: {
2253 x = (uint16_t) va_arg(ap, int);
2254 r = sd_bus_message_append_basic(m, *t, &x);
2258 case SD_BUS_TYPE_INT64:
2259 case SD_BUS_TYPE_UINT64:
2260 case SD_BUS_TYPE_DOUBLE: {
2263 x = va_arg(ap, uint64_t);
2264 r = sd_bus_message_append_basic(m, *t, &x);
2268 case SD_BUS_TYPE_STRING:
2269 case SD_BUS_TYPE_OBJECT_PATH:
2270 case SD_BUS_TYPE_SIGNATURE: {
2273 x = va_arg(ap, const char*);
2274 r = sd_bus_message_append_basic(m, *t, x);
2278 case SD_BUS_TYPE_ARRAY: {
2281 r = signature_element_length(t + 1, &k);
2287 memcpy(s, t + 1, k);
2290 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2295 if (n_array == (unsigned) -1) {
2300 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2306 n_array = va_arg(ap, unsigned);
2311 case SD_BUS_TYPE_VARIANT: {
2314 s = va_arg(ap, const char*);
2318 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2322 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2327 n_struct = strlen(s);
2328 n_array = (unsigned) -1;
2333 case SD_BUS_TYPE_STRUCT_BEGIN:
2334 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2337 r = signature_element_length(t, &k);
2344 memcpy(s, t + 1, k - 2);
2347 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, 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 = (unsigned) -1;
2379 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2383 assert_return(m, -EINVAL);
2384 assert_return(types, -EINVAL);
2385 assert_return(!m->sealed, -EPERM);
2386 assert_return(!m->poisoned, -ESTALE);
2388 va_start(ap, types);
2389 r = bus_message_append_ap(m, types, ap);
2395 _public_ int sd_bus_message_append_array_space(
2405 assert_return(m, -EINVAL);
2406 assert_return(!m->sealed, -EPERM);
2407 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2408 assert_return(ptr || size == 0, -EINVAL);
2409 assert_return(!m->poisoned, -ESTALE);
2411 /* alignment and size of the trivial types (except bool) is
2412 * identical for gvariant and dbus1 marshalling */
2413 align = bus_type_get_alignment(type);
2414 sz = bus_type_get_size(type);
2416 assert_se(align > 0);
2422 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2426 a = message_extend_body(m, align, size, false);
2430 r = sd_bus_message_close_container(m);
2438 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2445 assert_return(m, -EINVAL);
2446 assert_return(!m->sealed, -EPERM);
2447 assert_return(bus_type_is_trivial(type), -EINVAL);
2448 assert_return(ptr || size == 0, -EINVAL);
2449 assert_return(!m->poisoned, -ESTALE);
2451 r = sd_bus_message_append_array_space(m, type, size, &p);
2456 memcpy(p, ptr, size);
2461 _public_ int sd_bus_message_append_array_iovec(
2464 const struct iovec *iov,
2472 assert_return(m, -EINVAL);
2473 assert_return(!m->sealed, -EPERM);
2474 assert_return(bus_type_is_trivial(type), -EINVAL);
2475 assert_return(iov || n == 0, -EINVAL);
2476 assert_return(!m->poisoned, -ESTALE);
2478 size = IOVEC_TOTAL_SIZE(iov, n);
2480 r = sd_bus_message_append_array_space(m, type, size, &p);
2484 for (i = 0; i < n; i++) {
2486 if (iov[i].iov_base)
2487 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2489 memset(p, 0, iov[i].iov_len);
2491 p = (uint8_t*) p + iov[i].iov_len;
2497 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2500 _cleanup_close_ int copy_fd = -1;
2501 struct bus_body_part *part;
2513 if (!bus_type_is_trivial(type))
2518 r = sd_memfd_set_sealed(memfd, true);
2522 copy_fd = sd_memfd_dup_fd(memfd);
2526 r = sd_memfd_get_size(memfd, &size);
2530 align = bus_type_get_alignment(type);
2531 sz = bus_type_get_size(type);
2533 assert_se(align > 0);
2539 if (size > (uint64_t) (uint32_t) -1)
2542 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2546 a = message_extend_body(m, align, 0, false);
2550 part = message_append_part(m);
2554 part->memfd = copy_fd;
2555 part->sealed = true;
2559 m->header->body_size += size;
2560 message_extend_containers(m, size);
2562 return sd_bus_message_close_container(m);
2565 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
2566 _cleanup_close_ int copy_fd = -1;
2567 struct bus_body_part *part;
2568 struct bus_container *c;
2573 assert_return(m, -EINVAL);
2574 assert_return(memfd, -EINVAL);
2575 assert_return(!m->sealed, -EPERM);
2576 assert_return(!m->poisoned, -ESTALE);
2578 r = sd_memfd_set_sealed(memfd, true);
2582 copy_fd = sd_memfd_dup_fd(memfd);
2586 r = sd_memfd_get_size(memfd, &size);
2590 /* We require this to be NUL terminated */
2594 if (size > (uint64_t) (uint32_t) -1)
2597 c = message_get_container(m);
2598 if (c->signature && c->signature[c->index]) {
2599 /* Container signature is already set */
2601 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2606 /* Maybe we can append to the signature? But only if this is the top-level container*/
2607 if (c->enclosing != 0)
2610 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2617 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2618 a = message_extend_body(m, 4, 4, false);
2622 *(uint32_t*) a = size - 1;
2625 part = message_append_part(m);
2629 part->memfd = copy_fd;
2630 part->sealed = true;
2634 m->header->body_size += size;
2635 message_extend_containers(m, size);
2637 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2638 r = message_add_offset(m, m->header->body_size);
2645 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2651 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2655 assert_return(m, -EINVAL);
2656 assert_return(!m->sealed, -EPERM);
2657 assert_return(!m->poisoned, -ESTALE);
2659 r = sd_bus_message_open_container(m, 'a', "s");
2663 STRV_FOREACH(i, l) {
2664 r = sd_bus_message_append_basic(m, 's', *i);
2669 return sd_bus_message_close_container(m);
2672 static int bus_message_close_header(sd_bus_message *m) {
2678 if (!BUS_MESSAGE_IS_GVARIANT(m))
2681 if (m->n_header_offsets < 1)
2684 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2686 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2688 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2692 for (i = 0; i < m->n_header_offsets; i++)
2693 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2698 int bus_message_seal(sd_bus_message *m, uint64_t serial) {
2699 struct bus_body_part *part;
2709 if (m->n_containers > 0)
2715 /* In vtables the return signature of method calls is listed,
2716 * let's check if they match if this is a response */
2717 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2718 m->enforced_reply_signature &&
2719 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2722 /* If gvariant marshalling is used we need to close the body structure */
2723 r = bus_message_close_struct(m, &m->root_container, false);
2727 /* If there's a non-trivial signature set, then add it in here */
2728 if (!isempty(m->root_container.signature)) {
2729 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2735 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2740 r = bus_message_close_header(m);
2744 m->header->serial = serial;
2746 /* Add padding at the end of the fields part, since we know
2747 * the body needs to start at an 8 byte alignment. We made
2748 * sure we allocated enough space for this, so all we need to
2749 * do here is to zero it out. */
2750 l = BUS_MESSAGE_FIELDS_SIZE(m);
2753 memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
2755 /* If this is something we can send as memfd, then let's seal
2756 the memfd now. Note that we can send memfds as payload only
2757 for directed messages, and not for broadcasts. */
2758 if (m->destination && m->bus && m->bus->use_memfd) {
2759 MESSAGE_FOREACH_PART(part, i, m)
2760 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2761 bus_body_part_unmap(part);
2763 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
2764 part->sealed = true;
2768 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2769 m->root_container.index = 0;
2770 m->root_container.offset_index = 0;
2771 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2778 int bus_body_part_map(struct bus_body_part *part) {
2787 if (part->size <= 0)
2790 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2791 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2792 static const uint8_t zeroes[7] = { };
2793 part->data = (void*) zeroes;
2797 psz = PAGE_ALIGN(part->size);
2799 if (part->memfd >= 0)
2800 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2801 else if (part->is_zero)
2802 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2806 if (p == MAP_FAILED)
2811 part->munmap_this = true;
2816 void bus_body_part_unmap(struct bus_body_part *part) {
2820 if (part->memfd < 0)
2826 if (!part->munmap_this)
2829 assert_se(munmap(part->data, part->mapped) == 0);
2833 part->munmap_this = false;
2838 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2839 size_t k, start, end;
2844 start = ALIGN_TO((size_t) *rindex, align);
2845 end = start + nbytes;
2850 /* Verify that padding is 0 */
2851 for (k = *rindex; k < start; k++)
2852 if (((const uint8_t*) p)[k] != 0)
2856 *r = (uint8_t*) p + start;
2863 static bool message_end_of_signature(sd_bus_message *m) {
2864 struct bus_container *c;
2868 c = message_get_container(m);
2869 return !c->signature || c->signature[c->index] == 0;
2872 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2873 struct bus_container *c;
2877 c = message_get_container(m);
2878 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2881 if (BUS_MESSAGE_IS_GVARIANT(m))
2882 return index >= c->end;
2884 assert(c->array_size);
2885 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2889 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2890 assert_return(m, -EINVAL);
2891 assert_return(m->sealed, -EPERM);
2893 if (complete && m->n_containers > 0)
2896 if (message_end_of_signature(m))
2899 if (message_end_of_array(m, m->rindex))
2905 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2906 struct bus_body_part *part;
2912 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2913 part = m->cached_rindex_part;
2914 begin = m->cached_rindex_part_begin;
2924 if (index + sz <= begin + part->size) {
2926 r = bus_body_part_map(part);
2931 *p = (uint8_t*) part->data + index - begin;
2933 m->cached_rindex_part = part;
2934 m->cached_rindex_part_begin = begin;
2939 begin += part->size;
2946 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2953 if (!BUS_MESSAGE_IS_GVARIANT(m))
2956 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2959 sz = bus_gvariant_get_size(c->signature);
2963 if (c->offset_index+1 >= c->n_offsets)
2966 /* Variable-size array */
2968 alignment = bus_gvariant_get_alignment(c->signature);
2969 assert(alignment > 0);
2971 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
2972 c->item_size = c->offsets[c->offset_index+1] - *rindex;
2975 if (c->offset_index+1 >= (c->end-c->begin)/sz)
2978 /* Fixed-size array */
2979 *rindex = c->begin + (c->offset_index+1) * sz;
2985 } else if (c->enclosing == 0 ||
2986 c->enclosing == SD_BUS_TYPE_STRUCT ||
2987 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
2992 if (c->offset_index+1 >= c->n_offsets)
2995 r = signature_element_length(c->signature + c->index, &n);
2999 r = signature_element_length(c->signature + c->index + n, &j);
3004 memcpy(t, c->signature + c->index + n, j);
3007 alignment = bus_gvariant_get_alignment(t);
3010 assert(alignment > 0);
3012 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3013 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3017 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3020 assert_not_reached("Unknown container type");
3025 /* Reached the end */
3032 static int message_peek_body(
3039 size_t k, start, end, padding;
3040 struct bus_body_part *part;
3047 start = ALIGN_TO((size_t) *rindex, align);
3048 padding = start - *rindex;
3049 end = start + nbytes;
3051 if (end > BUS_MESSAGE_BODY_SIZE(m))
3054 part = find_part(m, *rindex, padding, (void**) &q);
3059 /* Verify padding */
3060 for (k = 0; k < padding; k++)
3065 part = find_part(m, start, nbytes, (void**) &q);
3066 if (!part || (nbytes > 0 && !q))
3077 static bool validate_nul(const char *s, size_t l) {
3079 /* Check for NUL chars in the string */
3080 if (memchr(s, 0, l))
3083 /* Check for NUL termination */
3090 static bool validate_string(const char *s, size_t l) {
3092 if (!validate_nul(s, l))
3095 /* Check if valid UTF8 */
3096 if (!utf8_is_valid(s))
3102 static bool validate_signature(const char *s, size_t l) {
3104 if (!validate_nul(s, l))
3107 /* Check if valid signature */
3108 if (!signature_is_valid(s, true))
3114 static bool validate_object_path(const char *s, size_t l) {
3116 if (!validate_nul(s, l))
3119 if (!object_path_is_valid(s))
3125 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3126 struct bus_container *c;
3131 assert_return(m, -EINVAL);
3132 assert_return(m->sealed, -EPERM);
3133 assert_return(bus_type_is_basic(type), -EINVAL);
3135 if (message_end_of_signature(m))
3138 if (message_end_of_array(m, m->rindex))
3141 c = message_get_container(m);
3142 if (c->signature[c->index] != type)
3147 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3149 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3152 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3156 if (type == SD_BUS_TYPE_STRING)
3157 ok = validate_string(q, c->item_size-1);
3158 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3159 ok = validate_object_path(q, c->item_size-1);
3161 ok = validate_signature(q, c->item_size-1);
3167 *(const char**) p = q;
3171 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3173 if ((size_t) sz != c->item_size)
3176 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3179 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3185 case SD_BUS_TYPE_BYTE:
3187 *(uint8_t*) p = *(uint8_t*) q;
3190 case SD_BUS_TYPE_BOOLEAN:
3192 *(int*) p = !!*(uint8_t*) q;
3195 case SD_BUS_TYPE_INT16:
3196 case SD_BUS_TYPE_UINT16:
3198 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3201 case SD_BUS_TYPE_INT32:
3202 case SD_BUS_TYPE_UINT32:
3204 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3207 case SD_BUS_TYPE_INT64:
3208 case SD_BUS_TYPE_UINT64:
3209 case SD_BUS_TYPE_DOUBLE:
3211 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3214 case SD_BUS_TYPE_UNIX_FD: {
3217 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3222 *(int*) p = m->fds[j];
3228 assert_not_reached("unexpected type");
3232 r = container_next_item(m, c, &rindex);
3239 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3243 r = message_peek_body(m, &rindex, 4, 4, &q);
3247 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3248 r = message_peek_body(m, &rindex, 1, l+1, &q);
3252 if (type == SD_BUS_TYPE_OBJECT_PATH)
3253 ok = validate_object_path(q, l);
3255 ok = validate_string(q, l);
3260 *(const char**) p = q;
3262 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3265 r = message_peek_body(m, &rindex, 1, 1, &q);
3270 r = message_peek_body(m, &rindex, 1, l+1, &q);
3274 if (!validate_signature(q, l))
3278 *(const char**) p = q;
3283 align = bus_type_get_alignment(type);
3286 sz = bus_type_get_size(type);
3289 r = message_peek_body(m, &rindex, align, sz, &q);
3295 case SD_BUS_TYPE_BYTE:
3297 *(uint8_t*) p = *(uint8_t*) q;
3300 case SD_BUS_TYPE_BOOLEAN:
3302 *(int*) p = !!*(uint32_t*) q;
3305 case SD_BUS_TYPE_INT16:
3306 case SD_BUS_TYPE_UINT16:
3308 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3311 case SD_BUS_TYPE_INT32:
3312 case SD_BUS_TYPE_UINT32:
3314 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3317 case SD_BUS_TYPE_INT64:
3318 case SD_BUS_TYPE_UINT64:
3319 case SD_BUS_TYPE_DOUBLE:
3321 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3324 case SD_BUS_TYPE_UNIX_FD: {
3327 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3332 *(int*) p = m->fds[j];
3337 assert_not_reached("Unknown basic type...");
3344 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3350 static int bus_message_enter_array(
3352 struct bus_container *c,
3353 const char *contents,
3354 uint32_t **array_size,
3357 size_t *n_offsets) {
3371 if (!signature_is_single(contents, true))
3374 if (!c->signature || c->signature[c->index] == 0)
3377 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3380 if (!startswith(c->signature + c->index + 1, contents))
3385 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3388 r = message_peek_body(m, &rindex, 4, 4, &q);
3392 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3395 alignment = bus_type_get_alignment(contents[0]);
3399 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3403 *array_size = (uint32_t*) q;
3405 } else if (c->item_size <= 0) {
3407 /* gvariant: empty array */
3412 } else if (bus_gvariant_is_fixed_size(contents)) {
3414 /* gvariant: fixed length array */
3415 *item_size = bus_gvariant_get_size(contents);
3420 size_t where, p = 0, framing, sz;
3423 /* gvariant: variable length array */
3424 sz = determine_word_size(c->item_size, 0);
3426 where = rindex + c->item_size - sz;
3427 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);
3444 *offsets = new(size_t, *n_offsets);
3448 for (i = 0; i < *n_offsets; i++) {
3451 x = read_word_le((uint8_t*) q + i * sz, sz);
3452 if (x > c->item_size - sz)
3457 (*offsets)[i] = rindex + x;
3461 *item_size = (*offsets)[0] - rindex;
3466 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3467 c->index += 1 + strlen(contents);
3472 static int bus_message_enter_variant(
3474 struct bus_container *c,
3475 const char *contents,
3476 size_t *item_size) {
3488 if (!signature_is_single(contents, false))
3491 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3494 if (!c->signature || c->signature[c->index] == 0)
3497 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3502 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3505 k = strlen(contents);
3506 if (1+k > c->item_size)
3509 where = rindex + c->item_size - (1+k);
3510 r = message_peek_body(m, &where, 1, 1+k, &q);
3514 if (*(char*) q != 0)
3517 if (memcmp((uint8_t*) q+1, contents, k))
3520 *item_size = c->item_size - (1+k);
3523 r = message_peek_body(m, &rindex, 1, 1, &q);
3528 r = message_peek_body(m, &rindex, 1, l+1, &q);
3532 if (!validate_signature(q, l))
3535 if (!streq(q, contents))
3541 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3547 static int build_struct_offsets(
3549 const char *signature,
3553 size_t *n_offsets) {
3555 unsigned n_variable = 0, n_total = 0, v;
3556 size_t previous = 0, where;
3567 if (isempty(signature)) {
3574 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);
3619 *offsets = new(size_t, n_total);
3625 /* Second, loop again and build an offset table */
3631 r = signature_element_length(p, &n);
3640 k = bus_gvariant_get_size(t);
3648 x = read_word_le((uint8_t*) q + v*sz, sz);
3651 if (m->rindex + x < previous)
3654 /* The last item's end
3655 * is determined from
3658 x = size - (n_variable * sz);
3660 offset = m->rindex + x;
3666 align = bus_gvariant_get_alignment(t);
3669 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3673 previous = (*offsets)[(*n_offsets)++] = offset;
3678 assert(*n_offsets == n_total);
3680 *item_size = (*offsets)[0] - m->rindex;
3684 static int enter_struct_or_dict_entry(
3686 struct bus_container *c,
3687 const char *contents,
3690 size_t *n_offsets) {
3701 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3704 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3708 } else if (c->item_size <= 0) {
3710 /* gvariant empty struct */
3715 /* gvariant with contents */
3716 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3721 static int bus_message_enter_struct(
3723 struct bus_container *c,
3724 const char *contents,
3727 size_t *n_offsets) {
3739 if (!signature_is_valid(contents, false))
3742 if (!c->signature || c->signature[c->index] == 0)
3745 l = strlen(contents);
3747 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3748 !startswith(c->signature + c->index + 1, contents) ||
3749 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3752 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3756 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3757 c->index += 1 + l + 1;
3762 static int bus_message_enter_dict_entry(
3764 struct bus_container *c,
3765 const char *contents,
3768 size_t *n_offsets) {
3777 if (!signature_is_pair(contents))
3780 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3783 if (!c->signature || c->signature[c->index] == 0)
3786 l = strlen(contents);
3788 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3789 !startswith(c->signature + c->index + 1, contents) ||
3790 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3793 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3797 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3798 c->index += 1 + l + 1;
3803 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3805 const char *contents) {
3806 struct bus_container *c, *w;
3807 uint32_t *array_size = NULL;
3810 size_t *offsets = NULL;
3811 size_t n_offsets = 0, item_size = 0;
3814 assert_return(m, -EINVAL);
3815 assert_return(m->sealed, -EPERM);
3816 assert_return(type != 0 || !contents, -EINVAL);
3818 if (type == 0 || !contents) {
3822 /* Allow entering into anonymous containers */
3823 r = sd_bus_message_peek_type(m, &tt, &cc);
3827 if (type != 0 && type != tt)
3830 if (contents && !streq(contents, cc))
3838 * We enforce a global limit on container depth, that is much
3839 * higher than the 32 structs and 32 arrays the specification
3840 * mandates. This is simpler to implement for us, and we need
3841 * this only to ensure our container array doesn't grow
3842 * without bounds. We are happy to return any data from a
3843 * message as long as the data itself is valid, even if the
3844 * overall message might be not.
3846 * Note that the message signature is validated when
3847 * parsing the headers, and that validation does check the
3850 * Note that the specification defines no limits on the depth
3851 * of stacked variants, but we do.
3853 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3856 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
3861 if (message_end_of_signature(m))
3864 if (message_end_of_array(m, m->rindex))
3867 c = message_get_container(m);
3869 signature = strdup(contents);
3873 c->saved_index = c->index;
3876 if (type == SD_BUS_TYPE_ARRAY)
3877 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3878 else if (type == SD_BUS_TYPE_VARIANT)
3879 r = bus_message_enter_variant(m, c, contents, &item_size);
3880 else if (type == SD_BUS_TYPE_STRUCT)
3881 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3882 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3883 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3893 /* OK, let's fill it in */
3894 w += m->n_containers++;
3895 w->enclosing = type;
3896 w->signature = signature;
3900 w->begin = m->rindex;
3901 w->end = m->rindex + c->item_size;
3903 w->array_size = array_size;
3904 w->item_size = item_size;
3905 w->offsets = offsets;
3906 w->n_offsets = n_offsets;
3907 w->offset_index = 0;
3912 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3913 struct bus_container *c;
3917 assert_return(m, -EINVAL);
3918 assert_return(m->sealed, -EPERM);
3919 assert_return(m->n_containers > 0, -ENXIO);
3921 c = message_get_container(m);
3923 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3924 if (c->signature && c->signature[c->index] != 0)
3928 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3929 if (m->rindex < c->end)
3932 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3935 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3936 if (c->begin + l != m->rindex)
3944 c = message_get_container(m);
3947 c->index = c->saved_index;
3948 r = container_next_item(m, c, &m->rindex);
3956 static void message_quit_container(sd_bus_message *m) {
3957 struct bus_container *c;
3961 assert(m->n_containers > 0);
3963 c = message_get_container(m);
3966 assert(m->rindex >= c->before);
3967 m->rindex = c->before;
3969 /* Free container */
3974 /* Correct index of new top-level container */
3975 c = message_get_container(m);
3976 c->index = c->saved_index;
3979 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
3980 struct bus_container *c;
3983 assert_return(m, -EINVAL);
3984 assert_return(m->sealed, -EPERM);
3986 if (message_end_of_signature(m))
3989 if (message_end_of_array(m, m->rindex))
3992 c = message_get_container(m);
3994 if (bus_type_is_basic(c->signature[c->index])) {
3998 *type = c->signature[c->index];
4002 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4008 r = signature_element_length(c->signature+c->index+1, &l);
4014 sig = strndup(c->signature + c->index + 1, l);
4018 free(m->peeked_signature);
4019 m->peeked_signature = sig;
4025 *type = SD_BUS_TYPE_ARRAY;
4030 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4031 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4037 r = signature_element_length(c->signature+c->index, &l);
4042 sig = strndup(c->signature + c->index + 1, l - 2);
4046 free(m->peeked_signature);
4047 m->peeked_signature = sig;
4053 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4058 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4062 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4065 if (c->item_size < 2)
4068 /* Look for the NUL delimiter that
4069 separates the payload from the
4070 signature. Since the body might be
4071 in a different part that then the
4072 signature we map byte by byte. */
4074 for (k = 2; k <= c->item_size; k++) {
4077 where = m->rindex + c->item_size - k;
4078 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);
4107 r = message_peek_body(m, &rindex, 1, l+1, &q);
4111 if (!validate_signature(q, l))
4119 *type = SD_BUS_TYPE_VARIANT;
4134 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4135 struct bus_container *c;
4137 assert_return(m, -EINVAL);
4138 assert_return(m->sealed, -EPERM);
4141 message_reset_containers(m);
4144 c = message_get_container(m);
4146 c = message_get_container(m);
4148 c->offset_index = 0;
4150 m->rindex = c->begin;
4153 c->offset_index = 0;
4154 c->item_size = c->n_offsets > 0 ? c->offsets[0] : c->end;
4156 return !isempty(c->signature);
4159 static int message_read_ap(
4164 unsigned n_array, n_struct;
4165 TypeStack stack[BUS_CONTAINER_DEPTH];
4166 unsigned stack_ptr = 0;
4167 unsigned n_loop = 0;
4175 /* Ideally, we'd just call ourselves recursively on every
4176 * complex type. However, the state of a va_list that is
4177 * passed to a function is undefined after that function
4178 * returns. This means we need to docode the va_list linearly
4179 * in a single stackframe. We hence implement our own
4180 * home-grown stack in an array. */
4182 n_array = (unsigned) -1; /* lenght of current array entries */
4183 n_struct = strlen(types); /* length of current struct contents signature */
4190 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4191 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4197 r = sd_bus_message_exit_container(m);
4205 if (n_array != (unsigned) -1)
4214 case SD_BUS_TYPE_BYTE:
4215 case SD_BUS_TYPE_BOOLEAN:
4216 case SD_BUS_TYPE_INT16:
4217 case SD_BUS_TYPE_UINT16:
4218 case SD_BUS_TYPE_INT32:
4219 case SD_BUS_TYPE_UINT32:
4220 case SD_BUS_TYPE_INT64:
4221 case SD_BUS_TYPE_UINT64:
4222 case SD_BUS_TYPE_DOUBLE:
4223 case SD_BUS_TYPE_STRING:
4224 case SD_BUS_TYPE_OBJECT_PATH:
4225 case SD_BUS_TYPE_SIGNATURE:
4226 case SD_BUS_TYPE_UNIX_FD: {
4229 p = va_arg(ap, void*);
4230 r = sd_bus_message_read_basic(m, *t, p);
4243 case SD_BUS_TYPE_ARRAY: {
4246 r = signature_element_length(t + 1, &k);
4252 memcpy(s, t + 1, k);
4255 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4266 if (n_array == (unsigned) -1) {
4271 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4277 n_array = va_arg(ap, unsigned);
4282 case SD_BUS_TYPE_VARIANT: {
4285 s = va_arg(ap, const char *);
4289 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4299 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4304 n_struct = strlen(s);
4305 n_array = (unsigned) -1;
4310 case SD_BUS_TYPE_STRUCT_BEGIN:
4311 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4314 r = signature_element_length(t, &k);
4320 memcpy(s, t + 1, k - 2);
4323 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4333 if (n_array == (unsigned) -1) {
4338 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4344 n_array = (unsigned) -1;
4357 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4361 assert_return(m, -EINVAL);
4362 assert_return(m->sealed, -EPERM);
4363 assert_return(types, -EINVAL);
4365 va_start(ap, types);
4366 r = message_read_ap(m, types, ap);
4372 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4375 assert_return(m, -EINVAL);
4376 assert_return(m->sealed, -EPERM);
4377 assert_return(types, -EINVAL);
4384 case SD_BUS_TYPE_BYTE:
4385 case SD_BUS_TYPE_BOOLEAN:
4386 case SD_BUS_TYPE_INT16:
4387 case SD_BUS_TYPE_UINT16:
4388 case SD_BUS_TYPE_INT32:
4389 case SD_BUS_TYPE_UINT32:
4390 case SD_BUS_TYPE_INT64:
4391 case SD_BUS_TYPE_UINT64:
4392 case SD_BUS_TYPE_DOUBLE:
4393 case SD_BUS_TYPE_STRING:
4394 case SD_BUS_TYPE_OBJECT_PATH:
4395 case SD_BUS_TYPE_SIGNATURE:
4396 case SD_BUS_TYPE_UNIX_FD:
4398 r = sd_bus_message_read_basic(m, *types, NULL);
4402 r = sd_bus_message_skip(m, types + 1);
4408 case SD_BUS_TYPE_ARRAY: {
4411 r = signature_element_length(types + 1, &k);
4417 memcpy(s, types+1, k);
4420 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4425 r = sd_bus_message_skip(m, s);
4432 r = sd_bus_message_exit_container(m);
4437 r = sd_bus_message_skip(m, types + 1 + k);
4444 case SD_BUS_TYPE_VARIANT: {
4445 const char *contents;
4448 r = sd_bus_message_peek_type(m, &x, &contents);
4452 if (x != SD_BUS_TYPE_VARIANT)
4455 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4459 r = sd_bus_message_skip(m, contents);
4464 r = sd_bus_message_exit_container(m);
4468 r = sd_bus_message_skip(m, types + 1);
4475 case SD_BUS_TYPE_STRUCT_BEGIN:
4476 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4479 r = signature_element_length(types, &k);
4485 memcpy(s, types+1, k-2);
4488 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4492 r = sd_bus_message_skip(m, s);
4497 r = sd_bus_message_exit_container(m);
4502 r = sd_bus_message_skip(m, types + k);
4514 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4518 struct bus_container *c;
4524 assert_return(m, -EINVAL);
4525 assert_return(m->sealed, -EPERM);
4526 assert_return(bus_type_is_trivial(type), -EINVAL);
4527 assert_return(ptr, -EINVAL);
4528 assert_return(size, -EINVAL);
4529 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4531 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4535 c = message_get_container(m);
4537 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4538 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4542 sz = c->end - c->begin;
4544 align = bus_type_get_alignment(type);
4548 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4552 /* Zero length array, let's return some aligned
4553 * pointer that is not NULL */
4554 p = (uint8_t*) NULL + align;
4556 r = message_peek_body(m, &m->rindex, align, sz, &p);
4561 r = sd_bus_message_exit_container(m);
4565 *ptr = (const void*) p;
4571 message_quit_container(m);
4575 static int message_peek_fields(
4586 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4589 static int message_peek_field_uint32(
4601 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4604 /* identical for gvariant and dbus1 */
4606 r = message_peek_fields(m, ri, 4, 4, &q);
4611 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4616 static int message_peek_field_string(
4618 bool (*validate)(const char *p),
4630 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4635 r = message_peek_fields(m, ri, 1, item_size, &q);
4641 r = message_peek_field_uint32(m, ri, 4, &l);
4645 r = message_peek_fields(m, ri, 1, l+1, &q);
4651 if (!validate_nul(q, l))
4657 if (!validate_string(q, l))
4667 static int message_peek_field_signature(
4680 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4685 r = message_peek_fields(m, ri, 1, item_size, &q);
4691 r = message_peek_fields(m, ri, 1, 1, &q);
4696 r = message_peek_fields(m, ri, 1, l+1, &q);
4701 if (!validate_signature(q, l))
4710 static int message_skip_fields(
4713 uint32_t array_size,
4714 const char **signature) {
4716 size_t original_index;
4722 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4724 original_index = *ri;
4730 if (array_size != (uint32_t) -1 &&
4731 array_size <= *ri - original_index)
4738 if (t == SD_BUS_TYPE_STRING) {
4740 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4746 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4748 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4754 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4756 r = message_peek_field_signature(m, ri, 0, NULL);
4762 } else if (bus_type_is_basic(t)) {
4765 align = bus_type_get_alignment(t);
4766 k = bus_type_get_size(t);
4767 assert(align > 0 && k > 0);
4769 r = message_peek_fields(m, ri, align, k, NULL);
4775 } else if (t == SD_BUS_TYPE_ARRAY) {
4777 r = signature_element_length(*signature+1, &l);
4787 strncpy(sig, *signature + 1, l-1);
4790 alignment = bus_type_get_alignment(sig[0]);
4794 r = message_peek_field_uint32(m, ri, 0, &nas);
4797 if (nas > BUS_ARRAY_MAX_SIZE)
4800 r = message_peek_fields(m, ri, alignment, 0, NULL);
4804 r = message_skip_fields(m, ri, nas, (const char**) &s);
4809 (*signature) += 1 + l;
4811 } else if (t == SD_BUS_TYPE_VARIANT) {
4814 r = message_peek_field_signature(m, ri, 0, &s);
4818 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4824 } else if (t == SD_BUS_TYPE_STRUCT ||
4825 t == SD_BUS_TYPE_DICT_ENTRY) {
4827 r = signature_element_length(*signature, &l);
4834 strncpy(sig, *signature + 1, l-1);
4837 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4848 int bus_message_parse_fields(sd_bus_message *m) {
4851 uint32_t unix_fds = 0;
4852 void *offsets = NULL;
4853 unsigned n_offsets = 0;
4859 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4862 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4866 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4867 r = message_peek_fields(m, &ri, 1, sz, &q);
4871 framing = read_word_le(q, sz);
4872 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4874 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4878 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4882 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4887 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4888 _cleanup_free_ char *sig = NULL;
4889 const char *signature;
4891 size_t item_size = (size_t) -1;
4893 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4900 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4903 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4907 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4912 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4917 where = ri = ALIGN_TO(ri, 8);
4918 item_size = end - ri;
4919 r = message_peek_fields(m, &where, 1, item_size, &q);
4923 b = memrchr(q, 0, item_size);
4927 sig = strndup(b+1, item_size - (b+1-(char*) q));
4932 item_size = b - (char*) q;
4934 r = message_peek_field_signature(m, &ri, 0, &signature);
4940 case _BUS_MESSAGE_HEADER_INVALID:
4943 case BUS_MESSAGE_HEADER_PATH:
4948 if (!streq(signature, "o"))
4951 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
4954 case BUS_MESSAGE_HEADER_INTERFACE:
4959 if (!streq(signature, "s"))
4962 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
4965 case BUS_MESSAGE_HEADER_MEMBER:
4970 if (!streq(signature, "s"))
4973 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
4976 case BUS_MESSAGE_HEADER_ERROR_NAME:
4981 if (!streq(signature, "s"))
4984 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
4986 m->error._need_free = -1;
4990 case BUS_MESSAGE_HEADER_DESTINATION:
4995 if (!streq(signature, "s"))
4998 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5001 case BUS_MESSAGE_HEADER_SENDER:
5006 if (!streq(signature, "s"))
5009 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5011 if (r >= 0 && m->sender[0] == ':' && m->bus && m->bus->bus_client && !m->bus->is_kernel) {
5012 m->creds.unique_name = (char*) m->sender;
5013 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5019 case BUS_MESSAGE_HEADER_SIGNATURE: {
5023 if (m->root_container.signature)
5026 if (!streq(signature, "g"))
5029 r = message_peek_field_signature(m, &ri, item_size, &s);
5037 free(m->root_container.signature);
5038 m->root_container.signature = c;
5042 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5043 if (m->reply_serial != 0)
5046 if (!streq(signature, "u"))
5049 r = message_peek_field_uint32(m, &ri, item_size, &m->reply_serial);
5053 if (m->reply_serial == 0)
5058 case BUS_MESSAGE_HEADER_UNIX_FDS:
5062 if (!streq(signature, "u"))
5065 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5075 if (!BUS_MESSAGE_IS_GVARIANT(m))
5076 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5085 if (m->n_fds != unix_fds)
5088 switch (m->header->type) {
5090 case SD_BUS_MESSAGE_SIGNAL:
5091 if (!m->path || !m->interface || !m->member)
5095 case SD_BUS_MESSAGE_METHOD_CALL:
5097 if (!m->path || !m->member)
5102 case SD_BUS_MESSAGE_METHOD_RETURN:
5104 if (m->reply_serial == 0)
5108 case SD_BUS_MESSAGE_METHOD_ERROR:
5110 if (m->reply_serial == 0 || !m->error.name)
5115 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5117 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5118 r = build_struct_offsets(
5120 m->root_container.signature,
5121 BUS_MESSAGE_BODY_SIZE(m),
5122 &m->root_container.item_size,
5123 &m->root_container.offsets,
5124 &m->root_container.n_offsets);
5129 /* Try to read the error message, but if we can't it's a non-issue */
5130 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5131 sd_bus_message_read(m, "s", &m->error.message);
5136 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5137 assert_return(m, -EINVAL);
5138 assert_return(destination, -EINVAL);
5139 assert_return(!m->sealed, -EPERM);
5140 assert_return(!m->destination, -EEXIST);
5142 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5145 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5149 struct bus_body_part *part;
5155 total = BUS_MESSAGE_SIZE(m);
5161 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5162 MESSAGE_FOREACH_PART(part, i, m)
5163 e = mempcpy(e, part->data, part->size);
5165 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5173 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5179 r = sd_bus_message_enter_container(m, 'a', "s");
5186 r = sd_bus_message_read_basic(m, 's', &s);
5192 r = strv_extend(l, s);
5197 r = sd_bus_message_exit_container(m);
5204 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5208 assert_return(m, -EINVAL);
5209 assert_return(m->sealed, -EPERM);
5210 assert_return(l, -EINVAL);
5212 r = bus_message_read_strv_extend(m, &strv);
5222 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5224 const char *t = NULL;
5229 r = sd_bus_message_rewind(m, true);
5233 for (j = 0; j <= i; j++) {
5236 r = sd_bus_message_peek_type(m, &type, NULL);
5240 if (type != SD_BUS_TYPE_STRING &&
5241 type != SD_BUS_TYPE_OBJECT_PATH &&
5242 type != SD_BUS_TYPE_SIGNATURE)
5245 r = sd_bus_message_read_basic(m, type, &t);
5253 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5259 if (size < sizeof(struct bus_header))
5262 full = sizeof(struct bus_header) +
5263 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5265 return size >= full;
5268 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5274 if (h->endian == BUS_NATIVE_ENDIAN) {
5275 fs = h->fields_size;
5277 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5278 fs = bswap_32(h->fields_size);
5279 bs = bswap_32(h->body_size);
5283 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5287 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5288 assert_return(m, -EINVAL);
5290 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5293 return sd_bus_error_get_errno(&m->error);
5296 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5297 struct bus_container *c;
5299 assert_return(m, NULL);
5301 c = complete ? &m->root_container : message_get_container(m);
5302 return strempty(c->signature);
5305 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5306 bool done_something = false;
5309 assert_return(m, -EINVAL);
5310 assert_return(source, -EINVAL);
5311 assert_return(!m->sealed, -EPERM);
5312 assert_return(source->sealed, -EPERM);
5315 const char *contents;
5330 r = sd_bus_message_peek_type(source, &type, &contents);
5336 done_something = true;
5338 if (bus_type_is_container(type) > 0) {
5340 r = sd_bus_message_enter_container(source, type, contents);
5344 r = sd_bus_message_open_container(m, type, contents);
5348 r = sd_bus_message_copy(m, source, true);
5352 r = sd_bus_message_close_container(m);
5356 r = sd_bus_message_exit_container(source);
5363 r = sd_bus_message_read_basic(source, type, &basic);
5369 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5370 type == SD_BUS_TYPE_SIGNATURE ||
5371 type == SD_BUS_TYPE_STRING)
5372 r = sd_bus_message_append_basic(m, type, basic.string);
5374 r = sd_bus_message_append_basic(m, type, &basic);
5381 return done_something;
5384 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5389 assert_return(m, -EINVAL);
5390 assert_return(m->sealed, -EPERM);
5391 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5392 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5393 assert_return(type || contents, -EINVAL);
5394 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5396 r = sd_bus_message_peek_type(m, &t, &c);
5400 if (type != 0 && type != t)
5403 if (contents && !streq_ptr(contents, c))
5409 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5410 assert_return(m, NULL);