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, usec_t timeout) {
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;
2745 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2747 /* Add padding at the end of the fields part, since we know
2748 * the body needs to start at an 8 byte alignment. We made
2749 * sure we allocated enough space for this, so all we need to
2750 * do here is to zero it out. */
2751 l = BUS_MESSAGE_FIELDS_SIZE(m);
2754 memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
2756 /* If this is something we can send as memfd, then let's seal
2757 the memfd now. Note that we can send memfds as payload only
2758 for directed messages, and not for broadcasts. */
2759 if (m->destination && m->bus && m->bus->use_memfd) {
2760 MESSAGE_FOREACH_PART(part, i, m)
2761 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2762 bus_body_part_unmap(part);
2764 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
2765 part->sealed = true;
2769 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2770 m->root_container.index = 0;
2771 m->root_container.offset_index = 0;
2772 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2779 int bus_body_part_map(struct bus_body_part *part) {
2788 if (part->size <= 0)
2791 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2792 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2793 static const uint8_t zeroes[7] = { };
2794 part->data = (void*) zeroes;
2798 psz = PAGE_ALIGN(part->size);
2800 if (part->memfd >= 0)
2801 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2802 else if (part->is_zero)
2803 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2807 if (p == MAP_FAILED)
2812 part->munmap_this = true;
2817 void bus_body_part_unmap(struct bus_body_part *part) {
2821 if (part->memfd < 0)
2827 if (!part->munmap_this)
2830 assert_se(munmap(part->data, part->mapped) == 0);
2834 part->munmap_this = false;
2839 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2840 size_t k, start, end;
2845 start = ALIGN_TO((size_t) *rindex, align);
2846 end = start + nbytes;
2851 /* Verify that padding is 0 */
2852 for (k = *rindex; k < start; k++)
2853 if (((const uint8_t*) p)[k] != 0)
2857 *r = (uint8_t*) p + start;
2864 static bool message_end_of_signature(sd_bus_message *m) {
2865 struct bus_container *c;
2869 c = message_get_container(m);
2870 return !c->signature || c->signature[c->index] == 0;
2873 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2874 struct bus_container *c;
2878 c = message_get_container(m);
2879 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2882 if (BUS_MESSAGE_IS_GVARIANT(m))
2883 return index >= c->end;
2885 assert(c->array_size);
2886 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2890 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2891 assert_return(m, -EINVAL);
2892 assert_return(m->sealed, -EPERM);
2894 if (complete && m->n_containers > 0)
2897 if (message_end_of_signature(m))
2900 if (message_end_of_array(m, m->rindex))
2906 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2907 struct bus_body_part *part;
2913 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2914 part = m->cached_rindex_part;
2915 begin = m->cached_rindex_part_begin;
2925 if (index + sz <= begin + part->size) {
2927 r = bus_body_part_map(part);
2932 *p = (uint8_t*) part->data + index - begin;
2934 m->cached_rindex_part = part;
2935 m->cached_rindex_part_begin = begin;
2940 begin += part->size;
2947 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2954 if (!BUS_MESSAGE_IS_GVARIANT(m))
2957 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2960 sz = bus_gvariant_get_size(c->signature);
2964 if (c->offset_index+1 >= c->n_offsets)
2967 /* Variable-size array */
2969 alignment = bus_gvariant_get_alignment(c->signature);
2970 assert(alignment > 0);
2972 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
2973 c->item_size = c->offsets[c->offset_index+1] - *rindex;
2976 if (c->offset_index+1 >= (c->end-c->begin)/sz)
2979 /* Fixed-size array */
2980 *rindex = c->begin + (c->offset_index+1) * sz;
2986 } else if (c->enclosing == 0 ||
2987 c->enclosing == SD_BUS_TYPE_STRUCT ||
2988 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
2993 if (c->offset_index+1 >= c->n_offsets)
2996 r = signature_element_length(c->signature + c->index, &n);
3000 r = signature_element_length(c->signature + c->index + n, &j);
3005 memcpy(t, c->signature + c->index + n, j);
3008 alignment = bus_gvariant_get_alignment(t);
3011 assert(alignment > 0);
3013 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3014 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3018 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3021 assert_not_reached("Unknown container type");
3026 /* Reached the end */
3033 static int message_peek_body(
3040 size_t k, start, end, padding;
3041 struct bus_body_part *part;
3048 start = ALIGN_TO((size_t) *rindex, align);
3049 padding = start - *rindex;
3050 end = start + nbytes;
3052 if (end > BUS_MESSAGE_BODY_SIZE(m))
3055 part = find_part(m, *rindex, padding, (void**) &q);
3060 /* Verify padding */
3061 for (k = 0; k < padding; k++)
3066 part = find_part(m, start, nbytes, (void**) &q);
3067 if (!part || (nbytes > 0 && !q))
3078 static bool validate_nul(const char *s, size_t l) {
3080 /* Check for NUL chars in the string */
3081 if (memchr(s, 0, l))
3084 /* Check for NUL termination */
3091 static bool validate_string(const char *s, size_t l) {
3093 if (!validate_nul(s, l))
3096 /* Check if valid UTF8 */
3097 if (!utf8_is_valid(s))
3103 static bool validate_signature(const char *s, size_t l) {
3105 if (!validate_nul(s, l))
3108 /* Check if valid signature */
3109 if (!signature_is_valid(s, true))
3115 static bool validate_object_path(const char *s, size_t l) {
3117 if (!validate_nul(s, l))
3120 if (!object_path_is_valid(s))
3126 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3127 struct bus_container *c;
3132 assert_return(m, -EINVAL);
3133 assert_return(m->sealed, -EPERM);
3134 assert_return(bus_type_is_basic(type), -EINVAL);
3136 if (message_end_of_signature(m))
3139 if (message_end_of_array(m, m->rindex))
3142 c = message_get_container(m);
3143 if (c->signature[c->index] != type)
3148 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3150 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3153 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3157 if (type == SD_BUS_TYPE_STRING)
3158 ok = validate_string(q, c->item_size-1);
3159 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3160 ok = validate_object_path(q, c->item_size-1);
3162 ok = validate_signature(q, c->item_size-1);
3168 *(const char**) p = q;
3172 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3174 if ((size_t) sz != c->item_size)
3177 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3180 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3186 case SD_BUS_TYPE_BYTE:
3188 *(uint8_t*) p = *(uint8_t*) q;
3191 case SD_BUS_TYPE_BOOLEAN:
3193 *(int*) p = !!*(uint8_t*) q;
3196 case SD_BUS_TYPE_INT16:
3197 case SD_BUS_TYPE_UINT16:
3199 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3202 case SD_BUS_TYPE_INT32:
3203 case SD_BUS_TYPE_UINT32:
3205 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3208 case SD_BUS_TYPE_INT64:
3209 case SD_BUS_TYPE_UINT64:
3210 case SD_BUS_TYPE_DOUBLE:
3212 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3215 case SD_BUS_TYPE_UNIX_FD: {
3218 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3223 *(int*) p = m->fds[j];
3229 assert_not_reached("unexpected type");
3233 r = container_next_item(m, c, &rindex);
3240 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3244 r = message_peek_body(m, &rindex, 4, 4, &q);
3248 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3249 r = message_peek_body(m, &rindex, 1, l+1, &q);
3253 if (type == SD_BUS_TYPE_OBJECT_PATH)
3254 ok = validate_object_path(q, l);
3256 ok = validate_string(q, l);
3261 *(const char**) p = q;
3263 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3266 r = message_peek_body(m, &rindex, 1, 1, &q);
3271 r = message_peek_body(m, &rindex, 1, l+1, &q);
3275 if (!validate_signature(q, l))
3279 *(const char**) p = q;
3284 align = bus_type_get_alignment(type);
3287 sz = bus_type_get_size(type);
3290 r = message_peek_body(m, &rindex, align, sz, &q);
3296 case SD_BUS_TYPE_BYTE:
3298 *(uint8_t*) p = *(uint8_t*) q;
3301 case SD_BUS_TYPE_BOOLEAN:
3303 *(int*) p = !!*(uint32_t*) q;
3306 case SD_BUS_TYPE_INT16:
3307 case SD_BUS_TYPE_UINT16:
3309 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3312 case SD_BUS_TYPE_INT32:
3313 case SD_BUS_TYPE_UINT32:
3315 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3318 case SD_BUS_TYPE_INT64:
3319 case SD_BUS_TYPE_UINT64:
3320 case SD_BUS_TYPE_DOUBLE:
3322 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3325 case SD_BUS_TYPE_UNIX_FD: {
3328 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3333 *(int*) p = m->fds[j];
3338 assert_not_reached("Unknown basic type...");
3345 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3351 static int bus_message_enter_array(
3353 struct bus_container *c,
3354 const char *contents,
3355 uint32_t **array_size,
3358 size_t *n_offsets) {
3372 if (!signature_is_single(contents, true))
3375 if (!c->signature || c->signature[c->index] == 0)
3378 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3381 if (!startswith(c->signature + c->index + 1, contents))
3386 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3389 r = message_peek_body(m, &rindex, 4, 4, &q);
3393 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3396 alignment = bus_type_get_alignment(contents[0]);
3400 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3404 *array_size = (uint32_t*) q;
3406 } else if (c->item_size <= 0) {
3408 /* gvariant: empty array */
3413 } else if (bus_gvariant_is_fixed_size(contents)) {
3415 /* gvariant: fixed length array */
3416 *item_size = bus_gvariant_get_size(contents);
3421 size_t where, p = 0, framing, sz;
3424 /* gvariant: variable length array */
3425 sz = determine_word_size(c->item_size, 0);
3427 where = rindex + c->item_size - sz;
3428 r = message_peek_body(m, &where, 1, sz, &q);
3432 framing = read_word_le(q, sz);
3433 if (framing > c->item_size - sz)
3435 if ((c->item_size - framing) % sz != 0)
3438 *n_offsets = (c->item_size - framing) / sz;
3440 where = rindex + framing;
3441 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3445 *offsets = new(size_t, *n_offsets);
3449 for (i = 0; i < *n_offsets; i++) {
3452 x = read_word_le((uint8_t*) q + i * sz, sz);
3453 if (x > c->item_size - sz)
3458 (*offsets)[i] = rindex + x;
3462 *item_size = (*offsets)[0] - rindex;
3467 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3468 c->index += 1 + strlen(contents);
3473 static int bus_message_enter_variant(
3475 struct bus_container *c,
3476 const char *contents,
3477 size_t *item_size) {
3489 if (!signature_is_single(contents, false))
3492 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3495 if (!c->signature || c->signature[c->index] == 0)
3498 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3503 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3506 k = strlen(contents);
3507 if (1+k > c->item_size)
3510 where = rindex + c->item_size - (1+k);
3511 r = message_peek_body(m, &where, 1, 1+k, &q);
3515 if (*(char*) q != 0)
3518 if (memcmp((uint8_t*) q+1, contents, k))
3521 *item_size = c->item_size - (1+k);
3524 r = message_peek_body(m, &rindex, 1, 1, &q);
3529 r = message_peek_body(m, &rindex, 1, l+1, &q);
3533 if (!validate_signature(q, l))
3536 if (!streq(q, contents))
3542 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3548 static int build_struct_offsets(
3550 const char *signature,
3554 size_t *n_offsets) {
3556 unsigned n_variable = 0, n_total = 0, v;
3557 size_t previous = 0, where;
3568 if (isempty(signature)) {
3575 sz = determine_word_size(size, 0);
3579 /* First, loop over signature and count variable elements and
3580 * elements in general. We use this to know how large the
3581 * offset array is at the end of the structure. Note that
3582 * GVariant only stores offsets for all variable size elements
3583 * that are not the last item. */
3589 r = signature_element_length(p, &n);
3598 r = bus_gvariant_is_fixed_size(t);
3603 if (r == 0 && p[n] != 0) /* except the last item */
3610 if (size < n_variable * sz)
3613 where = m->rindex + size - (n_variable * sz);
3614 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3620 *offsets = new(size_t, n_total);
3626 /* Second, loop again and build an offset table */
3632 r = signature_element_length(p, &n);
3641 k = bus_gvariant_get_size(t);
3649 x = read_word_le((uint8_t*) q + v*sz, sz);
3652 if (m->rindex + x < previous)
3655 /* The last item's end
3656 * is determined from
3659 x = size - (n_variable * sz);
3661 offset = m->rindex + x;
3667 align = bus_gvariant_get_alignment(t);
3670 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3674 previous = (*offsets)[(*n_offsets)++] = offset;
3679 assert(*n_offsets == n_total);
3681 *item_size = (*offsets)[0] - m->rindex;
3685 static int enter_struct_or_dict_entry(
3687 struct bus_container *c,
3688 const char *contents,
3691 size_t *n_offsets) {
3702 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3705 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3709 } else if (c->item_size <= 0) {
3711 /* gvariant empty struct */
3716 /* gvariant with contents */
3717 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3722 static int bus_message_enter_struct(
3724 struct bus_container *c,
3725 const char *contents,
3728 size_t *n_offsets) {
3740 if (!signature_is_valid(contents, false))
3743 if (!c->signature || c->signature[c->index] == 0)
3746 l = strlen(contents);
3748 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3749 !startswith(c->signature + c->index + 1, contents) ||
3750 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3753 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3757 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3758 c->index += 1 + l + 1;
3763 static int bus_message_enter_dict_entry(
3765 struct bus_container *c,
3766 const char *contents,
3769 size_t *n_offsets) {
3778 if (!signature_is_pair(contents))
3781 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3784 if (!c->signature || c->signature[c->index] == 0)
3787 l = strlen(contents);
3789 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3790 !startswith(c->signature + c->index + 1, contents) ||
3791 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3794 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3798 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3799 c->index += 1 + l + 1;
3804 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3806 const char *contents) {
3807 struct bus_container *c, *w;
3808 uint32_t *array_size = NULL;
3811 size_t *offsets = NULL;
3812 size_t n_offsets = 0, item_size = 0;
3815 assert_return(m, -EINVAL);
3816 assert_return(m->sealed, -EPERM);
3817 assert_return(type != 0 || !contents, -EINVAL);
3819 if (type == 0 || !contents) {
3823 /* Allow entering into anonymous containers */
3824 r = sd_bus_message_peek_type(m, &tt, &cc);
3828 if (type != 0 && type != tt)
3831 if (contents && !streq(contents, cc))
3839 * We enforce a global limit on container depth, that is much
3840 * higher than the 32 structs and 32 arrays the specification
3841 * mandates. This is simpler to implement for us, and we need
3842 * this only to ensure our container array doesn't grow
3843 * without bounds. We are happy to return any data from a
3844 * message as long as the data itself is valid, even if the
3845 * overall message might be not.
3847 * Note that the message signature is validated when
3848 * parsing the headers, and that validation does check the
3851 * Note that the specification defines no limits on the depth
3852 * of stacked variants, but we do.
3854 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3857 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
3862 if (message_end_of_signature(m))
3865 if (message_end_of_array(m, m->rindex))
3868 c = message_get_container(m);
3870 signature = strdup(contents);
3874 c->saved_index = c->index;
3877 if (type == SD_BUS_TYPE_ARRAY)
3878 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3879 else if (type == SD_BUS_TYPE_VARIANT)
3880 r = bus_message_enter_variant(m, c, contents, &item_size);
3881 else if (type == SD_BUS_TYPE_STRUCT)
3882 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3883 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3884 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3894 /* OK, let's fill it in */
3895 w += m->n_containers++;
3896 w->enclosing = type;
3897 w->signature = signature;
3901 w->begin = m->rindex;
3902 w->end = m->rindex + c->item_size;
3904 w->array_size = array_size;
3905 w->item_size = item_size;
3906 w->offsets = offsets;
3907 w->n_offsets = n_offsets;
3908 w->offset_index = 0;
3913 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3914 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);
3948 c->index = c->saved_index;
3949 r = container_next_item(m, c, &m->rindex);
3957 static void message_quit_container(sd_bus_message *m) {
3958 struct bus_container *c;
3962 assert(m->n_containers > 0);
3964 c = message_get_container(m);
3967 assert(m->rindex >= c->before);
3968 m->rindex = c->before;
3970 /* Free container */
3975 /* Correct index of new top-level container */
3976 c = message_get_container(m);
3977 c->index = c->saved_index;
3980 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
3981 struct bus_container *c;
3984 assert_return(m, -EINVAL);
3985 assert_return(m->sealed, -EPERM);
3987 if (message_end_of_signature(m))
3990 if (message_end_of_array(m, m->rindex))
3993 c = message_get_container(m);
3995 if (bus_type_is_basic(c->signature[c->index])) {
3999 *type = c->signature[c->index];
4003 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4009 r = signature_element_length(c->signature+c->index+1, &l);
4015 sig = strndup(c->signature + c->index + 1, l);
4019 free(m->peeked_signature);
4020 m->peeked_signature = sig;
4026 *type = SD_BUS_TYPE_ARRAY;
4031 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4032 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4038 r = signature_element_length(c->signature+c->index, &l);
4043 sig = strndup(c->signature + c->index + 1, l - 2);
4047 free(m->peeked_signature);
4048 m->peeked_signature = sig;
4054 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4059 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4063 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4066 if (c->item_size < 2)
4069 /* Look for the NUL delimiter that
4070 separates the payload from the
4071 signature. Since the body might be
4072 in a different part that then the
4073 signature we map byte by byte. */
4075 for (k = 2; k <= c->item_size; k++) {
4078 where = m->rindex + c->item_size - k;
4079 r = message_peek_body(m, &where, 1, k, &q);
4083 if (*(char*) q == 0)
4087 if (k > c->item_size)
4090 free(m->peeked_signature);
4091 m->peeked_signature = strndup((char*) q + 1, k - 1);
4092 if (!m->peeked_signature)
4095 if (!signature_is_valid(m->peeked_signature, true))
4098 *contents = m->peeked_signature;
4103 r = message_peek_body(m, &rindex, 1, 1, &q);
4108 r = message_peek_body(m, &rindex, 1, l+1, &q);
4112 if (!validate_signature(q, l))
4120 *type = SD_BUS_TYPE_VARIANT;
4135 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4136 struct bus_container *c;
4138 assert_return(m, -EINVAL);
4139 assert_return(m->sealed, -EPERM);
4142 message_reset_containers(m);
4145 c = message_get_container(m);
4147 c = message_get_container(m);
4149 c->offset_index = 0;
4151 m->rindex = c->begin;
4154 c->offset_index = 0;
4155 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - 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));
4543 sz = c->end - c->begin;
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);
4562 r = sd_bus_message_exit_container(m);
4566 *ptr = (const void*) p;
4572 message_quit_container(m);
4576 static int message_peek_fields(
4587 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4590 static int message_peek_field_uint32(
4602 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4605 /* identical for gvariant and dbus1 */
4607 r = message_peek_fields(m, ri, 4, 4, &q);
4612 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4617 static int message_peek_field_string(
4619 bool (*validate)(const char *p),
4631 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4636 r = message_peek_fields(m, ri, 1, item_size, &q);
4642 r = message_peek_field_uint32(m, ri, 4, &l);
4646 r = message_peek_fields(m, ri, 1, l+1, &q);
4652 if (!validate_nul(q, l))
4658 if (!validate_string(q, l))
4668 static int message_peek_field_signature(
4681 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4686 r = message_peek_fields(m, ri, 1, item_size, &q);
4692 r = message_peek_fields(m, ri, 1, 1, &q);
4697 r = message_peek_fields(m, ri, 1, l+1, &q);
4702 if (!validate_signature(q, l))
4711 static int message_skip_fields(
4714 uint32_t array_size,
4715 const char **signature) {
4717 size_t original_index;
4723 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4725 original_index = *ri;
4731 if (array_size != (uint32_t) -1 &&
4732 array_size <= *ri - original_index)
4739 if (t == SD_BUS_TYPE_STRING) {
4741 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4747 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4749 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4755 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4757 r = message_peek_field_signature(m, ri, 0, NULL);
4763 } else if (bus_type_is_basic(t)) {
4766 align = bus_type_get_alignment(t);
4767 k = bus_type_get_size(t);
4768 assert(align > 0 && k > 0);
4770 r = message_peek_fields(m, ri, align, k, NULL);
4776 } else if (t == SD_BUS_TYPE_ARRAY) {
4778 r = signature_element_length(*signature+1, &l);
4788 strncpy(sig, *signature + 1, l-1);
4791 alignment = bus_type_get_alignment(sig[0]);
4795 r = message_peek_field_uint32(m, ri, 0, &nas);
4798 if (nas > BUS_ARRAY_MAX_SIZE)
4801 r = message_peek_fields(m, ri, alignment, 0, NULL);
4805 r = message_skip_fields(m, ri, nas, (const char**) &s);
4810 (*signature) += 1 + l;
4812 } else if (t == SD_BUS_TYPE_VARIANT) {
4815 r = message_peek_field_signature(m, ri, 0, &s);
4819 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4825 } else if (t == SD_BUS_TYPE_STRUCT ||
4826 t == SD_BUS_TYPE_DICT_ENTRY) {
4828 r = signature_element_length(*signature, &l);
4835 strncpy(sig, *signature + 1, l-1);
4838 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4849 int bus_message_parse_fields(sd_bus_message *m) {
4852 uint32_t unix_fds = 0;
4853 void *offsets = NULL;
4854 unsigned n_offsets = 0;
4860 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4863 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4867 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4868 r = message_peek_fields(m, &ri, 1, sz, &q);
4872 framing = read_word_le(q, sz);
4873 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4875 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4879 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4883 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4888 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4889 _cleanup_free_ char *sig = NULL;
4890 const char *signature;
4892 size_t item_size = (size_t) -1;
4894 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4901 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4904 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4908 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4913 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4918 where = ri = ALIGN_TO(ri, 8);
4919 item_size = end - ri;
4920 r = message_peek_fields(m, &where, 1, item_size, &q);
4924 b = memrchr(q, 0, item_size);
4928 sig = strndup(b+1, item_size - (b+1-(char*) q));
4933 item_size = b - (char*) q;
4935 r = message_peek_field_signature(m, &ri, 0, &signature);
4941 case _BUS_MESSAGE_HEADER_INVALID:
4944 case BUS_MESSAGE_HEADER_PATH:
4949 if (!streq(signature, "o"))
4952 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
4955 case BUS_MESSAGE_HEADER_INTERFACE:
4960 if (!streq(signature, "s"))
4963 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
4966 case BUS_MESSAGE_HEADER_MEMBER:
4971 if (!streq(signature, "s"))
4974 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
4977 case BUS_MESSAGE_HEADER_ERROR_NAME:
4982 if (!streq(signature, "s"))
4985 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
4987 m->error._need_free = -1;
4991 case BUS_MESSAGE_HEADER_DESTINATION:
4996 if (!streq(signature, "s"))
4999 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5002 case BUS_MESSAGE_HEADER_SENDER:
5007 if (!streq(signature, "s"))
5010 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5012 if (r >= 0 && m->sender[0] == ':' && m->bus && m->bus->bus_client && !m->bus->is_kernel) {
5013 m->creds.unique_name = (char*) m->sender;
5014 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5020 case BUS_MESSAGE_HEADER_SIGNATURE: {
5024 if (m->root_container.signature)
5027 if (!streq(signature, "g"))
5030 r = message_peek_field_signature(m, &ri, item_size, &s);
5038 free(m->root_container.signature);
5039 m->root_container.signature = c;
5043 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5044 if (m->reply_serial != 0)
5047 if (!streq(signature, "u"))
5050 r = message_peek_field_uint32(m, &ri, item_size, &m->reply_serial);
5054 if (m->reply_serial == 0)
5059 case BUS_MESSAGE_HEADER_UNIX_FDS:
5063 if (!streq(signature, "u"))
5066 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5076 if (!BUS_MESSAGE_IS_GVARIANT(m))
5077 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5086 if (m->n_fds != unix_fds)
5089 switch (m->header->type) {
5091 case SD_BUS_MESSAGE_SIGNAL:
5092 if (!m->path || !m->interface || !m->member)
5096 case SD_BUS_MESSAGE_METHOD_CALL:
5098 if (!m->path || !m->member)
5103 case SD_BUS_MESSAGE_METHOD_RETURN:
5105 if (m->reply_serial == 0)
5109 case SD_BUS_MESSAGE_METHOD_ERROR:
5111 if (m->reply_serial == 0 || !m->error.name)
5116 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5118 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5119 r = build_struct_offsets(
5121 m->root_container.signature,
5122 BUS_MESSAGE_BODY_SIZE(m),
5123 &m->root_container.item_size,
5124 &m->root_container.offsets,
5125 &m->root_container.n_offsets);
5130 /* Try to read the error message, but if we can't it's a non-issue */
5131 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5132 sd_bus_message_read(m, "s", &m->error.message);
5137 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5138 assert_return(m, -EINVAL);
5139 assert_return(destination, -EINVAL);
5140 assert_return(!m->sealed, -EPERM);
5141 assert_return(!m->destination, -EEXIST);
5143 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5146 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5150 struct bus_body_part *part;
5156 total = BUS_MESSAGE_SIZE(m);
5162 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5163 MESSAGE_FOREACH_PART(part, i, m)
5164 e = mempcpy(e, part->data, part->size);
5166 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5174 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5180 r = sd_bus_message_enter_container(m, 'a', "s");
5187 r = sd_bus_message_read_basic(m, 's', &s);
5193 r = strv_extend(l, s);
5198 r = sd_bus_message_exit_container(m);
5205 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5209 assert_return(m, -EINVAL);
5210 assert_return(m->sealed, -EPERM);
5211 assert_return(l, -EINVAL);
5213 r = bus_message_read_strv_extend(m, &strv);
5223 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5225 const char *t = NULL;
5230 r = sd_bus_message_rewind(m, true);
5234 for (j = 0; j <= i; j++) {
5237 r = sd_bus_message_peek_type(m, &type, NULL);
5241 if (type != SD_BUS_TYPE_STRING &&
5242 type != SD_BUS_TYPE_OBJECT_PATH &&
5243 type != SD_BUS_TYPE_SIGNATURE)
5246 r = sd_bus_message_read_basic(m, type, &t);
5254 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5260 if (size < sizeof(struct bus_header))
5263 full = sizeof(struct bus_header) +
5264 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5266 return size >= full;
5269 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5275 if (h->endian == BUS_NATIVE_ENDIAN) {
5276 fs = h->fields_size;
5278 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5279 fs = bswap_32(h->fields_size);
5280 bs = bswap_32(h->body_size);
5284 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5288 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5289 assert_return(m, -EINVAL);
5291 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5294 return sd_bus_error_get_errno(&m->error);
5297 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5298 struct bus_container *c;
5300 assert_return(m, NULL);
5302 c = complete ? &m->root_container : message_get_container(m);
5303 return strempty(c->signature);
5306 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5307 bool done_something = false;
5310 assert_return(m, -EINVAL);
5311 assert_return(source, -EINVAL);
5312 assert_return(!m->sealed, -EPERM);
5313 assert_return(source->sealed, -EPERM);
5316 const char *contents;
5331 r = sd_bus_message_peek_type(source, &type, &contents);
5337 done_something = true;
5339 if (bus_type_is_container(type) > 0) {
5341 r = sd_bus_message_enter_container(source, type, contents);
5345 r = sd_bus_message_open_container(m, type, contents);
5349 r = sd_bus_message_copy(m, source, true);
5353 r = sd_bus_message_close_container(m);
5357 r = sd_bus_message_exit_container(source);
5364 r = sd_bus_message_read_basic(source, type, &basic);
5370 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5371 type == SD_BUS_TYPE_SIGNATURE ||
5372 type == SD_BUS_TYPE_STRING)
5373 r = sd_bus_message_append_basic(m, type, basic.string);
5375 r = sd_bus_message_append_basic(m, type, &basic);
5382 return done_something;
5385 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5390 assert_return(m, -EINVAL);
5391 assert_return(m->sealed, -EPERM);
5392 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5393 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5394 assert_return(type || contents, -EINVAL);
5395 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5397 r = sd_bus_message_peek_type(m, &t, &c);
5401 if (type != 0 && type != t)
5404 if (contents && !streq_ptr(contents, c))
5410 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5411 assert_return(m, NULL);