2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "alloc-util.h"
27 #include "bus-gvariant.h"
28 #include "bus-internal.h"
29 #include "bus-message.h"
30 #include "bus-signature.h"
35 #include "memfd-util.h"
36 #include "string-util.h"
38 #include "time-util.h"
42 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
44 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
49 if (old_base == new_base)
52 if ((uint8_t*) p < (uint8_t*) old_base)
55 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
58 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
61 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
65 if (part->memfd >= 0) {
66 /* If we can reuse the memfd, try that. For that it
67 * can't be sealed yet. */
70 assert(part->memfd_offset == 0);
71 assert(part->data == part->mmap_begin);
72 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
75 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
77 safe_close(part->memfd);
80 } else if (part->munmap_this)
81 munmap(part->mmap_begin, part->mapped);
82 else if (part->free_this)
89 static void message_reset_parts(sd_bus_message *m) {
90 struct bus_body_part *part;
95 while (m->n_body_parts > 0) {
96 struct bus_body_part *next = part->next;
97 message_free_part(m, part);
104 m->cached_rindex_part = NULL;
105 m->cached_rindex_part_begin = 0;
108 static void message_reset_containers(sd_bus_message *m) {
113 for (i = 0; i < m->n_containers; i++) {
114 free(m->containers[i].signature);
115 free(m->containers[i].offsets);
118 m->containers = mfree(m->containers);
120 m->n_containers = m->containers_allocated = 0;
121 m->root_container.index = 0;
124 static void message_free(sd_bus_message *m) {
130 message_reset_parts(m);
132 if (m->release_kdbus)
133 bus_kernel_cmd_free(m->bus, (uint8_t *) m->kdbus - (uint8_t *) m->bus->kdbus_buffer);
138 sd_bus_unref(m->bus);
141 close_many(m->fds, m->n_fds);
145 if (m->iovec != m->iovec_fixed)
148 m->destination_ptr = mfree(m->destination_ptr);
149 message_reset_containers(m);
150 free(m->root_container.signature);
151 free(m->root_container.offsets);
153 free(m->root_container.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->fields_size;
169 start = ALIGN_TO(old_size, align);
170 new_size = start + sz;
172 if (new_size < start ||
173 new_size > (size_t) ((uint32_t) -1))
176 if (old_size == new_size)
177 return (uint8_t*) m->header + old_size;
179 if (m->free_header) {
180 np = realloc(m->header, ALIGN8(new_size));
184 /* Initially, the header is allocated as part of
185 * the sd_bus_message itself, let's replace it by
188 np = malloc(ALIGN8(new_size));
192 memcpy(np, m->header, sizeof(struct bus_header));
195 /* Zero out padding */
196 if (start > old_size)
197 memzero((uint8_t*) np + old_size, start - old_size);
201 m->fields_size = new_size - sizeof(struct bus_header);
203 /* Adjust quick access pointers */
204 m->path = adjust_pointer(m->path, op, old_size, m->header);
205 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
206 m->member = adjust_pointer(m->member, op, old_size, m->header);
207 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
208 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
209 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
211 m->free_header = true;
214 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
217 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
220 return (uint8_t*) np + start;
227 static int message_append_field_string(
239 /* dbus1 only allows 8bit header field ids */
243 /* dbus1 doesn't allow strings over 32bit, let's enforce this
244 * globally, to not risk convertability */
246 if (l > (size_t) (uint32_t) -1)
249 /* Signature "(yv)" where the variant contains "s" */
251 if (BUS_MESSAGE_IS_GVARIANT(m)) {
253 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
254 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
258 *((uint64_t*) p) = h;
265 *ret = (char*) p + 8;
268 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
269 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
278 ((uint32_t*) p)[1] = l;
279 memcpy(p + 8, s, l + 1);
282 *ret = (char*) p + 8;
288 static int message_append_field_signature(
299 /* dbus1 only allows 8bit header field ids */
303 /* dbus1 doesn't allow signatures over 8bit, let's enforce
304 * this globally, to not risk convertability */
309 /* Signature "(yv)" where the variant contains "g" */
311 if (BUS_MESSAGE_IS_GVARIANT(m))
312 /* For gvariant the serialization is the same as for normal strings */
313 return message_append_field_string(m, h, 'g', s, ret);
315 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
316 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
322 p[2] = SD_BUS_TYPE_SIGNATURE;
325 memcpy(p + 5, s, l + 1);
328 *ret = (const char*) p + 5;
334 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
339 /* dbus1 only allows 8bit header field ids */
343 if (BUS_MESSAGE_IS_GVARIANT(m)) {
344 /* (field id 64bit + ((value + NUL + signature string 'u') */
346 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
350 *((uint64_t*) p) = h;
351 *((uint32_t*) (p + 8)) = x;
355 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
356 p = message_extend_fields(m, 8, 4 + 4, false);
365 ((uint32_t*) p)[1] = x;
371 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
376 /* dbus1 only allows 8bit header field ids */
380 if (BUS_MESSAGE_IS_GVARIANT(m)) {
381 /* (field id 64bit + ((value + NUL + signature string 't') */
383 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
387 *((uint64_t*) p) = h;
388 *((uint64_t*) (p + 8)) = x;
392 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
393 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
406 ((uint64_t*) p)[1] = x;
412 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
415 if (BUS_MESSAGE_IS_GVARIANT(m))
416 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
418 /* 64bit cookies are not supported on dbus1 */
419 if (cookie > 0xffffffffUL)
422 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
426 int bus_message_from_header(
429 size_t header_accessible,
431 size_t footer_accessible,
437 sd_bus_message **ret) {
439 _cleanup_free_ sd_bus_message *m = NULL;
440 struct bus_header *h;
444 assert(header || header_accessible <= 0);
445 assert(footer || footer_accessible <= 0);
446 assert(fds || n_fds <= 0);
449 if (header_accessible < sizeof(struct bus_header))
452 if (header_accessible > message_size)
454 if (footer_accessible > message_size)
458 if (!IN_SET(h->version, 1, 2))
461 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
464 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
467 /* Note that we are happy with unknown flags in the flags header! */
469 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
472 label_sz = strlen(label);
483 m->header_accessible = header_accessible;
485 m->footer_accessible = footer_accessible;
487 if (BUS_MESSAGE_IS_GVARIANT(m)) {
490 if (h->dbus2.cookie == 0)
493 /* dbus2 derives the sizes from the message size and
494 the offset table at the end, since it is formatted as
495 gvariant "yyyyuta{tv}v". Since the message itself is a
496 structure with precisely to variable sized entries,
497 there's only one offset in the table, which marks the
498 end of the fields array. */
500 ws = bus_gvariant_determine_word_size(message_size, 0);
501 if (footer_accessible < ws)
504 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
505 if (ALIGN8(m->fields_size) > message_size - ws)
507 if (m->fields_size < sizeof(struct bus_header))
510 m->fields_size -= sizeof(struct bus_header);
511 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
513 if (h->dbus1.serial == 0)
516 /* dbus1 has the sizes in the header */
517 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
518 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
520 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
528 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
529 memcpy(m->creds.label, label, label_sz + 1);
531 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
534 m->bus = sd_bus_ref(bus);
541 int bus_message_from_malloc(
548 sd_bus_message **ret) {
554 r = bus_message_from_header(
556 buffer, length, /* in this case the initial bytes and the final bytes are the same */
565 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
568 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
570 m->body.sealed = true;
575 m->iovec = m->iovec_fixed;
576 m->iovec[0].iov_base = buffer;
577 m->iovec[0].iov_len = length;
579 r = bus_message_parse_fields(m);
583 /* We take possession of the memory and fds now */
584 m->free_header = true;
595 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
600 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
605 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
606 m->header->endian = BUS_NATIVE_ENDIAN;
607 m->header->type = type;
608 m->header->version = bus->message_version;
609 m->allow_fds = bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
610 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
611 m->bus = sd_bus_ref(bus);
613 if (bus->allow_interactive_authorization)
614 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
619 _public_ int sd_bus_message_new_signal(
623 const char *interface,
624 const char *member) {
629 assert_return(bus, -ENOTCONN);
630 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
631 assert_return(object_path_is_valid(path), -EINVAL);
632 assert_return(interface_name_is_valid(interface), -EINVAL);
633 assert_return(member_name_is_valid(member), -EINVAL);
634 assert_return(m, -EINVAL);
636 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
640 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
642 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
645 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
648 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
656 sd_bus_message_unref(t);
660 _public_ int sd_bus_message_new_method_call(
663 const char *destination,
665 const char *interface,
666 const char *member) {
671 assert_return(bus, -ENOTCONN);
672 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
673 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
674 assert_return(object_path_is_valid(path), -EINVAL);
675 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
676 assert_return(member_name_is_valid(member), -EINVAL);
677 assert_return(m, -EINVAL);
679 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
683 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
686 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
691 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
697 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
710 static int message_new_reply(
711 sd_bus_message *call,
713 sd_bus_message **m) {
718 assert_return(call, -EINVAL);
719 assert_return(call->sealed, -EPERM);
720 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
721 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
722 assert_return(m, -EINVAL);
724 t = message_new(call->bus, type);
728 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
729 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
730 if (t->reply_cookie == 0)
733 r = message_append_reply_cookie(t, t->reply_cookie);
738 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
743 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
744 t->enforced_reply_signature = call->enforced_reply_signature;
754 _public_ int sd_bus_message_new_method_return(
755 sd_bus_message *call,
756 sd_bus_message **m) {
758 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
761 _public_ int sd_bus_message_new_method_error(
762 sd_bus_message *call,
764 const sd_bus_error *e) {
769 assert_return(sd_bus_error_is_set(e), -EINVAL);
770 assert_return(m, -EINVAL);
772 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
776 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
781 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
786 t->error._need_free = -1;
796 _public_ int sd_bus_message_new_method_errorf(
797 sd_bus_message *call,
803 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
806 assert_return(name, -EINVAL);
807 assert_return(m, -EINVAL);
809 va_start(ap, format);
810 bus_error_setfv(&error, name, format, ap);
813 return sd_bus_message_new_method_error(call, m, &error);
816 _public_ int sd_bus_message_new_method_errno(
817 sd_bus_message *call,
820 const sd_bus_error *p) {
822 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
824 if (sd_bus_error_is_set(p))
825 return sd_bus_message_new_method_error(call, m, p);
827 sd_bus_error_set_errno(&berror, error);
829 return sd_bus_message_new_method_error(call, m, &berror);
832 _public_ int sd_bus_message_new_method_errnof(
833 sd_bus_message *call,
839 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
842 va_start(ap, format);
843 sd_bus_error_set_errnofv(&berror, error, format, ap);
846 return sd_bus_message_new_method_error(call, m, &berror);
849 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
853 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
854 m->creds.well_known_names_local = true;
855 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
858 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
862 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
863 m->creds.well_known_names_driver = true;
864 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
867 int bus_message_new_synthetic_error(
870 const sd_bus_error *e,
871 sd_bus_message **m) {
877 assert(sd_bus_error_is_set(e));
880 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
884 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
885 t->reply_cookie = cookie;
887 r = message_append_reply_cookie(t, t->reply_cookie);
891 if (bus && bus->unique_name) {
892 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
897 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
902 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
907 t->error._need_free = -1;
909 bus_message_set_sender_driver(bus, t);
919 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
924 assert(m->n_ref > 0);
930 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
935 assert(m->n_ref > 0);
945 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
946 assert_return(m, -EINVAL);
947 assert_return(type, -EINVAL);
949 *type = m->header->type;
953 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
956 assert_return(m, -EINVAL);
957 assert_return(cookie, -EINVAL);
959 c = BUS_MESSAGE_COOKIE(m);
963 *cookie = BUS_MESSAGE_COOKIE(m);
967 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
968 assert_return(m, -EINVAL);
969 assert_return(cookie, -EINVAL);
971 if (m->reply_cookie == 0)
974 *cookie = m->reply_cookie;
978 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
979 assert_return(m, -EINVAL);
981 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
982 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
985 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
986 assert_return(m, -EINVAL);
988 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
991 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
992 assert_return(m, -EINVAL);
994 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
995 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
998 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
999 assert_return(m, NULL);
1004 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1005 assert_return(m, NULL);
1007 return m->interface;
1010 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1011 assert_return(m, NULL);
1016 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1017 assert_return(m, NULL);
1019 return m->destination;
1022 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1023 assert_return(m, NULL);
1028 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1029 assert_return(m, NULL);
1031 if (!sd_bus_error_is_set(&m->error))
1037 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1038 assert_return(m, -EINVAL);
1039 assert_return(usec, -EINVAL);
1041 if (m->monotonic <= 0)
1044 *usec = m->monotonic;
1048 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1049 assert_return(m, -EINVAL);
1050 assert_return(usec, -EINVAL);
1052 if (m->realtime <= 0)
1055 *usec = m->realtime;
1059 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1060 assert_return(m, -EINVAL);
1061 assert_return(seqnum, -EINVAL);
1066 *seqnum = m->seqnum;
1070 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1071 assert_return(m, NULL);
1073 if (m->creds.mask == 0)
1079 _public_ int sd_bus_message_is_signal(
1081 const char *interface,
1082 const char *member) {
1084 assert_return(m, -EINVAL);
1086 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1089 if (interface && (!m->interface || !streq(m->interface, interface)))
1092 if (member && (!m->member || !streq(m->member, member)))
1098 _public_ int sd_bus_message_is_method_call(
1100 const char *interface,
1101 const char *member) {
1103 assert_return(m, -EINVAL);
1105 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1108 if (interface && (!m->interface || !streq(m->interface, interface)))
1111 if (member && (!m->member || !streq(m->member, member)))
1117 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1118 assert_return(m, -EINVAL);
1120 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1123 if (name && (!m->error.name || !streq(m->error.name, name)))
1129 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1130 assert_return(m, -EINVAL);
1131 assert_return(!m->sealed, -EPERM);
1132 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1134 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
1139 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1140 assert_return(m, -EINVAL);
1141 assert_return(!m->sealed, -EPERM);
1143 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
1148 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1149 assert_return(m, -EINVAL);
1150 assert_return(!m->sealed, -EPERM);
1152 SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
1157 static struct bus_container *message_get_container(sd_bus_message *m) {
1160 if (m->n_containers == 0)
1161 return &m->root_container;
1163 assert(m->containers);
1164 return m->containers + m->n_containers - 1;
1167 struct bus_body_part *message_append_part(sd_bus_message *m) {
1168 struct bus_body_part *part;
1175 if (m->n_body_parts <= 0) {
1179 assert(m->body_end);
1181 part = new0(struct bus_body_part, 1);
1187 m->body_end->next = part;
1197 static void part_zero(struct bus_body_part *part, size_t sz) {
1202 /* All other fields can be left in their defaults */
1203 assert(!part->data);
1204 assert(part->memfd < 0);
1207 part->is_zero = true;
1208 part->sealed = true;
1211 static int part_make_space(
1212 struct sd_bus_message *m,
1213 struct bus_body_part *part,
1222 assert(!part->sealed);
1227 if (!part->data && part->memfd < 0) {
1228 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1229 part->mmap_begin = part->data;
1232 if (part->memfd >= 0) {
1234 if (part->allocated == 0 || sz > part->allocated) {
1235 uint64_t new_allocated;
1237 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1238 r = memfd_set_size(part->memfd, new_allocated);
1244 part->allocated = new_allocated;
1247 if (!part->data || sz > part->mapped) {
1250 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1251 if (part->mapped <= 0)
1252 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1254 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1256 if (n == MAP_FAILED) {
1261 part->mmap_begin = part->data = n;
1263 part->memfd_offset = 0;
1266 part->munmap_this = true;
1268 if (part->allocated == 0 || sz > part->allocated) {
1269 size_t new_allocated;
1271 new_allocated = sz > 0 ? 2 * sz : 64;
1272 n = realloc(part->data, new_allocated);
1279 part->allocated = new_allocated;
1280 part->free_this = true;
1285 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1291 static int message_add_offset(sd_bus_message *m, size_t offset) {
1292 struct bus_container *c;
1295 assert(BUS_MESSAGE_IS_GVARIANT(m));
1297 /* Add offset to current container, unless this is the first
1298 * item in it, which will have the 0 offset, which we can
1300 c = message_get_container(m);
1302 if (!c->need_offsets)
1305 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1308 c->offsets[c->n_offsets++] = offset;
1312 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1313 struct bus_container *c;
1320 /* Update counters */
1321 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1324 *c->array_size += expand;
1328 static void *message_extend_body(
1333 bool force_inline) {
1335 size_t start_body, end_body, padding, added;
1346 start_body = ALIGN_TO((size_t) m->body_size, align);
1347 end_body = start_body + sz;
1349 padding = start_body - m->body_size;
1350 added = padding + sz;
1352 /* Check for 32bit overflows */
1353 if (end_body > (size_t) ((uint32_t) -1) ||
1354 end_body < start_body) {
1360 struct bus_body_part *part = NULL;
1364 m->n_body_parts <= 0 ||
1365 m->body_end->sealed ||
1366 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1367 (force_inline && m->body_end->size > MEMFD_MIN_SIZE); /* if this must be an inlined extension, let's create a new part if the previous part is large enough to be inlined */
1371 part = message_append_part(m);
1375 part_zero(part, padding);
1378 part = message_append_part(m);
1382 r = part_make_space(m, part, sz, &p);
1386 struct bus_container *c;
1388 size_t os, start_part, end_part;
1394 start_part = ALIGN_TO(part->size, align);
1395 end_part = start_part + sz;
1397 r = part_make_space(m, part, end_part, &p);
1402 memzero(p, padding);
1403 p = (uint8_t*) p + padding;
1406 /* Readjust pointers */
1407 for (c = m->containers; c < m->containers + m->n_containers; c++)
1408 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1410 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1413 /* Return something that is not NULL and is aligned */
1414 p = (uint8_t *) NULL + align;
1416 m->body_size = end_body;
1417 message_extend_containers(m, added);
1420 r = message_add_offset(m, end_body);
1430 static int message_push_fd(sd_bus_message *m, int fd) {
1441 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1445 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1453 m->fds[m->n_fds] = copy;
1459 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1460 _cleanup_close_ int fd = -1;
1461 struct bus_container *c;
1465 assert_return(m, -EINVAL);
1466 assert_return(!m->sealed, -EPERM);
1467 assert_return(bus_type_is_basic(type), -EINVAL);
1468 assert_return(!m->poisoned, -ESTALE);
1470 c = message_get_container(m);
1472 if (c->signature && c->signature[c->index]) {
1473 /* Container signature is already set */
1475 if (c->signature[c->index] != type)
1480 /* Maybe we can append to the signature? But only if this is the top-level container */
1481 if (c->enclosing != 0)
1484 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1491 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1497 case SD_BUS_TYPE_SIGNATURE:
1498 case SD_BUS_TYPE_STRING:
1501 /* Fall through... */
1502 case SD_BUS_TYPE_OBJECT_PATH:
1510 case SD_BUS_TYPE_BOOLEAN:
1512 u8 = p && *(int*) p;
1518 case SD_BUS_TYPE_UNIX_FD:
1523 fd = message_push_fd(m, *(int*) p);
1534 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1535 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1542 a = message_extend_body(m, align, sz, true, false);
1549 *stored = (const uint8_t*) a;
1556 case SD_BUS_TYPE_STRING:
1557 /* To make things easy we'll serialize a NULL string
1558 * into the empty string */
1561 /* Fall through... */
1562 case SD_BUS_TYPE_OBJECT_PATH:
1568 sz = 4 + strlen(p) + 1;
1571 case SD_BUS_TYPE_SIGNATURE:
1576 sz = 1 + strlen(p) + 1;
1579 case SD_BUS_TYPE_BOOLEAN:
1581 u32 = p && *(int*) p;
1587 case SD_BUS_TYPE_UNIX_FD:
1592 fd = message_push_fd(m, *(int*) p);
1603 align = bus_type_get_alignment(type);
1604 sz = bus_type_get_size(type);
1611 a = message_extend_body(m, align, sz, false, false);
1615 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1616 *(uint32_t*) a = sz - 5;
1617 memcpy((uint8_t*) a + 4, p, sz - 4);
1620 *stored = (const uint8_t*) a + 4;
1622 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1623 *(uint8_t*) a = sz - 2;
1624 memcpy((uint8_t*) a + 1, p, sz - 1);
1627 *stored = (const uint8_t*) a + 1;
1636 if (type == SD_BUS_TYPE_UNIX_FD)
1639 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1646 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1647 return message_append_basic(m, type, p, NULL);
1650 _public_ int sd_bus_message_append_string_space(
1655 struct bus_container *c;
1658 assert_return(m, -EINVAL);
1659 assert_return(s, -EINVAL);
1660 assert_return(!m->sealed, -EPERM);
1661 assert_return(!m->poisoned, -ESTALE);
1663 c = message_get_container(m);
1665 if (c->signature && c->signature[c->index]) {
1666 /* Container signature is already set */
1668 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1673 /* Maybe we can append to the signature? But only if this is the top-level container */
1674 if (c->enclosing != 0)
1677 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1684 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1685 a = message_extend_body(m, 1, size + 1, true, false);
1691 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1695 *(uint32_t*) a = size;
1701 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1707 _public_ int sd_bus_message_append_string_iovec(
1709 const struct iovec *iov,
1717 assert_return(m, -EINVAL);
1718 assert_return(!m->sealed, -EPERM);
1719 assert_return(iov || n == 0, -EINVAL);
1720 assert_return(!m->poisoned, -ESTALE);
1722 size = IOVEC_TOTAL_SIZE(iov, n);
1724 r = sd_bus_message_append_string_space(m, size, &p);
1728 for (i = 0; i < n; i++) {
1730 if (iov[i].iov_base)
1731 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1733 memset(p, ' ', iov[i].iov_len);
1735 p += iov[i].iov_len;
1741 static int bus_message_open_array(
1743 struct bus_container *c,
1744 const char *contents,
1745 uint32_t **array_size,
1747 bool *need_offsets) {
1757 assert(need_offsets);
1759 if (!signature_is_single(contents, true))
1762 if (c->signature && c->signature[c->index]) {
1764 /* Verify the existing signature */
1766 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1769 if (!startswith(c->signature + c->index + 1, contents))
1772 nindex = c->index + 1 + strlen(contents);
1776 if (c->enclosing != 0)
1779 /* Extend the existing signature */
1781 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1787 nindex = e - c->signature;
1790 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1791 alignment = bus_gvariant_get_alignment(contents);
1795 /* Add alignment padding and add to offset list */
1796 if (!message_extend_body(m, alignment, 0, false, false))
1799 r = bus_gvariant_is_fixed_size(contents);
1803 *begin = m->body_size;
1804 *need_offsets = r == 0;
1808 struct bus_body_part *o;
1810 alignment = bus_type_get_alignment(contents[0]);
1814 a = message_extend_body(m, 4, 4, false, false);
1819 op = m->body_end->data;
1820 os = m->body_end->size;
1822 /* Add alignment between size and first element */
1823 if (!message_extend_body(m, alignment, 0, false, false))
1826 /* location of array size might have changed so let's readjust a */
1827 if (o == m->body_end)
1828 a = adjust_pointer(a, op, os, m->body_end->data);
1834 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1840 static int bus_message_open_variant(
1842 struct bus_container *c,
1843 const char *contents) {
1849 if (!signature_is_single(contents, false))
1852 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1855 if (c->signature && c->signature[c->index]) {
1857 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1863 if (c->enclosing != 0)
1866 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1873 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1874 /* Variants are always aligned to 8 */
1876 if (!message_extend_body(m, 8, 0, false, false))
1883 l = strlen(contents);
1884 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1889 memcpy((uint8_t*) a + 1, contents, l + 1);
1892 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1898 static int bus_message_open_struct(
1900 struct bus_container *c,
1901 const char *contents,
1903 bool *need_offsets) {
1912 assert(need_offsets);
1914 if (!signature_is_valid(contents, false))
1917 if (c->signature && c->signature[c->index]) {
1920 l = strlen(contents);
1922 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1923 !startswith(c->signature + c->index + 1, contents) ||
1924 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1927 nindex = c->index + 1 + l + 1;
1931 if (c->enclosing != 0)
1934 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1940 nindex = e - c->signature;
1943 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1946 alignment = bus_gvariant_get_alignment(contents);
1950 if (!message_extend_body(m, alignment, 0, false, false))
1953 r = bus_gvariant_is_fixed_size(contents);
1957 *begin = m->body_size;
1958 *need_offsets = r == 0;
1960 /* Align contents to 8 byte boundary */
1961 if (!message_extend_body(m, 8, 0, false, false))
1965 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1971 static int bus_message_open_dict_entry(
1973 struct bus_container *c,
1974 const char *contents,
1976 bool *need_offsets) {
1984 assert(need_offsets);
1986 if (!signature_is_pair(contents))
1989 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1992 if (c->signature && c->signature[c->index]) {
1995 l = strlen(contents);
1997 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1998 !startswith(c->signature + c->index + 1, contents) ||
1999 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2004 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2007 alignment = bus_gvariant_get_alignment(contents);
2011 if (!message_extend_body(m, alignment, 0, false, false))
2014 r = bus_gvariant_is_fixed_size(contents);
2018 *begin = m->body_size;
2019 *need_offsets = r == 0;
2021 /* Align contents to 8 byte boundary */
2022 if (!message_extend_body(m, 8, 0, false, false))
2029 _public_ int sd_bus_message_open_container(
2032 const char *contents) {
2034 struct bus_container *c, *w;
2035 uint32_t *array_size = NULL;
2037 size_t before, begin = 0;
2038 bool need_offsets = false;
2041 assert_return(m, -EINVAL);
2042 assert_return(!m->sealed, -EPERM);
2043 assert_return(contents, -EINVAL);
2044 assert_return(!m->poisoned, -ESTALE);
2046 /* Make sure we have space for one more container */
2047 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2052 c = message_get_container(m);
2054 signature = strdup(contents);
2060 /* Save old index in the parent container, in case we have to
2061 * abort this container */
2062 c->saved_index = c->index;
2063 before = m->body_size;
2065 if (type == SD_BUS_TYPE_ARRAY)
2066 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2067 else if (type == SD_BUS_TYPE_VARIANT)
2068 r = bus_message_open_variant(m, c, contents);
2069 else if (type == SD_BUS_TYPE_STRUCT)
2070 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2071 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2072 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2081 /* OK, let's fill it in */
2082 w = m->containers + m->n_containers++;
2083 w->enclosing = type;
2084 w->signature = signature;
2086 w->array_size = array_size;
2089 w->n_offsets = w->offsets_allocated = 0;
2091 w->need_offsets = need_offsets;
2096 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2101 if (!BUS_MESSAGE_IS_GVARIANT(m))
2104 if (c->need_offsets) {
2105 size_t payload, sz, i;
2108 /* Variable-width arrays */
2110 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2111 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2113 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2117 for (i = 0; i < c->n_offsets; i++)
2118 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2122 /* Fixed-width or empty arrays */
2124 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2132 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2138 assert(c->signature);
2140 if (!BUS_MESSAGE_IS_GVARIANT(m))
2143 l = strlen(c->signature);
2145 a = message_extend_body(m, 1, 1 + l, true, false);
2150 memcpy(a+1, c->signature, l);
2155 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2156 bool fixed_size = true;
2157 size_t n_variable = 0;
2166 if (!BUS_MESSAGE_IS_GVARIANT(m))
2169 p = strempty(c->signature);
2173 r = signature_element_length(p, &n);
2182 r = bus_gvariant_is_fixed_size(t);
2187 assert(!c->need_offsets || i <= c->n_offsets);
2189 /* We need to add an offset for each item that has a
2190 * variable size and that is not the last one in the
2194 if (r == 0 && p[n] != 0)
2201 assert(!c->need_offsets || i == c->n_offsets);
2202 assert(c->need_offsets || n_variable == 0);
2204 if (isempty(c->signature)) {
2205 /* The unary type is encoded as fixed 1 byte padding */
2206 a = message_extend_body(m, 1, 1, add_offset, false);
2211 } else if (n_variable <= 0) {
2214 /* Structures with fixed-size members only have to be
2215 * fixed-size themselves. But gvariant requires all fixed-size
2216 * elements to be sized a multiple of their alignment. Hence,
2217 * we must *always* add final padding after the last member so
2218 * the overall size of the structure is properly aligned. */
2220 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2222 assert(alignment > 0);
2224 a = message_extend_body(m, alignment, 0, add_offset, false);
2231 assert(c->offsets[c->n_offsets-1] == m->body_size);
2233 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2235 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2239 p = strempty(c->signature);
2240 for (i = 0, j = 0; i < c->n_offsets; i++) {
2244 r = signature_element_length(p, &n);
2255 r = bus_gvariant_is_fixed_size(t);
2258 if (r > 0 || p[0] == 0)
2262 k = n_variable - 1 - j;
2264 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2273 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2274 struct bus_container *c;
2277 assert_return(m, -EINVAL);
2278 assert_return(!m->sealed, -EPERM);
2279 assert_return(m->n_containers > 0, -EINVAL);
2280 assert_return(!m->poisoned, -ESTALE);
2282 c = message_get_container(m);
2284 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2285 if (c->signature && c->signature[c->index] != 0)
2290 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2291 r = bus_message_close_array(m, c);
2292 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2293 r = bus_message_close_variant(m, c);
2294 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2295 r = bus_message_close_struct(m, c, true);
2297 assert_not_reached("Unknown container type");
2311 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2318 stack[*i].types = types;
2319 stack[*i].n_struct = n_struct;
2320 stack[*i].n_array = n_array;
2326 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2337 *types = stack[*i].types;
2338 *n_struct = stack[*i].n_struct;
2339 *n_array = stack[*i].n_array;
2344 _public_ int sd_bus_message_appendv(
2349 unsigned n_array, n_struct;
2350 TypeStack stack[BUS_CONTAINER_DEPTH];
2351 unsigned stack_ptr = 0;
2354 assert_return(m, -EINVAL);
2355 assert_return(types, -EINVAL);
2356 assert_return(!m->sealed, -EPERM);
2357 assert_return(!m->poisoned, -ESTALE);
2359 n_array = (unsigned) -1;
2360 n_struct = strlen(types);
2365 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2366 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2372 r = sd_bus_message_close_container(m);
2380 if (n_array != (unsigned) -1)
2389 case SD_BUS_TYPE_BYTE: {
2392 x = (uint8_t) va_arg(ap, int);
2393 r = sd_bus_message_append_basic(m, *t, &x);
2397 case SD_BUS_TYPE_BOOLEAN:
2398 case SD_BUS_TYPE_INT32:
2399 case SD_BUS_TYPE_UINT32:
2400 case SD_BUS_TYPE_UNIX_FD: {
2403 /* We assume a boolean is the same as int32_t */
2404 assert_cc(sizeof(int32_t) == sizeof(int));
2406 x = va_arg(ap, uint32_t);
2407 r = sd_bus_message_append_basic(m, *t, &x);
2411 case SD_BUS_TYPE_INT16:
2412 case SD_BUS_TYPE_UINT16: {
2415 x = (uint16_t) va_arg(ap, int);
2416 r = sd_bus_message_append_basic(m, *t, &x);
2420 case SD_BUS_TYPE_INT64:
2421 case SD_BUS_TYPE_UINT64: {
2424 x = va_arg(ap, uint64_t);
2425 r = sd_bus_message_append_basic(m, *t, &x);
2429 case SD_BUS_TYPE_DOUBLE: {
2432 x = va_arg(ap, double);
2433 r = sd_bus_message_append_basic(m, *t, &x);
2437 case SD_BUS_TYPE_STRING:
2438 case SD_BUS_TYPE_OBJECT_PATH:
2439 case SD_BUS_TYPE_SIGNATURE: {
2442 x = va_arg(ap, const char*);
2443 r = sd_bus_message_append_basic(m, *t, x);
2447 case SD_BUS_TYPE_ARRAY: {
2450 r = signature_element_length(t + 1, &k);
2456 memcpy(s, t + 1, k);
2459 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2464 if (n_array == (unsigned) -1) {
2469 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2475 n_array = va_arg(ap, unsigned);
2480 case SD_BUS_TYPE_VARIANT: {
2483 s = va_arg(ap, const char*);
2487 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2491 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2496 n_struct = strlen(s);
2497 n_array = (unsigned) -1;
2502 case SD_BUS_TYPE_STRUCT_BEGIN:
2503 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2506 r = signature_element_length(t, &k);
2513 memcpy(s, t + 1, k - 2);
2516 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2521 if (n_array == (unsigned) -1) {
2526 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2532 n_array = (unsigned) -1;
2548 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2552 assert_return(m, -EINVAL);
2553 assert_return(types, -EINVAL);
2554 assert_return(!m->sealed, -EPERM);
2555 assert_return(!m->poisoned, -ESTALE);
2557 va_start(ap, types);
2558 r = sd_bus_message_appendv(m, types, ap);
2564 _public_ int sd_bus_message_append_array_space(
2574 assert_return(m, -EINVAL);
2575 assert_return(!m->sealed, -EPERM);
2576 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2577 assert_return(ptr || size == 0, -EINVAL);
2578 assert_return(!m->poisoned, -ESTALE);
2580 /* alignment and size of the trivial types (except bool) is
2581 * identical for gvariant and dbus1 marshalling */
2582 align = bus_type_get_alignment(type);
2583 sz = bus_type_get_size(type);
2585 assert_se(align > 0);
2591 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2595 a = message_extend_body(m, align, size, false, false);
2599 r = sd_bus_message_close_container(m);
2607 _public_ int sd_bus_message_append_array(
2615 assert_return(m, -EINVAL);
2616 assert_return(!m->sealed, -EPERM);
2617 assert_return(bus_type_is_trivial(type), -EINVAL);
2618 assert_return(ptr || size == 0, -EINVAL);
2619 assert_return(!m->poisoned, -ESTALE);
2621 r = sd_bus_message_append_array_space(m, type, size, &p);
2625 memcpy_safe(p, ptr, size);
2630 _public_ int sd_bus_message_append_array_iovec(
2633 const struct iovec *iov,
2641 assert_return(m, -EINVAL);
2642 assert_return(!m->sealed, -EPERM);
2643 assert_return(bus_type_is_trivial(type), -EINVAL);
2644 assert_return(iov || n == 0, -EINVAL);
2645 assert_return(!m->poisoned, -ESTALE);
2647 size = IOVEC_TOTAL_SIZE(iov, n);
2649 r = sd_bus_message_append_array_space(m, type, size, &p);
2653 for (i = 0; i < n; i++) {
2655 if (iov[i].iov_base)
2656 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2658 memzero(p, iov[i].iov_len);
2660 p = (uint8_t*) p + iov[i].iov_len;
2666 _public_ int sd_bus_message_append_array_memfd(
2673 _cleanup_close_ int copy_fd = -1;
2674 struct bus_body_part *part;
2680 assert_return(m, -EINVAL);
2681 assert_return(memfd >= 0, -EBADF);
2682 assert_return(bus_type_is_trivial(type), -EINVAL);
2683 assert_return(size > 0, -EINVAL);
2684 assert_return(!m->sealed, -EPERM);
2685 assert_return(!m->poisoned, -ESTALE);
2687 r = memfd_set_sealed(memfd);
2691 copy_fd = dup(memfd);
2695 r = memfd_get_size(memfd, &real_size);
2699 if (offset == 0 && size == (uint64_t) -1)
2701 else if (offset + size > real_size)
2704 align = bus_type_get_alignment(type);
2705 sz = bus_type_get_size(type);
2707 assert_se(align > 0);
2710 if (offset % align != 0)
2716 if (size > (uint64_t) (uint32_t) -1)
2719 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2723 a = message_extend_body(m, align, 0, false, false);
2727 part = message_append_part(m);
2731 part->memfd = copy_fd;
2732 part->memfd_offset = offset;
2733 part->sealed = true;
2737 m->body_size += size;
2738 message_extend_containers(m, size);
2740 return sd_bus_message_close_container(m);
2743 _public_ int sd_bus_message_append_string_memfd(
2749 _cleanup_close_ int copy_fd = -1;
2750 struct bus_body_part *part;
2751 struct bus_container *c;
2756 assert_return(m, -EINVAL);
2757 assert_return(memfd >= 0, -EBADF);
2758 assert_return(size > 0, -EINVAL);
2759 assert_return(!m->sealed, -EPERM);
2760 assert_return(!m->poisoned, -ESTALE);
2762 r = memfd_set_sealed(memfd);
2766 copy_fd = dup(memfd);
2770 r = memfd_get_size(memfd, &real_size);
2774 if (offset == 0 && size == (uint64_t) -1)
2776 else if (offset + size > real_size)
2779 /* We require this to be NUL terminated */
2783 if (size > (uint64_t) (uint32_t) -1)
2786 c = message_get_container(m);
2787 if (c->signature && c->signature[c->index]) {
2788 /* Container signature is already set */
2790 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2795 /* Maybe we can append to the signature? But only if this is the top-level container */
2796 if (c->enclosing != 0)
2799 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2806 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2807 a = message_extend_body(m, 4, 4, false, false);
2811 *(uint32_t*) a = size - 1;
2814 part = message_append_part(m);
2818 part->memfd = copy_fd;
2819 part->memfd_offset = offset;
2820 part->sealed = true;
2824 m->body_size += size;
2825 message_extend_containers(m, size);
2827 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2828 r = message_add_offset(m, m->body_size);
2835 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2841 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2845 assert_return(m, -EINVAL);
2846 assert_return(!m->sealed, -EPERM);
2847 assert_return(!m->poisoned, -ESTALE);
2849 r = sd_bus_message_open_container(m, 'a', "s");
2853 STRV_FOREACH(i, l) {
2854 r = sd_bus_message_append_basic(m, 's', *i);
2859 return sd_bus_message_close_container(m);
2862 static int bus_message_close_header(sd_bus_message *m) {
2866 /* The actual user data is finished now, we just complete the
2867 variant and struct now (at least on gvariant). Remember
2868 this position, so that during parsing we know where to
2869 put the outer container end. */
2870 m->user_body_size = m->body_size;
2872 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2873 const char *signature;
2877 /* Add offset table to end of fields array */
2878 if (m->n_header_offsets >= 1) {
2882 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2884 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2885 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2889 for (i = 0; i < m->n_header_offsets; i++)
2890 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2893 /* Add gvariant NUL byte plus signature to the end of
2894 * the body, followed by the final offset pointing to
2895 * the end of the fields array */
2897 signature = strempty(m->root_container.signature);
2898 l = strlen(signature);
2900 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2901 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2906 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2907 memcpy((uint8_t*) d + 2, signature, l);
2908 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2910 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2913 m->footer_accessible = 1 + l + 2 + sz;
2915 m->header->dbus1.fields_size = m->fields_size;
2916 m->header->dbus1.body_size = m->body_size;
2922 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2923 struct bus_body_part *part;
2933 if (m->n_containers > 0)
2939 if (cookie > 0xffffffffULL &&
2940 !BUS_MESSAGE_IS_GVARIANT(m))
2943 /* In vtables the return signature of method calls is listed,
2944 * let's check if they match if this is a response */
2945 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2946 m->enforced_reply_signature &&
2947 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2950 /* If gvariant marshalling is used we need to close the body structure */
2951 r = bus_message_close_struct(m, &m->root_container, false);
2955 /* If there's a non-trivial signature set, then add it in
2956 * here, but only on dbus1 */
2957 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2958 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2964 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2969 r = bus_message_close_header(m);
2973 if (BUS_MESSAGE_IS_GVARIANT(m))
2974 m->header->dbus2.cookie = cookie;
2976 m->header->dbus1.serial = (uint32_t) cookie;
2978 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2980 /* Add padding at the end of the fields part, since we know
2981 * the body needs to start at an 8 byte alignment. We made
2982 * sure we allocated enough space for this, so all we need to
2983 * do here is to zero it out. */
2984 a = ALIGN8(m->fields_size) - m->fields_size;
2986 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2988 /* If this is something we can send as memfd, then let's seal
2989 the memfd now. Note that we can send memfds as payload only
2990 for directed messages, and not for broadcasts. */
2991 if (m->destination && m->bus->use_memfd) {
2992 MESSAGE_FOREACH_PART(part, i, m)
2993 if (part->memfd >= 0 &&
2995 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2996 part != m->body_end) { /* The last part may never be sent as memfd */
2999 /* Try to seal it if that makes
3000 * sense. First, unmap our own map to
3001 * make sure we don't keep it busy. */
3002 bus_body_part_unmap(part);
3004 /* Then, sync up real memfd size */
3006 r = memfd_set_size(part->memfd, sz);
3010 /* Finally, try to seal */
3011 if (memfd_set_sealed(part->memfd) >= 0)
3012 part->sealed = true;
3016 m->root_container.end = m->user_body_size;
3017 m->root_container.index = 0;
3018 m->root_container.offset_index = 0;
3019 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3026 int bus_body_part_map(struct bus_body_part *part) {
3035 if (part->size <= 0)
3038 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3039 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3040 static const uint8_t zeroes[7] = { };
3041 part->data = (void*) zeroes;
3045 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3046 psz = PAGE_ALIGN(part->size + shift);
3048 if (part->memfd >= 0)
3049 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3050 else if (part->is_zero)
3051 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3055 if (p == MAP_FAILED)
3059 part->mmap_begin = p;
3060 part->data = (uint8_t*) p + shift;
3061 part->munmap_this = true;
3066 void bus_body_part_unmap(struct bus_body_part *part) {
3070 if (part->memfd < 0)
3073 if (!part->mmap_begin)
3076 if (!part->munmap_this)
3079 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3081 part->mmap_begin = NULL;
3084 part->munmap_this = false;
3089 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3090 size_t k, start, end;
3095 start = ALIGN_TO((size_t) *rindex, align);
3096 end = start + nbytes;
3101 /* Verify that padding is 0 */
3102 for (k = *rindex; k < start; k++)
3103 if (((const uint8_t*) p)[k] != 0)
3107 *r = (uint8_t*) p + start;
3114 static bool message_end_of_signature(sd_bus_message *m) {
3115 struct bus_container *c;
3119 c = message_get_container(m);
3120 return !c->signature || c->signature[c->index] == 0;
3123 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3124 struct bus_container *c;
3128 c = message_get_container(m);
3129 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3132 if (BUS_MESSAGE_IS_GVARIANT(m))
3133 return index >= c->end;
3135 assert(c->array_size);
3136 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3140 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3141 assert_return(m, -EINVAL);
3142 assert_return(m->sealed, -EPERM);
3144 if (complete && m->n_containers > 0)
3147 if (message_end_of_signature(m))
3150 if (message_end_of_array(m, m->rindex))
3156 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3157 struct bus_body_part *part;
3163 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3164 part = m->cached_rindex_part;
3165 begin = m->cached_rindex_part_begin;
3175 if (index + sz <= begin + part->size) {
3177 r = bus_body_part_map(part);
3182 *p = (uint8_t*) part->data + index - begin;
3184 m->cached_rindex_part = part;
3185 m->cached_rindex_part_begin = begin;
3190 begin += part->size;
3197 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3204 if (!BUS_MESSAGE_IS_GVARIANT(m))
3207 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3210 sz = bus_gvariant_get_size(c->signature);
3214 if (c->offset_index+1 >= c->n_offsets)
3217 /* Variable-size array */
3219 alignment = bus_gvariant_get_alignment(c->signature);
3220 assert(alignment > 0);
3222 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3223 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3226 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3229 /* Fixed-size array */
3230 *rindex = c->begin + (c->offset_index+1) * sz;
3236 } else if (c->enclosing == 0 ||
3237 c->enclosing == SD_BUS_TYPE_STRUCT ||
3238 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3243 if (c->offset_index+1 >= c->n_offsets)
3246 r = signature_element_length(c->signature + c->index, &n);
3250 r = signature_element_length(c->signature + c->index + n, &j);
3255 memcpy(t, c->signature + c->index + n, j);
3258 alignment = bus_gvariant_get_alignment(t);
3261 assert(alignment > 0);
3263 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3264 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3268 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3271 assert_not_reached("Unknown container type");
3276 /* Reached the end */
3283 static int message_peek_body(
3290 size_t k, start, end, padding;
3291 struct bus_body_part *part;
3298 start = ALIGN_TO((size_t) *rindex, align);
3299 padding = start - *rindex;
3300 end = start + nbytes;
3302 if (end > m->user_body_size)
3305 part = find_part(m, *rindex, padding, (void**) &q);
3310 /* Verify padding */
3311 for (k = 0; k < padding; k++)
3316 part = find_part(m, start, nbytes, (void**) &q);
3317 if (!part || (nbytes > 0 && !q))
3328 static bool validate_nul(const char *s, size_t l) {
3330 /* Check for NUL chars in the string */
3331 if (memchr(s, 0, l))
3334 /* Check for NUL termination */
3341 static bool validate_string(const char *s, size_t l) {
3343 if (!validate_nul(s, l))
3346 /* Check if valid UTF8 */
3347 if (!utf8_is_valid(s))
3353 static bool validate_signature(const char *s, size_t l) {
3355 if (!validate_nul(s, l))
3358 /* Check if valid signature */
3359 if (!signature_is_valid(s, true))
3365 static bool validate_object_path(const char *s, size_t l) {
3367 if (!validate_nul(s, l))
3370 if (!object_path_is_valid(s))
3376 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3377 struct bus_container *c;
3382 assert_return(m, -EINVAL);
3383 assert_return(m->sealed, -EPERM);
3384 assert_return(bus_type_is_basic(type), -EINVAL);
3386 if (message_end_of_signature(m))
3389 if (message_end_of_array(m, m->rindex))
3392 c = message_get_container(m);
3393 if (c->signature[c->index] != type)
3398 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3400 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3403 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3407 if (type == SD_BUS_TYPE_STRING)
3408 ok = validate_string(q, c->item_size-1);
3409 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3410 ok = validate_object_path(q, c->item_size-1);
3412 ok = validate_signature(q, c->item_size-1);
3418 *(const char**) p = q;
3422 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3424 if ((size_t) sz != c->item_size)
3427 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3430 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3436 case SD_BUS_TYPE_BYTE:
3438 *(uint8_t*) p = *(uint8_t*) q;
3441 case SD_BUS_TYPE_BOOLEAN:
3443 *(int*) p = !!*(uint8_t*) q;
3446 case SD_BUS_TYPE_INT16:
3447 case SD_BUS_TYPE_UINT16:
3449 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3452 case SD_BUS_TYPE_INT32:
3453 case SD_BUS_TYPE_UINT32:
3455 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3458 case SD_BUS_TYPE_INT64:
3459 case SD_BUS_TYPE_UINT64:
3460 case SD_BUS_TYPE_DOUBLE:
3462 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3465 case SD_BUS_TYPE_UNIX_FD: {
3468 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3473 *(int*) p = m->fds[j];
3479 assert_not_reached("unexpected type");
3483 r = container_next_item(m, c, &rindex);
3488 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3492 r = message_peek_body(m, &rindex, 4, 4, &q);
3496 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3497 r = message_peek_body(m, &rindex, 1, l+1, &q);
3501 if (type == SD_BUS_TYPE_OBJECT_PATH)
3502 ok = validate_object_path(q, l);
3504 ok = validate_string(q, l);
3509 *(const char**) p = q;
3511 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3514 r = message_peek_body(m, &rindex, 1, 1, &q);
3519 r = message_peek_body(m, &rindex, 1, l+1, &q);
3523 if (!validate_signature(q, l))
3527 *(const char**) p = q;
3532 align = bus_type_get_alignment(type);
3535 sz = bus_type_get_size(type);
3538 r = message_peek_body(m, &rindex, align, sz, &q);
3544 case SD_BUS_TYPE_BYTE:
3546 *(uint8_t*) p = *(uint8_t*) q;
3549 case SD_BUS_TYPE_BOOLEAN:
3551 *(int*) p = !!*(uint32_t*) q;
3554 case SD_BUS_TYPE_INT16:
3555 case SD_BUS_TYPE_UINT16:
3557 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3560 case SD_BUS_TYPE_INT32:
3561 case SD_BUS_TYPE_UINT32:
3563 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3566 case SD_BUS_TYPE_INT64:
3567 case SD_BUS_TYPE_UINT64:
3568 case SD_BUS_TYPE_DOUBLE:
3570 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3573 case SD_BUS_TYPE_UNIX_FD: {
3576 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3581 *(int*) p = m->fds[j];
3586 assert_not_reached("Unknown basic type...");
3593 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3599 static int bus_message_enter_array(
3601 struct bus_container *c,
3602 const char *contents,
3603 uint32_t **array_size,
3606 size_t *n_offsets) {
3620 if (!signature_is_single(contents, true))
3623 if (!c->signature || c->signature[c->index] == 0)
3626 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3629 if (!startswith(c->signature + c->index + 1, contents))
3634 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3637 r = message_peek_body(m, &rindex, 4, 4, &q);
3641 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3644 alignment = bus_type_get_alignment(contents[0]);
3648 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3652 *array_size = (uint32_t*) q;
3654 } else if (c->item_size <= 0) {
3656 /* gvariant: empty array */
3661 } else if (bus_gvariant_is_fixed_size(contents)) {
3663 /* gvariant: fixed length array */
3664 *item_size = bus_gvariant_get_size(contents);
3669 size_t where, p = 0, framing, sz;
3672 /* gvariant: variable length array */
3673 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3675 where = rindex + c->item_size - sz;
3676 r = message_peek_body(m, &where, 1, sz, &q);
3680 framing = bus_gvariant_read_word_le(q, sz);
3681 if (framing > c->item_size - sz)
3683 if ((c->item_size - framing) % sz != 0)
3686 *n_offsets = (c->item_size - framing) / sz;
3688 where = rindex + framing;
3689 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3693 *offsets = new(size_t, *n_offsets);
3697 for (i = 0; i < *n_offsets; i++) {
3700 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3701 if (x > c->item_size - sz)
3706 (*offsets)[i] = rindex + x;
3710 *item_size = (*offsets)[0] - rindex;
3715 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3716 c->index += 1 + strlen(contents);
3721 static int bus_message_enter_variant(
3723 struct bus_container *c,
3724 const char *contents,
3725 size_t *item_size) {
3737 if (!signature_is_single(contents, false))
3740 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3743 if (!c->signature || c->signature[c->index] == 0)
3746 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3751 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3754 k = strlen(contents);
3755 if (1+k > c->item_size)
3758 where = rindex + c->item_size - (1+k);
3759 r = message_peek_body(m, &where, 1, 1+k, &q);
3763 if (*(char*) q != 0)
3766 if (memcmp((uint8_t*) q+1, contents, k))
3769 *item_size = c->item_size - (1+k);
3772 r = message_peek_body(m, &rindex, 1, 1, &q);
3777 r = message_peek_body(m, &rindex, 1, l+1, &q);
3781 if (!validate_signature(q, l))
3784 if (!streq(q, contents))
3790 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3796 static int build_struct_offsets(
3798 const char *signature,
3802 size_t *n_offsets) {
3804 unsigned n_variable = 0, n_total = 0, v;
3805 size_t previous = 0, where;
3816 if (isempty(signature)) {
3817 /* Unary type is encoded as *fixed* 1 byte padding */
3818 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3822 if (*(uint8_t *) q != 0)
3831 sz = bus_gvariant_determine_word_size(size, 0);
3835 /* First, loop over signature and count variable elements and
3836 * elements in general. We use this to know how large the
3837 * offset array is at the end of the structure. Note that
3838 * GVariant only stores offsets for all variable size elements
3839 * that are not the last item. */
3845 r = signature_element_length(p, &n);
3854 r = bus_gvariant_is_fixed_size(t);
3859 if (r == 0 && p[n] != 0) /* except the last item */
3866 if (size < n_variable * sz)
3869 where = m->rindex + size - (n_variable * sz);
3870 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3876 *offsets = new(size_t, n_total);
3882 /* Second, loop again and build an offset table */
3888 r = signature_element_length(p, &n);
3897 k = bus_gvariant_get_size(t);
3905 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3908 if (m->rindex + x < previous)
3911 /* The last item's end
3912 * is determined from
3915 x = size - (n_variable * sz);
3917 offset = m->rindex + x;
3923 align = bus_gvariant_get_alignment(t);
3926 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3930 previous = (*offsets)[(*n_offsets)++] = offset;
3935 assert(*n_offsets == n_total);
3937 *item_size = (*offsets)[0] - m->rindex;
3941 static int enter_struct_or_dict_entry(
3943 struct bus_container *c,
3944 const char *contents,
3947 size_t *n_offsets) {
3958 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3961 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3966 /* gvariant with contents */
3967 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3972 static int bus_message_enter_struct(
3974 struct bus_container *c,
3975 const char *contents,
3978 size_t *n_offsets) {
3990 if (!signature_is_valid(contents, false))
3993 if (!c->signature || c->signature[c->index] == 0)
3996 l = strlen(contents);
3998 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3999 !startswith(c->signature + c->index + 1, contents) ||
4000 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4003 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4007 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4008 c->index += 1 + l + 1;
4013 static int bus_message_enter_dict_entry(
4015 struct bus_container *c,
4016 const char *contents,
4019 size_t *n_offsets) {
4028 if (!signature_is_pair(contents))
4031 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4034 if (!c->signature || c->signature[c->index] == 0)
4037 l = strlen(contents);
4039 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4040 !startswith(c->signature + c->index + 1, contents) ||
4041 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4044 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4048 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4049 c->index += 1 + l + 1;
4054 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4056 const char *contents) {
4057 struct bus_container *c, *w;
4058 uint32_t *array_size = NULL;
4061 size_t *offsets = NULL;
4062 size_t n_offsets = 0, item_size = 0;
4065 assert_return(m, -EINVAL);
4066 assert_return(m->sealed, -EPERM);
4067 assert_return(type != 0 || !contents, -EINVAL);
4069 if (type == 0 || !contents) {
4073 /* Allow entering into anonymous containers */
4074 r = sd_bus_message_peek_type(m, &tt, &cc);
4078 if (type != 0 && type != tt)
4081 if (contents && !streq(contents, cc))
4089 * We enforce a global limit on container depth, that is much
4090 * higher than the 32 structs and 32 arrays the specification
4091 * mandates. This is simpler to implement for us, and we need
4092 * this only to ensure our container array doesn't grow
4093 * without bounds. We are happy to return any data from a
4094 * message as long as the data itself is valid, even if the
4095 * overall message might be not.
4097 * Note that the message signature is validated when
4098 * parsing the headers, and that validation does check the
4101 * Note that the specification defines no limits on the depth
4102 * of stacked variants, but we do.
4104 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4107 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4110 if (message_end_of_signature(m))
4113 if (message_end_of_array(m, m->rindex))
4116 c = message_get_container(m);
4118 signature = strdup(contents);
4122 c->saved_index = c->index;
4125 if (type == SD_BUS_TYPE_ARRAY)
4126 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4127 else if (type == SD_BUS_TYPE_VARIANT)
4128 r = bus_message_enter_variant(m, c, contents, &item_size);
4129 else if (type == SD_BUS_TYPE_STRUCT)
4130 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4131 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4132 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4142 /* OK, let's fill it in */
4143 w = m->containers + m->n_containers++;
4144 w->enclosing = type;
4145 w->signature = signature;
4146 w->peeked_signature = NULL;
4150 w->begin = m->rindex;
4152 /* Unary type has fixed size of 1, but virtual size of 0 */
4153 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4154 type == SD_BUS_TYPE_STRUCT &&
4156 w->end = m->rindex + 0;
4158 w->end = m->rindex + c->item_size;
4160 w->array_size = array_size;
4161 w->item_size = item_size;
4162 w->offsets = offsets;
4163 w->n_offsets = n_offsets;
4164 w->offset_index = 0;
4169 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4170 struct bus_container *c;
4174 assert_return(m, -EINVAL);
4175 assert_return(m->sealed, -EPERM);
4176 assert_return(m->n_containers > 0, -ENXIO);
4178 c = message_get_container(m);
4180 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4181 if (c->signature && c->signature[c->index] != 0)
4185 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4186 if (m->rindex < c->end)
4189 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4192 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4193 if (c->begin + l != m->rindex)
4198 free(c->peeked_signature);
4202 c = message_get_container(m);
4205 c->index = c->saved_index;
4206 r = container_next_item(m, c, &m->rindex);
4214 static void message_quit_container(sd_bus_message *m) {
4215 struct bus_container *c;
4219 assert(m->n_containers > 0);
4221 c = message_get_container(m);
4224 assert(m->rindex >= c->before);
4225 m->rindex = c->before;
4227 /* Free container */
4232 /* Correct index of new top-level container */
4233 c = message_get_container(m);
4234 c->index = c->saved_index;
4237 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4238 struct bus_container *c;
4241 assert_return(m, -EINVAL);
4242 assert_return(m->sealed, -EPERM);
4244 if (message_end_of_signature(m))
4247 if (message_end_of_array(m, m->rindex))
4250 c = message_get_container(m);
4252 if (bus_type_is_basic(c->signature[c->index])) {
4256 *type = c->signature[c->index];
4260 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4266 r = signature_element_length(c->signature+c->index+1, &l);
4272 sig = strndup(c->signature + c->index + 1, l);
4276 free(c->peeked_signature);
4277 *contents = c->peeked_signature = sig;
4281 *type = SD_BUS_TYPE_ARRAY;
4286 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4287 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4293 r = signature_element_length(c->signature+c->index, &l);
4298 sig = strndup(c->signature + c->index + 1, l - 2);
4302 free(c->peeked_signature);
4303 *contents = c->peeked_signature = sig;
4307 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4312 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4316 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4319 if (c->item_size < 2)
4322 /* Look for the NUL delimiter that
4323 separates the payload from the
4324 signature. Since the body might be
4325 in a different part that then the
4326 signature we map byte by byte. */
4328 for (k = 2; k <= c->item_size; k++) {
4331 where = m->rindex + c->item_size - k;
4332 r = message_peek_body(m, &where, 1, k, &q);
4336 if (*(char*) q == 0)
4340 if (k > c->item_size)
4343 free(c->peeked_signature);
4344 c->peeked_signature = strndup((char*) q + 1, k - 1);
4345 if (!c->peeked_signature)
4348 if (!signature_is_valid(c->peeked_signature, true))
4351 *contents = c->peeked_signature;
4356 r = message_peek_body(m, &rindex, 1, 1, &q);
4361 r = message_peek_body(m, &rindex, 1, l+1, &q);
4365 if (!validate_signature(q, l))
4373 *type = SD_BUS_TYPE_VARIANT;
4388 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4389 struct bus_container *c;
4391 assert_return(m, -EINVAL);
4392 assert_return(m->sealed, -EPERM);
4395 message_reset_containers(m);
4398 c = message_get_container(m);
4400 c = message_get_container(m);
4402 c->offset_index = 0;
4404 m->rindex = c->begin;
4407 c->offset_index = 0;
4408 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4410 return !isempty(c->signature);
4413 static int message_read_ap(
4418 unsigned n_array, n_struct;
4419 TypeStack stack[BUS_CONTAINER_DEPTH];
4420 unsigned stack_ptr = 0;
4421 unsigned n_loop = 0;
4429 /* Ideally, we'd just call ourselves recursively on every
4430 * complex type. However, the state of a va_list that is
4431 * passed to a function is undefined after that function
4432 * returns. This means we need to docode the va_list linearly
4433 * in a single stackframe. We hence implement our own
4434 * home-grown stack in an array. */
4436 n_array = (unsigned) -1; /* length of current array entries */
4437 n_struct = strlen(types); /* length of current struct contents signature */
4444 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4445 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4451 r = sd_bus_message_exit_container(m);
4459 if (n_array != (unsigned) -1)
4468 case SD_BUS_TYPE_BYTE:
4469 case SD_BUS_TYPE_BOOLEAN:
4470 case SD_BUS_TYPE_INT16:
4471 case SD_BUS_TYPE_UINT16:
4472 case SD_BUS_TYPE_INT32:
4473 case SD_BUS_TYPE_UINT32:
4474 case SD_BUS_TYPE_INT64:
4475 case SD_BUS_TYPE_UINT64:
4476 case SD_BUS_TYPE_DOUBLE:
4477 case SD_BUS_TYPE_STRING:
4478 case SD_BUS_TYPE_OBJECT_PATH:
4479 case SD_BUS_TYPE_SIGNATURE:
4480 case SD_BUS_TYPE_UNIX_FD: {
4483 p = va_arg(ap, void*);
4484 r = sd_bus_message_read_basic(m, *t, p);
4497 case SD_BUS_TYPE_ARRAY: {
4500 r = signature_element_length(t + 1, &k);
4506 memcpy(s, t + 1, k);
4509 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4520 if (n_array == (unsigned) -1) {
4525 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4531 n_array = va_arg(ap, unsigned);
4536 case SD_BUS_TYPE_VARIANT: {
4539 s = va_arg(ap, const char *);
4543 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4553 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4558 n_struct = strlen(s);
4559 n_array = (unsigned) -1;
4564 case SD_BUS_TYPE_STRUCT_BEGIN:
4565 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4568 r = signature_element_length(t, &k);
4574 memcpy(s, t + 1, k - 2);
4577 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4587 if (n_array == (unsigned) -1) {
4592 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4598 n_array = (unsigned) -1;
4611 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4615 assert_return(m, -EINVAL);
4616 assert_return(m->sealed, -EPERM);
4617 assert_return(types, -EINVAL);
4619 va_start(ap, types);
4620 r = message_read_ap(m, types, ap);
4626 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4629 assert_return(m, -EINVAL);
4630 assert_return(m->sealed, -EPERM);
4632 /* If types is NULL, read exactly one element */
4634 struct bus_container *c;
4637 if (message_end_of_signature(m))
4640 if (message_end_of_array(m, m->rindex))
4643 c = message_get_container(m);
4645 r = signature_element_length(c->signature + c->index, &l);
4649 types = strndupa(c->signature + c->index, l);
4654 case 0: /* Nothing to drop */
4657 case SD_BUS_TYPE_BYTE:
4658 case SD_BUS_TYPE_BOOLEAN:
4659 case SD_BUS_TYPE_INT16:
4660 case SD_BUS_TYPE_UINT16:
4661 case SD_BUS_TYPE_INT32:
4662 case SD_BUS_TYPE_UINT32:
4663 case SD_BUS_TYPE_INT64:
4664 case SD_BUS_TYPE_UINT64:
4665 case SD_BUS_TYPE_DOUBLE:
4666 case SD_BUS_TYPE_STRING:
4667 case SD_BUS_TYPE_OBJECT_PATH:
4668 case SD_BUS_TYPE_SIGNATURE:
4669 case SD_BUS_TYPE_UNIX_FD:
4671 r = sd_bus_message_read_basic(m, *types, NULL);
4675 r = sd_bus_message_skip(m, types + 1);
4681 case SD_BUS_TYPE_ARRAY: {
4684 r = signature_element_length(types + 1, &k);
4690 memcpy(s, types+1, k);
4693 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4698 r = sd_bus_message_skip(m, s);
4705 r = sd_bus_message_exit_container(m);
4710 r = sd_bus_message_skip(m, types + 1 + k);
4717 case SD_BUS_TYPE_VARIANT: {
4718 const char *contents;
4721 r = sd_bus_message_peek_type(m, &x, &contents);
4725 if (x != SD_BUS_TYPE_VARIANT)
4728 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4732 r = sd_bus_message_skip(m, contents);
4737 r = sd_bus_message_exit_container(m);
4741 r = sd_bus_message_skip(m, types + 1);
4748 case SD_BUS_TYPE_STRUCT_BEGIN:
4749 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4752 r = signature_element_length(types, &k);
4758 memcpy(s, types+1, k-2);
4761 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4765 r = sd_bus_message_skip(m, s);
4769 r = sd_bus_message_exit_container(m);
4774 r = sd_bus_message_skip(m, types + k);
4786 _public_ int sd_bus_message_read_array(
4792 struct bus_container *c;
4798 assert_return(m, -EINVAL);
4799 assert_return(m->sealed, -EPERM);
4800 assert_return(bus_type_is_trivial(type), -EINVAL);
4801 assert_return(ptr, -EINVAL);
4802 assert_return(size, -EINVAL);
4803 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4805 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4809 c = message_get_container(m);
4811 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4812 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4816 sz = c->end - c->begin;
4818 align = bus_type_get_alignment(type);
4822 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4826 /* Zero length array, let's return some aligned
4827 * pointer that is not NULL */
4828 p = (uint8_t*) NULL + align;
4830 r = message_peek_body(m, &m->rindex, align, sz, &p);
4835 r = sd_bus_message_exit_container(m);
4839 *ptr = (const void*) p;
4845 message_quit_container(m);
4849 static int message_peek_fields(
4860 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4863 static int message_peek_field_uint32(
4875 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4878 /* identical for gvariant and dbus1 */
4880 r = message_peek_fields(m, ri, 4, 4, &q);
4885 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4890 static int message_peek_field_uint64(
4902 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4905 /* identical for gvariant and dbus1 */
4907 r = message_peek_fields(m, ri, 8, 8, &q);
4912 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4917 static int message_peek_field_string(
4919 bool (*validate)(const char *p),
4931 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4936 r = message_peek_fields(m, ri, 1, item_size, &q);
4942 r = message_peek_field_uint32(m, ri, 4, &l);
4946 r = message_peek_fields(m, ri, 1, l+1, &q);
4952 if (!validate_nul(q, l))
4958 if (!validate_string(q, l))
4968 static int message_peek_field_signature(
4981 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4986 r = message_peek_fields(m, ri, 1, item_size, &q);
4992 r = message_peek_fields(m, ri, 1, 1, &q);
4997 r = message_peek_fields(m, ri, 1, l+1, &q);
5002 if (!validate_signature(q, l))
5011 static int message_skip_fields(
5014 uint32_t array_size,
5015 const char **signature) {
5017 size_t original_index;
5023 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5025 original_index = *ri;
5031 if (array_size != (uint32_t) -1 &&
5032 array_size <= *ri - original_index)
5039 if (t == SD_BUS_TYPE_STRING) {
5041 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5047 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5049 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5055 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5057 r = message_peek_field_signature(m, ri, 0, NULL);
5063 } else if (bus_type_is_basic(t)) {
5066 align = bus_type_get_alignment(t);
5067 k = bus_type_get_size(t);
5068 assert(align > 0 && k > 0);
5070 r = message_peek_fields(m, ri, align, k, NULL);
5076 } else if (t == SD_BUS_TYPE_ARRAY) {
5078 r = signature_element_length(*signature+1, &l);
5088 strncpy(sig, *signature + 1, l-1);
5091 alignment = bus_type_get_alignment(sig[0]);
5095 r = message_peek_field_uint32(m, ri, 0, &nas);
5098 if (nas > BUS_ARRAY_MAX_SIZE)
5101 r = message_peek_fields(m, ri, alignment, 0, NULL);
5105 r = message_skip_fields(m, ri, nas, (const char**) &s);
5110 (*signature) += 1 + l;
5112 } else if (t == SD_BUS_TYPE_VARIANT) {
5115 r = message_peek_field_signature(m, ri, 0, &s);
5119 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5125 } else if (t == SD_BUS_TYPE_STRUCT ||
5126 t == SD_BUS_TYPE_DICT_ENTRY) {
5128 r = signature_element_length(*signature, &l);
5135 strncpy(sig, *signature + 1, l-1);
5138 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5149 int bus_message_parse_fields(sd_bus_message *m) {
5152 uint32_t unix_fds = 0;
5153 bool unix_fds_set = false;
5154 void *offsets = NULL;
5155 unsigned n_offsets = 0;
5161 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5164 /* Read the signature from the end of the body variant first */
5165 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5166 if (m->footer_accessible < 1 + sz)
5169 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5171 if (p < (char*) m->footer)
5178 /* We found the beginning of the signature
5179 * string, yay! We require the body to be a
5180 * structure, so verify it and then strip the
5181 * opening/closing brackets. */
5183 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5185 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5186 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5189 c = strndup(p + 1 + 1, l - 2);
5193 free(m->root_container.signature);
5194 m->root_container.signature = c;
5201 /* Calculate the actual user body size, by removing
5202 * the trailing variant signature and struct offset
5204 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5206 /* Pull out the offset table for the fields array */
5207 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5212 ri = m->fields_size - sz;
5213 r = message_peek_fields(m, &ri, 1, sz, &q);
5217 framing = bus_gvariant_read_word_le(q, sz);
5218 if (framing >= m->fields_size - sz)
5220 if ((m->fields_size - framing) % sz != 0)
5224 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5228 n_offsets = (m->fields_size - framing) / sz;
5231 m->user_body_size = m->body_size;
5234 while (ri < m->fields_size) {
5235 _cleanup_free_ char *sig = NULL;
5236 const char *signature;
5237 uint64_t field_type;
5238 size_t item_size = (size_t) -1;
5240 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5249 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5251 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5255 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5259 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5266 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5271 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5276 where = ri = ALIGN_TO(ri, 8);
5277 item_size = end - ri;
5278 r = message_peek_fields(m, &where, 1, item_size, &q);
5282 b = memrchr(q, 0, item_size);
5286 sig = strndup(b+1, item_size - (b+1-(char*) q));
5291 item_size = b - (char*) q;
5293 r = message_peek_field_signature(m, &ri, 0, &signature);
5298 switch (field_type) {
5300 case _BUS_MESSAGE_HEADER_INVALID:
5303 case BUS_MESSAGE_HEADER_PATH:
5308 if (!streq(signature, "o"))
5311 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5314 case BUS_MESSAGE_HEADER_INTERFACE:
5319 if (!streq(signature, "s"))
5322 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5325 case BUS_MESSAGE_HEADER_MEMBER:
5330 if (!streq(signature, "s"))
5333 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5336 case BUS_MESSAGE_HEADER_ERROR_NAME:
5341 if (!streq(signature, "s"))
5344 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5346 m->error._need_free = -1;
5350 case BUS_MESSAGE_HEADER_DESTINATION:
5355 if (!streq(signature, "s"))
5358 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5361 case BUS_MESSAGE_HEADER_SENDER:
5366 if (!streq(signature, "s"))
5369 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5371 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5372 m->creds.unique_name = (char*) m->sender;
5373 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5379 case BUS_MESSAGE_HEADER_SIGNATURE: {
5383 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5386 if (m->root_container.signature)
5389 if (!streq(signature, "g"))
5392 r = message_peek_field_signature(m, &ri, item_size, &s);
5400 free(m->root_container.signature);
5401 m->root_container.signature = c;
5405 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5407 if (m->reply_cookie != 0)
5410 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5411 /* 64bit on dbus2 */
5413 if (!streq(signature, "t"))
5416 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5420 /* 32bit on dbus1 */
5423 if (!streq(signature, "u"))
5426 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5430 m->reply_cookie = serial;
5433 if (m->reply_cookie == 0)
5438 case BUS_MESSAGE_HEADER_UNIX_FDS:
5442 if (!streq(signature, "u"))
5445 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5449 unix_fds_set = true;
5453 if (!BUS_MESSAGE_IS_GVARIANT(m))
5454 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5463 if (m->n_fds != unix_fds)
5466 switch (m->header->type) {
5468 case SD_BUS_MESSAGE_SIGNAL:
5469 if (!m->path || !m->interface || !m->member)
5472 if (m->reply_cookie != 0)
5477 case SD_BUS_MESSAGE_METHOD_CALL:
5479 if (!m->path || !m->member)
5482 if (m->reply_cookie != 0)
5487 case SD_BUS_MESSAGE_METHOD_RETURN:
5489 if (m->reply_cookie == 0)
5493 case SD_BUS_MESSAGE_METHOD_ERROR:
5495 if (m->reply_cookie == 0 || !m->error.name)
5500 /* Refuse non-local messages that claim they are local */
5501 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5503 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5505 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5508 m->root_container.end = m->user_body_size;
5510 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5511 r = build_struct_offsets(
5513 m->root_container.signature,
5515 &m->root_container.item_size,
5516 &m->root_container.offsets,
5517 &m->root_container.n_offsets);
5522 /* Try to read the error message, but if we can't it's a non-issue */
5523 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5524 (void) sd_bus_message_read(m, "s", &m->error.message);
5529 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5530 assert_return(m, -EINVAL);
5531 assert_return(destination, -EINVAL);
5532 assert_return(!m->sealed, -EPERM);
5533 assert_return(!m->destination, -EEXIST);
5535 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5538 #if 0 /// UNNEEDED by elogind
5539 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5543 struct bus_body_part *part;
5549 total = BUS_MESSAGE_SIZE(m);
5555 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5556 MESSAGE_FOREACH_PART(part, i, m)
5557 e = mempcpy(e, part->data, part->size);
5559 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5568 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5575 r = sd_bus_message_enter_container(m, 'a', "s");
5579 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5580 r = strv_extend(l, s);
5587 r = sd_bus_message_exit_container(m);
5594 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5598 assert_return(m, -EINVAL);
5599 assert_return(m->sealed, -EPERM);
5600 assert_return(l, -EINVAL);
5602 r = bus_message_read_strv_extend(m, &strv);
5612 static int bus_message_get_arg_skip(
5616 const char **_contents) {
5621 r = sd_bus_message_rewind(m, true);
5626 const char *contents;
5629 r = sd_bus_message_peek_type(m, &type, &contents);
5635 /* Don't match against arguments after the first one we don't understand */
5636 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5637 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5642 *_contents = contents;
5648 r = sd_bus_message_skip(m, NULL);
5655 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5662 r = bus_message_get_arg_skip(m, i, &type, NULL);
5666 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5669 return sd_bus_message_read_basic(m, type, str);
5672 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5673 const char *contents;
5680 r = bus_message_get_arg_skip(m, i, &type, &contents);
5684 if (type != SD_BUS_TYPE_ARRAY)
5686 if (!STR_IN_SET(contents, "s", "o", "g"))
5689 return sd_bus_message_read_strv(m, strv);
5692 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5693 assert_return(m, EINVAL);
5695 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5698 return sd_bus_error_get_errno(&m->error);
5701 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5702 struct bus_container *c;
5704 assert_return(m, NULL);
5706 c = complete ? &m->root_container : message_get_container(m);
5707 return strempty(c->signature);
5710 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5711 assert_return(m, -EINVAL);
5713 return isempty(m->root_container.signature);
5716 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5717 assert_return(m, -EINVAL);
5719 return streq(strempty(m->root_container.signature), strempty(signature));
5722 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5723 bool done_something = false;
5726 assert_return(m, -EINVAL);
5727 assert_return(source, -EINVAL);
5728 assert_return(!m->sealed, -EPERM);
5729 assert_return(source->sealed, -EPERM);
5732 const char *contents;
5747 r = sd_bus_message_peek_type(source, &type, &contents);
5753 done_something = true;
5755 if (bus_type_is_container(type) > 0) {
5757 r = sd_bus_message_enter_container(source, type, contents);
5761 r = sd_bus_message_open_container(m, type, contents);
5765 r = sd_bus_message_copy(m, source, true);
5769 r = sd_bus_message_close_container(m);
5773 r = sd_bus_message_exit_container(source);
5780 r = sd_bus_message_read_basic(source, type, &basic);
5786 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5787 type == SD_BUS_TYPE_SIGNATURE ||
5788 type == SD_BUS_TYPE_STRING)
5789 r = sd_bus_message_append_basic(m, type, basic.string);
5791 r = sd_bus_message_append_basic(m, type, &basic);
5798 return done_something;
5801 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5806 assert_return(m, -EINVAL);
5807 assert_return(m->sealed, -EPERM);
5808 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5809 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5810 assert_return(type || contents, -EINVAL);
5811 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5813 r = sd_bus_message_peek_type(m, &t, &c);
5817 if (type != 0 && type != t)
5820 if (contents && !streq_ptr(contents, c))
5826 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5827 assert_return(m, NULL);
5832 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5833 _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5841 switch ((*m)->header->type) {
5843 case SD_BUS_MESSAGE_SIGNAL:
5844 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5850 case SD_BUS_MESSAGE_METHOD_CALL:
5851 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5857 case SD_BUS_MESSAGE_METHOD_RETURN:
5858 case SD_BUS_MESSAGE_METHOD_ERROR:
5860 n = message_new(bus, (*m)->header->type);
5864 n->reply_cookie = (*m)->reply_cookie;
5866 r = message_append_reply_cookie(n, n->reply_cookie);
5870 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5871 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5875 n->error._need_free = -1;
5884 if ((*m)->destination && !n->destination) {
5885 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5890 if ((*m)->sender && !n->sender) {
5891 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5896 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5898 r = sd_bus_message_copy(n, *m, true);
5902 timeout = (*m)->timeout;
5903 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5904 timeout = BUS_DEFAULT_TIMEOUT;
5906 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5910 sd_bus_message_unref(*m);
5917 #if 0 /// UNNEEDED by elogind
5918 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5922 assert_return(!m->sealed, -EPERM);
5923 assert_return(!m->sender, -EPERM);
5925 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5929 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5930 assert_return(m, -EINVAL);
5931 assert_return(priority, -EINVAL);
5933 *priority = m->priority;
5937 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5938 assert_return(m, -EINVAL);
5939 assert_return(!m->sealed, -EPERM);
5941 m->priority = priority;