1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include "time-util.h"
30 #include "cgroup-util.h"
33 #include "bus-message.h"
34 #include "bus-internal.h"
36 #include "bus-signature.h"
37 #include "bus-gvariant.h"
39 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
41 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
46 if (old_base == new_base)
49 if ((uint8_t*) p < (uint8_t*) old_base)
52 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
55 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
58 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
62 if (part->memfd >= 0) {
63 /* If we can reuse the memfd, try that. For that it
64 * can't be sealed yet. */
67 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped);
70 assert_se(munmap(part->data, part->mapped) == 0);
72 close_nointr_nofail(part->memfd);
75 } else if (part->munmap_this)
76 munmap(part->data, part->mapped);
77 else if (part->free_this)
84 static void message_reset_parts(sd_bus_message *m) {
85 struct bus_body_part *part;
90 while (m->n_body_parts > 0) {
91 struct bus_body_part *next = part->next;
92 message_free_part(m, part);
99 m->cached_rindex_part = NULL;
100 m->cached_rindex_part_begin = 0;
103 static void message_reset_containers(sd_bus_message *m) {
108 for (i = 0; i < m->n_containers; i++) {
109 free(m->containers[i].signature);
110 free(m->containers[i].offsets);
114 m->containers = NULL;
117 m->root_container.index = 0;
120 static void message_free(sd_bus_message *m) {
126 message_reset_parts(m);
131 if (m->release_kdbus) {
134 off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
135 ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &off);
139 sd_bus_unref(m->bus);
142 close_many(m->fds, m->n_fds);
146 if (m->iovec != m->iovec_fixed)
149 message_reset_containers(m);
150 free(m->root_container.signature);
151 free(m->root_container.offsets);
153 free(m->peeked_signature);
155 bus_creds_done(&m->creds);
159 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
161 size_t old_size, new_size, start;
168 old_size = sizeof(struct bus_header) + m->header->fields_size;
169 start = ALIGN_TO(old_size, align);
170 new_size = start + sz;
172 if (old_size == new_size)
173 return (uint8_t*) m->header + old_size;
175 if (new_size > (size_t) ((uint32_t) -1))
178 if (m->free_header) {
179 np = realloc(m->header, ALIGN8(new_size));
183 /* Initially, the header is allocated as part of of
184 * the sd_bus_message itself, let's replace it by
187 np = malloc(ALIGN8(new_size));
191 memcpy(np, m->header, sizeof(struct bus_header));
194 /* Zero out padding */
195 if (start > old_size)
196 memset((uint8_t*) np + old_size, 0, start - old_size);
200 m->header->fields_size = new_size - sizeof(struct bus_header);
202 /* Adjust quick access pointers */
203 m->path = adjust_pointer(m->path, op, old_size, m->header);
204 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
205 m->member = adjust_pointer(m->member, op, old_size, m->header);
206 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
207 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
208 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
210 m->free_header = true;
213 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
216 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
219 return (uint8_t*) np + start;
226 static int message_append_field_string(
238 /* dbus1 doesn't allow strings over 32bit, let's enforce this
239 * globally, to not risk convertability */
241 if (l > (size_t) (uint32_t) -1)
244 /* Signature "(yv)" where the variant contains "s" */
246 if (BUS_MESSAGE_IS_GVARIANT(m)) {
248 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
249 p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
261 *ret = (char*) p + 8;
264 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
265 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
274 ((uint32_t*) p)[1] = l;
275 memcpy(p + 8, s, l + 1);
278 *ret = (char*) p + 8;
284 static int message_append_field_signature(
295 /* dbus1 doesn't allow signatures over 32bit, let's enforce
296 * this globally, to not risk convertability */
301 /* Signature "(yv)" where the variant contains "g" */
303 if (BUS_MESSAGE_IS_GVARIANT(m))
304 /* For gvariant the serialization is the same as for normal strings */
305 return message_append_field_string(m, h, 'g', s, ret);
307 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
308 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
314 p[2] = SD_BUS_TYPE_SIGNATURE;
317 memcpy(p + 5, s, l + 1);
320 *ret = (const char*) p + 5;
326 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
331 if (BUS_MESSAGE_IS_GVARIANT(m)) {
332 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
334 p = message_extend_fields(m, 8, 1 + 7 + 4 + 1 + 1, true);
340 *((uint32_t*) (p + 8)) = x;
344 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
345 p = message_extend_fields(m, 8, 4 + 4, false);
351 p[2] = SD_BUS_TYPE_UINT32;
354 ((uint32_t*) p)[1] = x;
360 int bus_message_from_header(
366 const struct ucred *ucred,
369 sd_bus_message **ret) {
372 struct bus_header *h;
375 assert(buffer || length <= 0);
376 assert(fds || n_fds <= 0);
379 if (length < sizeof(struct bus_header))
383 if (h->version != 1 &&
390 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
393 if (h->endian != BUS_LITTLE_ENDIAN &&
394 h->endian != BUS_BIG_ENDIAN)
397 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
400 label_sz = strlen(label);
415 m->creds.uid = ucred->uid;
416 m->creds.pid = ucred->pid;
417 m->creds.gid = ucred->gid;
418 m->creds.mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID;
422 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
423 memcpy(m->creds.label, label, label_sz + 1);
425 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
429 m->bus = sd_bus_ref(bus);
435 int bus_message_from_malloc(
441 const struct ucred *ucred,
443 sd_bus_message **ret) {
449 r = bus_message_from_header(bus, buffer, length, fds, n_fds, ucred, label, 0, &m);
453 if (length != BUS_MESSAGE_SIZE(m)) {
458 sz = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
461 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
463 m->body.sealed = true;
468 m->iovec = m->iovec_fixed;
469 m->iovec[0].iov_base = buffer;
470 m->iovec[0].iov_len = length;
472 r = bus_message_parse_fields(m);
476 /* We take possession of the memory and fds now */
477 m->free_header = true;
488 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
491 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
496 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
497 m->header->endian = BUS_NATIVE_ENDIAN;
498 m->header->type = type;
499 m->header->version = bus ? bus->message_version : 1;
500 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
501 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
504 m->bus = sd_bus_ref(bus);
509 _public_ int sd_bus_message_new_signal(
512 const char *interface,
514 sd_bus_message **m) {
519 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
520 assert_return(object_path_is_valid(path), -EINVAL);
521 assert_return(interface_name_is_valid(interface), -EINVAL);
522 assert_return(member_name_is_valid(member), -EINVAL);
523 assert_return(m, -EINVAL);
525 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
529 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
531 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
534 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
537 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
545 sd_bus_message_unref(t);
549 _public_ int sd_bus_message_new_method_call(
551 const char *destination,
553 const char *interface,
555 sd_bus_message **m) {
560 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
561 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
562 assert_return(object_path_is_valid(path), -EINVAL);
563 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
564 assert_return(member_name_is_valid(member), -EINVAL);
565 assert_return(m, -EINVAL);
567 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
571 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
574 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
579 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
585 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
598 static int message_new_reply(
599 sd_bus_message *call,
601 sd_bus_message **m) {
606 assert_return(call, -EINVAL);
607 assert_return(call->sealed, -EPERM);
608 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
609 assert_return(!call->bus || call->bus->state != BUS_UNSET, -ENOTCONN);
610 assert_return(m, -EINVAL);
612 t = message_new(call->bus, type);
616 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
617 t->reply_serial = BUS_MESSAGE_SERIAL(call);
619 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
624 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
629 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
630 t->enforced_reply_signature = call->enforced_reply_signature;
640 _public_ int sd_bus_message_new_method_return(
641 sd_bus_message *call,
642 sd_bus_message **m) {
644 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
647 _public_ int sd_bus_message_new_method_error(
648 sd_bus_message *call,
649 const sd_bus_error *e,
650 sd_bus_message **m) {
655 assert_return(sd_bus_error_is_set(e), -EINVAL);
656 assert_return(m, -EINVAL);
658 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
662 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
667 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
672 t->error._need_free = -1;
682 _public_ int sd_bus_message_new_method_errorf(
683 sd_bus_message *call,
689 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
692 assert_return(name, -EINVAL);
693 assert_return(m, -EINVAL);
695 va_start(ap, format);
696 bus_error_setfv(&error, name, format, ap);
699 return sd_bus_message_new_method_error(call, &error, m);
702 _public_ int sd_bus_message_new_method_errno(
703 sd_bus_message *call,
705 const sd_bus_error *p,
706 sd_bus_message **m) {
708 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
710 if (sd_bus_error_is_set(p))
711 return sd_bus_message_new_method_error(call, p, m);
713 sd_bus_error_set_errno(&berror, error);
715 return sd_bus_message_new_method_error(call, &berror, m);
718 _public_ int sd_bus_message_new_method_errnof(
719 sd_bus_message *call,
725 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
728 va_start(ap, format);
729 bus_error_set_errnofv(&berror, error, format, ap);
732 return sd_bus_message_new_method_error(call, &berror, m);
735 int bus_message_new_synthetic_error(
738 const sd_bus_error *e,
739 sd_bus_message **m) {
744 assert(sd_bus_error_is_set(e));
747 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
751 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
752 t->reply_serial = serial;
754 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
758 if (bus && bus->unique_name) {
759 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
764 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
769 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
774 t->error._need_free = -1;
784 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
785 assert_return(m, NULL);
787 assert(m->n_ref > 0);
793 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
794 assert_return(m, NULL);
796 assert(m->n_ref > 0);
805 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
806 assert_return(m, -EINVAL);
807 assert_return(type, -EINVAL);
809 *type = m->header->type;
813 _public_ int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
814 assert_return(m, -EINVAL);
815 assert_return(serial, -EINVAL);
816 assert_return(m->header->serial != 0, -ENOENT);
818 *serial = BUS_MESSAGE_SERIAL(m);
822 _public_ int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
823 assert_return(m, -EINVAL);
824 assert_return(serial, -EINVAL);
825 assert_return(m->reply_serial != 0, -ENOENT);
827 *serial = m->reply_serial;
831 _public_ int sd_bus_message_get_no_reply(sd_bus_message *m) {
832 assert_return(m, -EINVAL);
834 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL ? !!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
837 _public_ int sd_bus_message_get_no_auto_start(sd_bus_message *m) {
838 assert_return(m, -EINVAL);
840 return !!(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
843 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
844 assert_return(m, NULL);
849 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
850 assert_return(m, NULL);
855 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
856 assert_return(m, NULL);
861 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
862 assert_return(m, NULL);
864 return m->destination;
867 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
868 assert_return(m, NULL);
873 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
874 assert_return(m, NULL);
875 assert_return(sd_bus_error_is_set(&m->error), NULL);
880 _public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
881 assert_return(m, -EINVAL);
882 assert_return(usec, -EINVAL);
883 assert_return(m->monotonic > 0, -ENODATA);
885 *usec = m->monotonic;
889 _public_ int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
890 assert_return(m, -EINVAL);
891 assert_return(usec, -EINVAL);
892 assert_return(m->realtime > 0, -ENODATA);
898 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
899 assert_return(m, NULL);
901 if (m->creds.mask == 0)
907 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
908 const char *interface,
909 const char *member) {
910 assert_return(m, -EINVAL);
912 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
915 if (interface && (!m->interface || !streq(m->interface, interface)))
918 if (member && (!m->member || !streq(m->member, member)))
924 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
925 const char *interface,
926 const char *member) {
927 assert_return(m, -EINVAL);
929 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
932 if (interface && (!m->interface || !streq(m->interface, interface)))
935 if (member && (!m->member || !streq(m->member, member)))
941 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
942 assert_return(m, -EINVAL);
944 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
947 if (name && (!m->error.name || !streq(m->error.name, name)))
953 _public_ int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
954 assert_return(m, -EINVAL);
955 assert_return(!m->sealed, -EPERM);
956 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
959 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
961 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
966 _public_ int sd_bus_message_set_no_auto_start(sd_bus_message *m, int b) {
967 assert_return(m, -EINVAL);
968 assert_return(!m->sealed, -EPERM);
971 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
973 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
978 static struct bus_container *message_get_container(sd_bus_message *m) {
981 if (m->n_containers == 0)
982 return &m->root_container;
984 assert(m->containers);
985 return m->containers + m->n_containers - 1;
988 struct bus_body_part *message_append_part(sd_bus_message *m) {
989 struct bus_body_part *part;
996 if (m->n_body_parts <= 0) {
1000 assert(m->body_end);
1002 part = new0(struct bus_body_part, 1);
1008 m->body_end->next = part;
1018 static void part_zero(struct bus_body_part *part, size_t sz) {
1023 /* All other fields can be left in their defaults */
1024 assert(!part->data);
1025 assert(part->memfd < 0);
1028 part->is_zero = true;
1029 part->sealed = true;
1032 static int part_make_space(
1033 struct sd_bus_message *m,
1034 struct bus_body_part *part,
1043 assert(!part->sealed);
1048 if (!part->data && part->memfd < 0)
1049 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped);
1051 if (part->memfd >= 0) {
1054 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &u);
1060 if (!part->data || sz > part->mapped) {
1061 size_t psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1063 if (part->mapped <= 0)
1064 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1066 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1068 if (n == MAP_FAILED) {
1077 part->munmap_this = true;
1079 n = realloc(part->data, MAX(sz, 1u));
1086 part->free_this = true;
1090 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1096 static int message_add_offset(sd_bus_message *m, size_t offset) {
1097 struct bus_container *c;
1100 assert(BUS_MESSAGE_IS_GVARIANT(m));
1102 /* Add offset to current container, unless this is the first
1103 * item in it, which will have the 0 offset, which we can
1105 c = message_get_container(m);
1107 if (!c->need_offsets)
1110 if (!GREEDY_REALLOC(c->offsets, c->n_offsets_allocated, c->n_offsets + 1))
1113 c->offsets[c->n_offsets++] = offset;
1117 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1118 struct bus_container *c;
1125 /* Update counters */
1126 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1129 *c->array_size += expand;
1133 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1134 size_t start_body, end_body, padding, added;
1145 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1146 end_body = start_body + sz;
1148 padding = start_body - m->header->body_size;
1149 added = padding + sz;
1151 /* Check for 32bit overflows */
1152 if (end_body > (size_t) ((uint32_t) -1)) {
1158 struct bus_body_part *part = NULL;
1162 m->n_body_parts <= 0 ||
1163 m->body_end->sealed ||
1164 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1168 part = message_append_part(m);
1172 part_zero(part, padding);
1175 part = message_append_part(m);
1179 r = part_make_space(m, part, sz, &p);
1183 struct bus_container *c;
1185 size_t os, start_part, end_part;
1191 start_part = ALIGN_TO(part->size, align);
1192 end_part = start_part + sz;
1194 r = part_make_space(m, part, end_part, &p);
1199 memset(p, 0, padding);
1200 p = (uint8_t*) p + padding;
1203 /* Readjust pointers */
1204 for (c = m->containers; c < m->containers + m->n_containers; c++)
1205 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1207 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1210 /* Return something that is not NULL and is aligned */
1211 p = (uint8_t *) NULL + align;
1213 m->header->body_size = end_body;
1214 message_extend_containers(m, added);
1217 r = message_add_offset(m, end_body);
1227 static int message_push_fd(sd_bus_message *m, int fd) {
1238 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1242 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1245 close_nointr_nofail(copy);
1250 m->fds[m->n_fds] = copy;
1256 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1257 _cleanup_close_ int fd = -1;
1258 struct bus_container *c;
1262 assert_return(m, -EINVAL);
1263 assert_return(!m->sealed, -EPERM);
1264 assert_return(bus_type_is_basic(type), -EINVAL);
1265 assert_return(!m->poisoned, -ESTALE);
1267 c = message_get_container(m);
1269 if (c->signature && c->signature[c->index]) {
1270 /* Container signature is already set */
1272 if (c->signature[c->index] != type)
1277 /* Maybe we can append to the signature? But only if this is the top-level container*/
1278 if (c->enclosing != 0)
1281 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1288 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1294 case SD_BUS_TYPE_SIGNATURE:
1295 case SD_BUS_TYPE_STRING:
1298 /* Fall through... */
1299 case SD_BUS_TYPE_OBJECT_PATH:
1307 case SD_BUS_TYPE_BOOLEAN:
1309 u8 = p && *(int*) p;
1315 case SD_BUS_TYPE_UNIX_FD:
1320 fd = message_push_fd(m, *(int*) p);
1331 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1332 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1339 a = message_extend_body(m, align, sz, true);
1346 *stored = (const uint8_t*) a;
1353 case SD_BUS_TYPE_STRING:
1354 /* To make things easy we'll serialize a NULL string
1355 * into the empty string */
1358 /* Fall through... */
1359 case SD_BUS_TYPE_OBJECT_PATH:
1365 sz = 4 + strlen(p) + 1;
1368 case SD_BUS_TYPE_SIGNATURE:
1373 sz = 1 + strlen(p) + 1;
1376 case SD_BUS_TYPE_BOOLEAN:
1378 u32 = p && *(int*) p;
1384 case SD_BUS_TYPE_UNIX_FD:
1389 fd = message_push_fd(m, *(int*) p);
1400 align = bus_type_get_alignment(type);
1401 sz = bus_type_get_size(type);
1408 a = message_extend_body(m, align, sz, false);
1412 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1413 *(uint32_t*) a = sz - 5;
1414 memcpy((uint8_t*) a + 4, p, sz - 4);
1417 *stored = (const uint8_t*) a + 4;
1419 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1420 *(uint8_t*) a = sz - 1;
1421 memcpy((uint8_t*) a + 1, p, sz - 1);
1424 *stored = (const uint8_t*) a + 1;
1433 if (type == SD_BUS_TYPE_UNIX_FD)
1436 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1443 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1444 return message_append_basic(m, type, p, NULL);
1447 _public_ int sd_bus_message_append_string_space(
1452 struct bus_container *c;
1455 assert_return(m, -EINVAL);
1456 assert_return(s, -EINVAL);
1457 assert_return(!m->sealed, -EPERM);
1458 assert_return(!m->poisoned, -ESTALE);
1460 c = message_get_container(m);
1462 if (c->signature && c->signature[c->index]) {
1463 /* Container signature is already set */
1465 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1470 /* Maybe we can append to the signature? But only if this is the top-level container*/
1471 if (c->enclosing != 0)
1474 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1481 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1482 a = message_extend_body(m, 1, size + 1, true);
1488 a = message_extend_body(m, 4, 4 + size + 1, false);
1492 *(uint32_t*) a = size;
1498 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1504 _public_ int sd_bus_message_append_string_iovec(
1506 const struct iovec *iov,
1514 assert_return(m, -EINVAL);
1515 assert_return(!m->sealed, -EPERM);
1516 assert_return(iov || n == 0, -EINVAL);
1517 assert_return(!m->poisoned, -ESTALE);
1519 size = IOVEC_TOTAL_SIZE(iov, n);
1521 r = sd_bus_message_append_string_space(m, size, &p);
1525 for (i = 0; i < n; i++) {
1527 if (iov[i].iov_base)
1528 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1530 memset(p, ' ', iov[i].iov_len);
1532 p += iov[i].iov_len;
1538 static int bus_message_open_array(
1540 struct bus_container *c,
1541 const char *contents,
1542 uint32_t **array_size,
1544 bool *need_offsets) {
1554 assert(need_offsets);
1556 if (!signature_is_single(contents, true))
1559 if (c->signature && c->signature[c->index]) {
1561 /* Verify the existing signature */
1563 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1566 if (!startswith(c->signature + c->index + 1, contents))
1569 nindex = c->index + 1 + strlen(contents);
1573 if (c->enclosing != 0)
1576 /* Extend the existing signature */
1578 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1584 nindex = e - c->signature;
1587 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1588 alignment = bus_gvariant_get_alignment(contents);
1592 /* Add alignment padding and add to offset list */
1593 if (!message_extend_body(m, alignment, 0, false))
1596 r = bus_gvariant_is_fixed_size(contents);
1600 *begin = m->header->body_size;
1601 *need_offsets = r == 0;
1605 struct bus_body_part *o;
1607 alignment = bus_type_get_alignment(contents[0]);
1611 a = message_extend_body(m, 4, 4, false);
1616 op = m->body_end->data;
1617 os = m->body_end->size;
1619 /* Add alignment between size and first element */
1620 if (!message_extend_body(m, alignment, 0, false))
1623 /* location of array size might have changed so let's readjust a */
1624 if (o == m->body_end)
1625 a = adjust_pointer(a, op, os, m->body_end->data);
1631 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1637 static int bus_message_open_variant(
1639 struct bus_container *c,
1640 const char *contents) {
1646 if (!signature_is_single(contents, false))
1649 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1652 if (c->signature && c->signature[c->index]) {
1654 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1660 if (c->enclosing != 0)
1663 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1670 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1671 /* Variants are always aligned to 8 */
1673 if (!message_extend_body(m, 8, 0, false))
1680 l = strlen(contents);
1681 a = message_extend_body(m, 1, 1 + l + 1, false);
1686 memcpy((uint8_t*) a + 1, contents, l + 1);
1689 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1695 static int bus_message_open_struct(
1697 struct bus_container *c,
1698 const char *contents,
1700 bool *need_offsets) {
1709 assert(need_offsets);
1711 if (!signature_is_valid(contents, false))
1714 if (c->signature && c->signature[c->index]) {
1717 l = strlen(contents);
1719 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1720 !startswith(c->signature + c->index + 1, contents) ||
1721 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1724 nindex = c->index + 1 + l + 1;
1728 if (c->enclosing != 0)
1731 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1737 nindex = e - c->signature;
1740 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1743 alignment = bus_gvariant_get_alignment(contents);
1747 if (!message_extend_body(m, alignment, 0, false))
1750 r = bus_gvariant_is_fixed_size(contents);
1754 *begin = m->header->body_size;
1755 *need_offsets = r == 0;
1757 /* Align contents to 8 byte boundary */
1758 if (!message_extend_body(m, 8, 0, false))
1762 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1768 static int bus_message_open_dict_entry(
1770 struct bus_container *c,
1771 const char *contents,
1773 bool *need_offsets) {
1781 assert(need_offsets);
1783 if (!signature_is_pair(contents))
1786 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1789 if (c->signature && c->signature[c->index]) {
1792 l = strlen(contents);
1794 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1795 !startswith(c->signature + c->index + 1, contents) ||
1796 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1801 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1804 alignment = bus_gvariant_get_alignment(contents);
1808 if (!message_extend_body(m, alignment, 0, false))
1811 r = bus_gvariant_is_fixed_size(contents);
1815 *begin = m->header->body_size;
1816 *need_offsets = r == 0;
1818 /* Align contents to 8 byte boundary */
1819 if (!message_extend_body(m, 8, 0, false))
1826 _public_ int sd_bus_message_open_container(
1829 const char *contents) {
1831 struct bus_container *c, *w;
1832 uint32_t *array_size = NULL;
1834 size_t before, begin;
1835 bool need_offsets = false;
1838 assert_return(m, -EINVAL);
1839 assert_return(!m->sealed, -EPERM);
1840 assert_return(contents, -EINVAL);
1841 assert_return(!m->poisoned, -ESTALE);
1843 /* Make sure we have space for one more container */
1844 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1852 c = message_get_container(m);
1854 signature = strdup(contents);
1860 /* Save old index in the parent container, in case we have to
1861 * abort this container */
1862 c->saved_index = c->index;
1863 before = m->header->body_size;
1865 if (type == SD_BUS_TYPE_ARRAY)
1866 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1867 else if (type == SD_BUS_TYPE_VARIANT)
1868 r = bus_message_open_variant(m, c, contents);
1869 else if (type == SD_BUS_TYPE_STRUCT)
1870 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1871 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1872 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1881 /* OK, let's fill it in */
1882 w += m->n_containers++;
1883 w->enclosing = type;
1884 w->signature = signature;
1886 w->array_size = array_size;
1889 w->n_offsets = w->n_offsets_allocated = 0;
1891 w->need_offsets = need_offsets;
1896 static size_t determine_word_size(size_t sz, size_t extra) {
1897 if (sz + extra <= 0xFF)
1899 else if (sz + extra*2 <= 0xFFFF)
1901 else if (sz + extra*4 <= 0xFFFFFFFF)
1907 static size_t read_word_le(void *p, size_t sz) {
1917 return *(uint8_t*) p;
1922 return le16toh(x.u16);
1924 return le32toh(x.u32);
1926 return le64toh(x.u64);
1928 assert_not_reached("unknown word width");
1931 static void write_word_le(void *p, size_t sz, size_t value) {
1939 assert(sz == 8 || (value < (1ULL << (sz*8))));
1942 *(uint8_t*) p = value;
1945 x.u16 = htole16((uint16_t) value);
1947 x.u32 = htole32((uint32_t) value);
1949 x.u64 = htole64((uint64_t) value);
1951 assert_not_reached("unknown word width");
1956 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1961 if (!BUS_MESSAGE_IS_GVARIANT(m))
1964 if (c->need_offsets) {
1965 size_t payload, sz, i;
1968 /* Variable-width arrays */
1970 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
1971 sz = determine_word_size(payload, c->n_offsets);
1973 a = message_extend_body(m, 1, sz * c->n_offsets, true);
1977 for (i = 0; i < c->n_offsets; i++)
1978 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
1982 /* Fixed-width or empty arrays */
1984 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
1992 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
1999 if (!BUS_MESSAGE_IS_GVARIANT(m))
2002 l = strlen(c->signature);
2004 a = message_extend_body(m, 1, 1 + l, true);
2009 memcpy(a+1, c->signature, l);
2014 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2015 size_t n_variable = 0;
2024 if (!BUS_MESSAGE_IS_GVARIANT(m))
2027 p = strempty(c->signature);
2031 r = signature_element_length(p, &n);
2040 r = bus_gvariant_is_fixed_size(t);
2045 assert(i <= c->n_offsets);
2047 /* We need to add an offset for each item that has a
2048 * variable size and that is not the last one in the
2050 if (r == 0 && p[n] != 0)
2057 assert(i == c->n_offsets);
2059 if (n_variable <= 0) {
2060 a = message_extend_body(m, 1, 0, add_offset);
2067 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2069 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2071 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2075 p = strempty(c->signature);
2076 for (i = 0, j = 0; i < c->n_offsets; i++) {
2080 r = signature_element_length(p, &n);
2091 r = bus_gvariant_is_fixed_size(t);
2094 if (r > 0 || p[0] == 0)
2098 k = n_variable - 1 - j;
2100 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2109 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2110 struct bus_container *c;
2113 assert_return(m, -EINVAL);
2114 assert_return(!m->sealed, -EPERM);
2115 assert_return(m->n_containers > 0, -EINVAL);
2116 assert_return(!m->poisoned, -ESTALE);
2118 c = message_get_container(m);
2120 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2121 if (c->signature && c->signature[c->index] != 0)
2126 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2127 r = bus_message_close_array(m, c);
2128 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2129 r = bus_message_close_variant(m, c);
2130 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2131 r = bus_message_close_struct(m, c, true);
2133 assert_not_reached("Unknown container type");
2147 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2154 stack[*i].types = types;
2155 stack[*i].n_struct = n_struct;
2156 stack[*i].n_array = n_array;
2162 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2173 *types = stack[*i].types;
2174 *n_struct = stack[*i].n_struct;
2175 *n_array = stack[*i].n_array;
2180 int bus_message_append_ap(
2185 unsigned n_array, n_struct;
2186 TypeStack stack[BUS_CONTAINER_DEPTH];
2187 unsigned stack_ptr = 0;
2195 n_array = (unsigned) -1;
2196 n_struct = strlen(types);
2201 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2202 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2208 r = sd_bus_message_close_container(m);
2216 if (n_array != (unsigned) -1)
2225 case SD_BUS_TYPE_BYTE: {
2228 x = (uint8_t) va_arg(ap, int);
2229 r = sd_bus_message_append_basic(m, *t, &x);
2233 case SD_BUS_TYPE_BOOLEAN:
2234 case SD_BUS_TYPE_INT32:
2235 case SD_BUS_TYPE_UINT32:
2236 case SD_BUS_TYPE_UNIX_FD: {
2239 /* We assume a boolean is the same as int32_t */
2240 assert_cc(sizeof(int32_t) == sizeof(int));
2242 x = va_arg(ap, uint32_t);
2243 r = sd_bus_message_append_basic(m, *t, &x);
2247 case SD_BUS_TYPE_INT16:
2248 case SD_BUS_TYPE_UINT16: {
2251 x = (uint16_t) va_arg(ap, int);
2252 r = sd_bus_message_append_basic(m, *t, &x);
2256 case SD_BUS_TYPE_INT64:
2257 case SD_BUS_TYPE_UINT64:
2258 case SD_BUS_TYPE_DOUBLE: {
2261 x = va_arg(ap, uint64_t);
2262 r = sd_bus_message_append_basic(m, *t, &x);
2266 case SD_BUS_TYPE_STRING:
2267 case SD_BUS_TYPE_OBJECT_PATH:
2268 case SD_BUS_TYPE_SIGNATURE: {
2271 x = va_arg(ap, const char*);
2272 r = sd_bus_message_append_basic(m, *t, x);
2276 case SD_BUS_TYPE_ARRAY: {
2279 r = signature_element_length(t + 1, &k);
2285 memcpy(s, t + 1, k);
2288 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2293 if (n_array == (unsigned) -1) {
2298 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2304 n_array = va_arg(ap, unsigned);
2309 case SD_BUS_TYPE_VARIANT: {
2312 s = va_arg(ap, const char*);
2316 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2320 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2325 n_struct = strlen(s);
2326 n_array = (unsigned) -1;
2331 case SD_BUS_TYPE_STRUCT_BEGIN:
2332 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2335 r = signature_element_length(t, &k);
2342 memcpy(s, t + 1, k - 2);
2345 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2350 if (n_array == (unsigned) -1) {
2355 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2361 n_array = (unsigned) -1;
2377 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2381 assert_return(m, -EINVAL);
2382 assert_return(types, -EINVAL);
2383 assert_return(!m->sealed, -EPERM);
2384 assert_return(!m->poisoned, -ESTALE);
2386 va_start(ap, types);
2387 r = bus_message_append_ap(m, types, ap);
2393 _public_ int sd_bus_message_append_array_space(
2403 assert_return(m, -EINVAL);
2404 assert_return(!m->sealed, -EPERM);
2405 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2406 assert_return(ptr || size == 0, -EINVAL);
2407 assert_return(!m->poisoned, -ESTALE);
2409 /* alignment and size of the trivial types (except bool) is
2410 * identical for gvariant and dbus1 marshalling */
2411 align = bus_type_get_alignment(type);
2412 sz = bus_type_get_size(type);
2414 assert_se(align > 0);
2420 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2424 a = message_extend_body(m, align, size, false);
2428 r = sd_bus_message_close_container(m);
2436 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2443 assert_return(m, -EINVAL);
2444 assert_return(!m->sealed, -EPERM);
2445 assert_return(bus_type_is_trivial(type), -EINVAL);
2446 assert_return(ptr || size == 0, -EINVAL);
2447 assert_return(!m->poisoned, -ESTALE);
2449 r = sd_bus_message_append_array_space(m, type, size, &p);
2454 memcpy(p, ptr, size);
2459 _public_ int sd_bus_message_append_array_iovec(
2462 const struct iovec *iov,
2470 assert_return(m, -EINVAL);
2471 assert_return(!m->sealed, -EPERM);
2472 assert_return(bus_type_is_trivial(type), -EINVAL);
2473 assert_return(iov || n == 0, -EINVAL);
2474 assert_return(!m->poisoned, -ESTALE);
2476 size = IOVEC_TOTAL_SIZE(iov, n);
2478 r = sd_bus_message_append_array_space(m, type, size, &p);
2482 for (i = 0; i < n; i++) {
2484 if (iov[i].iov_base)
2485 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2487 memset(p, 0, iov[i].iov_len);
2489 p = (uint8_t*) p + iov[i].iov_len;
2495 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2498 _cleanup_close_ int copy_fd = -1;
2499 struct bus_body_part *part;
2511 if (!bus_type_is_trivial(type))
2516 r = sd_memfd_set_sealed(memfd, true);
2520 copy_fd = sd_memfd_dup_fd(memfd);
2524 r = sd_memfd_get_size(memfd, &size);
2528 align = bus_type_get_alignment(type);
2529 sz = bus_type_get_size(type);
2531 assert_se(align > 0);
2537 if (size > (uint64_t) (uint32_t) -1)
2540 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2544 a = message_extend_body(m, align, 0, false);
2548 part = message_append_part(m);
2552 part->memfd = copy_fd;
2553 part->sealed = true;
2557 m->header->body_size += size;
2558 message_extend_containers(m, size);
2560 return sd_bus_message_close_container(m);
2563 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
2564 _cleanup_close_ int copy_fd = -1;
2565 struct bus_body_part *part;
2566 struct bus_container *c;
2571 assert_return(m, -EINVAL);
2572 assert_return(memfd, -EINVAL);
2573 assert_return(!m->sealed, -EPERM);
2574 assert_return(!m->poisoned, -ESTALE);
2576 r = sd_memfd_set_sealed(memfd, true);
2580 copy_fd = sd_memfd_dup_fd(memfd);
2584 r = sd_memfd_get_size(memfd, &size);
2588 /* We require this to be NUL terminated */
2592 if (size > (uint64_t) (uint32_t) -1)
2595 c = message_get_container(m);
2596 if (c->signature && c->signature[c->index]) {
2597 /* Container signature is already set */
2599 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2604 /* Maybe we can append to the signature? But only if this is the top-level container*/
2605 if (c->enclosing != 0)
2608 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2615 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2616 a = message_extend_body(m, 4, 4, false);
2620 *(uint32_t*) a = size - 1;
2623 part = message_append_part(m);
2627 part->memfd = copy_fd;
2628 part->sealed = true;
2632 m->header->body_size += size;
2633 message_extend_containers(m, size);
2635 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2636 r = message_add_offset(m, m->header->body_size);
2643 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2649 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2653 assert_return(m, -EINVAL);
2654 assert_return(!m->sealed, -EPERM);
2655 assert_return(!m->poisoned, -ESTALE);
2657 r = sd_bus_message_open_container(m, 'a', "s");
2661 STRV_FOREACH(i, l) {
2662 r = sd_bus_message_append_basic(m, 's', *i);
2667 return sd_bus_message_close_container(m);
2670 static int bus_message_close_header(sd_bus_message *m) {
2676 if (!BUS_MESSAGE_IS_GVARIANT(m))
2679 if (m->n_header_offsets < 1)
2682 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2684 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2686 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2690 for (i = 0; i < m->n_header_offsets; i++)
2691 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2696 int bus_message_seal(sd_bus_message *m, uint64_t serial) {
2697 struct bus_body_part *part;
2707 if (m->n_containers > 0)
2713 /* In vtables the return signature of method calls is listed,
2714 * let's check if they match if this is a response */
2715 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2716 m->enforced_reply_signature &&
2717 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2720 /* If gvariant marshalling is used we need to close the body structure */
2721 r = bus_message_close_struct(m, &m->root_container, false);
2725 /* If there's a non-trivial signature set, then add it in here */
2726 if (!isempty(m->root_container.signature)) {
2727 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2733 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2738 r = bus_message_close_header(m);
2742 m->header->serial = serial;
2744 /* Add padding at the end of the fields part, since we know
2745 * the body needs to start at an 8 byte alignment. We made
2746 * sure we allocated enough space for this, so all we need to
2747 * do here is to zero it out. */
2748 l = BUS_MESSAGE_FIELDS_SIZE(m);
2751 memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
2753 /* If this is something we can send as memfd, then let's seal
2754 the memfd now. Note that we can send memfds as payload only
2755 for directed messages, and not for broadcasts. */
2756 if (m->destination && m->bus && m->bus->use_memfd) {
2757 MESSAGE_FOREACH_PART(part, i, m)
2758 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2759 bus_body_part_unmap(part);
2761 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
2762 part->sealed = true;
2766 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2767 m->root_container.index = 0;
2768 m->root_container.offset_index = 0;
2769 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2776 int bus_body_part_map(struct bus_body_part *part) {
2785 if (part->size <= 0)
2788 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2789 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2790 static const uint8_t zeroes[7] = { };
2791 part->data = (void*) zeroes;
2795 psz = PAGE_ALIGN(part->size);
2797 if (part->memfd >= 0)
2798 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2799 else if (part->is_zero)
2800 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2804 if (p == MAP_FAILED)
2809 part->munmap_this = true;
2814 void bus_body_part_unmap(struct bus_body_part *part) {
2818 if (part->memfd < 0)
2824 if (!part->munmap_this)
2827 assert_se(munmap(part->data, part->mapped) == 0);
2831 part->munmap_this = false;
2836 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2837 size_t k, start, end;
2842 start = ALIGN_TO((size_t) *rindex, align);
2843 end = start + nbytes;
2848 /* Verify that padding is 0 */
2849 for (k = *rindex; k < start; k++)
2850 if (((const uint8_t*) p)[k] != 0)
2854 *r = (uint8_t*) p + start;
2861 static bool message_end_of_signature(sd_bus_message *m) {
2862 struct bus_container *c;
2866 c = message_get_container(m);
2867 return !c->signature || c->signature[c->index] == 0;
2870 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2871 struct bus_container *c;
2875 c = message_get_container(m);
2876 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2879 if (BUS_MESSAGE_IS_GVARIANT(m))
2880 return index >= c->end;
2882 assert(c->array_size);
2883 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2887 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2888 assert_return(m, -EINVAL);
2889 assert_return(m->sealed, -EPERM);
2891 if (complete && m->n_containers > 0)
2894 if (message_end_of_signature(m))
2897 if (message_end_of_array(m, m->rindex))
2903 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2904 struct bus_body_part *part;
2910 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2911 part = m->cached_rindex_part;
2912 begin = m->cached_rindex_part_begin;
2922 if (index + sz <= begin + part->size) {
2924 r = bus_body_part_map(part);
2929 *p = (uint8_t*) part->data + index - begin;
2931 m->cached_rindex_part = part;
2932 m->cached_rindex_part_begin = begin;
2937 begin += part->size;
2944 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2951 if (!BUS_MESSAGE_IS_GVARIANT(m))
2954 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2957 sz = bus_gvariant_get_size(c->signature);
2961 if (c->offset_index+1 >= c->n_offsets)
2964 /* Variable-size array */
2966 alignment = bus_gvariant_get_alignment(c->signature);
2967 assert(alignment > 0);
2969 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
2970 c->item_size = c->offsets[c->offset_index+1] - *rindex;
2973 if (c->offset_index+1 >= (c->end-c->begin)/sz)
2976 /* Fixed-size array */
2977 *rindex = c->begin + (c->offset_index+1) * sz;
2983 } else if (c->enclosing == 0 ||
2984 c->enclosing == SD_BUS_TYPE_STRUCT ||
2985 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
2990 if (c->offset_index+1 >= c->n_offsets)
2993 r = signature_element_length(c->signature + c->index, &n);
2997 r = signature_element_length(c->signature + c->index + n, &j);
3002 memcpy(t, c->signature + c->index + n, j);
3005 alignment = bus_gvariant_get_alignment(t);
3008 assert(alignment > 0);
3010 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3011 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3015 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3018 assert_not_reached("Unknown container type");
3023 /* Reached the end */
3030 static int message_peek_body(
3037 size_t k, start, end, padding;
3038 struct bus_body_part *part;
3045 start = ALIGN_TO((size_t) *rindex, align);
3046 padding = start - *rindex;
3047 end = start + nbytes;
3049 if (end > BUS_MESSAGE_BODY_SIZE(m))
3052 part = find_part(m, *rindex, padding, (void**) &q);
3057 /* Verify padding */
3058 for (k = 0; k < padding; k++)
3063 part = find_part(m, start, nbytes, (void**) &q);
3064 if (!part || (nbytes > 0 && !q))
3075 static bool validate_nul(const char *s, size_t l) {
3077 /* Check for NUL chars in the string */
3078 if (memchr(s, 0, l))
3081 /* Check for NUL termination */
3088 static bool validate_string(const char *s, size_t l) {
3090 if (!validate_nul(s, l))
3093 /* Check if valid UTF8 */
3094 if (!utf8_is_valid(s))
3100 static bool validate_signature(const char *s, size_t l) {
3102 if (!validate_nul(s, l))
3105 /* Check if valid signature */
3106 if (!signature_is_valid(s, true))
3112 static bool validate_object_path(const char *s, size_t l) {
3114 if (!validate_nul(s, l))
3117 if (!object_path_is_valid(s))
3123 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3124 struct bus_container *c;
3129 assert_return(m, -EINVAL);
3130 assert_return(m->sealed, -EPERM);
3131 assert_return(bus_type_is_basic(type), -EINVAL);
3133 if (message_end_of_signature(m))
3136 if (message_end_of_array(m, m->rindex))
3139 c = message_get_container(m);
3140 if (c->signature[c->index] != type)
3145 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3147 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3150 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3154 if (type == SD_BUS_TYPE_STRING)
3155 ok = validate_string(q, c->item_size-1);
3156 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3157 ok = validate_object_path(q, c->item_size-1);
3159 ok = validate_signature(q, c->item_size-1);
3165 *(const char**) p = q;
3169 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3171 if ((size_t) sz != c->item_size)
3174 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3177 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3183 case SD_BUS_TYPE_BYTE:
3185 *(uint8_t*) p = *(uint8_t*) q;
3188 case SD_BUS_TYPE_BOOLEAN:
3190 *(int*) p = !!*(uint8_t*) q;
3193 case SD_BUS_TYPE_INT16:
3194 case SD_BUS_TYPE_UINT16:
3196 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3199 case SD_BUS_TYPE_INT32:
3200 case SD_BUS_TYPE_UINT32:
3202 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3205 case SD_BUS_TYPE_INT64:
3206 case SD_BUS_TYPE_UINT64:
3207 case SD_BUS_TYPE_DOUBLE:
3209 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3212 case SD_BUS_TYPE_UNIX_FD: {
3215 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3220 *(int*) p = m->fds[j];
3226 assert_not_reached("unexpected type");
3230 r = container_next_item(m, c, &rindex);
3237 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3241 r = message_peek_body(m, &rindex, 4, 4, &q);
3245 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3246 r = message_peek_body(m, &rindex, 1, l+1, &q);
3250 if (type == SD_BUS_TYPE_OBJECT_PATH)
3251 ok = validate_object_path(q, l);
3253 ok = validate_string(q, l);
3258 *(const char**) p = q;
3260 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3263 r = message_peek_body(m, &rindex, 1, 1, &q);
3268 r = message_peek_body(m, &rindex, 1, l+1, &q);
3272 if (!validate_signature(q, l))
3276 *(const char**) p = q;
3281 align = bus_type_get_alignment(type);
3284 sz = bus_type_get_size(type);
3287 r = message_peek_body(m, &rindex, align, sz, &q);
3293 case SD_BUS_TYPE_BYTE:
3295 *(uint8_t*) p = *(uint8_t*) q;
3298 case SD_BUS_TYPE_BOOLEAN:
3300 *(int*) p = !!*(uint32_t*) q;
3303 case SD_BUS_TYPE_INT16:
3304 case SD_BUS_TYPE_UINT16:
3306 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3309 case SD_BUS_TYPE_INT32:
3310 case SD_BUS_TYPE_UINT32:
3312 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3315 case SD_BUS_TYPE_INT64:
3316 case SD_BUS_TYPE_UINT64:
3317 case SD_BUS_TYPE_DOUBLE:
3319 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3322 case SD_BUS_TYPE_UNIX_FD: {
3325 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3330 *(int*) p = m->fds[j];
3335 assert_not_reached("Unknown basic type...");
3342 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3348 static int bus_message_enter_array(
3350 struct bus_container *c,
3351 const char *contents,
3352 uint32_t **array_size,
3355 size_t *n_offsets) {
3369 if (!signature_is_single(contents, true))
3372 if (!c->signature || c->signature[c->index] == 0)
3375 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3378 if (!startswith(c->signature + c->index + 1, contents))
3383 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3386 r = message_peek_body(m, &rindex, 4, 4, &q);
3390 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3393 alignment = bus_type_get_alignment(contents[0]);
3397 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3401 *array_size = (uint32_t*) q;
3403 } else if (c->item_size <= 0) {
3405 /* gvariant: empty array */
3410 } else if (bus_gvariant_is_fixed_size(contents)) {
3412 /* gvariant: fixed length array */
3413 *item_size = bus_gvariant_get_size(contents);
3418 size_t where, p = 0, framing, sz;
3421 /* gvariant: variable length array */
3422 sz = determine_word_size(c->item_size, 0);
3424 where = rindex + c->item_size - sz;
3425 r = message_peek_body(m, &where, 1, sz, &q);
3429 framing = read_word_le(q, sz);
3430 if (framing > c->item_size - sz)
3432 if ((c->item_size - framing) % sz != 0)
3435 *n_offsets = (c->item_size - framing) / sz;
3437 where = rindex + framing;
3438 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3442 *offsets = new(size_t, *n_offsets);
3446 for (i = 0; i < *n_offsets; i++) {
3449 x = read_word_le((uint8_t*) q + i * sz, sz);
3450 if (x > c->item_size - sz)
3455 (*offsets)[i] = rindex + x;
3459 *item_size = (*offsets)[0] - rindex;
3464 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3465 c->index += 1 + strlen(contents);
3470 static int bus_message_enter_variant(
3472 struct bus_container *c,
3473 const char *contents,
3474 size_t *item_size) {
3486 if (!signature_is_single(contents, false))
3489 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3492 if (!c->signature || c->signature[c->index] == 0)
3495 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3500 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3503 k = strlen(contents);
3504 if (1+k > c->item_size)
3507 where = rindex + c->item_size - (1+k);
3508 r = message_peek_body(m, &where, 1, 1+k, &q);
3512 if (*(char*) q != 0)
3515 if (memcmp((uint8_t*) q+1, contents, k))
3518 *item_size = c->item_size - (1+k);
3521 r = message_peek_body(m, &rindex, 1, 1, &q);
3526 r = message_peek_body(m, &rindex, 1, l+1, &q);
3530 if (!validate_signature(q, l))
3533 if (!streq(q, contents))
3539 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3545 static int build_struct_offsets(
3547 const char *signature,
3551 size_t *n_offsets) {
3553 unsigned n_variable = 0, n_total = 0, v;
3554 size_t previous = 0, where;
3565 if (isempty(signature)) {
3572 sz = determine_word_size(size, 0);
3576 /* First, loop over signature and count variable elements and
3577 * elements in general. We use this to know how large the
3578 * offset array is at the end of the structure. Note that
3579 * GVariant only stores offsets for all variable size elements
3580 * that are not the last item. */
3586 r = signature_element_length(p, &n);
3595 r = bus_gvariant_is_fixed_size(t);
3600 if (r == 0 && p[n] != 0) /* except the last item */
3607 if (size < n_variable * sz)
3610 where = m->rindex + size - (n_variable * sz);
3611 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3617 *offsets = new(size_t, n_total);
3623 /* Second, loop again and build an offset table */
3629 r = signature_element_length(p, &n);
3638 k = bus_gvariant_get_size(t);
3646 x = read_word_le((uint8_t*) q + v*sz, sz);
3649 if (m->rindex + x < previous)
3652 /* The last item's end
3653 * is determined from
3656 x = size - (n_variable * sz);
3658 offset = m->rindex + x;
3664 align = bus_gvariant_get_alignment(t);
3667 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3671 previous = (*offsets)[(*n_offsets)++] = offset;
3676 assert(*n_offsets == n_total);
3678 *item_size = (*offsets)[0] - m->rindex;
3682 static int enter_struct_or_dict_entry(
3684 struct bus_container *c,
3685 const char *contents,
3688 size_t *n_offsets) {
3699 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3702 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3706 } else if (c->item_size <= 0) {
3708 /* gvariant empty struct */
3713 /* gvariant with contents */
3714 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3719 static int bus_message_enter_struct(
3721 struct bus_container *c,
3722 const char *contents,
3725 size_t *n_offsets) {
3737 if (!signature_is_valid(contents, false))
3740 if (!c->signature || c->signature[c->index] == 0)
3743 l = strlen(contents);
3745 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3746 !startswith(c->signature + c->index + 1, contents) ||
3747 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3750 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3754 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3755 c->index += 1 + l + 1;
3760 static int bus_message_enter_dict_entry(
3762 struct bus_container *c,
3763 const char *contents,
3766 size_t *n_offsets) {
3775 if (!signature_is_pair(contents))
3778 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3781 if (!c->signature || c->signature[c->index] == 0)
3784 l = strlen(contents);
3786 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3787 !startswith(c->signature + c->index + 1, contents) ||
3788 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3791 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3795 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3796 c->index += 1 + l + 1;
3801 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3803 const char *contents) {
3804 struct bus_container *c, *w;
3805 uint32_t *array_size = NULL;
3808 size_t *offsets = NULL;
3809 size_t n_offsets = 0, item_size = 0;
3812 assert_return(m, -EINVAL);
3813 assert_return(m->sealed, -EPERM);
3814 assert_return(type != 0 || !contents, -EINVAL);
3816 if (type == 0 || !contents) {
3820 /* Allow entering into anonymous containers */
3821 r = sd_bus_message_peek_type(m, &tt, &cc);
3825 if (type != 0 && type != tt)
3828 if (contents && !streq(contents, cc))
3836 * We enforce a global limit on container depth, that is much
3837 * higher than the 32 structs and 32 arrays the specification
3838 * mandates. This is simpler to implement for us, and we need
3839 * this only to ensure our container array doesn't grow
3840 * without bounds. We are happy to return any data from a
3841 * message as long as the data itself is valid, even if the
3842 * overall message might be not.
3844 * Note that the message signature is validated when
3845 * parsing the headers, and that validation does check the
3848 * Note that the specification defines no limits on the depth
3849 * of stacked variants, but we do.
3851 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3854 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
3859 if (message_end_of_signature(m))
3862 if (message_end_of_array(m, m->rindex))
3865 c = message_get_container(m);
3867 signature = strdup(contents);
3871 c->saved_index = c->index;
3874 if (type == SD_BUS_TYPE_ARRAY)
3875 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3876 else if (type == SD_BUS_TYPE_VARIANT)
3877 r = bus_message_enter_variant(m, c, contents, &item_size);
3878 else if (type == SD_BUS_TYPE_STRUCT)
3879 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3880 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3881 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3891 /* OK, let's fill it in */
3892 w += m->n_containers++;
3893 w->enclosing = type;
3894 w->signature = signature;
3898 w->begin = m->rindex;
3899 w->end = m->rindex + c->item_size;
3901 w->array_size = array_size;
3902 w->item_size = item_size;
3903 w->offsets = offsets;
3904 w->n_offsets = n_offsets;
3905 w->offset_index = 0;
3910 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3911 struct bus_container *c;
3915 assert_return(m, -EINVAL);
3916 assert_return(m->sealed, -EPERM);
3917 assert_return(m->n_containers > 0, -ENXIO);
3919 c = message_get_container(m);
3921 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3922 if (c->signature && c->signature[c->index] != 0)
3926 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3927 if (m->rindex < c->end)
3930 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3933 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3934 if (c->begin + l != m->rindex)
3942 c = message_get_container(m);
3945 c->index = c->saved_index;
3946 r = container_next_item(m, c, &m->rindex);
3954 static void message_quit_container(sd_bus_message *m) {
3955 struct bus_container *c;
3959 assert(m->n_containers > 0);
3961 c = message_get_container(m);
3964 assert(m->rindex >= c->before);
3965 m->rindex = c->before;
3967 /* Free container */
3972 /* Correct index of new top-level container */
3973 c = message_get_container(m);
3974 c->index = c->saved_index;
3977 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
3978 struct bus_container *c;
3981 assert_return(m, -EINVAL);
3982 assert_return(m->sealed, -EPERM);
3984 if (message_end_of_signature(m))
3987 if (message_end_of_array(m, m->rindex))
3990 c = message_get_container(m);
3992 if (bus_type_is_basic(c->signature[c->index])) {
3996 *type = c->signature[c->index];
4000 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4006 r = signature_element_length(c->signature+c->index+1, &l);
4012 sig = strndup(c->signature + c->index + 1, l);
4016 free(m->peeked_signature);
4017 m->peeked_signature = sig;
4023 *type = SD_BUS_TYPE_ARRAY;
4028 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4029 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4035 r = signature_element_length(c->signature+c->index, &l);
4040 sig = strndup(c->signature + c->index + 1, l - 2);
4044 free(m->peeked_signature);
4045 m->peeked_signature = sig;
4051 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4056 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4060 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4063 if (c->item_size < 2)
4066 /* Look for the NUL delimiter that
4067 separates the payload from the
4068 signature. Since the body might be
4069 in a different part that then the
4070 signature we map byte by byte. */
4072 for (k = 2; k <= c->item_size; k++) {
4075 where = m->rindex + c->item_size - k;
4076 r = message_peek_body(m, &where, 1, k, &q);
4080 if (*(char*) q == 0)
4084 if (k > c->item_size)
4087 free(m->peeked_signature);
4088 m->peeked_signature = strndup((char*) q + 1, k - 1);
4089 if (!m->peeked_signature)
4092 if (!signature_is_valid(m->peeked_signature, true))
4095 *contents = m->peeked_signature;
4100 r = message_peek_body(m, &rindex, 1, 1, &q);
4105 r = message_peek_body(m, &rindex, 1, l+1, &q);
4109 if (!validate_signature(q, l))
4117 *type = SD_BUS_TYPE_VARIANT;
4132 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4133 struct bus_container *c;
4135 assert_return(m, -EINVAL);
4136 assert_return(m->sealed, -EPERM);
4139 message_reset_containers(m);
4142 c = message_get_container(m);
4144 c = message_get_container(m);
4146 c->offset_index = 0;
4148 m->rindex = c->begin;
4151 c->offset_index = 0;
4152 c->item_size = c->n_offsets > 0 ? c->offsets[0] : c->end;
4154 return !isempty(c->signature);
4157 static int message_read_ap(
4162 unsigned n_array, n_struct;
4163 TypeStack stack[BUS_CONTAINER_DEPTH];
4164 unsigned stack_ptr = 0;
4165 unsigned n_loop = 0;
4173 /* Ideally, we'd just call ourselves recursively on every
4174 * complex type. However, the state of a va_list that is
4175 * passed to a function is undefined after that function
4176 * returns. This means we need to docode the va_list linearly
4177 * in a single stackframe. We hence implement our own
4178 * home-grown stack in an array. */
4180 n_array = (unsigned) -1; /* lenght of current array entries */
4181 n_struct = strlen(types); /* length of current struct contents signature */
4188 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4189 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4195 r = sd_bus_message_exit_container(m);
4203 if (n_array != (unsigned) -1)
4212 case SD_BUS_TYPE_BYTE:
4213 case SD_BUS_TYPE_BOOLEAN:
4214 case SD_BUS_TYPE_INT16:
4215 case SD_BUS_TYPE_UINT16:
4216 case SD_BUS_TYPE_INT32:
4217 case SD_BUS_TYPE_UINT32:
4218 case SD_BUS_TYPE_INT64:
4219 case SD_BUS_TYPE_UINT64:
4220 case SD_BUS_TYPE_DOUBLE:
4221 case SD_BUS_TYPE_STRING:
4222 case SD_BUS_TYPE_OBJECT_PATH:
4223 case SD_BUS_TYPE_SIGNATURE:
4224 case SD_BUS_TYPE_UNIX_FD: {
4227 p = va_arg(ap, void*);
4228 r = sd_bus_message_read_basic(m, *t, p);
4241 case SD_BUS_TYPE_ARRAY: {
4244 r = signature_element_length(t + 1, &k);
4250 memcpy(s, t + 1, k);
4253 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4264 if (n_array == (unsigned) -1) {
4269 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4275 n_array = va_arg(ap, unsigned);
4280 case SD_BUS_TYPE_VARIANT: {
4283 s = va_arg(ap, const char *);
4287 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4297 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4302 n_struct = strlen(s);
4303 n_array = (unsigned) -1;
4308 case SD_BUS_TYPE_STRUCT_BEGIN:
4309 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4312 r = signature_element_length(t, &k);
4318 memcpy(s, t + 1, k - 2);
4321 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4331 if (n_array == (unsigned) -1) {
4336 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4342 n_array = (unsigned) -1;
4355 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4359 assert_return(m, -EINVAL);
4360 assert_return(m->sealed, -EPERM);
4361 assert_return(types, -EINVAL);
4363 va_start(ap, types);
4364 r = message_read_ap(m, types, ap);
4370 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4373 assert_return(m, -EINVAL);
4374 assert_return(m->sealed, -EPERM);
4375 assert_return(types, -EINVAL);
4382 case SD_BUS_TYPE_BYTE:
4383 case SD_BUS_TYPE_BOOLEAN:
4384 case SD_BUS_TYPE_INT16:
4385 case SD_BUS_TYPE_UINT16:
4386 case SD_BUS_TYPE_INT32:
4387 case SD_BUS_TYPE_UINT32:
4388 case SD_BUS_TYPE_INT64:
4389 case SD_BUS_TYPE_UINT64:
4390 case SD_BUS_TYPE_DOUBLE:
4391 case SD_BUS_TYPE_STRING:
4392 case SD_BUS_TYPE_OBJECT_PATH:
4393 case SD_BUS_TYPE_SIGNATURE:
4394 case SD_BUS_TYPE_UNIX_FD:
4396 r = sd_bus_message_read_basic(m, *types, NULL);
4400 r = sd_bus_message_skip(m, types + 1);
4406 case SD_BUS_TYPE_ARRAY: {
4409 r = signature_element_length(types + 1, &k);
4415 memcpy(s, types+1, k);
4418 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4423 r = sd_bus_message_skip(m, s);
4430 r = sd_bus_message_exit_container(m);
4435 r = sd_bus_message_skip(m, types + 1 + k);
4442 case SD_BUS_TYPE_VARIANT: {
4443 const char *contents;
4446 r = sd_bus_message_peek_type(m, &x, &contents);
4450 if (x != SD_BUS_TYPE_VARIANT)
4453 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4457 r = sd_bus_message_skip(m, contents);
4462 r = sd_bus_message_exit_container(m);
4466 r = sd_bus_message_skip(m, types + 1);
4473 case SD_BUS_TYPE_STRUCT_BEGIN:
4474 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4477 r = signature_element_length(types, &k);
4483 memcpy(s, types+1, k-2);
4486 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4490 r = sd_bus_message_skip(m, s);
4495 r = sd_bus_message_exit_container(m);
4500 r = sd_bus_message_skip(m, types + k);
4512 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4516 struct bus_container *c;
4522 assert_return(m, -EINVAL);
4523 assert_return(m->sealed, -EPERM);
4524 assert_return(bus_type_is_trivial(type), -EINVAL);
4525 assert_return(ptr, -EINVAL);
4526 assert_return(size, -EINVAL);
4527 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4529 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4533 c = message_get_container(m);
4535 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4536 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4540 sz = c->end - c->begin;
4542 align = bus_type_get_alignment(type);
4546 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4550 /* Zero length array, let's return some aligned
4551 * pointer that is not NULL */
4552 p = (uint8_t*) NULL + align;
4554 r = message_peek_body(m, &m->rindex, align, sz, &p);
4559 r = sd_bus_message_exit_container(m);
4563 *ptr = (const void*) p;
4569 message_quit_container(m);
4573 static int message_peek_fields(
4584 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4587 static int message_peek_field_uint32(
4599 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4602 /* identical for gvariant and dbus1 */
4604 r = message_peek_fields(m, ri, 4, 4, &q);
4609 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4614 static int message_peek_field_string(
4616 bool (*validate)(const char *p),
4628 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4633 r = message_peek_fields(m, ri, 1, item_size, &q);
4639 r = message_peek_field_uint32(m, ri, 4, &l);
4643 r = message_peek_fields(m, ri, 1, l+1, &q);
4649 if (!validate_nul(q, l))
4655 if (!validate_string(q, l))
4665 static int message_peek_field_signature(
4678 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4683 r = message_peek_fields(m, ri, 1, item_size, &q);
4689 r = message_peek_fields(m, ri, 1, 1, &q);
4694 r = message_peek_fields(m, ri, 1, l+1, &q);
4699 if (!validate_signature(q, l))
4708 static int message_skip_fields(
4711 uint32_t array_size,
4712 const char **signature) {
4714 size_t original_index;
4720 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4722 original_index = *ri;
4728 if (array_size != (uint32_t) -1 &&
4729 array_size <= *ri - original_index)
4736 if (t == SD_BUS_TYPE_STRING) {
4738 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4744 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4746 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4752 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4754 r = message_peek_field_signature(m, ri, 0, NULL);
4760 } else if (bus_type_is_basic(t)) {
4763 align = bus_type_get_alignment(t);
4764 k = bus_type_get_size(t);
4765 assert(align > 0 && k > 0);
4767 r = message_peek_fields(m, ri, align, k, NULL);
4773 } else if (t == SD_BUS_TYPE_ARRAY) {
4775 r = signature_element_length(*signature+1, &l);
4785 strncpy(sig, *signature + 1, l-1);
4788 alignment = bus_type_get_alignment(sig[0]);
4792 r = message_peek_field_uint32(m, ri, 0, &nas);
4795 if (nas > BUS_ARRAY_MAX_SIZE)
4798 r = message_peek_fields(m, ri, alignment, 0, NULL);
4802 r = message_skip_fields(m, ri, nas, (const char**) &s);
4807 (*signature) += 1 + l;
4809 } else if (t == SD_BUS_TYPE_VARIANT) {
4812 r = message_peek_field_signature(m, ri, 0, &s);
4816 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4822 } else if (t == SD_BUS_TYPE_STRUCT ||
4823 t == SD_BUS_TYPE_DICT_ENTRY) {
4825 r = signature_element_length(*signature, &l);
4832 strncpy(sig, *signature + 1, l-1);
4835 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4846 int bus_message_parse_fields(sd_bus_message *m) {
4849 uint32_t unix_fds = 0;
4850 void *offsets = NULL;
4851 unsigned n_offsets = 0;
4857 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4860 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4864 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4865 r = message_peek_fields(m, &ri, 1, sz, &q);
4869 framing = read_word_le(q, sz);
4870 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4872 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4876 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4880 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4885 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4886 _cleanup_free_ char *sig = NULL;
4887 const char *signature;
4889 size_t item_size = (size_t) -1;
4891 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4898 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4901 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4905 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4910 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4915 where = ri = ALIGN_TO(ri, 8);
4916 item_size = end - ri;
4917 r = message_peek_fields(m, &where, 1, item_size, &q);
4921 b = memrchr(q, 0, item_size);
4925 sig = strndup(b+1, item_size - (b+1-(char*) q));
4930 item_size = b - (char*) q;
4932 r = message_peek_field_signature(m, &ri, 0, &signature);
4938 case _BUS_MESSAGE_HEADER_INVALID:
4941 case BUS_MESSAGE_HEADER_PATH:
4946 if (!streq(signature, "o"))
4949 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
4952 case BUS_MESSAGE_HEADER_INTERFACE:
4957 if (!streq(signature, "s"))
4960 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
4963 case BUS_MESSAGE_HEADER_MEMBER:
4968 if (!streq(signature, "s"))
4971 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
4974 case BUS_MESSAGE_HEADER_ERROR_NAME:
4979 if (!streq(signature, "s"))
4982 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
4984 m->error._need_free = -1;
4988 case BUS_MESSAGE_HEADER_DESTINATION:
4993 if (!streq(signature, "s"))
4996 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
4999 case BUS_MESSAGE_HEADER_SENDER:
5004 if (!streq(signature, "s"))
5007 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5009 if (r >= 0 && m->sender[0] == ':' && m->bus && m->bus->bus_client && !m->bus->is_kernel) {
5010 m->creds.unique_name = (char*) m->sender;
5011 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5017 case BUS_MESSAGE_HEADER_SIGNATURE: {
5021 if (m->root_container.signature)
5024 if (!streq(signature, "g"))
5027 r = message_peek_field_signature(m, &ri, item_size, &s);
5035 free(m->root_container.signature);
5036 m->root_container.signature = c;
5040 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5041 if (m->reply_serial != 0)
5044 if (!streq(signature, "u"))
5047 r = message_peek_field_uint32(m, &ri, item_size, &m->reply_serial);
5051 if (m->reply_serial == 0)
5056 case BUS_MESSAGE_HEADER_UNIX_FDS:
5060 if (!streq(signature, "u"))
5063 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5073 if (!BUS_MESSAGE_IS_GVARIANT(m))
5074 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5083 if (m->n_fds != unix_fds)
5086 switch (m->header->type) {
5088 case SD_BUS_MESSAGE_SIGNAL:
5089 if (!m->path || !m->interface || !m->member)
5093 case SD_BUS_MESSAGE_METHOD_CALL:
5095 if (!m->path || !m->member)
5100 case SD_BUS_MESSAGE_METHOD_RETURN:
5102 if (m->reply_serial == 0)
5106 case SD_BUS_MESSAGE_METHOD_ERROR:
5108 if (m->reply_serial == 0 || !m->error.name)
5113 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5115 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5116 r = build_struct_offsets(
5118 m->root_container.signature,
5119 BUS_MESSAGE_BODY_SIZE(m),
5120 &m->root_container.item_size,
5121 &m->root_container.offsets,
5122 &m->root_container.n_offsets);
5127 /* Try to read the error message, but if we can't it's a non-issue */
5128 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5129 sd_bus_message_read(m, "s", &m->error.message);
5134 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5135 assert_return(m, -EINVAL);
5136 assert_return(destination, -EINVAL);
5137 assert_return(!m->sealed, -EPERM);
5138 assert_return(!m->destination, -EEXIST);
5140 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5143 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5147 struct bus_body_part *part;
5153 total = BUS_MESSAGE_SIZE(m);
5159 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5160 MESSAGE_FOREACH_PART(part, i, m)
5161 e = mempcpy(e, part->data, part->size);
5163 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5171 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5177 r = sd_bus_message_enter_container(m, 'a', "s");
5184 r = sd_bus_message_read_basic(m, 's', &s);
5190 r = strv_extend(l, s);
5195 r = sd_bus_message_exit_container(m);
5202 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5206 assert_return(m, -EINVAL);
5207 assert_return(m->sealed, -EPERM);
5208 assert_return(l, -EINVAL);
5210 r = bus_message_read_strv_extend(m, &strv);
5220 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5222 const char *t = NULL;
5227 r = sd_bus_message_rewind(m, true);
5231 for (j = 0; j <= i; j++) {
5234 r = sd_bus_message_peek_type(m, &type, NULL);
5238 if (type != SD_BUS_TYPE_STRING &&
5239 type != SD_BUS_TYPE_OBJECT_PATH &&
5240 type != SD_BUS_TYPE_SIGNATURE)
5243 r = sd_bus_message_read_basic(m, type, &t);
5251 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5257 if (size < sizeof(struct bus_header))
5260 full = sizeof(struct bus_header) +
5261 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5263 return size >= full;
5266 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5272 if (h->endian == BUS_NATIVE_ENDIAN) {
5273 fs = h->fields_size;
5275 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5276 fs = bswap_32(h->fields_size);
5277 bs = bswap_32(h->body_size);
5281 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5285 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5286 assert_return(m, -EINVAL);
5288 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5291 return sd_bus_error_get_errno(&m->error);
5294 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5295 struct bus_container *c;
5297 assert_return(m, NULL);
5299 c = complete ? &m->root_container : message_get_container(m);
5300 return strempty(c->signature);
5303 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5304 bool done_something = false;
5307 assert_return(m, -EINVAL);
5308 assert_return(source, -EINVAL);
5309 assert_return(!m->sealed, -EPERM);
5310 assert_return(source->sealed, -EPERM);
5313 const char *contents;
5328 r = sd_bus_message_peek_type(source, &type, &contents);
5334 done_something = true;
5336 if (bus_type_is_container(type) > 0) {
5338 r = sd_bus_message_enter_container(source, type, contents);
5342 r = sd_bus_message_open_container(m, type, contents);
5346 r = sd_bus_message_copy(m, source, true);
5350 r = sd_bus_message_close_container(m);
5354 r = sd_bus_message_exit_container(source);
5361 r = sd_bus_message_read_basic(source, type, &basic);
5367 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5368 type == SD_BUS_TYPE_SIGNATURE ||
5369 type == SD_BUS_TYPE_STRING)
5370 r = sd_bus_message_append_basic(m, type, basic.string);
5372 r = sd_bus_message_append_basic(m, type, &basic);
5379 return done_something;
5382 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5387 assert_return(m, -EINVAL);
5388 assert_return(m->sealed, -EPERM);
5389 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5390 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5391 assert_return(type || contents, -EINVAL);
5392 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5394 r = sd_bus_message_peek_type(m, &t, &c);
5398 if (type != 0 && type != t)
5401 if (contents && !streq_ptr(contents, c))
5407 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5408 assert_return(m, NULL);