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 || !IN_SET(bus->state, BUS_HELLO, 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 (IN_SET(type, SD_BUS_TYPE_STRING, 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 (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, 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 (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
3241 if (c->offset_index+1 >= c->n_offsets)
3244 r = signature_element_length(c->signature + c->index, &n);
3248 r = signature_element_length(c->signature + c->index + n, &j);
3253 memcpy(t, c->signature + c->index + n, j);
3256 alignment = bus_gvariant_get_alignment(t);
3259 assert(alignment > 0);
3261 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3262 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3266 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3269 assert_not_reached("Unknown container type");
3274 /* Reached the end */
3281 static int message_peek_body(
3288 size_t k, start, end, padding;
3289 struct bus_body_part *part;
3296 start = ALIGN_TO((size_t) *rindex, align);
3297 padding = start - *rindex;
3298 end = start + nbytes;
3300 if (end > m->user_body_size)
3303 part = find_part(m, *rindex, padding, (void**) &q);
3308 /* Verify padding */
3309 for (k = 0; k < padding; k++)
3314 part = find_part(m, start, nbytes, (void**) &q);
3315 if (!part || (nbytes > 0 && !q))
3326 static bool validate_nul(const char *s, size_t l) {
3328 /* Check for NUL chars in the string */
3329 if (memchr(s, 0, l))
3332 /* Check for NUL termination */
3339 static bool validate_string(const char *s, size_t l) {
3341 if (!validate_nul(s, l))
3344 /* Check if valid UTF8 */
3345 if (!utf8_is_valid(s))
3351 static bool validate_signature(const char *s, size_t l) {
3353 if (!validate_nul(s, l))
3356 /* Check if valid signature */
3357 if (!signature_is_valid(s, true))
3363 static bool validate_object_path(const char *s, size_t l) {
3365 if (!validate_nul(s, l))
3368 if (!object_path_is_valid(s))
3374 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3375 struct bus_container *c;
3380 assert_return(m, -EINVAL);
3381 assert_return(m->sealed, -EPERM);
3382 assert_return(bus_type_is_basic(type), -EINVAL);
3384 if (message_end_of_signature(m))
3387 if (message_end_of_array(m, m->rindex))
3390 c = message_get_container(m);
3391 if (c->signature[c->index] != type)
3396 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3398 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3401 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3405 if (type == SD_BUS_TYPE_STRING)
3406 ok = validate_string(q, c->item_size-1);
3407 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3408 ok = validate_object_path(q, c->item_size-1);
3410 ok = validate_signature(q, c->item_size-1);
3416 *(const char**) p = q;
3420 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3422 if ((size_t) sz != c->item_size)
3425 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3428 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3434 case SD_BUS_TYPE_BYTE:
3436 *(uint8_t*) p = *(uint8_t*) q;
3439 case SD_BUS_TYPE_BOOLEAN:
3441 *(int*) p = !!*(uint8_t*) q;
3444 case SD_BUS_TYPE_INT16:
3445 case SD_BUS_TYPE_UINT16:
3447 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3450 case SD_BUS_TYPE_INT32:
3451 case SD_BUS_TYPE_UINT32:
3453 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3456 case SD_BUS_TYPE_INT64:
3457 case SD_BUS_TYPE_UINT64:
3458 case SD_BUS_TYPE_DOUBLE:
3460 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3463 case SD_BUS_TYPE_UNIX_FD: {
3466 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3471 *(int*) p = m->fds[j];
3477 assert_not_reached("unexpected type");
3481 r = container_next_item(m, c, &rindex);
3486 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3490 r = message_peek_body(m, &rindex, 4, 4, &q);
3494 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3495 r = message_peek_body(m, &rindex, 1, l+1, &q);
3499 if (type == SD_BUS_TYPE_OBJECT_PATH)
3500 ok = validate_object_path(q, l);
3502 ok = validate_string(q, l);
3507 *(const char**) p = q;
3509 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3512 r = message_peek_body(m, &rindex, 1, 1, &q);
3517 r = message_peek_body(m, &rindex, 1, l+1, &q);
3521 if (!validate_signature(q, l))
3525 *(const char**) p = q;
3530 align = bus_type_get_alignment(type);
3533 sz = bus_type_get_size(type);
3536 r = message_peek_body(m, &rindex, align, sz, &q);
3542 case SD_BUS_TYPE_BYTE:
3544 *(uint8_t*) p = *(uint8_t*) q;
3547 case SD_BUS_TYPE_BOOLEAN:
3549 *(int*) p = !!*(uint32_t*) q;
3552 case SD_BUS_TYPE_INT16:
3553 case SD_BUS_TYPE_UINT16:
3555 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3558 case SD_BUS_TYPE_INT32:
3559 case SD_BUS_TYPE_UINT32:
3561 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3564 case SD_BUS_TYPE_INT64:
3565 case SD_BUS_TYPE_UINT64:
3566 case SD_BUS_TYPE_DOUBLE:
3568 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3571 case SD_BUS_TYPE_UNIX_FD: {
3574 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3579 *(int*) p = m->fds[j];
3584 assert_not_reached("Unknown basic type...");
3591 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3597 static int bus_message_enter_array(
3599 struct bus_container *c,
3600 const char *contents,
3601 uint32_t **array_size,
3604 size_t *n_offsets) {
3618 if (!signature_is_single(contents, true))
3621 if (!c->signature || c->signature[c->index] == 0)
3624 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3627 if (!startswith(c->signature + c->index + 1, contents))
3632 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3635 r = message_peek_body(m, &rindex, 4, 4, &q);
3639 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3642 alignment = bus_type_get_alignment(contents[0]);
3646 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3650 *array_size = (uint32_t*) q;
3652 } else if (c->item_size <= 0) {
3654 /* gvariant: empty array */
3659 } else if (bus_gvariant_is_fixed_size(contents)) {
3661 /* gvariant: fixed length array */
3662 *item_size = bus_gvariant_get_size(contents);
3667 size_t where, p = 0, framing, sz;
3670 /* gvariant: variable length array */
3671 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3673 where = rindex + c->item_size - sz;
3674 r = message_peek_body(m, &where, 1, sz, &q);
3678 framing = bus_gvariant_read_word_le(q, sz);
3679 if (framing > c->item_size - sz)
3681 if ((c->item_size - framing) % sz != 0)
3684 *n_offsets = (c->item_size - framing) / sz;
3686 where = rindex + framing;
3687 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3691 *offsets = new(size_t, *n_offsets);
3695 for (i = 0; i < *n_offsets; i++) {
3698 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3699 if (x > c->item_size - sz)
3704 (*offsets)[i] = rindex + x;
3708 *item_size = (*offsets)[0] - rindex;
3713 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3714 c->index += 1 + strlen(contents);
3719 static int bus_message_enter_variant(
3721 struct bus_container *c,
3722 const char *contents,
3723 size_t *item_size) {
3735 if (!signature_is_single(contents, false))
3738 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3741 if (!c->signature || c->signature[c->index] == 0)
3744 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3749 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3752 k = strlen(contents);
3753 if (1+k > c->item_size)
3756 where = rindex + c->item_size - (1+k);
3757 r = message_peek_body(m, &where, 1, 1+k, &q);
3761 if (*(char*) q != 0)
3764 if (memcmp((uint8_t*) q+1, contents, k))
3767 *item_size = c->item_size - (1+k);
3770 r = message_peek_body(m, &rindex, 1, 1, &q);
3775 r = message_peek_body(m, &rindex, 1, l+1, &q);
3779 if (!validate_signature(q, l))
3782 if (!streq(q, contents))
3788 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3794 static int build_struct_offsets(
3796 const char *signature,
3800 size_t *n_offsets) {
3802 unsigned n_variable = 0, n_total = 0, v;
3803 size_t previous = 0, where;
3814 if (isempty(signature)) {
3815 /* Unary type is encoded as *fixed* 1 byte padding */
3816 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3820 if (*(uint8_t *) q != 0)
3829 sz = bus_gvariant_determine_word_size(size, 0);
3833 /* First, loop over signature and count variable elements and
3834 * elements in general. We use this to know how large the
3835 * offset array is at the end of the structure. Note that
3836 * GVariant only stores offsets for all variable size elements
3837 * that are not the last item. */
3843 r = signature_element_length(p, &n);
3852 r = bus_gvariant_is_fixed_size(t);
3857 if (r == 0 && p[n] != 0) /* except the last item */
3864 if (size < n_variable * sz)
3867 where = m->rindex + size - (n_variable * sz);
3868 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3874 *offsets = new(size_t, n_total);
3880 /* Second, loop again and build an offset table */
3886 r = signature_element_length(p, &n);
3895 k = bus_gvariant_get_size(t);
3903 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3906 if (m->rindex + x < previous)
3909 /* The last item's end
3910 * is determined from
3913 x = size - (n_variable * sz);
3915 offset = m->rindex + x;
3921 align = bus_gvariant_get_alignment(t);
3924 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3928 previous = (*offsets)[(*n_offsets)++] = offset;
3933 assert(*n_offsets == n_total);
3935 *item_size = (*offsets)[0] - m->rindex;
3939 static int enter_struct_or_dict_entry(
3941 struct bus_container *c,
3942 const char *contents,
3945 size_t *n_offsets) {
3956 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3959 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3964 /* gvariant with contents */
3965 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3970 static int bus_message_enter_struct(
3972 struct bus_container *c,
3973 const char *contents,
3976 size_t *n_offsets) {
3988 if (!signature_is_valid(contents, false))
3991 if (!c->signature || c->signature[c->index] == 0)
3994 l = strlen(contents);
3996 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3997 !startswith(c->signature + c->index + 1, contents) ||
3998 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4001 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4005 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4006 c->index += 1 + l + 1;
4011 static int bus_message_enter_dict_entry(
4013 struct bus_container *c,
4014 const char *contents,
4017 size_t *n_offsets) {
4026 if (!signature_is_pair(contents))
4029 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4032 if (!c->signature || c->signature[c->index] == 0)
4035 l = strlen(contents);
4037 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4038 !startswith(c->signature + c->index + 1, contents) ||
4039 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4042 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4046 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4047 c->index += 1 + l + 1;
4052 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4054 const char *contents) {
4055 struct bus_container *c, *w;
4056 uint32_t *array_size = NULL;
4059 size_t *offsets = NULL;
4060 size_t n_offsets = 0, item_size = 0;
4063 assert_return(m, -EINVAL);
4064 assert_return(m->sealed, -EPERM);
4065 assert_return(type != 0 || !contents, -EINVAL);
4067 if (type == 0 || !contents) {
4071 /* Allow entering into anonymous containers */
4072 r = sd_bus_message_peek_type(m, &tt, &cc);
4076 if (type != 0 && type != tt)
4079 if (contents && !streq(contents, cc))
4087 * We enforce a global limit on container depth, that is much
4088 * higher than the 32 structs and 32 arrays the specification
4089 * mandates. This is simpler to implement for us, and we need
4090 * this only to ensure our container array doesn't grow
4091 * without bounds. We are happy to return any data from a
4092 * message as long as the data itself is valid, even if the
4093 * overall message might be not.
4095 * Note that the message signature is validated when
4096 * parsing the headers, and that validation does check the
4099 * Note that the specification defines no limits on the depth
4100 * of stacked variants, but we do.
4102 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4105 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4108 if (message_end_of_signature(m))
4111 if (message_end_of_array(m, m->rindex))
4114 c = message_get_container(m);
4116 signature = strdup(contents);
4120 c->saved_index = c->index;
4123 if (type == SD_BUS_TYPE_ARRAY)
4124 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4125 else if (type == SD_BUS_TYPE_VARIANT)
4126 r = bus_message_enter_variant(m, c, contents, &item_size);
4127 else if (type == SD_BUS_TYPE_STRUCT)
4128 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4129 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4130 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4140 /* OK, let's fill it in */
4141 w = m->containers + m->n_containers++;
4142 w->enclosing = type;
4143 w->signature = signature;
4144 w->peeked_signature = NULL;
4148 w->begin = m->rindex;
4150 /* Unary type has fixed size of 1, but virtual size of 0 */
4151 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4152 type == SD_BUS_TYPE_STRUCT &&
4154 w->end = m->rindex + 0;
4156 w->end = m->rindex + c->item_size;
4158 w->array_size = array_size;
4159 w->item_size = item_size;
4160 w->offsets = offsets;
4161 w->n_offsets = n_offsets;
4162 w->offset_index = 0;
4167 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4168 struct bus_container *c;
4172 assert_return(m, -EINVAL);
4173 assert_return(m->sealed, -EPERM);
4174 assert_return(m->n_containers > 0, -ENXIO);
4176 c = message_get_container(m);
4178 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4179 if (c->signature && c->signature[c->index] != 0)
4183 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4184 if (m->rindex < c->end)
4187 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4190 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4191 if (c->begin + l != m->rindex)
4196 free(c->peeked_signature);
4200 c = message_get_container(m);
4203 c->index = c->saved_index;
4204 r = container_next_item(m, c, &m->rindex);
4212 static void message_quit_container(sd_bus_message *m) {
4213 struct bus_container *c;
4217 assert(m->n_containers > 0);
4219 c = message_get_container(m);
4222 assert(m->rindex >= c->before);
4223 m->rindex = c->before;
4225 /* Free container */
4230 /* Correct index of new top-level container */
4231 c = message_get_container(m);
4232 c->index = c->saved_index;
4235 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4236 struct bus_container *c;
4239 assert_return(m, -EINVAL);
4240 assert_return(m->sealed, -EPERM);
4242 if (message_end_of_signature(m))
4245 if (message_end_of_array(m, m->rindex))
4248 c = message_get_container(m);
4250 if (bus_type_is_basic(c->signature[c->index])) {
4254 *type = c->signature[c->index];
4258 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4264 r = signature_element_length(c->signature+c->index+1, &l);
4270 sig = strndup(c->signature + c->index + 1, l);
4274 free(c->peeked_signature);
4275 *contents = c->peeked_signature = sig;
4279 *type = SD_BUS_TYPE_ARRAY;
4284 if (IN_SET(c->signature[c->index], SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN)) {
4290 r = signature_element_length(c->signature+c->index, &l);
4295 sig = strndup(c->signature + c->index + 1, l - 2);
4299 free(c->peeked_signature);
4300 *contents = c->peeked_signature = sig;
4304 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4309 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4313 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4316 if (c->item_size < 2)
4319 /* Look for the NUL delimiter that
4320 separates the payload from the
4321 signature. Since the body might be
4322 in a different part that then the
4323 signature we map byte by byte. */
4325 for (k = 2; k <= c->item_size; k++) {
4328 where = m->rindex + c->item_size - k;
4329 r = message_peek_body(m, &where, 1, k, &q);
4333 if (*(char*) q == 0)
4337 if (k > c->item_size)
4340 free(c->peeked_signature);
4341 c->peeked_signature = strndup((char*) q + 1, k - 1);
4342 if (!c->peeked_signature)
4345 if (!signature_is_valid(c->peeked_signature, true))
4348 *contents = c->peeked_signature;
4353 r = message_peek_body(m, &rindex, 1, 1, &q);
4358 r = message_peek_body(m, &rindex, 1, l+1, &q);
4362 if (!validate_signature(q, l))
4370 *type = SD_BUS_TYPE_VARIANT;
4385 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4386 struct bus_container *c;
4388 assert_return(m, -EINVAL);
4389 assert_return(m->sealed, -EPERM);
4392 message_reset_containers(m);
4395 c = message_get_container(m);
4397 c = message_get_container(m);
4399 c->offset_index = 0;
4401 m->rindex = c->begin;
4404 c->offset_index = 0;
4405 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4407 return !isempty(c->signature);
4410 static int message_read_ap(
4415 unsigned n_array, n_struct;
4416 TypeStack stack[BUS_CONTAINER_DEPTH];
4417 unsigned stack_ptr = 0;
4418 unsigned n_loop = 0;
4426 /* Ideally, we'd just call ourselves recursively on every
4427 * complex type. However, the state of a va_list that is
4428 * passed to a function is undefined after that function
4429 * returns. This means we need to docode the va_list linearly
4430 * in a single stackframe. We hence implement our own
4431 * home-grown stack in an array. */
4433 n_array = (unsigned) -1; /* length of current array entries */
4434 n_struct = strlen(types); /* length of current struct contents signature */
4441 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4442 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4448 r = sd_bus_message_exit_container(m);
4456 if (n_array != (unsigned) -1)
4465 case SD_BUS_TYPE_BYTE:
4466 case SD_BUS_TYPE_BOOLEAN:
4467 case SD_BUS_TYPE_INT16:
4468 case SD_BUS_TYPE_UINT16:
4469 case SD_BUS_TYPE_INT32:
4470 case SD_BUS_TYPE_UINT32:
4471 case SD_BUS_TYPE_INT64:
4472 case SD_BUS_TYPE_UINT64:
4473 case SD_BUS_TYPE_DOUBLE:
4474 case SD_BUS_TYPE_STRING:
4475 case SD_BUS_TYPE_OBJECT_PATH:
4476 case SD_BUS_TYPE_SIGNATURE:
4477 case SD_BUS_TYPE_UNIX_FD: {
4480 p = va_arg(ap, void*);
4481 r = sd_bus_message_read_basic(m, *t, p);
4494 case SD_BUS_TYPE_ARRAY: {
4497 r = signature_element_length(t + 1, &k);
4503 memcpy(s, t + 1, k);
4506 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4517 if (n_array == (unsigned) -1) {
4522 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4528 n_array = va_arg(ap, unsigned);
4533 case SD_BUS_TYPE_VARIANT: {
4536 s = va_arg(ap, const char *);
4540 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4550 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4555 n_struct = strlen(s);
4556 n_array = (unsigned) -1;
4561 case SD_BUS_TYPE_STRUCT_BEGIN:
4562 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4565 r = signature_element_length(t, &k);
4571 memcpy(s, t + 1, k - 2);
4574 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4584 if (n_array == (unsigned) -1) {
4589 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4595 n_array = (unsigned) -1;
4608 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4612 assert_return(m, -EINVAL);
4613 assert_return(m->sealed, -EPERM);
4614 assert_return(types, -EINVAL);
4616 va_start(ap, types);
4617 r = message_read_ap(m, types, ap);
4623 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4626 assert_return(m, -EINVAL);
4627 assert_return(m->sealed, -EPERM);
4629 /* If types is NULL, read exactly one element */
4631 struct bus_container *c;
4634 if (message_end_of_signature(m))
4637 if (message_end_of_array(m, m->rindex))
4640 c = message_get_container(m);
4642 r = signature_element_length(c->signature + c->index, &l);
4646 types = strndupa(c->signature + c->index, l);
4651 case 0: /* Nothing to drop */
4654 case SD_BUS_TYPE_BYTE:
4655 case SD_BUS_TYPE_BOOLEAN:
4656 case SD_BUS_TYPE_INT16:
4657 case SD_BUS_TYPE_UINT16:
4658 case SD_BUS_TYPE_INT32:
4659 case SD_BUS_TYPE_UINT32:
4660 case SD_BUS_TYPE_INT64:
4661 case SD_BUS_TYPE_UINT64:
4662 case SD_BUS_TYPE_DOUBLE:
4663 case SD_BUS_TYPE_STRING:
4664 case SD_BUS_TYPE_OBJECT_PATH:
4665 case SD_BUS_TYPE_SIGNATURE:
4666 case SD_BUS_TYPE_UNIX_FD:
4668 r = sd_bus_message_read_basic(m, *types, NULL);
4672 r = sd_bus_message_skip(m, types + 1);
4678 case SD_BUS_TYPE_ARRAY: {
4681 r = signature_element_length(types + 1, &k);
4687 memcpy(s, types+1, k);
4690 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4695 r = sd_bus_message_skip(m, s);
4702 r = sd_bus_message_exit_container(m);
4707 r = sd_bus_message_skip(m, types + 1 + k);
4714 case SD_BUS_TYPE_VARIANT: {
4715 const char *contents;
4718 r = sd_bus_message_peek_type(m, &x, &contents);
4722 if (x != SD_BUS_TYPE_VARIANT)
4725 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4729 r = sd_bus_message_skip(m, contents);
4734 r = sd_bus_message_exit_container(m);
4738 r = sd_bus_message_skip(m, types + 1);
4745 case SD_BUS_TYPE_STRUCT_BEGIN:
4746 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4749 r = signature_element_length(types, &k);
4755 memcpy(s, types+1, k-2);
4758 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4762 r = sd_bus_message_skip(m, s);
4766 r = sd_bus_message_exit_container(m);
4771 r = sd_bus_message_skip(m, types + k);
4783 _public_ int sd_bus_message_read_array(
4789 struct bus_container *c;
4795 assert_return(m, -EINVAL);
4796 assert_return(m->sealed, -EPERM);
4797 assert_return(bus_type_is_trivial(type), -EINVAL);
4798 assert_return(ptr, -EINVAL);
4799 assert_return(size, -EINVAL);
4800 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4802 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4806 c = message_get_container(m);
4808 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4809 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4813 sz = c->end - c->begin;
4815 align = bus_type_get_alignment(type);
4819 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4823 /* Zero length array, let's return some aligned
4824 * pointer that is not NULL */
4825 p = (uint8_t*) NULL + align;
4827 r = message_peek_body(m, &m->rindex, align, sz, &p);
4832 r = sd_bus_message_exit_container(m);
4836 *ptr = (const void*) p;
4842 message_quit_container(m);
4846 static int message_peek_fields(
4857 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4860 static int message_peek_field_uint32(
4872 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4875 /* identical for gvariant and dbus1 */
4877 r = message_peek_fields(m, ri, 4, 4, &q);
4882 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4887 static int message_peek_field_uint64(
4899 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4902 /* identical for gvariant and dbus1 */
4904 r = message_peek_fields(m, ri, 8, 8, &q);
4909 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4914 static int message_peek_field_string(
4916 bool (*validate)(const char *p),
4928 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4933 r = message_peek_fields(m, ri, 1, item_size, &q);
4939 r = message_peek_field_uint32(m, ri, 4, &l);
4943 r = message_peek_fields(m, ri, 1, l+1, &q);
4949 if (!validate_nul(q, l))
4955 if (!validate_string(q, l))
4965 static int message_peek_field_signature(
4978 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4983 r = message_peek_fields(m, ri, 1, item_size, &q);
4989 r = message_peek_fields(m, ri, 1, 1, &q);
4994 r = message_peek_fields(m, ri, 1, l+1, &q);
4999 if (!validate_signature(q, l))
5008 static int message_skip_fields(
5011 uint32_t array_size,
5012 const char **signature) {
5014 size_t original_index;
5020 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5022 original_index = *ri;
5028 if (array_size != (uint32_t) -1 &&
5029 array_size <= *ri - original_index)
5036 if (t == SD_BUS_TYPE_STRING) {
5038 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5044 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5046 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5052 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5054 r = message_peek_field_signature(m, ri, 0, NULL);
5060 } else if (bus_type_is_basic(t)) {
5063 align = bus_type_get_alignment(t);
5064 k = bus_type_get_size(t);
5065 assert(align > 0 && k > 0);
5067 r = message_peek_fields(m, ri, align, k, NULL);
5073 } else if (t == SD_BUS_TYPE_ARRAY) {
5075 r = signature_element_length(*signature+1, &l);
5085 strncpy(sig, *signature + 1, l-1);
5088 alignment = bus_type_get_alignment(sig[0]);
5092 r = message_peek_field_uint32(m, ri, 0, &nas);
5095 if (nas > BUS_ARRAY_MAX_SIZE)
5098 r = message_peek_fields(m, ri, alignment, 0, NULL);
5102 r = message_skip_fields(m, ri, nas, (const char**) &s);
5107 (*signature) += 1 + l;
5109 } else if (t == SD_BUS_TYPE_VARIANT) {
5112 r = message_peek_field_signature(m, ri, 0, &s);
5116 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5122 } else if (IN_SET(t, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
5124 r = signature_element_length(*signature, &l);
5131 strncpy(sig, *signature + 1, l-1);
5134 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5145 int bus_message_parse_fields(sd_bus_message *m) {
5148 uint32_t unix_fds = 0;
5149 bool unix_fds_set = false;
5150 void *offsets = NULL;
5151 unsigned n_offsets = 0;
5157 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5160 /* Read the signature from the end of the body variant first */
5161 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5162 if (m->footer_accessible < 1 + sz)
5165 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5167 if (p < (char*) m->footer)
5174 /* We found the beginning of the signature
5175 * string, yay! We require the body to be a
5176 * structure, so verify it and then strip the
5177 * opening/closing brackets. */
5179 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5181 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5182 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5185 c = strndup(p + 1 + 1, l - 2);
5189 free(m->root_container.signature);
5190 m->root_container.signature = c;
5197 /* Calculate the actual user body size, by removing
5198 * the trailing variant signature and struct offset
5200 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5202 /* Pull out the offset table for the fields array */
5203 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5208 ri = m->fields_size - sz;
5209 r = message_peek_fields(m, &ri, 1, sz, &q);
5213 framing = bus_gvariant_read_word_le(q, sz);
5214 if (framing >= m->fields_size - sz)
5216 if ((m->fields_size - framing) % sz != 0)
5220 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5224 n_offsets = (m->fields_size - framing) / sz;
5227 m->user_body_size = m->body_size;
5230 while (ri < m->fields_size) {
5231 _cleanup_free_ char *sig = NULL;
5232 const char *signature;
5233 uint64_t field_type;
5234 size_t item_size = (size_t) -1;
5236 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5245 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5247 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5251 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5255 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5262 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5267 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5272 where = ri = ALIGN_TO(ri, 8);
5273 item_size = end - ri;
5274 r = message_peek_fields(m, &where, 1, item_size, &q);
5278 b = memrchr(q, 0, item_size);
5282 sig = strndup(b+1, item_size - (b+1-(char*) q));
5287 item_size = b - (char*) q;
5289 r = message_peek_field_signature(m, &ri, 0, &signature);
5294 switch (field_type) {
5296 case _BUS_MESSAGE_HEADER_INVALID:
5299 case BUS_MESSAGE_HEADER_PATH:
5304 if (!streq(signature, "o"))
5307 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5310 case BUS_MESSAGE_HEADER_INTERFACE:
5315 if (!streq(signature, "s"))
5318 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5321 case BUS_MESSAGE_HEADER_MEMBER:
5326 if (!streq(signature, "s"))
5329 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5332 case BUS_MESSAGE_HEADER_ERROR_NAME:
5337 if (!streq(signature, "s"))
5340 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5342 m->error._need_free = -1;
5346 case BUS_MESSAGE_HEADER_DESTINATION:
5351 if (!streq(signature, "s"))
5354 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5357 case BUS_MESSAGE_HEADER_SENDER:
5362 if (!streq(signature, "s"))
5365 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5367 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5368 m->creds.unique_name = (char*) m->sender;
5369 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5375 case BUS_MESSAGE_HEADER_SIGNATURE: {
5379 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5382 if (m->root_container.signature)
5385 if (!streq(signature, "g"))
5388 r = message_peek_field_signature(m, &ri, item_size, &s);
5396 free(m->root_container.signature);
5397 m->root_container.signature = c;
5401 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5403 if (m->reply_cookie != 0)
5406 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5407 /* 64bit on dbus2 */
5409 if (!streq(signature, "t"))
5412 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5416 /* 32bit on dbus1 */
5419 if (!streq(signature, "u"))
5422 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5426 m->reply_cookie = serial;
5429 if (m->reply_cookie == 0)
5434 case BUS_MESSAGE_HEADER_UNIX_FDS:
5438 if (!streq(signature, "u"))
5441 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5445 unix_fds_set = true;
5449 if (!BUS_MESSAGE_IS_GVARIANT(m))
5450 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5459 if (m->n_fds != unix_fds)
5462 switch (m->header->type) {
5464 case SD_BUS_MESSAGE_SIGNAL:
5465 if (!m->path || !m->interface || !m->member)
5468 if (m->reply_cookie != 0)
5473 case SD_BUS_MESSAGE_METHOD_CALL:
5475 if (!m->path || !m->member)
5478 if (m->reply_cookie != 0)
5483 case SD_BUS_MESSAGE_METHOD_RETURN:
5485 if (m->reply_cookie == 0)
5489 case SD_BUS_MESSAGE_METHOD_ERROR:
5491 if (m->reply_cookie == 0 || !m->error.name)
5496 /* Refuse non-local messages that claim they are local */
5497 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5499 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5501 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5504 m->root_container.end = m->user_body_size;
5506 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5507 r = build_struct_offsets(
5509 m->root_container.signature,
5511 &m->root_container.item_size,
5512 &m->root_container.offsets,
5513 &m->root_container.n_offsets);
5518 /* Try to read the error message, but if we can't it's a non-issue */
5519 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5520 (void) sd_bus_message_read(m, "s", &m->error.message);
5525 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5526 assert_return(m, -EINVAL);
5527 assert_return(destination, -EINVAL);
5528 assert_return(!m->sealed, -EPERM);
5529 assert_return(!m->destination, -EEXIST);
5531 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5534 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5538 struct bus_body_part *part;
5544 total = BUS_MESSAGE_SIZE(m);
5550 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5551 MESSAGE_FOREACH_PART(part, i, m)
5552 e = mempcpy(e, part->data, part->size);
5554 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5562 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5569 r = sd_bus_message_enter_container(m, 'a', "s");
5573 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5574 r = strv_extend(l, s);
5581 r = sd_bus_message_exit_container(m);
5588 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5592 assert_return(m, -EINVAL);
5593 assert_return(m->sealed, -EPERM);
5594 assert_return(l, -EINVAL);
5596 r = bus_message_read_strv_extend(m, &strv);
5606 static int bus_message_get_arg_skip(
5610 const char **_contents) {
5615 r = sd_bus_message_rewind(m, true);
5620 const char *contents;
5623 r = sd_bus_message_peek_type(m, &type, &contents);
5629 /* Don't match against arguments after the first one we don't understand */
5630 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5631 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5636 *_contents = contents;
5642 r = sd_bus_message_skip(m, NULL);
5649 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5656 r = bus_message_get_arg_skip(m, i, &type, NULL);
5660 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5663 return sd_bus_message_read_basic(m, type, str);
5666 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5667 const char *contents;
5674 r = bus_message_get_arg_skip(m, i, &type, &contents);
5678 if (type != SD_BUS_TYPE_ARRAY)
5680 if (!STR_IN_SET(contents, "s", "o", "g"))
5683 return sd_bus_message_read_strv(m, strv);
5686 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5687 assert_return(m, EINVAL);
5689 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5692 return sd_bus_error_get_errno(&m->error);
5695 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5696 struct bus_container *c;
5698 assert_return(m, NULL);
5700 c = complete ? &m->root_container : message_get_container(m);
5701 return strempty(c->signature);
5704 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5705 assert_return(m, -EINVAL);
5707 return isempty(m->root_container.signature);
5710 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5711 assert_return(m, -EINVAL);
5713 return streq(strempty(m->root_container.signature), strempty(signature));
5716 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5717 bool done_something = false;
5720 assert_return(m, -EINVAL);
5721 assert_return(source, -EINVAL);
5722 assert_return(!m->sealed, -EPERM);
5723 assert_return(source->sealed, -EPERM);
5726 const char *contents;
5741 r = sd_bus_message_peek_type(source, &type, &contents);
5747 done_something = true;
5749 if (bus_type_is_container(type) > 0) {
5751 r = sd_bus_message_enter_container(source, type, contents);
5755 r = sd_bus_message_open_container(m, type, contents);
5759 r = sd_bus_message_copy(m, source, true);
5763 r = sd_bus_message_close_container(m);
5767 r = sd_bus_message_exit_container(source);
5774 r = sd_bus_message_read_basic(source, type, &basic);
5780 if (IN_SET(type, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_STRING))
5781 r = sd_bus_message_append_basic(m, type, basic.string);
5783 r = sd_bus_message_append_basic(m, type, &basic);
5790 return done_something;
5793 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5798 assert_return(m, -EINVAL);
5799 assert_return(m->sealed, -EPERM);
5800 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5801 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5802 assert_return(type || contents, -EINVAL);
5803 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5805 r = sd_bus_message_peek_type(m, &t, &c);
5809 if (type != 0 && type != t)
5812 if (contents && !streq_ptr(contents, c))
5818 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5819 assert_return(m, NULL);
5824 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5825 _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5833 switch ((*m)->header->type) {
5835 case SD_BUS_MESSAGE_SIGNAL:
5836 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5842 case SD_BUS_MESSAGE_METHOD_CALL:
5843 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5849 case SD_BUS_MESSAGE_METHOD_RETURN:
5850 case SD_BUS_MESSAGE_METHOD_ERROR:
5852 n = message_new(bus, (*m)->header->type);
5856 n->reply_cookie = (*m)->reply_cookie;
5858 r = message_append_reply_cookie(n, n->reply_cookie);
5862 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5863 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5867 n->error._need_free = -1;
5876 if ((*m)->destination && !n->destination) {
5877 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5882 if ((*m)->sender && !n->sender) {
5883 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5888 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5890 r = sd_bus_message_copy(n, *m, true);
5894 timeout = (*m)->timeout;
5895 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5896 timeout = BUS_DEFAULT_TIMEOUT;
5898 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5902 sd_bus_message_unref(*m);
5909 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5913 assert_return(!m->sealed, -EPERM);
5914 assert_return(!m->sender, -EPERM);
5916 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5919 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5920 assert_return(m, -EINVAL);
5921 assert_return(priority, -EINVAL);
5923 *priority = m->priority;
5927 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5928 assert_return(m, -EINVAL);
5929 assert_return(!m->sealed, -EPERM);
5931 m->priority = priority;