1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include "time-util.h"
30 #include "memfd-util.h"
33 #include "bus-message.h"
34 #include "bus-internal.h"
36 #include "bus-signature.h"
37 #include "bus-gvariant.h"
40 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
42 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
47 if (old_base == new_base)
50 if ((uint8_t*) p < (uint8_t*) old_base)
53 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
56 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
59 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
63 if (part->memfd >= 0) {
64 /* If we can reuse the memfd, try that. For that it
65 * can't be sealed yet. */
68 assert(part->memfd_offset == 0);
69 assert(part->data == part->mmap_begin);
70 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
73 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
75 safe_close(part->memfd);
78 } else if (part->munmap_this)
79 munmap(part->mmap_begin, part->mapped);
80 else if (part->free_this)
87 static void message_reset_parts(sd_bus_message *m) {
88 struct bus_body_part *part;
93 while (m->n_body_parts > 0) {
94 struct bus_body_part *next = part->next;
95 message_free_part(m, part);
102 m->cached_rindex_part = NULL;
103 m->cached_rindex_part_begin = 0;
106 static void message_reset_containers(sd_bus_message *m) {
111 for (i = 0; i < m->n_containers; i++) {
112 free(m->containers[i].signature);
113 free(m->containers[i].offsets);
117 m->containers = NULL;
119 m->n_containers = m->containers_allocated = 0;
120 m->root_container.index = 0;
123 static void message_free(sd_bus_message *m) {
129 message_reset_parts(m);
131 if (m->release_kdbus)
132 bus_kernel_cmd_free(m->bus, (uint8_t *) m->kdbus - (uint8_t *) m->bus->kdbus_buffer);
137 sd_bus_unref(m->bus);
140 close_many(m->fds, m->n_fds);
144 if (m->iovec != m->iovec_fixed)
147 m->destination_ptr = mfree(m->destination_ptr);
148 message_reset_containers(m);
149 free(m->root_container.signature);
150 free(m->root_container.offsets);
152 free(m->root_container.peeked_signature);
154 bus_creds_done(&m->creds);
158 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
160 size_t old_size, new_size, start;
167 old_size = sizeof(struct bus_header) + m->fields_size;
168 start = ALIGN_TO(old_size, align);
169 new_size = start + sz;
171 if (new_size < start ||
172 new_size > (size_t) ((uint32_t) -1))
175 if (old_size == new_size)
176 return (uint8_t*) m->header + old_size;
178 if (m->free_header) {
179 np = realloc(m->header, ALIGN8(new_size));
183 /* Initially, the header is allocated as part of of
184 * the sd_bus_message itself, let's replace it by
187 np = malloc(ALIGN8(new_size));
191 memcpy(np, m->header, sizeof(struct bus_header));
194 /* Zero out padding */
195 if (start > old_size)
196 memzero((uint8_t*) np + old_size, start - old_size);
200 m->fields_size = new_size - sizeof(struct bus_header);
202 /* Adjust quick access pointers */
203 m->path = adjust_pointer(m->path, op, old_size, m->header);
204 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
205 m->member = adjust_pointer(m->member, op, old_size, m->header);
206 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
207 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
208 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
210 m->free_header = true;
213 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
216 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
219 return (uint8_t*) np + start;
226 static int message_append_field_string(
238 /* dbus1 only allows 8bit header field ids */
242 /* dbus1 doesn't allow strings over 32bit, let's enforce this
243 * globally, to not risk convertability */
245 if (l > (size_t) (uint32_t) -1)
248 /* Signature "(yv)" where the variant contains "s" */
250 if (BUS_MESSAGE_IS_GVARIANT(m)) {
252 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
253 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
257 *((uint64_t*) p) = h;
264 *ret = (char*) p + 8;
267 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
268 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
277 ((uint32_t*) p)[1] = l;
278 memcpy(p + 8, s, l + 1);
281 *ret = (char*) p + 8;
287 static int message_append_field_signature(
298 /* dbus1 only allows 8bit header field ids */
302 /* dbus1 doesn't allow signatures over 8bit, let's enforce
303 * this globally, to not risk convertability */
308 /* Signature "(yv)" where the variant contains "g" */
310 if (BUS_MESSAGE_IS_GVARIANT(m))
311 /* For gvariant the serialization is the same as for normal strings */
312 return message_append_field_string(m, h, 'g', s, ret);
314 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
315 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
321 p[2] = SD_BUS_TYPE_SIGNATURE;
324 memcpy(p + 5, s, l + 1);
327 *ret = (const char*) p + 5;
333 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
338 /* dbus1 only allows 8bit header field ids */
342 if (BUS_MESSAGE_IS_GVARIANT(m)) {
343 /* (field id 64bit + ((value + NUL + signature string 'u') */
345 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
349 *((uint64_t*) p) = h;
350 *((uint32_t*) (p + 8)) = x;
354 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
355 p = message_extend_fields(m, 8, 4 + 4, false);
364 ((uint32_t*) p)[1] = x;
370 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
375 /* dbus1 only allows 8bit header field ids */
379 if (BUS_MESSAGE_IS_GVARIANT(m)) {
380 /* (field id 64bit + ((value + NUL + signature string 't') */
382 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
386 *((uint64_t*) p) = h;
387 *((uint64_t*) (p + 8)) = x;
391 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
392 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
405 ((uint64_t*) p)[1] = x;
411 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
414 if (BUS_MESSAGE_IS_GVARIANT(m))
415 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
417 /* 64bit cookies are not supported on dbus1 */
418 if (cookie > 0xffffffffUL)
421 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
425 int bus_message_from_header(
428 size_t header_accessible,
430 size_t footer_accessible,
436 sd_bus_message **ret) {
438 _cleanup_free_ sd_bus_message *m = NULL;
439 struct bus_header *h;
443 assert(header || header_accessible <= 0);
444 assert(footer || footer_accessible <= 0);
445 assert(fds || n_fds <= 0);
448 if (header_accessible < sizeof(struct bus_header))
451 if (header_accessible > message_size)
453 if (footer_accessible > message_size)
457 if (!IN_SET(h->version, 1, 2))
460 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
463 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
466 /* Note that we are happy with unknown flags in the flags header! */
468 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
471 label_sz = strlen(label);
482 m->header_accessible = header_accessible;
484 m->footer_accessible = footer_accessible;
486 if (BUS_MESSAGE_IS_GVARIANT(m)) {
489 if (h->dbus2.cookie == 0)
492 /* dbus2 derives the sizes from the message size and
493 the offset table at the end, since it is formatted as
494 gvariant "yyyyuta{tv}v". Since the message itself is a
495 structure with precisely to variable sized entries,
496 there's only one offset in the table, which marks the
497 end of the fields array. */
499 ws = bus_gvariant_determine_word_size(message_size, 0);
500 if (footer_accessible < ws)
503 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
504 if (ALIGN8(m->fields_size) > message_size - ws)
506 if (m->fields_size < sizeof(struct bus_header))
509 m->fields_size -= sizeof(struct bus_header);
510 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
512 if (h->dbus1.serial == 0)
515 /* dbus1 has the sizes in the header */
516 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
517 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
519 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
527 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
528 memcpy(m->creds.label, label, label_sz + 1);
530 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
533 m->bus = sd_bus_ref(bus);
540 int bus_message_from_malloc(
547 sd_bus_message **ret) {
553 r = bus_message_from_header(
555 buffer, length, /* in this case the initial bytes and the final bytes are the same */
564 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
567 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
569 m->body.sealed = true;
574 m->iovec = m->iovec_fixed;
575 m->iovec[0].iov_base = buffer;
576 m->iovec[0].iov_len = length;
578 r = bus_message_parse_fields(m);
582 /* We take possession of the memory and fds now */
583 m->free_header = true;
594 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
599 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
604 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
605 m->header->endian = BUS_NATIVE_ENDIAN;
606 m->header->type = type;
607 m->header->version = bus->message_version;
608 m->allow_fds = bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
609 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
610 m->bus = sd_bus_ref(bus);
612 if (bus->allow_interactive_authorization)
613 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
618 _public_ int sd_bus_message_new_signal(
622 const char *interface,
623 const char *member) {
628 assert_return(bus, -ENOTCONN);
629 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
630 assert_return(object_path_is_valid(path), -EINVAL);
631 assert_return(interface_name_is_valid(interface), -EINVAL);
632 assert_return(member_name_is_valid(member), -EINVAL);
633 assert_return(m, -EINVAL);
635 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
639 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
641 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
644 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
647 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
655 sd_bus_message_unref(t);
659 _public_ int sd_bus_message_new_method_call(
662 const char *destination,
664 const char *interface,
665 const char *member) {
670 assert_return(bus, -ENOTCONN);
671 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
672 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
673 assert_return(object_path_is_valid(path), -EINVAL);
674 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
675 assert_return(member_name_is_valid(member), -EINVAL);
676 assert_return(m, -EINVAL);
678 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
682 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
685 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
690 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
696 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
709 static int message_new_reply(
710 sd_bus_message *call,
712 sd_bus_message **m) {
717 assert_return(call, -EINVAL);
718 assert_return(call->sealed, -EPERM);
719 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
720 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
721 assert_return(m, -EINVAL);
723 t = message_new(call->bus, type);
727 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
728 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
729 if (t->reply_cookie == 0)
732 r = message_append_reply_cookie(t, t->reply_cookie);
737 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
742 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
743 t->enforced_reply_signature = call->enforced_reply_signature;
753 _public_ int sd_bus_message_new_method_return(
754 sd_bus_message *call,
755 sd_bus_message **m) {
757 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
760 _public_ int sd_bus_message_new_method_error(
761 sd_bus_message *call,
763 const sd_bus_error *e) {
768 assert_return(sd_bus_error_is_set(e), -EINVAL);
769 assert_return(m, -EINVAL);
771 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
775 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
780 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
785 t->error._need_free = -1;
795 _public_ int sd_bus_message_new_method_errorf(
796 sd_bus_message *call,
802 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
805 assert_return(name, -EINVAL);
806 assert_return(m, -EINVAL);
808 va_start(ap, format);
809 bus_error_setfv(&error, name, format, ap);
812 return sd_bus_message_new_method_error(call, m, &error);
815 _public_ int sd_bus_message_new_method_errno(
816 sd_bus_message *call,
819 const sd_bus_error *p) {
821 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
823 if (sd_bus_error_is_set(p))
824 return sd_bus_message_new_method_error(call, m, p);
826 sd_bus_error_set_errno(&berror, error);
828 return sd_bus_message_new_method_error(call, m, &berror);
831 /// UNNEEDED by elogind
833 _public_ int sd_bus_message_new_method_errnof(
834 sd_bus_message *call,
840 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
843 va_start(ap, format);
844 sd_bus_error_set_errnofv(&berror, error, format, ap);
847 return sd_bus_message_new_method_error(call, m, &berror);
851 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
855 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
856 m->creds.well_known_names_local = true;
857 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
860 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
864 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
865 m->creds.well_known_names_driver = true;
866 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
869 int bus_message_new_synthetic_error(
872 const sd_bus_error *e,
873 sd_bus_message **m) {
879 assert(sd_bus_error_is_set(e));
882 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
886 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
887 t->reply_cookie = cookie;
889 r = message_append_reply_cookie(t, t->reply_cookie);
893 if (bus && bus->unique_name) {
894 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
899 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
904 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
909 t->error._need_free = -1;
911 bus_message_set_sender_driver(bus, t);
921 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
922 assert_return(m, NULL);
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 /// UNNEEDED by elogind
947 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
948 assert_return(m, -EINVAL);
949 assert_return(type, -EINVAL);
951 *type = m->header->type;
955 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
958 assert_return(m, -EINVAL);
959 assert_return(cookie, -EINVAL);
961 c = BUS_MESSAGE_COOKIE(m);
965 *cookie = BUS_MESSAGE_COOKIE(m);
969 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
970 assert_return(m, -EINVAL);
971 assert_return(cookie, -EINVAL);
973 if (m->reply_cookie == 0)
976 *cookie = m->reply_cookie;
980 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
981 assert_return(m, -EINVAL);
983 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
984 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
987 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
988 assert_return(m, -EINVAL);
990 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
994 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
995 assert_return(m, -EINVAL);
997 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
998 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
1001 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1002 assert_return(m, NULL);
1007 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1008 assert_return(m, NULL);
1010 return m->interface;
1013 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1014 assert_return(m, NULL);
1019 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1020 assert_return(m, NULL);
1022 return m->destination;
1025 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1026 assert_return(m, NULL);
1031 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1032 assert_return(m, NULL);
1033 assert_return(sd_bus_error_is_set(&m->error), NULL);
1038 /// UNNEEDED by elogind
1040 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1041 assert_return(m, -EINVAL);
1042 assert_return(usec, -EINVAL);
1044 if (m->monotonic <= 0)
1047 *usec = m->monotonic;
1051 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1052 assert_return(m, -EINVAL);
1053 assert_return(usec, -EINVAL);
1055 if (m->realtime <= 0)
1058 *usec = m->realtime;
1062 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1063 assert_return(m, -EINVAL);
1064 assert_return(seqnum, -EINVAL);
1069 *seqnum = m->seqnum;
1074 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1075 assert_return(m, NULL);
1077 if (m->creds.mask == 0)
1083 /// UNNEEDED by elogind
1085 _public_ int sd_bus_message_is_signal(
1087 const char *interface,
1088 const char *member) {
1090 assert_return(m, -EINVAL);
1092 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1095 if (interface && (!m->interface || !streq(m->interface, interface)))
1098 if (member && (!m->member || !streq(m->member, member)))
1105 _public_ int sd_bus_message_is_method_call(
1107 const char *interface,
1108 const char *member) {
1110 assert_return(m, -EINVAL);
1112 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1115 if (interface && (!m->interface || !streq(m->interface, interface)))
1118 if (member && (!m->member || !streq(m->member, member)))
1124 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1125 assert_return(m, -EINVAL);
1127 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1130 if (name && (!m->error.name || !streq(m->error.name, name)))
1136 /// UNNEEDED by elogind
1138 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1139 assert_return(m, -EINVAL);
1140 assert_return(!m->sealed, -EPERM);
1141 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1144 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1146 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1152 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1153 assert_return(m, -EINVAL);
1154 assert_return(!m->sealed, -EPERM);
1157 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1159 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1164 /// UNNEEDED by elogind
1166 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1167 assert_return(m, -EINVAL);
1168 assert_return(!m->sealed, -EPERM);
1171 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1173 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1179 static struct bus_container *message_get_container(sd_bus_message *m) {
1182 if (m->n_containers == 0)
1183 return &m->root_container;
1185 assert(m->containers);
1186 return m->containers + m->n_containers - 1;
1189 struct bus_body_part *message_append_part(sd_bus_message *m) {
1190 struct bus_body_part *part;
1197 if (m->n_body_parts <= 0) {
1201 assert(m->body_end);
1203 part = new0(struct bus_body_part, 1);
1209 m->body_end->next = part;
1219 static void part_zero(struct bus_body_part *part, size_t sz) {
1224 /* All other fields can be left in their defaults */
1225 assert(!part->data);
1226 assert(part->memfd < 0);
1229 part->is_zero = true;
1230 part->sealed = true;
1233 static int part_make_space(
1234 struct sd_bus_message *m,
1235 struct bus_body_part *part,
1244 assert(!part->sealed);
1249 if (!part->data && part->memfd < 0) {
1250 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1251 part->mmap_begin = part->data;
1254 if (part->memfd >= 0) {
1256 if (part->allocated == 0 || sz > part->allocated) {
1257 uint64_t new_allocated;
1259 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1260 r = memfd_set_size(part->memfd, new_allocated);
1266 part->allocated = new_allocated;
1269 if (!part->data || sz > part->mapped) {
1272 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1273 if (part->mapped <= 0)
1274 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1276 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1278 if (n == MAP_FAILED) {
1283 part->mmap_begin = part->data = n;
1285 part->memfd_offset = 0;
1288 part->munmap_this = true;
1290 if (part->allocated == 0 || sz > part->allocated) {
1291 size_t new_allocated;
1293 new_allocated = sz > 0 ? 2 * sz : 64;
1294 n = realloc(part->data, new_allocated);
1301 part->allocated = new_allocated;
1302 part->free_this = true;
1307 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1313 static int message_add_offset(sd_bus_message *m, size_t offset) {
1314 struct bus_container *c;
1317 assert(BUS_MESSAGE_IS_GVARIANT(m));
1319 /* Add offset to current container, unless this is the first
1320 * item in it, which will have the 0 offset, which we can
1322 c = message_get_container(m);
1324 if (!c->need_offsets)
1327 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1330 c->offsets[c->n_offsets++] = offset;
1334 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1335 struct bus_container *c;
1342 /* Update counters */
1343 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1346 *c->array_size += expand;
1350 static void *message_extend_body(
1355 bool force_inline) {
1357 size_t start_body, end_body, padding, added;
1368 start_body = ALIGN_TO((size_t) m->body_size, align);
1369 end_body = start_body + sz;
1371 padding = start_body - m->body_size;
1372 added = padding + sz;
1374 /* Check for 32bit overflows */
1375 if (end_body > (size_t) ((uint32_t) -1) ||
1376 end_body < start_body) {
1382 struct bus_body_part *part = NULL;
1386 m->n_body_parts <= 0 ||
1387 m->body_end->sealed ||
1388 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1389 (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 */
1393 part = message_append_part(m);
1397 part_zero(part, padding);
1400 part = message_append_part(m);
1404 r = part_make_space(m, part, sz, &p);
1408 struct bus_container *c;
1410 size_t os, start_part, end_part;
1416 start_part = ALIGN_TO(part->size, align);
1417 end_part = start_part + sz;
1419 r = part_make_space(m, part, end_part, &p);
1424 memzero(p, padding);
1425 p = (uint8_t*) p + padding;
1428 /* Readjust pointers */
1429 for (c = m->containers; c < m->containers + m->n_containers; c++)
1430 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1432 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1435 /* Return something that is not NULL and is aligned */
1436 p = (uint8_t *) NULL + align;
1438 m->body_size = end_body;
1439 message_extend_containers(m, added);
1442 r = message_add_offset(m, end_body);
1452 static int message_push_fd(sd_bus_message *m, int fd) {
1463 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1467 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1475 m->fds[m->n_fds] = copy;
1481 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1482 _cleanup_close_ int fd = -1;
1483 struct bus_container *c;
1487 assert_return(m, -EINVAL);
1488 assert_return(!m->sealed, -EPERM);
1489 assert_return(bus_type_is_basic(type), -EINVAL);
1490 assert_return(!m->poisoned, -ESTALE);
1492 c = message_get_container(m);
1494 if (c->signature && c->signature[c->index]) {
1495 /* Container signature is already set */
1497 if (c->signature[c->index] != type)
1502 /* Maybe we can append to the signature? But only if this is the top-level container */
1503 if (c->enclosing != 0)
1506 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1513 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1519 case SD_BUS_TYPE_SIGNATURE:
1520 case SD_BUS_TYPE_STRING:
1523 /* Fall through... */
1524 case SD_BUS_TYPE_OBJECT_PATH:
1532 case SD_BUS_TYPE_BOOLEAN:
1534 u8 = p && *(int*) p;
1540 case SD_BUS_TYPE_UNIX_FD:
1545 fd = message_push_fd(m, *(int*) p);
1556 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1557 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1564 a = message_extend_body(m, align, sz, true, false);
1571 *stored = (const uint8_t*) a;
1578 case SD_BUS_TYPE_STRING:
1579 /* To make things easy we'll serialize a NULL string
1580 * into the empty string */
1583 /* Fall through... */
1584 case SD_BUS_TYPE_OBJECT_PATH:
1590 sz = 4 + strlen(p) + 1;
1593 case SD_BUS_TYPE_SIGNATURE:
1598 sz = 1 + strlen(p) + 1;
1601 case SD_BUS_TYPE_BOOLEAN:
1603 u32 = p && *(int*) p;
1609 case SD_BUS_TYPE_UNIX_FD:
1614 fd = message_push_fd(m, *(int*) p);
1625 align = bus_type_get_alignment(type);
1626 sz = bus_type_get_size(type);
1633 a = message_extend_body(m, align, sz, false, false);
1637 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1638 *(uint32_t*) a = sz - 5;
1639 memcpy((uint8_t*) a + 4, p, sz - 4);
1642 *stored = (const uint8_t*) a + 4;
1644 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1645 *(uint8_t*) a = sz - 2;
1646 memcpy((uint8_t*) a + 1, p, sz - 1);
1649 *stored = (const uint8_t*) a + 1;
1658 if (type == SD_BUS_TYPE_UNIX_FD)
1661 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1668 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1669 return message_append_basic(m, type, p, NULL);
1672 _public_ int sd_bus_message_append_string_space(
1677 struct bus_container *c;
1680 assert_return(m, -EINVAL);
1681 assert_return(s, -EINVAL);
1682 assert_return(!m->sealed, -EPERM);
1683 assert_return(!m->poisoned, -ESTALE);
1685 c = message_get_container(m);
1687 if (c->signature && c->signature[c->index]) {
1688 /* Container signature is already set */
1690 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1695 /* Maybe we can append to the signature? But only if this is the top-level container */
1696 if (c->enclosing != 0)
1699 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1706 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1707 a = message_extend_body(m, 1, size + 1, true, false);
1713 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1717 *(uint32_t*) a = size;
1723 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1729 /// UNNEEDED by elogind
1731 _public_ int sd_bus_message_append_string_iovec(
1733 const struct iovec *iov,
1741 assert_return(m, -EINVAL);
1742 assert_return(!m->sealed, -EPERM);
1743 assert_return(iov || n == 0, -EINVAL);
1744 assert_return(!m->poisoned, -ESTALE);
1746 size = IOVEC_TOTAL_SIZE(iov, n);
1748 r = sd_bus_message_append_string_space(m, size, &p);
1752 for (i = 0; i < n; i++) {
1754 if (iov[i].iov_base)
1755 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1757 memset(p, ' ', iov[i].iov_len);
1759 p += iov[i].iov_len;
1766 static int bus_message_open_array(
1768 struct bus_container *c,
1769 const char *contents,
1770 uint32_t **array_size,
1772 bool *need_offsets) {
1782 assert(need_offsets);
1784 if (!signature_is_single(contents, true))
1787 if (c->signature && c->signature[c->index]) {
1789 /* Verify the existing signature */
1791 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1794 if (!startswith(c->signature + c->index + 1, contents))
1797 nindex = c->index + 1 + strlen(contents);
1801 if (c->enclosing != 0)
1804 /* Extend the existing signature */
1806 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1812 nindex = e - c->signature;
1815 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1816 alignment = bus_gvariant_get_alignment(contents);
1820 /* Add alignment padding and add to offset list */
1821 if (!message_extend_body(m, alignment, 0, false, false))
1824 r = bus_gvariant_is_fixed_size(contents);
1828 *begin = m->body_size;
1829 *need_offsets = r == 0;
1833 struct bus_body_part *o;
1835 alignment = bus_type_get_alignment(contents[0]);
1839 a = message_extend_body(m, 4, 4, false, false);
1844 op = m->body_end->data;
1845 os = m->body_end->size;
1847 /* Add alignment between size and first element */
1848 if (!message_extend_body(m, alignment, 0, false, false))
1851 /* location of array size might have changed so let's readjust a */
1852 if (o == m->body_end)
1853 a = adjust_pointer(a, op, os, m->body_end->data);
1859 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1865 static int bus_message_open_variant(
1867 struct bus_container *c,
1868 const char *contents) {
1874 if (!signature_is_single(contents, false))
1877 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1880 if (c->signature && c->signature[c->index]) {
1882 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1888 if (c->enclosing != 0)
1891 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1898 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1899 /* Variants are always aligned to 8 */
1901 if (!message_extend_body(m, 8, 0, false, false))
1908 l = strlen(contents);
1909 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1914 memcpy((uint8_t*) a + 1, contents, l + 1);
1917 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1923 static int bus_message_open_struct(
1925 struct bus_container *c,
1926 const char *contents,
1928 bool *need_offsets) {
1937 assert(need_offsets);
1939 if (!signature_is_valid(contents, false))
1942 if (c->signature && c->signature[c->index]) {
1945 l = strlen(contents);
1947 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1948 !startswith(c->signature + c->index + 1, contents) ||
1949 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1952 nindex = c->index + 1 + l + 1;
1956 if (c->enclosing != 0)
1959 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1965 nindex = e - c->signature;
1968 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1971 alignment = bus_gvariant_get_alignment(contents);
1975 if (!message_extend_body(m, alignment, 0, false, false))
1978 r = bus_gvariant_is_fixed_size(contents);
1982 *begin = m->body_size;
1983 *need_offsets = r == 0;
1985 /* Align contents to 8 byte boundary */
1986 if (!message_extend_body(m, 8, 0, false, false))
1990 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1996 static int bus_message_open_dict_entry(
1998 struct bus_container *c,
1999 const char *contents,
2001 bool *need_offsets) {
2009 assert(need_offsets);
2011 if (!signature_is_pair(contents))
2014 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2017 if (c->signature && c->signature[c->index]) {
2020 l = strlen(contents);
2022 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2023 !startswith(c->signature + c->index + 1, contents) ||
2024 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2029 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2032 alignment = bus_gvariant_get_alignment(contents);
2036 if (!message_extend_body(m, alignment, 0, false, false))
2039 r = bus_gvariant_is_fixed_size(contents);
2043 *begin = m->body_size;
2044 *need_offsets = r == 0;
2046 /* Align contents to 8 byte boundary */
2047 if (!message_extend_body(m, 8, 0, false, false))
2054 _public_ int sd_bus_message_open_container(
2057 const char *contents) {
2059 struct bus_container *c, *w;
2060 uint32_t *array_size = NULL;
2062 size_t before, begin = 0;
2063 bool need_offsets = false;
2066 assert_return(m, -EINVAL);
2067 assert_return(!m->sealed, -EPERM);
2068 assert_return(contents, -EINVAL);
2069 assert_return(!m->poisoned, -ESTALE);
2071 /* Make sure we have space for one more container */
2072 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2077 c = message_get_container(m);
2079 signature = strdup(contents);
2085 /* Save old index in the parent container, in case we have to
2086 * abort this container */
2087 c->saved_index = c->index;
2088 before = m->body_size;
2090 if (type == SD_BUS_TYPE_ARRAY)
2091 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2092 else if (type == SD_BUS_TYPE_VARIANT)
2093 r = bus_message_open_variant(m, c, contents);
2094 else if (type == SD_BUS_TYPE_STRUCT)
2095 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2096 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2097 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2106 /* OK, let's fill it in */
2107 w = m->containers + m->n_containers++;
2108 w->enclosing = type;
2109 w->signature = signature;
2111 w->array_size = array_size;
2114 w->n_offsets = w->offsets_allocated = 0;
2116 w->need_offsets = need_offsets;
2121 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2126 if (!BUS_MESSAGE_IS_GVARIANT(m))
2129 if (c->need_offsets) {
2130 size_t payload, sz, i;
2133 /* Variable-width arrays */
2135 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2136 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2138 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2142 for (i = 0; i < c->n_offsets; i++)
2143 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2147 /* Fixed-width or empty arrays */
2149 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2157 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2163 assert(c->signature);
2165 if (!BUS_MESSAGE_IS_GVARIANT(m))
2168 l = strlen(c->signature);
2170 a = message_extend_body(m, 1, 1 + l, true, false);
2175 memcpy(a+1, c->signature, l);
2180 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2181 bool fixed_size = true;
2182 size_t n_variable = 0;
2191 if (!BUS_MESSAGE_IS_GVARIANT(m))
2194 p = strempty(c->signature);
2198 r = signature_element_length(p, &n);
2207 r = bus_gvariant_is_fixed_size(t);
2212 assert(!c->need_offsets || i <= c->n_offsets);
2214 /* We need to add an offset for each item that has a
2215 * variable size and that is not the last one in the
2219 if (r == 0 && p[n] != 0)
2226 assert(!c->need_offsets || i == c->n_offsets);
2227 assert(c->need_offsets || n_variable == 0);
2229 if (isempty(c->signature)) {
2230 /* The unary type is encoded as fixed 1 byte padding */
2231 a = message_extend_body(m, 1, 1, add_offset, false);
2236 } else if (n_variable <= 0) {
2239 /* Structures with fixed-size members only have to be
2240 * fixed-size themselves. But gvariant requires all fixed-size
2241 * elements to be sized a multiple of their alignment. Hence,
2242 * we must *always* add final padding after the last member so
2243 * the overall size of the structure is properly aligned. */
2245 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2247 assert(alignment > 0);
2249 a = message_extend_body(m, alignment, 0, add_offset, false);
2256 assert(c->offsets[c->n_offsets-1] == m->body_size);
2258 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2260 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2264 p = strempty(c->signature);
2265 for (i = 0, j = 0; i < c->n_offsets; i++) {
2269 r = signature_element_length(p, &n);
2280 r = bus_gvariant_is_fixed_size(t);
2283 if (r > 0 || p[0] == 0)
2287 k = n_variable - 1 - j;
2289 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2298 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2299 struct bus_container *c;
2302 assert_return(m, -EINVAL);
2303 assert_return(!m->sealed, -EPERM);
2304 assert_return(m->n_containers > 0, -EINVAL);
2305 assert_return(!m->poisoned, -ESTALE);
2307 c = message_get_container(m);
2309 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2310 if (c->signature && c->signature[c->index] != 0)
2315 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2316 r = bus_message_close_array(m, c);
2317 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2318 r = bus_message_close_variant(m, c);
2319 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2320 r = bus_message_close_struct(m, c, true);
2322 assert_not_reached("Unknown container type");
2336 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2343 stack[*i].types = types;
2344 stack[*i].n_struct = n_struct;
2345 stack[*i].n_array = n_array;
2351 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2362 *types = stack[*i].types;
2363 *n_struct = stack[*i].n_struct;
2364 *n_array = stack[*i].n_array;
2369 int bus_message_append_ap(
2374 unsigned n_array, n_struct;
2375 TypeStack stack[BUS_CONTAINER_DEPTH];
2376 unsigned stack_ptr = 0;
2384 n_array = (unsigned) -1;
2385 n_struct = strlen(types);
2390 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2391 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2397 r = sd_bus_message_close_container(m);
2405 if (n_array != (unsigned) -1)
2414 case SD_BUS_TYPE_BYTE: {
2417 x = (uint8_t) va_arg(ap, int);
2418 r = sd_bus_message_append_basic(m, *t, &x);
2422 case SD_BUS_TYPE_BOOLEAN:
2423 case SD_BUS_TYPE_INT32:
2424 case SD_BUS_TYPE_UINT32:
2425 case SD_BUS_TYPE_UNIX_FD: {
2428 /* We assume a boolean is the same as int32_t */
2429 assert_cc(sizeof(int32_t) == sizeof(int));
2431 x = va_arg(ap, uint32_t);
2432 r = sd_bus_message_append_basic(m, *t, &x);
2436 case SD_BUS_TYPE_INT16:
2437 case SD_BUS_TYPE_UINT16: {
2440 x = (uint16_t) va_arg(ap, int);
2441 r = sd_bus_message_append_basic(m, *t, &x);
2445 case SD_BUS_TYPE_INT64:
2446 case SD_BUS_TYPE_UINT64: {
2449 x = va_arg(ap, uint64_t);
2450 r = sd_bus_message_append_basic(m, *t, &x);
2454 case SD_BUS_TYPE_DOUBLE: {
2457 x = va_arg(ap, double);
2458 r = sd_bus_message_append_basic(m, *t, &x);
2462 case SD_BUS_TYPE_STRING:
2463 case SD_BUS_TYPE_OBJECT_PATH:
2464 case SD_BUS_TYPE_SIGNATURE: {
2467 x = va_arg(ap, const char*);
2468 r = sd_bus_message_append_basic(m, *t, x);
2472 case SD_BUS_TYPE_ARRAY: {
2475 r = signature_element_length(t + 1, &k);
2481 memcpy(s, t + 1, k);
2484 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2489 if (n_array == (unsigned) -1) {
2494 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2500 n_array = va_arg(ap, unsigned);
2505 case SD_BUS_TYPE_VARIANT: {
2508 s = va_arg(ap, const char*);
2512 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2516 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2521 n_struct = strlen(s);
2522 n_array = (unsigned) -1;
2527 case SD_BUS_TYPE_STRUCT_BEGIN:
2528 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2531 r = signature_element_length(t, &k);
2538 memcpy(s, t + 1, k - 2);
2541 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2546 if (n_array == (unsigned) -1) {
2551 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2557 n_array = (unsigned) -1;
2573 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2577 assert_return(m, -EINVAL);
2578 assert_return(types, -EINVAL);
2579 assert_return(!m->sealed, -EPERM);
2580 assert_return(!m->poisoned, -ESTALE);
2582 va_start(ap, types);
2583 r = bus_message_append_ap(m, types, ap);
2589 _public_ int sd_bus_message_append_array_space(
2599 assert_return(m, -EINVAL);
2600 assert_return(!m->sealed, -EPERM);
2601 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2602 assert_return(ptr || size == 0, -EINVAL);
2603 assert_return(!m->poisoned, -ESTALE);
2605 /* alignment and size of the trivial types (except bool) is
2606 * identical for gvariant and dbus1 marshalling */
2607 align = bus_type_get_alignment(type);
2608 sz = bus_type_get_size(type);
2610 assert_se(align > 0);
2616 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2620 a = message_extend_body(m, align, size, false, false);
2624 r = sd_bus_message_close_container(m);
2632 _public_ int sd_bus_message_append_array(
2640 assert_return(m, -EINVAL);
2641 assert_return(!m->sealed, -EPERM);
2642 assert_return(bus_type_is_trivial(type), -EINVAL);
2643 assert_return(ptr || size == 0, -EINVAL);
2644 assert_return(!m->poisoned, -ESTALE);
2646 r = sd_bus_message_append_array_space(m, type, size, &p);
2651 memcpy(p, ptr, size);
2656 /// UNNEEDED by elogind
2658 _public_ int sd_bus_message_append_array_iovec(
2661 const struct iovec *iov,
2669 assert_return(m, -EINVAL);
2670 assert_return(!m->sealed, -EPERM);
2671 assert_return(bus_type_is_trivial(type), -EINVAL);
2672 assert_return(iov || n == 0, -EINVAL);
2673 assert_return(!m->poisoned, -ESTALE);
2675 size = IOVEC_TOTAL_SIZE(iov, n);
2677 r = sd_bus_message_append_array_space(m, type, size, &p);
2681 for (i = 0; i < n; i++) {
2683 if (iov[i].iov_base)
2684 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2686 memzero(p, iov[i].iov_len);
2688 p = (uint8_t*) p + iov[i].iov_len;
2694 _public_ int sd_bus_message_append_array_memfd(
2701 _cleanup_close_ int copy_fd = -1;
2702 struct bus_body_part *part;
2708 assert_return(m, -EINVAL);
2709 assert_return(memfd >= 0, -EINVAL);
2710 assert_return(bus_type_is_trivial(type), -EINVAL);
2711 assert_return(size > 0, -EINVAL);
2712 assert_return(!m->sealed, -EPERM);
2713 assert_return(!m->poisoned, -ESTALE);
2715 r = memfd_set_sealed(memfd);
2719 copy_fd = dup(memfd);
2723 r = memfd_get_size(memfd, &real_size);
2727 if (offset == 0 && size == (uint64_t) -1)
2729 else if (offset + size > real_size)
2732 align = bus_type_get_alignment(type);
2733 sz = bus_type_get_size(type);
2735 assert_se(align > 0);
2738 if (offset % align != 0)
2744 if (size > (uint64_t) (uint32_t) -1)
2747 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2751 a = message_extend_body(m, align, 0, false, false);
2755 part = message_append_part(m);
2759 part->memfd = copy_fd;
2760 part->memfd_offset = offset;
2761 part->sealed = true;
2765 m->body_size += size;
2766 message_extend_containers(m, size);
2768 return sd_bus_message_close_container(m);
2771 _public_ int sd_bus_message_append_string_memfd(
2777 _cleanup_close_ int copy_fd = -1;
2778 struct bus_body_part *part;
2779 struct bus_container *c;
2784 assert_return(m, -EINVAL);
2785 assert_return(memfd >= 0, -EINVAL);
2786 assert_return(size > 0, -EINVAL);
2787 assert_return(!m->sealed, -EPERM);
2788 assert_return(!m->poisoned, -ESTALE);
2790 r = memfd_set_sealed(memfd);
2794 copy_fd = dup(memfd);
2798 r = memfd_get_size(memfd, &real_size);
2802 if (offset == 0 && size == (uint64_t) -1)
2804 else if (offset + size > real_size)
2807 /* We require this to be NUL terminated */
2811 if (size > (uint64_t) (uint32_t) -1)
2814 c = message_get_container(m);
2815 if (c->signature && c->signature[c->index]) {
2816 /* Container signature is already set */
2818 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2823 /* Maybe we can append to the signature? But only if this is the top-level container */
2824 if (c->enclosing != 0)
2827 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2834 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2835 a = message_extend_body(m, 4, 4, false, false);
2839 *(uint32_t*) a = size - 1;
2842 part = message_append_part(m);
2846 part->memfd = copy_fd;
2847 part->memfd_offset = offset;
2848 part->sealed = true;
2852 m->body_size += size;
2853 message_extend_containers(m, size);
2855 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2856 r = message_add_offset(m, m->body_size);
2863 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2870 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2874 assert_return(m, -EINVAL);
2875 assert_return(!m->sealed, -EPERM);
2876 assert_return(!m->poisoned, -ESTALE);
2878 r = sd_bus_message_open_container(m, 'a', "s");
2882 STRV_FOREACH(i, l) {
2883 r = sd_bus_message_append_basic(m, 's', *i);
2888 return sd_bus_message_close_container(m);
2891 static int bus_message_close_header(sd_bus_message *m) {
2895 /* The actual user data is finished now, we just complete the
2896 variant and struct now (at least on gvariant). Remember
2897 this position, so that during parsing we know where to to
2898 put the outer container end. */
2899 m->user_body_size = m->body_size;
2901 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2902 const char *signature;
2906 /* Add offset table to end of fields array */
2907 if (m->n_header_offsets >= 1) {
2911 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2913 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2914 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2918 for (i = 0; i < m->n_header_offsets; i++)
2919 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2922 /* Add gvariant NUL byte plus signature to the end of
2923 * the body, followed by the final offset pointing to
2924 * the end of the fields array */
2926 signature = strempty(m->root_container.signature);
2927 l = strlen(signature);
2929 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2930 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2935 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2936 memcpy((uint8_t*) d + 2, signature, l);
2937 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2939 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2942 m->footer_accessible = 1 + l + 2 + sz;
2944 m->header->dbus1.fields_size = m->fields_size;
2945 m->header->dbus1.body_size = m->body_size;
2951 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2952 struct bus_body_part *part;
2962 if (m->n_containers > 0)
2968 if (cookie > 0xffffffffULL &&
2969 !BUS_MESSAGE_IS_GVARIANT(m))
2972 /* In vtables the return signature of method calls is listed,
2973 * let's check if they match if this is a response */
2974 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2975 m->enforced_reply_signature &&
2976 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2979 /* If gvariant marshalling is used we need to close the body structure */
2980 r = bus_message_close_struct(m, &m->root_container, false);
2984 /* If there's a non-trivial signature set, then add it in
2985 * here, but only on dbus1 */
2986 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2987 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2993 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2998 r = bus_message_close_header(m);
3002 if (BUS_MESSAGE_IS_GVARIANT(m))
3003 m->header->dbus2.cookie = cookie;
3005 m->header->dbus1.serial = (uint32_t) cookie;
3007 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
3009 /* Add padding at the end of the fields part, since we know
3010 * the body needs to start at an 8 byte alignment. We made
3011 * sure we allocated enough space for this, so all we need to
3012 * do here is to zero it out. */
3013 a = ALIGN8(m->fields_size) - m->fields_size;
3015 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
3017 /* If this is something we can send as memfd, then let's seal
3018 the memfd now. Note that we can send memfds as payload only
3019 for directed messages, and not for broadcasts. */
3020 if (m->destination && m->bus->use_memfd) {
3021 MESSAGE_FOREACH_PART(part, i, m)
3022 if (part->memfd >= 0 &&
3024 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3025 part != m->body_end) { /* The last part may never be sent as memfd */
3028 /* Try to seal it if that makes
3029 * sense. First, unmap our own map to
3030 * make sure we don't keep it busy. */
3031 bus_body_part_unmap(part);
3033 /* Then, sync up real memfd size */
3035 r = memfd_set_size(part->memfd, sz);
3039 /* Finally, try to seal */
3040 if (memfd_set_sealed(part->memfd) >= 0)
3041 part->sealed = true;
3045 m->root_container.end = m->user_body_size;
3046 m->root_container.index = 0;
3047 m->root_container.offset_index = 0;
3048 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3055 int bus_body_part_map(struct bus_body_part *part) {
3064 if (part->size <= 0)
3067 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3068 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3069 static const uint8_t zeroes[7] = { };
3070 part->data = (void*) zeroes;
3074 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3075 psz = PAGE_ALIGN(part->size + shift);
3077 if (part->memfd >= 0)
3078 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3079 else if (part->is_zero)
3080 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3084 if (p == MAP_FAILED)
3088 part->mmap_begin = p;
3089 part->data = (uint8_t*) p + shift;
3090 part->munmap_this = true;
3095 void bus_body_part_unmap(struct bus_body_part *part) {
3099 if (part->memfd < 0)
3102 if (!part->mmap_begin)
3105 if (!part->munmap_this)
3108 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3110 part->mmap_begin = NULL;
3113 part->munmap_this = false;
3118 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3119 size_t k, start, end;
3124 start = ALIGN_TO((size_t) *rindex, align);
3125 end = start + nbytes;
3130 /* Verify that padding is 0 */
3131 for (k = *rindex; k < start; k++)
3132 if (((const uint8_t*) p)[k] != 0)
3136 *r = (uint8_t*) p + start;
3143 static bool message_end_of_signature(sd_bus_message *m) {
3144 struct bus_container *c;
3148 c = message_get_container(m);
3149 return !c->signature || c->signature[c->index] == 0;
3152 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3153 struct bus_container *c;
3157 c = message_get_container(m);
3158 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3161 if (BUS_MESSAGE_IS_GVARIANT(m))
3162 return index >= c->end;
3164 assert(c->array_size);
3165 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3169 /// UNNEEDED by elogind
3171 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3172 assert_return(m, -EINVAL);
3173 assert_return(m->sealed, -EPERM);
3175 if (complete && m->n_containers > 0)
3178 if (message_end_of_signature(m))
3181 if (message_end_of_array(m, m->rindex))
3188 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3189 struct bus_body_part *part;
3195 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3196 part = m->cached_rindex_part;
3197 begin = m->cached_rindex_part_begin;
3207 if (index + sz <= begin + part->size) {
3209 r = bus_body_part_map(part);
3214 *p = (uint8_t*) part->data + index - begin;
3216 m->cached_rindex_part = part;
3217 m->cached_rindex_part_begin = begin;
3222 begin += part->size;
3229 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3236 if (!BUS_MESSAGE_IS_GVARIANT(m))
3239 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3242 sz = bus_gvariant_get_size(c->signature);
3246 if (c->offset_index+1 >= c->n_offsets)
3249 /* Variable-size array */
3251 alignment = bus_gvariant_get_alignment(c->signature);
3252 assert(alignment > 0);
3254 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3255 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3258 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3261 /* Fixed-size array */
3262 *rindex = c->begin + (c->offset_index+1) * sz;
3268 } else if (c->enclosing == 0 ||
3269 c->enclosing == SD_BUS_TYPE_STRUCT ||
3270 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3275 if (c->offset_index+1 >= c->n_offsets)
3278 r = signature_element_length(c->signature + c->index, &n);
3282 r = signature_element_length(c->signature + c->index + n, &j);
3287 memcpy(t, c->signature + c->index + n, j);
3290 alignment = bus_gvariant_get_alignment(t);
3293 assert(alignment > 0);
3295 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3296 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3300 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3303 assert_not_reached("Unknown container type");
3308 /* Reached the end */
3315 static int message_peek_body(
3322 size_t k, start, end, padding;
3323 struct bus_body_part *part;
3330 start = ALIGN_TO((size_t) *rindex, align);
3331 padding = start - *rindex;
3332 end = start + nbytes;
3334 if (end > m->user_body_size)
3337 part = find_part(m, *rindex, padding, (void**) &q);
3342 /* Verify padding */
3343 for (k = 0; k < padding; k++)
3348 part = find_part(m, start, nbytes, (void**) &q);
3349 if (!part || (nbytes > 0 && !q))
3360 static bool validate_nul(const char *s, size_t l) {
3362 /* Check for NUL chars in the string */
3363 if (memchr(s, 0, l))
3366 /* Check for NUL termination */
3373 static bool validate_string(const char *s, size_t l) {
3375 if (!validate_nul(s, l))
3378 /* Check if valid UTF8 */
3379 if (!utf8_is_valid(s))
3385 static bool validate_signature(const char *s, size_t l) {
3387 if (!validate_nul(s, l))
3390 /* Check if valid signature */
3391 if (!signature_is_valid(s, true))
3397 static bool validate_object_path(const char *s, size_t l) {
3399 if (!validate_nul(s, l))
3402 if (!object_path_is_valid(s))
3408 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3409 struct bus_container *c;
3414 assert_return(m, -EINVAL);
3415 assert_return(m->sealed, -EPERM);
3416 assert_return(bus_type_is_basic(type), -EINVAL);
3418 if (message_end_of_signature(m))
3421 if (message_end_of_array(m, m->rindex))
3424 c = message_get_container(m);
3425 if (c->signature[c->index] != type)
3430 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3432 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3435 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3439 if (type == SD_BUS_TYPE_STRING)
3440 ok = validate_string(q, c->item_size-1);
3441 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3442 ok = validate_object_path(q, c->item_size-1);
3444 ok = validate_signature(q, c->item_size-1);
3450 *(const char**) p = q;
3454 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3456 if ((size_t) sz != c->item_size)
3459 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3462 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3468 case SD_BUS_TYPE_BYTE:
3470 *(uint8_t*) p = *(uint8_t*) q;
3473 case SD_BUS_TYPE_BOOLEAN:
3475 *(int*) p = !!*(uint8_t*) q;
3478 case SD_BUS_TYPE_INT16:
3479 case SD_BUS_TYPE_UINT16:
3481 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3484 case SD_BUS_TYPE_INT32:
3485 case SD_BUS_TYPE_UINT32:
3487 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3490 case SD_BUS_TYPE_INT64:
3491 case SD_BUS_TYPE_UINT64:
3492 case SD_BUS_TYPE_DOUBLE:
3494 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3497 case SD_BUS_TYPE_UNIX_FD: {
3500 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3505 *(int*) p = m->fds[j];
3511 assert_not_reached("unexpected type");
3515 r = container_next_item(m, c, &rindex);
3520 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3524 r = message_peek_body(m, &rindex, 4, 4, &q);
3528 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3529 r = message_peek_body(m, &rindex, 1, l+1, &q);
3533 if (type == SD_BUS_TYPE_OBJECT_PATH)
3534 ok = validate_object_path(q, l);
3536 ok = validate_string(q, l);
3541 *(const char**) p = q;
3543 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3546 r = message_peek_body(m, &rindex, 1, 1, &q);
3551 r = message_peek_body(m, &rindex, 1, l+1, &q);
3555 if (!validate_signature(q, l))
3559 *(const char**) p = q;
3564 align = bus_type_get_alignment(type);
3567 sz = bus_type_get_size(type);
3570 r = message_peek_body(m, &rindex, align, sz, &q);
3576 case SD_BUS_TYPE_BYTE:
3578 *(uint8_t*) p = *(uint8_t*) q;
3581 case SD_BUS_TYPE_BOOLEAN:
3583 *(int*) p = !!*(uint32_t*) q;
3586 case SD_BUS_TYPE_INT16:
3587 case SD_BUS_TYPE_UINT16:
3589 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3592 case SD_BUS_TYPE_INT32:
3593 case SD_BUS_TYPE_UINT32:
3595 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3598 case SD_BUS_TYPE_INT64:
3599 case SD_BUS_TYPE_UINT64:
3600 case SD_BUS_TYPE_DOUBLE:
3602 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3605 case SD_BUS_TYPE_UNIX_FD: {
3608 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3613 *(int*) p = m->fds[j];
3618 assert_not_reached("Unknown basic type...");
3625 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3631 static int bus_message_enter_array(
3633 struct bus_container *c,
3634 const char *contents,
3635 uint32_t **array_size,
3638 size_t *n_offsets) {
3652 if (!signature_is_single(contents, true))
3655 if (!c->signature || c->signature[c->index] == 0)
3658 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3661 if (!startswith(c->signature + c->index + 1, contents))
3666 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3669 r = message_peek_body(m, &rindex, 4, 4, &q);
3673 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3676 alignment = bus_type_get_alignment(contents[0]);
3680 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3684 *array_size = (uint32_t*) q;
3686 } else if (c->item_size <= 0) {
3688 /* gvariant: empty array */
3693 } else if (bus_gvariant_is_fixed_size(contents)) {
3695 /* gvariant: fixed length array */
3696 *item_size = bus_gvariant_get_size(contents);
3701 size_t where, p = 0, framing, sz;
3704 /* gvariant: variable length array */
3705 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3707 where = rindex + c->item_size - sz;
3708 r = message_peek_body(m, &where, 1, sz, &q);
3712 framing = bus_gvariant_read_word_le(q, sz);
3713 if (framing > c->item_size - sz)
3715 if ((c->item_size - framing) % sz != 0)
3718 *n_offsets = (c->item_size - framing) / sz;
3720 where = rindex + framing;
3721 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3725 *offsets = new(size_t, *n_offsets);
3729 for (i = 0; i < *n_offsets; i++) {
3732 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3733 if (x > c->item_size - sz)
3738 (*offsets)[i] = rindex + x;
3742 *item_size = (*offsets)[0] - rindex;
3747 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3748 c->index += 1 + strlen(contents);
3753 static int bus_message_enter_variant(
3755 struct bus_container *c,
3756 const char *contents,
3757 size_t *item_size) {
3769 if (!signature_is_single(contents, false))
3772 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3775 if (!c->signature || c->signature[c->index] == 0)
3778 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3783 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3786 k = strlen(contents);
3787 if (1+k > c->item_size)
3790 where = rindex + c->item_size - (1+k);
3791 r = message_peek_body(m, &where, 1, 1+k, &q);
3795 if (*(char*) q != 0)
3798 if (memcmp((uint8_t*) q+1, contents, k))
3801 *item_size = c->item_size - (1+k);
3804 r = message_peek_body(m, &rindex, 1, 1, &q);
3809 r = message_peek_body(m, &rindex, 1, l+1, &q);
3813 if (!validate_signature(q, l))
3816 if (!streq(q, contents))
3822 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3828 static int build_struct_offsets(
3830 const char *signature,
3834 size_t *n_offsets) {
3836 unsigned n_variable = 0, n_total = 0, v;
3837 size_t previous = 0, where;
3848 if (isempty(signature)) {
3849 /* Unary type is encoded as *fixed* 1 byte padding */
3850 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3854 if (*(uint8_t *) q != 0)
3863 sz = bus_gvariant_determine_word_size(size, 0);
3867 /* First, loop over signature and count variable elements and
3868 * elements in general. We use this to know how large the
3869 * offset array is at the end of the structure. Note that
3870 * GVariant only stores offsets for all variable size elements
3871 * that are not the last item. */
3877 r = signature_element_length(p, &n);
3886 r = bus_gvariant_is_fixed_size(t);
3891 if (r == 0 && p[n] != 0) /* except the last item */
3898 if (size < n_variable * sz)
3901 where = m->rindex + size - (n_variable * sz);
3902 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3908 *offsets = new(size_t, n_total);
3914 /* Second, loop again and build an offset table */
3920 r = signature_element_length(p, &n);
3929 k = bus_gvariant_get_size(t);
3937 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3940 if (m->rindex + x < previous)
3943 /* The last item's end
3944 * is determined from
3947 x = size - (n_variable * sz);
3949 offset = m->rindex + x;
3955 align = bus_gvariant_get_alignment(t);
3958 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3962 previous = (*offsets)[(*n_offsets)++] = offset;
3967 assert(*n_offsets == n_total);
3969 *item_size = (*offsets)[0] - m->rindex;
3973 static int enter_struct_or_dict_entry(
3975 struct bus_container *c,
3976 const char *contents,
3979 size_t *n_offsets) {
3990 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3993 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3998 /* gvariant with contents */
3999 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
4004 static int bus_message_enter_struct(
4006 struct bus_container *c,
4007 const char *contents,
4010 size_t *n_offsets) {
4022 if (!signature_is_valid(contents, false))
4025 if (!c->signature || c->signature[c->index] == 0)
4028 l = strlen(contents);
4030 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4031 !startswith(c->signature + c->index + 1, contents) ||
4032 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4035 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4039 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4040 c->index += 1 + l + 1;
4045 static int bus_message_enter_dict_entry(
4047 struct bus_container *c,
4048 const char *contents,
4051 size_t *n_offsets) {
4060 if (!signature_is_pair(contents))
4063 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4066 if (!c->signature || c->signature[c->index] == 0)
4069 l = strlen(contents);
4071 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4072 !startswith(c->signature + c->index + 1, contents) ||
4073 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4076 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4080 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4081 c->index += 1 + l + 1;
4086 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4088 const char *contents) {
4089 struct bus_container *c, *w;
4090 uint32_t *array_size = NULL;
4093 size_t *offsets = NULL;
4094 size_t n_offsets = 0, item_size = 0;
4097 assert_return(m, -EINVAL);
4098 assert_return(m->sealed, -EPERM);
4099 assert_return(type != 0 || !contents, -EINVAL);
4101 if (type == 0 || !contents) {
4105 /* Allow entering into anonymous containers */
4106 r = sd_bus_message_peek_type(m, &tt, &cc);
4110 if (type != 0 && type != tt)
4113 if (contents && !streq(contents, cc))
4121 * We enforce a global limit on container depth, that is much
4122 * higher than the 32 structs and 32 arrays the specification
4123 * mandates. This is simpler to implement for us, and we need
4124 * this only to ensure our container array doesn't grow
4125 * without bounds. We are happy to return any data from a
4126 * message as long as the data itself is valid, even if the
4127 * overall message might be not.
4129 * Note that the message signature is validated when
4130 * parsing the headers, and that validation does check the
4133 * Note that the specification defines no limits on the depth
4134 * of stacked variants, but we do.
4136 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4139 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4142 if (message_end_of_signature(m))
4145 if (message_end_of_array(m, m->rindex))
4148 c = message_get_container(m);
4150 signature = strdup(contents);
4154 c->saved_index = c->index;
4157 if (type == SD_BUS_TYPE_ARRAY)
4158 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4159 else if (type == SD_BUS_TYPE_VARIANT)
4160 r = bus_message_enter_variant(m, c, contents, &item_size);
4161 else if (type == SD_BUS_TYPE_STRUCT)
4162 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4163 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4164 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4174 /* OK, let's fill it in */
4175 w = m->containers + m->n_containers++;
4176 w->enclosing = type;
4177 w->signature = signature;
4178 w->peeked_signature = NULL;
4182 w->begin = m->rindex;
4184 /* Unary type has fixed size of 1, but virtual size of 0 */
4185 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4186 type == SD_BUS_TYPE_STRUCT &&
4188 w->end = m->rindex + 0;
4190 w->end = m->rindex + c->item_size;
4192 w->array_size = array_size;
4193 w->item_size = item_size;
4194 w->offsets = offsets;
4195 w->n_offsets = n_offsets;
4196 w->offset_index = 0;
4201 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4202 struct bus_container *c;
4206 assert_return(m, -EINVAL);
4207 assert_return(m->sealed, -EPERM);
4208 assert_return(m->n_containers > 0, -ENXIO);
4210 c = message_get_container(m);
4212 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4213 if (c->signature && c->signature[c->index] != 0)
4217 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4218 if (m->rindex < c->end)
4221 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4224 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4225 if (c->begin + l != m->rindex)
4230 free(c->peeked_signature);
4234 c = message_get_container(m);
4237 c->index = c->saved_index;
4238 r = container_next_item(m, c, &m->rindex);
4246 static void message_quit_container(sd_bus_message *m) {
4247 struct bus_container *c;
4251 assert(m->n_containers > 0);
4253 c = message_get_container(m);
4256 assert(m->rindex >= c->before);
4257 m->rindex = c->before;
4259 /* Free container */
4264 /* Correct index of new top-level container */
4265 c = message_get_container(m);
4266 c->index = c->saved_index;
4269 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4270 struct bus_container *c;
4273 assert_return(m, -EINVAL);
4274 assert_return(m->sealed, -EPERM);
4276 if (message_end_of_signature(m))
4279 if (message_end_of_array(m, m->rindex))
4282 c = message_get_container(m);
4284 if (bus_type_is_basic(c->signature[c->index])) {
4288 *type = c->signature[c->index];
4292 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4298 r = signature_element_length(c->signature+c->index+1, &l);
4304 sig = strndup(c->signature + c->index + 1, l);
4308 free(c->peeked_signature);
4309 *contents = c->peeked_signature = sig;
4313 *type = SD_BUS_TYPE_ARRAY;
4318 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4319 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4325 r = signature_element_length(c->signature+c->index, &l);
4330 sig = strndup(c->signature + c->index + 1, l - 2);
4334 free(c->peeked_signature);
4335 *contents = c->peeked_signature = sig;
4339 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4344 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4348 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4351 if (c->item_size < 2)
4354 /* Look for the NUL delimiter that
4355 separates the payload from the
4356 signature. Since the body might be
4357 in a different part that then the
4358 signature we map byte by byte. */
4360 for (k = 2; k <= c->item_size; k++) {
4363 where = m->rindex + c->item_size - k;
4364 r = message_peek_body(m, &where, 1, k, &q);
4368 if (*(char*) q == 0)
4372 if (k > c->item_size)
4375 free(c->peeked_signature);
4376 c->peeked_signature = strndup((char*) q + 1, k - 1);
4377 if (!c->peeked_signature)
4380 if (!signature_is_valid(c->peeked_signature, true))
4383 *contents = c->peeked_signature;
4388 r = message_peek_body(m, &rindex, 1, 1, &q);
4393 r = message_peek_body(m, &rindex, 1, l+1, &q);
4397 if (!validate_signature(q, l))
4405 *type = SD_BUS_TYPE_VARIANT;
4420 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4421 struct bus_container *c;
4423 assert_return(m, -EINVAL);
4424 assert_return(m->sealed, -EPERM);
4427 message_reset_containers(m);
4430 c = message_get_container(m);
4432 c = message_get_container(m);
4434 c->offset_index = 0;
4436 m->rindex = c->begin;
4439 c->offset_index = 0;
4440 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4442 return !isempty(c->signature);
4445 static int message_read_ap(
4450 unsigned n_array, n_struct;
4451 TypeStack stack[BUS_CONTAINER_DEPTH];
4452 unsigned stack_ptr = 0;
4453 unsigned n_loop = 0;
4461 /* Ideally, we'd just call ourselves recursively on every
4462 * complex type. However, the state of a va_list that is
4463 * passed to a function is undefined after that function
4464 * returns. This means we need to docode the va_list linearly
4465 * in a single stackframe. We hence implement our own
4466 * home-grown stack in an array. */
4468 n_array = (unsigned) -1; /* length of current array entries */
4469 n_struct = strlen(types); /* length of current struct contents signature */
4476 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4477 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4483 r = sd_bus_message_exit_container(m);
4491 if (n_array != (unsigned) -1)
4500 case SD_BUS_TYPE_BYTE:
4501 case SD_BUS_TYPE_BOOLEAN:
4502 case SD_BUS_TYPE_INT16:
4503 case SD_BUS_TYPE_UINT16:
4504 case SD_BUS_TYPE_INT32:
4505 case SD_BUS_TYPE_UINT32:
4506 case SD_BUS_TYPE_INT64:
4507 case SD_BUS_TYPE_UINT64:
4508 case SD_BUS_TYPE_DOUBLE:
4509 case SD_BUS_TYPE_STRING:
4510 case SD_BUS_TYPE_OBJECT_PATH:
4511 case SD_BUS_TYPE_SIGNATURE:
4512 case SD_BUS_TYPE_UNIX_FD: {
4515 p = va_arg(ap, void*);
4516 r = sd_bus_message_read_basic(m, *t, p);
4529 case SD_BUS_TYPE_ARRAY: {
4532 r = signature_element_length(t + 1, &k);
4538 memcpy(s, t + 1, k);
4541 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4552 if (n_array == (unsigned) -1) {
4557 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4563 n_array = va_arg(ap, unsigned);
4568 case SD_BUS_TYPE_VARIANT: {
4571 s = va_arg(ap, const char *);
4575 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4585 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4590 n_struct = strlen(s);
4591 n_array = (unsigned) -1;
4596 case SD_BUS_TYPE_STRUCT_BEGIN:
4597 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4600 r = signature_element_length(t, &k);
4606 memcpy(s, t + 1, k - 2);
4609 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4619 if (n_array == (unsigned) -1) {
4624 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4630 n_array = (unsigned) -1;
4643 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4647 assert_return(m, -EINVAL);
4648 assert_return(m->sealed, -EPERM);
4649 assert_return(types, -EINVAL);
4651 va_start(ap, types);
4652 r = message_read_ap(m, types, ap);
4658 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4661 assert_return(m, -EINVAL);
4662 assert_return(m->sealed, -EPERM);
4664 /* If types is NULL, read exactly one element */
4666 struct bus_container *c;
4669 if (message_end_of_signature(m))
4672 if (message_end_of_array(m, m->rindex))
4675 c = message_get_container(m);
4677 r = signature_element_length(c->signature + c->index, &l);
4681 types = strndupa(c->signature + c->index, l);
4686 case 0: /* Nothing to drop */
4689 case SD_BUS_TYPE_BYTE:
4690 case SD_BUS_TYPE_BOOLEAN:
4691 case SD_BUS_TYPE_INT16:
4692 case SD_BUS_TYPE_UINT16:
4693 case SD_BUS_TYPE_INT32:
4694 case SD_BUS_TYPE_UINT32:
4695 case SD_BUS_TYPE_INT64:
4696 case SD_BUS_TYPE_UINT64:
4697 case SD_BUS_TYPE_DOUBLE:
4698 case SD_BUS_TYPE_STRING:
4699 case SD_BUS_TYPE_OBJECT_PATH:
4700 case SD_BUS_TYPE_SIGNATURE:
4701 case SD_BUS_TYPE_UNIX_FD:
4703 r = sd_bus_message_read_basic(m, *types, NULL);
4707 r = sd_bus_message_skip(m, types + 1);
4713 case SD_BUS_TYPE_ARRAY: {
4716 r = signature_element_length(types + 1, &k);
4722 memcpy(s, types+1, k);
4725 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4730 r = sd_bus_message_skip(m, s);
4737 r = sd_bus_message_exit_container(m);
4742 r = sd_bus_message_skip(m, types + 1 + k);
4749 case SD_BUS_TYPE_VARIANT: {
4750 const char *contents;
4753 r = sd_bus_message_peek_type(m, &x, &contents);
4757 if (x != SD_BUS_TYPE_VARIANT)
4760 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4764 r = sd_bus_message_skip(m, contents);
4769 r = sd_bus_message_exit_container(m);
4773 r = sd_bus_message_skip(m, types + 1);
4780 case SD_BUS_TYPE_STRUCT_BEGIN:
4781 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4784 r = signature_element_length(types, &k);
4790 memcpy(s, types+1, k-2);
4793 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4797 r = sd_bus_message_skip(m, s);
4801 r = sd_bus_message_exit_container(m);
4806 r = sd_bus_message_skip(m, types + k);
4818 _public_ int sd_bus_message_read_array(
4824 struct bus_container *c;
4830 assert_return(m, -EINVAL);
4831 assert_return(m->sealed, -EPERM);
4832 assert_return(bus_type_is_trivial(type), -EINVAL);
4833 assert_return(ptr, -EINVAL);
4834 assert_return(size, -EINVAL);
4835 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4837 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4841 c = message_get_container(m);
4843 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4844 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4848 sz = c->end - c->begin;
4850 align = bus_type_get_alignment(type);
4854 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4858 /* Zero length array, let's return some aligned
4859 * pointer that is not NULL */
4860 p = (uint8_t*) NULL + align;
4862 r = message_peek_body(m, &m->rindex, align, sz, &p);
4867 r = sd_bus_message_exit_container(m);
4871 *ptr = (const void*) p;
4877 message_quit_container(m);
4881 static int message_peek_fields(
4892 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4895 static int message_peek_field_uint32(
4907 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4910 /* identical for gvariant and dbus1 */
4912 r = message_peek_fields(m, ri, 4, 4, &q);
4917 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4922 static int message_peek_field_uint64(
4934 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4937 /* identical for gvariant and dbus1 */
4939 r = message_peek_fields(m, ri, 8, 8, &q);
4944 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4949 static int message_peek_field_string(
4951 bool (*validate)(const char *p),
4963 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4968 r = message_peek_fields(m, ri, 1, item_size, &q);
4974 r = message_peek_field_uint32(m, ri, 4, &l);
4978 r = message_peek_fields(m, ri, 1, l+1, &q);
4984 if (!validate_nul(q, l))
4990 if (!validate_string(q, l))
5000 static int message_peek_field_signature(
5013 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5018 r = message_peek_fields(m, ri, 1, item_size, &q);
5024 r = message_peek_fields(m, ri, 1, 1, &q);
5029 r = message_peek_fields(m, ri, 1, l+1, &q);
5034 if (!validate_signature(q, l))
5043 static int message_skip_fields(
5046 uint32_t array_size,
5047 const char **signature) {
5049 size_t original_index;
5055 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5057 original_index = *ri;
5063 if (array_size != (uint32_t) -1 &&
5064 array_size <= *ri - original_index)
5071 if (t == SD_BUS_TYPE_STRING) {
5073 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5079 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5081 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5087 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5089 r = message_peek_field_signature(m, ri, 0, NULL);
5095 } else if (bus_type_is_basic(t)) {
5098 align = bus_type_get_alignment(t);
5099 k = bus_type_get_size(t);
5100 assert(align > 0 && k > 0);
5102 r = message_peek_fields(m, ri, align, k, NULL);
5108 } else if (t == SD_BUS_TYPE_ARRAY) {
5110 r = signature_element_length(*signature+1, &l);
5120 strncpy(sig, *signature + 1, l-1);
5123 alignment = bus_type_get_alignment(sig[0]);
5127 r = message_peek_field_uint32(m, ri, 0, &nas);
5130 if (nas > BUS_ARRAY_MAX_SIZE)
5133 r = message_peek_fields(m, ri, alignment, 0, NULL);
5137 r = message_skip_fields(m, ri, nas, (const char**) &s);
5142 (*signature) += 1 + l;
5144 } else if (t == SD_BUS_TYPE_VARIANT) {
5147 r = message_peek_field_signature(m, ri, 0, &s);
5151 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5157 } else if (t == SD_BUS_TYPE_STRUCT ||
5158 t == SD_BUS_TYPE_DICT_ENTRY) {
5160 r = signature_element_length(*signature, &l);
5167 strncpy(sig, *signature + 1, l-1);
5170 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5181 int bus_message_parse_fields(sd_bus_message *m) {
5184 uint32_t unix_fds = 0;
5185 bool unix_fds_set = false;
5186 void *offsets = NULL;
5187 unsigned n_offsets = 0;
5193 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5196 /* Read the signature from the end of the body variant first */
5197 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5198 if (m->footer_accessible < 1 + sz)
5201 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5203 if (p < (char*) m->footer)
5210 /* We found the beginning of the signature
5211 * string, yay! We require the body to be a
5212 * structure, so verify it and then strip the
5213 * opening/closing brackets. */
5215 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5217 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5218 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5221 c = strndup(p + 1 + 1, l - 2);
5225 free(m->root_container.signature);
5226 m->root_container.signature = c;
5233 /* Calculate the actual user body size, by removing
5234 * the trailing variant signature and struct offset
5236 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5238 /* Pull out the offset table for the fields array */
5239 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5244 ri = m->fields_size - sz;
5245 r = message_peek_fields(m, &ri, 1, sz, &q);
5249 framing = bus_gvariant_read_word_le(q, sz);
5250 if (framing >= m->fields_size - sz)
5252 if ((m->fields_size - framing) % sz != 0)
5256 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5260 n_offsets = (m->fields_size - framing) / sz;
5263 m->user_body_size = m->body_size;
5266 while (ri < m->fields_size) {
5267 _cleanup_free_ char *sig = NULL;
5268 const char *signature;
5269 uint64_t field_type;
5270 size_t item_size = (size_t) -1;
5272 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5281 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5283 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5287 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5291 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5298 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5303 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5308 where = ri = ALIGN_TO(ri, 8);
5309 item_size = end - ri;
5310 r = message_peek_fields(m, &where, 1, item_size, &q);
5314 b = memrchr(q, 0, item_size);
5318 sig = strndup(b+1, item_size - (b+1-(char*) q));
5323 item_size = b - (char*) q;
5325 r = message_peek_field_signature(m, &ri, 0, &signature);
5330 switch (field_type) {
5332 case _BUS_MESSAGE_HEADER_INVALID:
5335 case BUS_MESSAGE_HEADER_PATH:
5340 if (!streq(signature, "o"))
5343 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5346 case BUS_MESSAGE_HEADER_INTERFACE:
5351 if (!streq(signature, "s"))
5354 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5357 case BUS_MESSAGE_HEADER_MEMBER:
5362 if (!streq(signature, "s"))
5365 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5368 case BUS_MESSAGE_HEADER_ERROR_NAME:
5373 if (!streq(signature, "s"))
5376 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5378 m->error._need_free = -1;
5382 case BUS_MESSAGE_HEADER_DESTINATION:
5387 if (!streq(signature, "s"))
5390 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5393 case BUS_MESSAGE_HEADER_SENDER:
5398 if (!streq(signature, "s"))
5401 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5403 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5404 m->creds.unique_name = (char*) m->sender;
5405 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5411 case BUS_MESSAGE_HEADER_SIGNATURE: {
5415 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5418 if (m->root_container.signature)
5421 if (!streq(signature, "g"))
5424 r = message_peek_field_signature(m, &ri, item_size, &s);
5432 free(m->root_container.signature);
5433 m->root_container.signature = c;
5437 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5439 if (m->reply_cookie != 0)
5442 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5443 /* 64bit on dbus2 */
5445 if (!streq(signature, "t"))
5448 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5452 /* 32bit on dbus1 */
5455 if (!streq(signature, "u"))
5458 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5462 m->reply_cookie = serial;
5465 if (m->reply_cookie == 0)
5470 case BUS_MESSAGE_HEADER_UNIX_FDS:
5474 if (!streq(signature, "u"))
5477 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5481 unix_fds_set = true;
5485 if (!BUS_MESSAGE_IS_GVARIANT(m))
5486 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5495 if (m->n_fds != unix_fds)
5498 switch (m->header->type) {
5500 case SD_BUS_MESSAGE_SIGNAL:
5501 if (!m->path || !m->interface || !m->member)
5504 if (m->reply_cookie != 0)
5509 case SD_BUS_MESSAGE_METHOD_CALL:
5511 if (!m->path || !m->member)
5514 if (m->reply_cookie != 0)
5519 case SD_BUS_MESSAGE_METHOD_RETURN:
5521 if (m->reply_cookie == 0)
5525 case SD_BUS_MESSAGE_METHOD_ERROR:
5527 if (m->reply_cookie == 0 || !m->error.name)
5532 /* Refuse non-local messages that claim they are local */
5533 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5535 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5537 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5540 m->root_container.end = m->user_body_size;
5542 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5543 r = build_struct_offsets(
5545 m->root_container.signature,
5547 &m->root_container.item_size,
5548 &m->root_container.offsets,
5549 &m->root_container.n_offsets);
5554 /* Try to read the error message, but if we can't it's a non-issue */
5555 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5556 (void) sd_bus_message_read(m, "s", &m->error.message);
5561 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5562 assert_return(m, -EINVAL);
5563 assert_return(destination, -EINVAL);
5564 assert_return(!m->sealed, -EPERM);
5565 assert_return(!m->destination, -EEXIST);
5567 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5570 /// UNNEEDED by elogind
5572 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5576 struct bus_body_part *part;
5582 total = BUS_MESSAGE_SIZE(m);
5588 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5589 MESSAGE_FOREACH_PART(part, i, m)
5590 e = mempcpy(e, part->data, part->size);
5592 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5601 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5608 r = sd_bus_message_enter_container(m, 'a', "s");
5612 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5613 r = strv_extend(l, s);
5620 r = sd_bus_message_exit_container(m);
5627 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5631 assert_return(m, -EINVAL);
5632 assert_return(m->sealed, -EPERM);
5633 assert_return(l, -EINVAL);
5635 r = bus_message_read_strv_extend(m, &strv);
5645 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5646 const char *contents;
5655 r = sd_bus_message_rewind(m, true);
5660 r = sd_bus_message_peek_type(m, &type, &contents);
5666 /* Don't match against arguments after the first one we don't understand */
5667 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5668 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5674 r = sd_bus_message_skip(m, NULL);
5679 if (type == SD_BUS_TYPE_ARRAY) {
5681 r = sd_bus_message_read_strv(m, strv);
5688 r = sd_bus_message_read_basic(m, type, str);
5698 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5699 assert_return(m, EINVAL);
5701 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5704 return sd_bus_error_get_errno(&m->error);
5707 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5708 struct bus_container *c;
5710 assert_return(m, NULL);
5712 c = complete ? &m->root_container : message_get_container(m);
5713 return strempty(c->signature);
5716 /// UNNEEDED by elogind
5718 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5719 assert_return(m, -EINVAL);
5721 return isempty(m->root_container.signature);
5724 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5725 assert_return(m, -EINVAL);
5727 return streq(strempty(m->root_container.signature), strempty(signature));
5731 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5732 bool done_something = false;
5735 assert_return(m, -EINVAL);
5736 assert_return(source, -EINVAL);
5737 assert_return(!m->sealed, -EPERM);
5738 assert_return(source->sealed, -EPERM);
5741 const char *contents;
5756 r = sd_bus_message_peek_type(source, &type, &contents);
5762 done_something = true;
5764 if (bus_type_is_container(type) > 0) {
5766 r = sd_bus_message_enter_container(source, type, contents);
5770 r = sd_bus_message_open_container(m, type, contents);
5774 r = sd_bus_message_copy(m, source, true);
5778 r = sd_bus_message_close_container(m);
5782 r = sd_bus_message_exit_container(source);
5789 r = sd_bus_message_read_basic(source, type, &basic);
5795 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5796 type == SD_BUS_TYPE_SIGNATURE ||
5797 type == SD_BUS_TYPE_STRING)
5798 r = sd_bus_message_append_basic(m, type, basic.string);
5800 r = sd_bus_message_append_basic(m, type, &basic);
5807 return done_something;
5810 /// UNNEEDED by elogind
5812 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5817 assert_return(m, -EINVAL);
5818 assert_return(m->sealed, -EPERM);
5819 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5820 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5821 assert_return(type || contents, -EINVAL);
5822 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5824 r = sd_bus_message_peek_type(m, &t, &c);
5828 if (type != 0 && type != t)
5831 if (contents && !streq_ptr(contents, c))
5838 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5839 assert_return(m, NULL);
5844 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5845 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5853 switch ((*m)->header->type) {
5855 case SD_BUS_MESSAGE_SIGNAL:
5856 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5862 case SD_BUS_MESSAGE_METHOD_CALL:
5863 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5869 case SD_BUS_MESSAGE_METHOD_RETURN:
5870 case SD_BUS_MESSAGE_METHOD_ERROR:
5872 n = message_new(bus, (*m)->header->type);
5876 n->reply_cookie = (*m)->reply_cookie;
5878 r = message_append_reply_cookie(n, n->reply_cookie);
5882 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5883 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5887 n->error._need_free = -1;
5896 if ((*m)->destination && !n->destination) {
5897 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5902 if ((*m)->sender && !n->sender) {
5903 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5908 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5910 r = sd_bus_message_copy(n, *m, true);
5914 timeout = (*m)->timeout;
5915 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5916 timeout = BUS_DEFAULT_TIMEOUT;
5918 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5922 sd_bus_message_unref(*m);
5929 /// UNNEEDED by elogind
5931 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5935 assert_return(!m->sealed, -EPERM);
5936 assert_return(!m->sender, -EPERM);
5938 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5941 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5942 assert_return(m, -EINVAL);
5943 assert_return(priority, -EINVAL);
5945 *priority = m->priority;
5949 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5950 assert_return(m, -EINVAL);
5951 assert_return(!m->sealed, -EPERM);
5953 m->priority = priority;