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);
116 m->containers = mfree(m->containers);
118 m->n_containers = m->containers_allocated = 0;
119 m->root_container.index = 0;
122 static void message_free(sd_bus_message *m) {
128 message_reset_parts(m);
130 if (m->release_kdbus)
131 bus_kernel_cmd_free(m->bus, (uint8_t *) m->kdbus - (uint8_t *) m->bus->kdbus_buffer);
136 sd_bus_unref(m->bus);
139 close_many(m->fds, m->n_fds);
143 if (m->iovec != m->iovec_fixed)
146 m->destination_ptr = mfree(m->destination_ptr);
147 message_reset_containers(m);
148 free(m->root_container.signature);
149 free(m->root_container.offsets);
151 free(m->root_container.peeked_signature);
153 bus_creds_done(&m->creds);
157 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
159 size_t old_size, new_size, start;
166 old_size = sizeof(struct bus_header) + m->fields_size;
167 start = ALIGN_TO(old_size, align);
168 new_size = start + sz;
170 if (new_size < start ||
171 new_size > (size_t) ((uint32_t) -1))
174 if (old_size == new_size)
175 return (uint8_t*) m->header + old_size;
177 if (m->free_header) {
178 np = realloc(m->header, ALIGN8(new_size));
182 /* Initially, the header is allocated as part of of
183 * the sd_bus_message itself, let's replace it by
186 np = malloc(ALIGN8(new_size));
190 memcpy(np, m->header, sizeof(struct bus_header));
193 /* Zero out padding */
194 if (start > old_size)
195 memzero((uint8_t*) np + old_size, start - old_size);
199 m->fields_size = new_size - sizeof(struct bus_header);
201 /* Adjust quick access pointers */
202 m->path = adjust_pointer(m->path, op, old_size, m->header);
203 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
204 m->member = adjust_pointer(m->member, op, old_size, m->header);
205 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
206 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
207 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
209 m->free_header = true;
212 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
215 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
218 return (uint8_t*) np + start;
225 static int message_append_field_string(
237 /* dbus1 only allows 8bit header field ids */
241 /* dbus1 doesn't allow strings over 32bit, let's enforce this
242 * globally, to not risk convertability */
244 if (l > (size_t) (uint32_t) -1)
247 /* Signature "(yv)" where the variant contains "s" */
249 if (BUS_MESSAGE_IS_GVARIANT(m)) {
251 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
252 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
256 *((uint64_t*) p) = h;
263 *ret = (char*) p + 8;
266 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
267 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
276 ((uint32_t*) p)[1] = l;
277 memcpy(p + 8, s, l + 1);
280 *ret = (char*) p + 8;
286 static int message_append_field_signature(
297 /* dbus1 only allows 8bit header field ids */
301 /* dbus1 doesn't allow signatures over 8bit, let's enforce
302 * this globally, to not risk convertability */
307 /* Signature "(yv)" where the variant contains "g" */
309 if (BUS_MESSAGE_IS_GVARIANT(m))
310 /* For gvariant the serialization is the same as for normal strings */
311 return message_append_field_string(m, h, 'g', s, ret);
313 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
314 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
320 p[2] = SD_BUS_TYPE_SIGNATURE;
323 memcpy(p + 5, s, l + 1);
326 *ret = (const char*) p + 5;
332 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
337 /* dbus1 only allows 8bit header field ids */
341 if (BUS_MESSAGE_IS_GVARIANT(m)) {
342 /* (field id 64bit + ((value + NUL + signature string 'u') */
344 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
348 *((uint64_t*) p) = h;
349 *((uint32_t*) (p + 8)) = x;
353 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
354 p = message_extend_fields(m, 8, 4 + 4, false);
363 ((uint32_t*) p)[1] = x;
369 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
374 /* dbus1 only allows 8bit header field ids */
378 if (BUS_MESSAGE_IS_GVARIANT(m)) {
379 /* (field id 64bit + ((value + NUL + signature string 't') */
381 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
385 *((uint64_t*) p) = h;
386 *((uint64_t*) (p + 8)) = x;
390 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
391 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
404 ((uint64_t*) p)[1] = x;
410 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
413 if (BUS_MESSAGE_IS_GVARIANT(m))
414 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
416 /* 64bit cookies are not supported on dbus1 */
417 if (cookie > 0xffffffffUL)
420 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
424 int bus_message_from_header(
427 size_t header_accessible,
429 size_t footer_accessible,
435 sd_bus_message **ret) {
437 _cleanup_free_ sd_bus_message *m = NULL;
438 struct bus_header *h;
442 assert(header || header_accessible <= 0);
443 assert(footer || footer_accessible <= 0);
444 assert(fds || n_fds <= 0);
447 if (header_accessible < sizeof(struct bus_header))
450 if (header_accessible > message_size)
452 if (footer_accessible > message_size)
456 if (!IN_SET(h->version, 1, 2))
459 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
462 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
465 /* Note that we are happy with unknown flags in the flags header! */
467 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
470 label_sz = strlen(label);
481 m->header_accessible = header_accessible;
483 m->footer_accessible = footer_accessible;
485 if (BUS_MESSAGE_IS_GVARIANT(m)) {
488 if (h->dbus2.cookie == 0)
491 /* dbus2 derives the sizes from the message size and
492 the offset table at the end, since it is formatted as
493 gvariant "yyyyuta{tv}v". Since the message itself is a
494 structure with precisely to variable sized entries,
495 there's only one offset in the table, which marks the
496 end of the fields array. */
498 ws = bus_gvariant_determine_word_size(message_size, 0);
499 if (footer_accessible < ws)
502 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
503 if (ALIGN8(m->fields_size) > message_size - ws)
505 if (m->fields_size < sizeof(struct bus_header))
508 m->fields_size -= sizeof(struct bus_header);
509 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
511 if (h->dbus1.serial == 0)
514 /* dbus1 has the sizes in the header */
515 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
516 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
518 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
526 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
527 memcpy(m->creds.label, label, label_sz + 1);
529 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
532 m->bus = sd_bus_ref(bus);
539 int bus_message_from_malloc(
546 sd_bus_message **ret) {
552 r = bus_message_from_header(
554 buffer, length, /* in this case the initial bytes and the final bytes are the same */
563 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
566 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
568 m->body.sealed = true;
573 m->iovec = m->iovec_fixed;
574 m->iovec[0].iov_base = buffer;
575 m->iovec[0].iov_len = length;
577 r = bus_message_parse_fields(m);
581 /* We take possession of the memory and fds now */
582 m->free_header = true;
593 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
598 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
603 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
604 m->header->endian = BUS_NATIVE_ENDIAN;
605 m->header->type = type;
606 m->header->version = bus->message_version;
607 m->allow_fds = bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
608 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
609 m->bus = sd_bus_ref(bus);
611 if (bus->allow_interactive_authorization)
612 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
617 _public_ int sd_bus_message_new_signal(
621 const char *interface,
622 const char *member) {
627 assert_return(bus, -ENOTCONN);
628 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
629 assert_return(object_path_is_valid(path), -EINVAL);
630 assert_return(interface_name_is_valid(interface), -EINVAL);
631 assert_return(member_name_is_valid(member), -EINVAL);
632 assert_return(m, -EINVAL);
634 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
638 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
640 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
643 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
646 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
654 sd_bus_message_unref(t);
658 _public_ int sd_bus_message_new_method_call(
661 const char *destination,
663 const char *interface,
664 const char *member) {
669 assert_return(bus, -ENOTCONN);
670 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
671 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
672 assert_return(object_path_is_valid(path), -EINVAL);
673 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
674 assert_return(member_name_is_valid(member), -EINVAL);
675 assert_return(m, -EINVAL);
677 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
681 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
684 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
689 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
695 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
708 static int message_new_reply(
709 sd_bus_message *call,
711 sd_bus_message **m) {
716 assert_return(call, -EINVAL);
717 assert_return(call->sealed, -EPERM);
718 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
719 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
720 assert_return(m, -EINVAL);
722 t = message_new(call->bus, type);
726 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
727 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
728 if (t->reply_cookie == 0)
731 r = message_append_reply_cookie(t, t->reply_cookie);
736 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
741 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
742 t->enforced_reply_signature = call->enforced_reply_signature;
752 _public_ int sd_bus_message_new_method_return(
753 sd_bus_message *call,
754 sd_bus_message **m) {
756 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
759 _public_ int sd_bus_message_new_method_error(
760 sd_bus_message *call,
762 const sd_bus_error *e) {
767 assert_return(sd_bus_error_is_set(e), -EINVAL);
768 assert_return(m, -EINVAL);
770 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
774 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
779 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
784 t->error._need_free = -1;
794 _public_ int sd_bus_message_new_method_errorf(
795 sd_bus_message *call,
801 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
804 assert_return(name, -EINVAL);
805 assert_return(m, -EINVAL);
807 va_start(ap, format);
808 bus_error_setfv(&error, name, format, ap);
811 return sd_bus_message_new_method_error(call, m, &error);
814 _public_ int sd_bus_message_new_method_errno(
815 sd_bus_message *call,
818 const sd_bus_error *p) {
820 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
822 if (sd_bus_error_is_set(p))
823 return sd_bus_message_new_method_error(call, m, p);
825 sd_bus_error_set_errno(&berror, error);
827 return sd_bus_message_new_method_error(call, m, &berror);
830 /// UNNEEDED by elogind
832 _public_ int sd_bus_message_new_method_errnof(
833 sd_bus_message *call,
839 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
842 va_start(ap, format);
843 sd_bus_error_set_errnofv(&berror, error, format, ap);
846 return sd_bus_message_new_method_error(call, m, &berror);
850 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
854 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
855 m->creds.well_known_names_local = true;
856 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
859 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
863 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
864 m->creds.well_known_names_driver = true;
865 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
868 int bus_message_new_synthetic_error(
871 const sd_bus_error *e,
872 sd_bus_message **m) {
878 assert(sd_bus_error_is_set(e));
881 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
885 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
886 t->reply_cookie = cookie;
888 r = message_append_reply_cookie(t, t->reply_cookie);
892 if (bus && bus->unique_name) {
893 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
898 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
903 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
908 t->error._need_free = -1;
910 bus_message_set_sender_driver(bus, t);
920 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
921 assert_return(m, NULL);
923 assert(m->n_ref > 0);
929 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
934 assert(m->n_ref > 0);
944 /// UNNEEDED by elogind
946 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
947 assert_return(m, -EINVAL);
948 assert_return(type, -EINVAL);
950 *type = m->header->type;
954 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
957 assert_return(m, -EINVAL);
958 assert_return(cookie, -EINVAL);
960 c = BUS_MESSAGE_COOKIE(m);
964 *cookie = BUS_MESSAGE_COOKIE(m);
968 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
969 assert_return(m, -EINVAL);
970 assert_return(cookie, -EINVAL);
972 if (m->reply_cookie == 0)
975 *cookie = m->reply_cookie;
979 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
980 assert_return(m, -EINVAL);
982 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
983 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
986 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
987 assert_return(m, -EINVAL);
989 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
993 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
994 assert_return(m, -EINVAL);
996 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
997 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
1000 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1001 assert_return(m, NULL);
1006 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1007 assert_return(m, NULL);
1009 return m->interface;
1012 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1013 assert_return(m, NULL);
1018 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1019 assert_return(m, NULL);
1021 return m->destination;
1024 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1025 assert_return(m, NULL);
1030 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1031 assert_return(m, NULL);
1033 if (!sd_bus_error_is_set(&m->error))
1039 /// UNNEEDED by elogind
1041 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1042 assert_return(m, -EINVAL);
1043 assert_return(usec, -EINVAL);
1045 if (m->monotonic <= 0)
1048 *usec = m->monotonic;
1052 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1053 assert_return(m, -EINVAL);
1054 assert_return(usec, -EINVAL);
1056 if (m->realtime <= 0)
1059 *usec = m->realtime;
1063 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1064 assert_return(m, -EINVAL);
1065 assert_return(seqnum, -EINVAL);
1070 *seqnum = m->seqnum;
1075 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1076 assert_return(m, NULL);
1078 if (m->creds.mask == 0)
1084 /// UNNEEDED by elogind
1086 _public_ int sd_bus_message_is_signal(
1088 const char *interface,
1089 const char *member) {
1091 assert_return(m, -EINVAL);
1093 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1096 if (interface && (!m->interface || !streq(m->interface, interface)))
1099 if (member && (!m->member || !streq(m->member, member)))
1106 _public_ int sd_bus_message_is_method_call(
1108 const char *interface,
1109 const char *member) {
1111 assert_return(m, -EINVAL);
1113 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1116 if (interface && (!m->interface || !streq(m->interface, interface)))
1119 if (member && (!m->member || !streq(m->member, member)))
1125 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1126 assert_return(m, -EINVAL);
1128 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1131 if (name && (!m->error.name || !streq(m->error.name, name)))
1137 /// UNNEEDED by elogind
1139 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1140 assert_return(m, -EINVAL);
1141 assert_return(!m->sealed, -EPERM);
1142 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1145 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1147 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1153 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1154 assert_return(m, -EINVAL);
1155 assert_return(!m->sealed, -EPERM);
1158 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1160 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1165 /// UNNEEDED by elogind
1167 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1168 assert_return(m, -EINVAL);
1169 assert_return(!m->sealed, -EPERM);
1172 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1174 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1180 static struct bus_container *message_get_container(sd_bus_message *m) {
1183 if (m->n_containers == 0)
1184 return &m->root_container;
1186 assert(m->containers);
1187 return m->containers + m->n_containers - 1;
1190 struct bus_body_part *message_append_part(sd_bus_message *m) {
1191 struct bus_body_part *part;
1198 if (m->n_body_parts <= 0) {
1202 assert(m->body_end);
1204 part = new0(struct bus_body_part, 1);
1210 m->body_end->next = part;
1220 static void part_zero(struct bus_body_part *part, size_t sz) {
1225 /* All other fields can be left in their defaults */
1226 assert(!part->data);
1227 assert(part->memfd < 0);
1230 part->is_zero = true;
1231 part->sealed = true;
1234 static int part_make_space(
1235 struct sd_bus_message *m,
1236 struct bus_body_part *part,
1245 assert(!part->sealed);
1250 if (!part->data && part->memfd < 0) {
1251 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1252 part->mmap_begin = part->data;
1255 if (part->memfd >= 0) {
1257 if (part->allocated == 0 || sz > part->allocated) {
1258 uint64_t new_allocated;
1260 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1261 r = memfd_set_size(part->memfd, new_allocated);
1267 part->allocated = new_allocated;
1270 if (!part->data || sz > part->mapped) {
1273 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1274 if (part->mapped <= 0)
1275 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1277 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1279 if (n == MAP_FAILED) {
1284 part->mmap_begin = part->data = n;
1286 part->memfd_offset = 0;
1289 part->munmap_this = true;
1291 if (part->allocated == 0 || sz > part->allocated) {
1292 size_t new_allocated;
1294 new_allocated = sz > 0 ? 2 * sz : 64;
1295 n = realloc(part->data, new_allocated);
1302 part->allocated = new_allocated;
1303 part->free_this = true;
1308 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1314 static int message_add_offset(sd_bus_message *m, size_t offset) {
1315 struct bus_container *c;
1318 assert(BUS_MESSAGE_IS_GVARIANT(m));
1320 /* Add offset to current container, unless this is the first
1321 * item in it, which will have the 0 offset, which we can
1323 c = message_get_container(m);
1325 if (!c->need_offsets)
1328 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1331 c->offsets[c->n_offsets++] = offset;
1335 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1336 struct bus_container *c;
1343 /* Update counters */
1344 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1347 *c->array_size += expand;
1351 static void *message_extend_body(
1356 bool force_inline) {
1358 size_t start_body, end_body, padding, added;
1369 start_body = ALIGN_TO((size_t) m->body_size, align);
1370 end_body = start_body + sz;
1372 padding = start_body - m->body_size;
1373 added = padding + sz;
1375 /* Check for 32bit overflows */
1376 if (end_body > (size_t) ((uint32_t) -1) ||
1377 end_body < start_body) {
1383 struct bus_body_part *part = NULL;
1387 m->n_body_parts <= 0 ||
1388 m->body_end->sealed ||
1389 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1390 (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 */
1394 part = message_append_part(m);
1398 part_zero(part, padding);
1401 part = message_append_part(m);
1405 r = part_make_space(m, part, sz, &p);
1409 struct bus_container *c;
1411 size_t os, start_part, end_part;
1417 start_part = ALIGN_TO(part->size, align);
1418 end_part = start_part + sz;
1420 r = part_make_space(m, part, end_part, &p);
1425 memzero(p, padding);
1426 p = (uint8_t*) p + padding;
1429 /* Readjust pointers */
1430 for (c = m->containers; c < m->containers + m->n_containers; c++)
1431 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1433 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1436 /* Return something that is not NULL and is aligned */
1437 p = (uint8_t *) NULL + align;
1439 m->body_size = end_body;
1440 message_extend_containers(m, added);
1443 r = message_add_offset(m, end_body);
1453 static int message_push_fd(sd_bus_message *m, int fd) {
1464 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1468 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1476 m->fds[m->n_fds] = copy;
1482 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1483 _cleanup_close_ int fd = -1;
1484 struct bus_container *c;
1488 assert_return(m, -EINVAL);
1489 assert_return(!m->sealed, -EPERM);
1490 assert_return(bus_type_is_basic(type), -EINVAL);
1491 assert_return(!m->poisoned, -ESTALE);
1493 c = message_get_container(m);
1495 if (c->signature && c->signature[c->index]) {
1496 /* Container signature is already set */
1498 if (c->signature[c->index] != type)
1503 /* Maybe we can append to the signature? But only if this is the top-level container */
1504 if (c->enclosing != 0)
1507 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1514 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1520 case SD_BUS_TYPE_SIGNATURE:
1521 case SD_BUS_TYPE_STRING:
1524 /* Fall through... */
1525 case SD_BUS_TYPE_OBJECT_PATH:
1533 case SD_BUS_TYPE_BOOLEAN:
1535 u8 = p && *(int*) p;
1541 case SD_BUS_TYPE_UNIX_FD:
1546 fd = message_push_fd(m, *(int*) p);
1557 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1558 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1565 a = message_extend_body(m, align, sz, true, false);
1572 *stored = (const uint8_t*) a;
1579 case SD_BUS_TYPE_STRING:
1580 /* To make things easy we'll serialize a NULL string
1581 * into the empty string */
1584 /* Fall through... */
1585 case SD_BUS_TYPE_OBJECT_PATH:
1591 sz = 4 + strlen(p) + 1;
1594 case SD_BUS_TYPE_SIGNATURE:
1599 sz = 1 + strlen(p) + 1;
1602 case SD_BUS_TYPE_BOOLEAN:
1604 u32 = p && *(int*) p;
1610 case SD_BUS_TYPE_UNIX_FD:
1615 fd = message_push_fd(m, *(int*) p);
1626 align = bus_type_get_alignment(type);
1627 sz = bus_type_get_size(type);
1634 a = message_extend_body(m, align, sz, false, false);
1638 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1639 *(uint32_t*) a = sz - 5;
1640 memcpy((uint8_t*) a + 4, p, sz - 4);
1643 *stored = (const uint8_t*) a + 4;
1645 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1646 *(uint8_t*) a = sz - 2;
1647 memcpy((uint8_t*) a + 1, p, sz - 1);
1650 *stored = (const uint8_t*) a + 1;
1659 if (type == SD_BUS_TYPE_UNIX_FD)
1662 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1669 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1670 return message_append_basic(m, type, p, NULL);
1673 _public_ int sd_bus_message_append_string_space(
1678 struct bus_container *c;
1681 assert_return(m, -EINVAL);
1682 assert_return(s, -EINVAL);
1683 assert_return(!m->sealed, -EPERM);
1684 assert_return(!m->poisoned, -ESTALE);
1686 c = message_get_container(m);
1688 if (c->signature && c->signature[c->index]) {
1689 /* Container signature is already set */
1691 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1696 /* Maybe we can append to the signature? But only if this is the top-level container */
1697 if (c->enclosing != 0)
1700 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1707 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1708 a = message_extend_body(m, 1, size + 1, true, false);
1714 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1718 *(uint32_t*) a = size;
1724 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1730 /// UNNEEDED by elogind
1732 _public_ int sd_bus_message_append_string_iovec(
1734 const struct iovec *iov,
1742 assert_return(m, -EINVAL);
1743 assert_return(!m->sealed, -EPERM);
1744 assert_return(iov || n == 0, -EINVAL);
1745 assert_return(!m->poisoned, -ESTALE);
1747 size = IOVEC_TOTAL_SIZE(iov, n);
1749 r = sd_bus_message_append_string_space(m, size, &p);
1753 for (i = 0; i < n; i++) {
1755 if (iov[i].iov_base)
1756 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1758 memset(p, ' ', iov[i].iov_len);
1760 p += iov[i].iov_len;
1767 static int bus_message_open_array(
1769 struct bus_container *c,
1770 const char *contents,
1771 uint32_t **array_size,
1773 bool *need_offsets) {
1783 assert(need_offsets);
1785 if (!signature_is_single(contents, true))
1788 if (c->signature && c->signature[c->index]) {
1790 /* Verify the existing signature */
1792 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1795 if (!startswith(c->signature + c->index + 1, contents))
1798 nindex = c->index + 1 + strlen(contents);
1802 if (c->enclosing != 0)
1805 /* Extend the existing signature */
1807 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1813 nindex = e - c->signature;
1816 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1817 alignment = bus_gvariant_get_alignment(contents);
1821 /* Add alignment padding and add to offset list */
1822 if (!message_extend_body(m, alignment, 0, false, false))
1825 r = bus_gvariant_is_fixed_size(contents);
1829 *begin = m->body_size;
1830 *need_offsets = r == 0;
1834 struct bus_body_part *o;
1836 alignment = bus_type_get_alignment(contents[0]);
1840 a = message_extend_body(m, 4, 4, false, false);
1845 op = m->body_end->data;
1846 os = m->body_end->size;
1848 /* Add alignment between size and first element */
1849 if (!message_extend_body(m, alignment, 0, false, false))
1852 /* location of array size might have changed so let's readjust a */
1853 if (o == m->body_end)
1854 a = adjust_pointer(a, op, os, m->body_end->data);
1860 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1866 static int bus_message_open_variant(
1868 struct bus_container *c,
1869 const char *contents) {
1875 if (!signature_is_single(contents, false))
1878 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1881 if (c->signature && c->signature[c->index]) {
1883 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1889 if (c->enclosing != 0)
1892 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1899 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1900 /* Variants are always aligned to 8 */
1902 if (!message_extend_body(m, 8, 0, false, false))
1909 l = strlen(contents);
1910 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1915 memcpy((uint8_t*) a + 1, contents, l + 1);
1918 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1924 static int bus_message_open_struct(
1926 struct bus_container *c,
1927 const char *contents,
1929 bool *need_offsets) {
1938 assert(need_offsets);
1940 if (!signature_is_valid(contents, false))
1943 if (c->signature && c->signature[c->index]) {
1946 l = strlen(contents);
1948 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1949 !startswith(c->signature + c->index + 1, contents) ||
1950 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1953 nindex = c->index + 1 + l + 1;
1957 if (c->enclosing != 0)
1960 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1966 nindex = e - c->signature;
1969 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1972 alignment = bus_gvariant_get_alignment(contents);
1976 if (!message_extend_body(m, alignment, 0, false, false))
1979 r = bus_gvariant_is_fixed_size(contents);
1983 *begin = m->body_size;
1984 *need_offsets = r == 0;
1986 /* Align contents to 8 byte boundary */
1987 if (!message_extend_body(m, 8, 0, false, false))
1991 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1997 static int bus_message_open_dict_entry(
1999 struct bus_container *c,
2000 const char *contents,
2002 bool *need_offsets) {
2010 assert(need_offsets);
2012 if (!signature_is_pair(contents))
2015 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2018 if (c->signature && c->signature[c->index]) {
2021 l = strlen(contents);
2023 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2024 !startswith(c->signature + c->index + 1, contents) ||
2025 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2030 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2033 alignment = bus_gvariant_get_alignment(contents);
2037 if (!message_extend_body(m, alignment, 0, false, false))
2040 r = bus_gvariant_is_fixed_size(contents);
2044 *begin = m->body_size;
2045 *need_offsets = r == 0;
2047 /* Align contents to 8 byte boundary */
2048 if (!message_extend_body(m, 8, 0, false, false))
2055 _public_ int sd_bus_message_open_container(
2058 const char *contents) {
2060 struct bus_container *c, *w;
2061 uint32_t *array_size = NULL;
2063 size_t before, begin = 0;
2064 bool need_offsets = false;
2067 assert_return(m, -EINVAL);
2068 assert_return(!m->sealed, -EPERM);
2069 assert_return(contents, -EINVAL);
2070 assert_return(!m->poisoned, -ESTALE);
2072 /* Make sure we have space for one more container */
2073 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2078 c = message_get_container(m);
2080 signature = strdup(contents);
2086 /* Save old index in the parent container, in case we have to
2087 * abort this container */
2088 c->saved_index = c->index;
2089 before = m->body_size;
2091 if (type == SD_BUS_TYPE_ARRAY)
2092 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2093 else if (type == SD_BUS_TYPE_VARIANT)
2094 r = bus_message_open_variant(m, c, contents);
2095 else if (type == SD_BUS_TYPE_STRUCT)
2096 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2097 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2098 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2107 /* OK, let's fill it in */
2108 w = m->containers + m->n_containers++;
2109 w->enclosing = type;
2110 w->signature = signature;
2112 w->array_size = array_size;
2115 w->n_offsets = w->offsets_allocated = 0;
2117 w->need_offsets = need_offsets;
2122 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2127 if (!BUS_MESSAGE_IS_GVARIANT(m))
2130 if (c->need_offsets) {
2131 size_t payload, sz, i;
2134 /* Variable-width arrays */
2136 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2137 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2139 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2143 for (i = 0; i < c->n_offsets; i++)
2144 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2148 /* Fixed-width or empty arrays */
2150 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2158 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2164 assert(c->signature);
2166 if (!BUS_MESSAGE_IS_GVARIANT(m))
2169 l = strlen(c->signature);
2171 a = message_extend_body(m, 1, 1 + l, true, false);
2176 memcpy(a+1, c->signature, l);
2181 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2182 bool fixed_size = true;
2183 size_t n_variable = 0;
2192 if (!BUS_MESSAGE_IS_GVARIANT(m))
2195 p = strempty(c->signature);
2199 r = signature_element_length(p, &n);
2208 r = bus_gvariant_is_fixed_size(t);
2213 assert(!c->need_offsets || i <= c->n_offsets);
2215 /* We need to add an offset for each item that has a
2216 * variable size and that is not the last one in the
2220 if (r == 0 && p[n] != 0)
2227 assert(!c->need_offsets || i == c->n_offsets);
2228 assert(c->need_offsets || n_variable == 0);
2230 if (isempty(c->signature)) {
2231 /* The unary type is encoded as fixed 1 byte padding */
2232 a = message_extend_body(m, 1, 1, add_offset, false);
2237 } else if (n_variable <= 0) {
2240 /* Structures with fixed-size members only have to be
2241 * fixed-size themselves. But gvariant requires all fixed-size
2242 * elements to be sized a multiple of their alignment. Hence,
2243 * we must *always* add final padding after the last member so
2244 * the overall size of the structure is properly aligned. */
2246 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2248 assert(alignment > 0);
2250 a = message_extend_body(m, alignment, 0, add_offset, false);
2257 assert(c->offsets[c->n_offsets-1] == m->body_size);
2259 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2261 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2265 p = strempty(c->signature);
2266 for (i = 0, j = 0; i < c->n_offsets; i++) {
2270 r = signature_element_length(p, &n);
2281 r = bus_gvariant_is_fixed_size(t);
2284 if (r > 0 || p[0] == 0)
2288 k = n_variable - 1 - j;
2290 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2299 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2300 struct bus_container *c;
2303 assert_return(m, -EINVAL);
2304 assert_return(!m->sealed, -EPERM);
2305 assert_return(m->n_containers > 0, -EINVAL);
2306 assert_return(!m->poisoned, -ESTALE);
2308 c = message_get_container(m);
2310 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2311 if (c->signature && c->signature[c->index] != 0)
2316 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2317 r = bus_message_close_array(m, c);
2318 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2319 r = bus_message_close_variant(m, c);
2320 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2321 r = bus_message_close_struct(m, c, true);
2323 assert_not_reached("Unknown container type");
2337 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2344 stack[*i].types = types;
2345 stack[*i].n_struct = n_struct;
2346 stack[*i].n_array = n_array;
2352 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2363 *types = stack[*i].types;
2364 *n_struct = stack[*i].n_struct;
2365 *n_array = stack[*i].n_array;
2370 int bus_message_append_ap(
2375 unsigned n_array, n_struct;
2376 TypeStack stack[BUS_CONTAINER_DEPTH];
2377 unsigned stack_ptr = 0;
2385 n_array = (unsigned) -1;
2386 n_struct = strlen(types);
2391 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2392 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2398 r = sd_bus_message_close_container(m);
2406 if (n_array != (unsigned) -1)
2415 case SD_BUS_TYPE_BYTE: {
2418 x = (uint8_t) va_arg(ap, int);
2419 r = sd_bus_message_append_basic(m, *t, &x);
2423 case SD_BUS_TYPE_BOOLEAN:
2424 case SD_BUS_TYPE_INT32:
2425 case SD_BUS_TYPE_UINT32:
2426 case SD_BUS_TYPE_UNIX_FD: {
2429 /* We assume a boolean is the same as int32_t */
2430 assert_cc(sizeof(int32_t) == sizeof(int));
2432 x = va_arg(ap, uint32_t);
2433 r = sd_bus_message_append_basic(m, *t, &x);
2437 case SD_BUS_TYPE_INT16:
2438 case SD_BUS_TYPE_UINT16: {
2441 x = (uint16_t) va_arg(ap, int);
2442 r = sd_bus_message_append_basic(m, *t, &x);
2446 case SD_BUS_TYPE_INT64:
2447 case SD_BUS_TYPE_UINT64: {
2450 x = va_arg(ap, uint64_t);
2451 r = sd_bus_message_append_basic(m, *t, &x);
2455 case SD_BUS_TYPE_DOUBLE: {
2458 x = va_arg(ap, double);
2459 r = sd_bus_message_append_basic(m, *t, &x);
2463 case SD_BUS_TYPE_STRING:
2464 case SD_BUS_TYPE_OBJECT_PATH:
2465 case SD_BUS_TYPE_SIGNATURE: {
2468 x = va_arg(ap, const char*);
2469 r = sd_bus_message_append_basic(m, *t, x);
2473 case SD_BUS_TYPE_ARRAY: {
2476 r = signature_element_length(t + 1, &k);
2482 memcpy(s, t + 1, k);
2485 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2490 if (n_array == (unsigned) -1) {
2495 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2501 n_array = va_arg(ap, unsigned);
2506 case SD_BUS_TYPE_VARIANT: {
2509 s = va_arg(ap, const char*);
2513 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2517 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2522 n_struct = strlen(s);
2523 n_array = (unsigned) -1;
2528 case SD_BUS_TYPE_STRUCT_BEGIN:
2529 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2532 r = signature_element_length(t, &k);
2539 memcpy(s, t + 1, k - 2);
2542 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2547 if (n_array == (unsigned) -1) {
2552 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2558 n_array = (unsigned) -1;
2574 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2578 assert_return(m, -EINVAL);
2579 assert_return(types, -EINVAL);
2580 assert_return(!m->sealed, -EPERM);
2581 assert_return(!m->poisoned, -ESTALE);
2583 va_start(ap, types);
2584 r = bus_message_append_ap(m, types, ap);
2590 _public_ int sd_bus_message_append_array_space(
2600 assert_return(m, -EINVAL);
2601 assert_return(!m->sealed, -EPERM);
2602 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2603 assert_return(ptr || size == 0, -EINVAL);
2604 assert_return(!m->poisoned, -ESTALE);
2606 /* alignment and size of the trivial types (except bool) is
2607 * identical for gvariant and dbus1 marshalling */
2608 align = bus_type_get_alignment(type);
2609 sz = bus_type_get_size(type);
2611 assert_se(align > 0);
2617 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2621 a = message_extend_body(m, align, size, false, false);
2625 r = sd_bus_message_close_container(m);
2633 _public_ int sd_bus_message_append_array(
2641 assert_return(m, -EINVAL);
2642 assert_return(!m->sealed, -EPERM);
2643 assert_return(bus_type_is_trivial(type), -EINVAL);
2644 assert_return(ptr || size == 0, -EINVAL);
2645 assert_return(!m->poisoned, -ESTALE);
2647 r = sd_bus_message_append_array_space(m, type, size, &p);
2652 memcpy(p, ptr, size);
2657 /// UNNEEDED by elogind
2659 _public_ int sd_bus_message_append_array_iovec(
2662 const struct iovec *iov,
2670 assert_return(m, -EINVAL);
2671 assert_return(!m->sealed, -EPERM);
2672 assert_return(bus_type_is_trivial(type), -EINVAL);
2673 assert_return(iov || n == 0, -EINVAL);
2674 assert_return(!m->poisoned, -ESTALE);
2676 size = IOVEC_TOTAL_SIZE(iov, n);
2678 r = sd_bus_message_append_array_space(m, type, size, &p);
2682 for (i = 0; i < n; i++) {
2684 if (iov[i].iov_base)
2685 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2687 memzero(p, iov[i].iov_len);
2689 p = (uint8_t*) p + iov[i].iov_len;
2695 _public_ int sd_bus_message_append_array_memfd(
2702 _cleanup_close_ int copy_fd = -1;
2703 struct bus_body_part *part;
2709 assert_return(m, -EINVAL);
2710 assert_return(memfd >= 0, -EBADF);
2711 assert_return(bus_type_is_trivial(type), -EINVAL);
2712 assert_return(size > 0, -EINVAL);
2713 assert_return(!m->sealed, -EPERM);
2714 assert_return(!m->poisoned, -ESTALE);
2716 r = memfd_set_sealed(memfd);
2720 copy_fd = dup(memfd);
2724 r = memfd_get_size(memfd, &real_size);
2728 if (offset == 0 && size == (uint64_t) -1)
2730 else if (offset + size > real_size)
2733 align = bus_type_get_alignment(type);
2734 sz = bus_type_get_size(type);
2736 assert_se(align > 0);
2739 if (offset % align != 0)
2745 if (size > (uint64_t) (uint32_t) -1)
2748 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2752 a = message_extend_body(m, align, 0, false, false);
2756 part = message_append_part(m);
2760 part->memfd = copy_fd;
2761 part->memfd_offset = offset;
2762 part->sealed = true;
2766 m->body_size += size;
2767 message_extend_containers(m, size);
2769 return sd_bus_message_close_container(m);
2772 _public_ int sd_bus_message_append_string_memfd(
2778 _cleanup_close_ int copy_fd = -1;
2779 struct bus_body_part *part;
2780 struct bus_container *c;
2785 assert_return(m, -EINVAL);
2786 assert_return(memfd >= 0, -EBADF);
2787 assert_return(size > 0, -EINVAL);
2788 assert_return(!m->sealed, -EPERM);
2789 assert_return(!m->poisoned, -ESTALE);
2791 r = memfd_set_sealed(memfd);
2795 copy_fd = dup(memfd);
2799 r = memfd_get_size(memfd, &real_size);
2803 if (offset == 0 && size == (uint64_t) -1)
2805 else if (offset + size > real_size)
2808 /* We require this to be NUL terminated */
2812 if (size > (uint64_t) (uint32_t) -1)
2815 c = message_get_container(m);
2816 if (c->signature && c->signature[c->index]) {
2817 /* Container signature is already set */
2819 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2824 /* Maybe we can append to the signature? But only if this is the top-level container */
2825 if (c->enclosing != 0)
2828 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2835 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2836 a = message_extend_body(m, 4, 4, false, false);
2840 *(uint32_t*) a = size - 1;
2843 part = message_append_part(m);
2847 part->memfd = copy_fd;
2848 part->memfd_offset = offset;
2849 part->sealed = true;
2853 m->body_size += size;
2854 message_extend_containers(m, size);
2856 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2857 r = message_add_offset(m, m->body_size);
2864 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2871 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2875 assert_return(m, -EINVAL);
2876 assert_return(!m->sealed, -EPERM);
2877 assert_return(!m->poisoned, -ESTALE);
2879 r = sd_bus_message_open_container(m, 'a', "s");
2883 STRV_FOREACH(i, l) {
2884 r = sd_bus_message_append_basic(m, 's', *i);
2889 return sd_bus_message_close_container(m);
2892 static int bus_message_close_header(sd_bus_message *m) {
2896 /* The actual user data is finished now, we just complete the
2897 variant and struct now (at least on gvariant). Remember
2898 this position, so that during parsing we know where to to
2899 put the outer container end. */
2900 m->user_body_size = m->body_size;
2902 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2903 const char *signature;
2907 /* Add offset table to end of fields array */
2908 if (m->n_header_offsets >= 1) {
2912 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2914 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2915 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2919 for (i = 0; i < m->n_header_offsets; i++)
2920 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2923 /* Add gvariant NUL byte plus signature to the end of
2924 * the body, followed by the final offset pointing to
2925 * the end of the fields array */
2927 signature = strempty(m->root_container.signature);
2928 l = strlen(signature);
2930 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2931 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2936 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2937 memcpy((uint8_t*) d + 2, signature, l);
2938 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2940 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2943 m->footer_accessible = 1 + l + 2 + sz;
2945 m->header->dbus1.fields_size = m->fields_size;
2946 m->header->dbus1.body_size = m->body_size;
2952 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2953 struct bus_body_part *part;
2963 if (m->n_containers > 0)
2969 if (cookie > 0xffffffffULL &&
2970 !BUS_MESSAGE_IS_GVARIANT(m))
2973 /* In vtables the return signature of method calls is listed,
2974 * let's check if they match if this is a response */
2975 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2976 m->enforced_reply_signature &&
2977 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2980 /* If gvariant marshalling is used we need to close the body structure */
2981 r = bus_message_close_struct(m, &m->root_container, false);
2985 /* If there's a non-trivial signature set, then add it in
2986 * here, but only on dbus1 */
2987 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2988 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2994 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2999 r = bus_message_close_header(m);
3003 if (BUS_MESSAGE_IS_GVARIANT(m))
3004 m->header->dbus2.cookie = cookie;
3006 m->header->dbus1.serial = (uint32_t) cookie;
3008 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
3010 /* Add padding at the end of the fields part, since we know
3011 * the body needs to start at an 8 byte alignment. We made
3012 * sure we allocated enough space for this, so all we need to
3013 * do here is to zero it out. */
3014 a = ALIGN8(m->fields_size) - m->fields_size;
3016 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
3018 /* If this is something we can send as memfd, then let's seal
3019 the memfd now. Note that we can send memfds as payload only
3020 for directed messages, and not for broadcasts. */
3021 if (m->destination && m->bus->use_memfd) {
3022 MESSAGE_FOREACH_PART(part, i, m)
3023 if (part->memfd >= 0 &&
3025 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3026 part != m->body_end) { /* The last part may never be sent as memfd */
3029 /* Try to seal it if that makes
3030 * sense. First, unmap our own map to
3031 * make sure we don't keep it busy. */
3032 bus_body_part_unmap(part);
3034 /* Then, sync up real memfd size */
3036 r = memfd_set_size(part->memfd, sz);
3040 /* Finally, try to seal */
3041 if (memfd_set_sealed(part->memfd) >= 0)
3042 part->sealed = true;
3046 m->root_container.end = m->user_body_size;
3047 m->root_container.index = 0;
3048 m->root_container.offset_index = 0;
3049 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3056 int bus_body_part_map(struct bus_body_part *part) {
3065 if (part->size <= 0)
3068 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3069 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3070 static const uint8_t zeroes[7] = { };
3071 part->data = (void*) zeroes;
3075 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3076 psz = PAGE_ALIGN(part->size + shift);
3078 if (part->memfd >= 0)
3079 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3080 else if (part->is_zero)
3081 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3085 if (p == MAP_FAILED)
3089 part->mmap_begin = p;
3090 part->data = (uint8_t*) p + shift;
3091 part->munmap_this = true;
3096 void bus_body_part_unmap(struct bus_body_part *part) {
3100 if (part->memfd < 0)
3103 if (!part->mmap_begin)
3106 if (!part->munmap_this)
3109 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3111 part->mmap_begin = NULL;
3114 part->munmap_this = false;
3119 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3120 size_t k, start, end;
3125 start = ALIGN_TO((size_t) *rindex, align);
3126 end = start + nbytes;
3131 /* Verify that padding is 0 */
3132 for (k = *rindex; k < start; k++)
3133 if (((const uint8_t*) p)[k] != 0)
3137 *r = (uint8_t*) p + start;
3144 static bool message_end_of_signature(sd_bus_message *m) {
3145 struct bus_container *c;
3149 c = message_get_container(m);
3150 return !c->signature || c->signature[c->index] == 0;
3153 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3154 struct bus_container *c;
3158 c = message_get_container(m);
3159 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3162 if (BUS_MESSAGE_IS_GVARIANT(m))
3163 return index >= c->end;
3165 assert(c->array_size);
3166 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3170 /// UNNEEDED by elogind
3172 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3173 assert_return(m, -EINVAL);
3174 assert_return(m->sealed, -EPERM);
3176 if (complete && m->n_containers > 0)
3179 if (message_end_of_signature(m))
3182 if (message_end_of_array(m, m->rindex))
3189 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3190 struct bus_body_part *part;
3196 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3197 part = m->cached_rindex_part;
3198 begin = m->cached_rindex_part_begin;
3208 if (index + sz <= begin + part->size) {
3210 r = bus_body_part_map(part);
3215 *p = (uint8_t*) part->data + index - begin;
3217 m->cached_rindex_part = part;
3218 m->cached_rindex_part_begin = begin;
3223 begin += part->size;
3230 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3237 if (!BUS_MESSAGE_IS_GVARIANT(m))
3240 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3243 sz = bus_gvariant_get_size(c->signature);
3247 if (c->offset_index+1 >= c->n_offsets)
3250 /* Variable-size array */
3252 alignment = bus_gvariant_get_alignment(c->signature);
3253 assert(alignment > 0);
3255 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3256 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3259 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3262 /* Fixed-size array */
3263 *rindex = c->begin + (c->offset_index+1) * sz;
3269 } else if (c->enclosing == 0 ||
3270 c->enclosing == SD_BUS_TYPE_STRUCT ||
3271 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3276 if (c->offset_index+1 >= c->n_offsets)
3279 r = signature_element_length(c->signature + c->index, &n);
3283 r = signature_element_length(c->signature + c->index + n, &j);
3288 memcpy(t, c->signature + c->index + n, j);
3291 alignment = bus_gvariant_get_alignment(t);
3294 assert(alignment > 0);
3296 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3297 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3301 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3304 assert_not_reached("Unknown container type");
3309 /* Reached the end */
3316 static int message_peek_body(
3323 size_t k, start, end, padding;
3324 struct bus_body_part *part;
3331 start = ALIGN_TO((size_t) *rindex, align);
3332 padding = start - *rindex;
3333 end = start + nbytes;
3335 if (end > m->user_body_size)
3338 part = find_part(m, *rindex, padding, (void**) &q);
3343 /* Verify padding */
3344 for (k = 0; k < padding; k++)
3349 part = find_part(m, start, nbytes, (void**) &q);
3350 if (!part || (nbytes > 0 && !q))
3361 static bool validate_nul(const char *s, size_t l) {
3363 /* Check for NUL chars in the string */
3364 if (memchr(s, 0, l))
3367 /* Check for NUL termination */
3374 static bool validate_string(const char *s, size_t l) {
3376 if (!validate_nul(s, l))
3379 /* Check if valid UTF8 */
3380 if (!utf8_is_valid(s))
3386 static bool validate_signature(const char *s, size_t l) {
3388 if (!validate_nul(s, l))
3391 /* Check if valid signature */
3392 if (!signature_is_valid(s, true))
3398 static bool validate_object_path(const char *s, size_t l) {
3400 if (!validate_nul(s, l))
3403 if (!object_path_is_valid(s))
3409 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3410 struct bus_container *c;
3415 assert_return(m, -EINVAL);
3416 assert_return(m->sealed, -EPERM);
3417 assert_return(bus_type_is_basic(type), -EINVAL);
3419 if (message_end_of_signature(m))
3422 if (message_end_of_array(m, m->rindex))
3425 c = message_get_container(m);
3426 if (c->signature[c->index] != type)
3431 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3433 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3436 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3440 if (type == SD_BUS_TYPE_STRING)
3441 ok = validate_string(q, c->item_size-1);
3442 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3443 ok = validate_object_path(q, c->item_size-1);
3445 ok = validate_signature(q, c->item_size-1);
3451 *(const char**) p = q;
3455 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3457 if ((size_t) sz != c->item_size)
3460 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3463 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3469 case SD_BUS_TYPE_BYTE:
3471 *(uint8_t*) p = *(uint8_t*) q;
3474 case SD_BUS_TYPE_BOOLEAN:
3476 *(int*) p = !!*(uint8_t*) q;
3479 case SD_BUS_TYPE_INT16:
3480 case SD_BUS_TYPE_UINT16:
3482 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3485 case SD_BUS_TYPE_INT32:
3486 case SD_BUS_TYPE_UINT32:
3488 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3491 case SD_BUS_TYPE_INT64:
3492 case SD_BUS_TYPE_UINT64:
3493 case SD_BUS_TYPE_DOUBLE:
3495 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3498 case SD_BUS_TYPE_UNIX_FD: {
3501 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3506 *(int*) p = m->fds[j];
3512 assert_not_reached("unexpected type");
3516 r = container_next_item(m, c, &rindex);
3521 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3525 r = message_peek_body(m, &rindex, 4, 4, &q);
3529 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3530 r = message_peek_body(m, &rindex, 1, l+1, &q);
3534 if (type == SD_BUS_TYPE_OBJECT_PATH)
3535 ok = validate_object_path(q, l);
3537 ok = validate_string(q, l);
3542 *(const char**) p = q;
3544 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3547 r = message_peek_body(m, &rindex, 1, 1, &q);
3552 r = message_peek_body(m, &rindex, 1, l+1, &q);
3556 if (!validate_signature(q, l))
3560 *(const char**) p = q;
3565 align = bus_type_get_alignment(type);
3568 sz = bus_type_get_size(type);
3571 r = message_peek_body(m, &rindex, align, sz, &q);
3577 case SD_BUS_TYPE_BYTE:
3579 *(uint8_t*) p = *(uint8_t*) q;
3582 case SD_BUS_TYPE_BOOLEAN:
3584 *(int*) p = !!*(uint32_t*) q;
3587 case SD_BUS_TYPE_INT16:
3588 case SD_BUS_TYPE_UINT16:
3590 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3593 case SD_BUS_TYPE_INT32:
3594 case SD_BUS_TYPE_UINT32:
3596 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3599 case SD_BUS_TYPE_INT64:
3600 case SD_BUS_TYPE_UINT64:
3601 case SD_BUS_TYPE_DOUBLE:
3603 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3606 case SD_BUS_TYPE_UNIX_FD: {
3609 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3614 *(int*) p = m->fds[j];
3619 assert_not_reached("Unknown basic type...");
3626 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3632 static int bus_message_enter_array(
3634 struct bus_container *c,
3635 const char *contents,
3636 uint32_t **array_size,
3639 size_t *n_offsets) {
3653 if (!signature_is_single(contents, true))
3656 if (!c->signature || c->signature[c->index] == 0)
3659 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3662 if (!startswith(c->signature + c->index + 1, contents))
3667 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3670 r = message_peek_body(m, &rindex, 4, 4, &q);
3674 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3677 alignment = bus_type_get_alignment(contents[0]);
3681 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3685 *array_size = (uint32_t*) q;
3687 } else if (c->item_size <= 0) {
3689 /* gvariant: empty array */
3694 } else if (bus_gvariant_is_fixed_size(contents)) {
3696 /* gvariant: fixed length array */
3697 *item_size = bus_gvariant_get_size(contents);
3702 size_t where, p = 0, framing, sz;
3705 /* gvariant: variable length array */
3706 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3708 where = rindex + c->item_size - sz;
3709 r = message_peek_body(m, &where, 1, sz, &q);
3713 framing = bus_gvariant_read_word_le(q, sz);
3714 if (framing > c->item_size - sz)
3716 if ((c->item_size - framing) % sz != 0)
3719 *n_offsets = (c->item_size - framing) / sz;
3721 where = rindex + framing;
3722 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3726 *offsets = new(size_t, *n_offsets);
3730 for (i = 0; i < *n_offsets; i++) {
3733 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3734 if (x > c->item_size - sz)
3739 (*offsets)[i] = rindex + x;
3743 *item_size = (*offsets)[0] - rindex;
3748 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3749 c->index += 1 + strlen(contents);
3754 static int bus_message_enter_variant(
3756 struct bus_container *c,
3757 const char *contents,
3758 size_t *item_size) {
3770 if (!signature_is_single(contents, false))
3773 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3776 if (!c->signature || c->signature[c->index] == 0)
3779 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3784 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3787 k = strlen(contents);
3788 if (1+k > c->item_size)
3791 where = rindex + c->item_size - (1+k);
3792 r = message_peek_body(m, &where, 1, 1+k, &q);
3796 if (*(char*) q != 0)
3799 if (memcmp((uint8_t*) q+1, contents, k))
3802 *item_size = c->item_size - (1+k);
3805 r = message_peek_body(m, &rindex, 1, 1, &q);
3810 r = message_peek_body(m, &rindex, 1, l+1, &q);
3814 if (!validate_signature(q, l))
3817 if (!streq(q, contents))
3823 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3829 static int build_struct_offsets(
3831 const char *signature,
3835 size_t *n_offsets) {
3837 unsigned n_variable = 0, n_total = 0, v;
3838 size_t previous = 0, where;
3849 if (isempty(signature)) {
3850 /* Unary type is encoded as *fixed* 1 byte padding */
3851 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3855 if (*(uint8_t *) q != 0)
3864 sz = bus_gvariant_determine_word_size(size, 0);
3868 /* First, loop over signature and count variable elements and
3869 * elements in general. We use this to know how large the
3870 * offset array is at the end of the structure. Note that
3871 * GVariant only stores offsets for all variable size elements
3872 * that are not the last item. */
3878 r = signature_element_length(p, &n);
3887 r = bus_gvariant_is_fixed_size(t);
3892 if (r == 0 && p[n] != 0) /* except the last item */
3899 if (size < n_variable * sz)
3902 where = m->rindex + size - (n_variable * sz);
3903 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3909 *offsets = new(size_t, n_total);
3915 /* Second, loop again and build an offset table */
3921 r = signature_element_length(p, &n);
3930 k = bus_gvariant_get_size(t);
3938 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3941 if (m->rindex + x < previous)
3944 /* The last item's end
3945 * is determined from
3948 x = size - (n_variable * sz);
3950 offset = m->rindex + x;
3956 align = bus_gvariant_get_alignment(t);
3959 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3963 previous = (*offsets)[(*n_offsets)++] = offset;
3968 assert(*n_offsets == n_total);
3970 *item_size = (*offsets)[0] - m->rindex;
3974 static int enter_struct_or_dict_entry(
3976 struct bus_container *c,
3977 const char *contents,
3980 size_t *n_offsets) {
3991 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3994 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3999 /* gvariant with contents */
4000 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
4005 static int bus_message_enter_struct(
4007 struct bus_container *c,
4008 const char *contents,
4011 size_t *n_offsets) {
4023 if (!signature_is_valid(contents, false))
4026 if (!c->signature || c->signature[c->index] == 0)
4029 l = strlen(contents);
4031 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4032 !startswith(c->signature + c->index + 1, contents) ||
4033 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4036 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4040 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4041 c->index += 1 + l + 1;
4046 static int bus_message_enter_dict_entry(
4048 struct bus_container *c,
4049 const char *contents,
4052 size_t *n_offsets) {
4061 if (!signature_is_pair(contents))
4064 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4067 if (!c->signature || c->signature[c->index] == 0)
4070 l = strlen(contents);
4072 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4073 !startswith(c->signature + c->index + 1, contents) ||
4074 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4077 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4081 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4082 c->index += 1 + l + 1;
4087 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4089 const char *contents) {
4090 struct bus_container *c, *w;
4091 uint32_t *array_size = NULL;
4094 size_t *offsets = NULL;
4095 size_t n_offsets = 0, item_size = 0;
4098 assert_return(m, -EINVAL);
4099 assert_return(m->sealed, -EPERM);
4100 assert_return(type != 0 || !contents, -EINVAL);
4102 if (type == 0 || !contents) {
4106 /* Allow entering into anonymous containers */
4107 r = sd_bus_message_peek_type(m, &tt, &cc);
4111 if (type != 0 && type != tt)
4114 if (contents && !streq(contents, cc))
4122 * We enforce a global limit on container depth, that is much
4123 * higher than the 32 structs and 32 arrays the specification
4124 * mandates. This is simpler to implement for us, and we need
4125 * this only to ensure our container array doesn't grow
4126 * without bounds. We are happy to return any data from a
4127 * message as long as the data itself is valid, even if the
4128 * overall message might be not.
4130 * Note that the message signature is validated when
4131 * parsing the headers, and that validation does check the
4134 * Note that the specification defines no limits on the depth
4135 * of stacked variants, but we do.
4137 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4140 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4143 if (message_end_of_signature(m))
4146 if (message_end_of_array(m, m->rindex))
4149 c = message_get_container(m);
4151 signature = strdup(contents);
4155 c->saved_index = c->index;
4158 if (type == SD_BUS_TYPE_ARRAY)
4159 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4160 else if (type == SD_BUS_TYPE_VARIANT)
4161 r = bus_message_enter_variant(m, c, contents, &item_size);
4162 else if (type == SD_BUS_TYPE_STRUCT)
4163 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4164 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4165 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4175 /* OK, let's fill it in */
4176 w = m->containers + m->n_containers++;
4177 w->enclosing = type;
4178 w->signature = signature;
4179 w->peeked_signature = NULL;
4183 w->begin = m->rindex;
4185 /* Unary type has fixed size of 1, but virtual size of 0 */
4186 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4187 type == SD_BUS_TYPE_STRUCT &&
4189 w->end = m->rindex + 0;
4191 w->end = m->rindex + c->item_size;
4193 w->array_size = array_size;
4194 w->item_size = item_size;
4195 w->offsets = offsets;
4196 w->n_offsets = n_offsets;
4197 w->offset_index = 0;
4202 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4203 struct bus_container *c;
4207 assert_return(m, -EINVAL);
4208 assert_return(m->sealed, -EPERM);
4209 assert_return(m->n_containers > 0, -ENXIO);
4211 c = message_get_container(m);
4213 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4214 if (c->signature && c->signature[c->index] != 0)
4218 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4219 if (m->rindex < c->end)
4222 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4225 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4226 if (c->begin + l != m->rindex)
4231 free(c->peeked_signature);
4235 c = message_get_container(m);
4238 c->index = c->saved_index;
4239 r = container_next_item(m, c, &m->rindex);
4247 static void message_quit_container(sd_bus_message *m) {
4248 struct bus_container *c;
4252 assert(m->n_containers > 0);
4254 c = message_get_container(m);
4257 assert(m->rindex >= c->before);
4258 m->rindex = c->before;
4260 /* Free container */
4265 /* Correct index of new top-level container */
4266 c = message_get_container(m);
4267 c->index = c->saved_index;
4270 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4271 struct bus_container *c;
4274 assert_return(m, -EINVAL);
4275 assert_return(m->sealed, -EPERM);
4277 if (message_end_of_signature(m))
4280 if (message_end_of_array(m, m->rindex))
4283 c = message_get_container(m);
4285 if (bus_type_is_basic(c->signature[c->index])) {
4289 *type = c->signature[c->index];
4293 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4299 r = signature_element_length(c->signature+c->index+1, &l);
4305 sig = strndup(c->signature + c->index + 1, l);
4309 free(c->peeked_signature);
4310 *contents = c->peeked_signature = sig;
4314 *type = SD_BUS_TYPE_ARRAY;
4319 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4320 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4326 r = signature_element_length(c->signature+c->index, &l);
4331 sig = strndup(c->signature + c->index + 1, l - 2);
4335 free(c->peeked_signature);
4336 *contents = c->peeked_signature = sig;
4340 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4345 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4349 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4352 if (c->item_size < 2)
4355 /* Look for the NUL delimiter that
4356 separates the payload from the
4357 signature. Since the body might be
4358 in a different part that then the
4359 signature we map byte by byte. */
4361 for (k = 2; k <= c->item_size; k++) {
4364 where = m->rindex + c->item_size - k;
4365 r = message_peek_body(m, &where, 1, k, &q);
4369 if (*(char*) q == 0)
4373 if (k > c->item_size)
4376 free(c->peeked_signature);
4377 c->peeked_signature = strndup((char*) q + 1, k - 1);
4378 if (!c->peeked_signature)
4381 if (!signature_is_valid(c->peeked_signature, true))
4384 *contents = c->peeked_signature;
4389 r = message_peek_body(m, &rindex, 1, 1, &q);
4394 r = message_peek_body(m, &rindex, 1, l+1, &q);
4398 if (!validate_signature(q, l))
4406 *type = SD_BUS_TYPE_VARIANT;
4421 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4422 struct bus_container *c;
4424 assert_return(m, -EINVAL);
4425 assert_return(m->sealed, -EPERM);
4428 message_reset_containers(m);
4431 c = message_get_container(m);
4433 c = message_get_container(m);
4435 c->offset_index = 0;
4437 m->rindex = c->begin;
4440 c->offset_index = 0;
4441 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4443 return !isempty(c->signature);
4446 static int message_read_ap(
4451 unsigned n_array, n_struct;
4452 TypeStack stack[BUS_CONTAINER_DEPTH];
4453 unsigned stack_ptr = 0;
4454 unsigned n_loop = 0;
4462 /* Ideally, we'd just call ourselves recursively on every
4463 * complex type. However, the state of a va_list that is
4464 * passed to a function is undefined after that function
4465 * returns. This means we need to docode the va_list linearly
4466 * in a single stackframe. We hence implement our own
4467 * home-grown stack in an array. */
4469 n_array = (unsigned) -1; /* length of current array entries */
4470 n_struct = strlen(types); /* length of current struct contents signature */
4477 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4478 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4484 r = sd_bus_message_exit_container(m);
4492 if (n_array != (unsigned) -1)
4501 case SD_BUS_TYPE_BYTE:
4502 case SD_BUS_TYPE_BOOLEAN:
4503 case SD_BUS_TYPE_INT16:
4504 case SD_BUS_TYPE_UINT16:
4505 case SD_BUS_TYPE_INT32:
4506 case SD_BUS_TYPE_UINT32:
4507 case SD_BUS_TYPE_INT64:
4508 case SD_BUS_TYPE_UINT64:
4509 case SD_BUS_TYPE_DOUBLE:
4510 case SD_BUS_TYPE_STRING:
4511 case SD_BUS_TYPE_OBJECT_PATH:
4512 case SD_BUS_TYPE_SIGNATURE:
4513 case SD_BUS_TYPE_UNIX_FD: {
4516 p = va_arg(ap, void*);
4517 r = sd_bus_message_read_basic(m, *t, p);
4530 case SD_BUS_TYPE_ARRAY: {
4533 r = signature_element_length(t + 1, &k);
4539 memcpy(s, t + 1, k);
4542 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4553 if (n_array == (unsigned) -1) {
4558 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4564 n_array = va_arg(ap, unsigned);
4569 case SD_BUS_TYPE_VARIANT: {
4572 s = va_arg(ap, const char *);
4576 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4586 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4591 n_struct = strlen(s);
4592 n_array = (unsigned) -1;
4597 case SD_BUS_TYPE_STRUCT_BEGIN:
4598 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4601 r = signature_element_length(t, &k);
4607 memcpy(s, t + 1, k - 2);
4610 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4620 if (n_array == (unsigned) -1) {
4625 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4631 n_array = (unsigned) -1;
4644 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4648 assert_return(m, -EINVAL);
4649 assert_return(m->sealed, -EPERM);
4650 assert_return(types, -EINVAL);
4652 va_start(ap, types);
4653 r = message_read_ap(m, types, ap);
4659 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4662 assert_return(m, -EINVAL);
4663 assert_return(m->sealed, -EPERM);
4665 /* If types is NULL, read exactly one element */
4667 struct bus_container *c;
4670 if (message_end_of_signature(m))
4673 if (message_end_of_array(m, m->rindex))
4676 c = message_get_container(m);
4678 r = signature_element_length(c->signature + c->index, &l);
4682 types = strndupa(c->signature + c->index, l);
4687 case 0: /* Nothing to drop */
4690 case SD_BUS_TYPE_BYTE:
4691 case SD_BUS_TYPE_BOOLEAN:
4692 case SD_BUS_TYPE_INT16:
4693 case SD_BUS_TYPE_UINT16:
4694 case SD_BUS_TYPE_INT32:
4695 case SD_BUS_TYPE_UINT32:
4696 case SD_BUS_TYPE_INT64:
4697 case SD_BUS_TYPE_UINT64:
4698 case SD_BUS_TYPE_DOUBLE:
4699 case SD_BUS_TYPE_STRING:
4700 case SD_BUS_TYPE_OBJECT_PATH:
4701 case SD_BUS_TYPE_SIGNATURE:
4702 case SD_BUS_TYPE_UNIX_FD:
4704 r = sd_bus_message_read_basic(m, *types, NULL);
4708 r = sd_bus_message_skip(m, types + 1);
4714 case SD_BUS_TYPE_ARRAY: {
4717 r = signature_element_length(types + 1, &k);
4723 memcpy(s, types+1, k);
4726 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4731 r = sd_bus_message_skip(m, s);
4738 r = sd_bus_message_exit_container(m);
4743 r = sd_bus_message_skip(m, types + 1 + k);
4750 case SD_BUS_TYPE_VARIANT: {
4751 const char *contents;
4754 r = sd_bus_message_peek_type(m, &x, &contents);
4758 if (x != SD_BUS_TYPE_VARIANT)
4761 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4765 r = sd_bus_message_skip(m, contents);
4770 r = sd_bus_message_exit_container(m);
4774 r = sd_bus_message_skip(m, types + 1);
4781 case SD_BUS_TYPE_STRUCT_BEGIN:
4782 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4785 r = signature_element_length(types, &k);
4791 memcpy(s, types+1, k-2);
4794 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4798 r = sd_bus_message_skip(m, s);
4802 r = sd_bus_message_exit_container(m);
4807 r = sd_bus_message_skip(m, types + k);
4819 _public_ int sd_bus_message_read_array(
4825 struct bus_container *c;
4831 assert_return(m, -EINVAL);
4832 assert_return(m->sealed, -EPERM);
4833 assert_return(bus_type_is_trivial(type), -EINVAL);
4834 assert_return(ptr, -EINVAL);
4835 assert_return(size, -EINVAL);
4836 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4838 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4842 c = message_get_container(m);
4844 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4845 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4849 sz = c->end - c->begin;
4851 align = bus_type_get_alignment(type);
4855 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4859 /* Zero length array, let's return some aligned
4860 * pointer that is not NULL */
4861 p = (uint8_t*) NULL + align;
4863 r = message_peek_body(m, &m->rindex, align, sz, &p);
4868 r = sd_bus_message_exit_container(m);
4872 *ptr = (const void*) p;
4878 message_quit_container(m);
4882 static int message_peek_fields(
4893 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4896 static int message_peek_field_uint32(
4908 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4911 /* identical for gvariant and dbus1 */
4913 r = message_peek_fields(m, ri, 4, 4, &q);
4918 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4923 static int message_peek_field_uint64(
4935 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4938 /* identical for gvariant and dbus1 */
4940 r = message_peek_fields(m, ri, 8, 8, &q);
4945 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4950 static int message_peek_field_string(
4952 bool (*validate)(const char *p),
4964 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4969 r = message_peek_fields(m, ri, 1, item_size, &q);
4975 r = message_peek_field_uint32(m, ri, 4, &l);
4979 r = message_peek_fields(m, ri, 1, l+1, &q);
4985 if (!validate_nul(q, l))
4991 if (!validate_string(q, l))
5001 static int message_peek_field_signature(
5014 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5019 r = message_peek_fields(m, ri, 1, item_size, &q);
5025 r = message_peek_fields(m, ri, 1, 1, &q);
5030 r = message_peek_fields(m, ri, 1, l+1, &q);
5035 if (!validate_signature(q, l))
5044 static int message_skip_fields(
5047 uint32_t array_size,
5048 const char **signature) {
5050 size_t original_index;
5056 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5058 original_index = *ri;
5064 if (array_size != (uint32_t) -1 &&
5065 array_size <= *ri - original_index)
5072 if (t == SD_BUS_TYPE_STRING) {
5074 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5080 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5082 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5088 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5090 r = message_peek_field_signature(m, ri, 0, NULL);
5096 } else if (bus_type_is_basic(t)) {
5099 align = bus_type_get_alignment(t);
5100 k = bus_type_get_size(t);
5101 assert(align > 0 && k > 0);
5103 r = message_peek_fields(m, ri, align, k, NULL);
5109 } else if (t == SD_BUS_TYPE_ARRAY) {
5111 r = signature_element_length(*signature+1, &l);
5121 strncpy(sig, *signature + 1, l-1);
5124 alignment = bus_type_get_alignment(sig[0]);
5128 r = message_peek_field_uint32(m, ri, 0, &nas);
5131 if (nas > BUS_ARRAY_MAX_SIZE)
5134 r = message_peek_fields(m, ri, alignment, 0, NULL);
5138 r = message_skip_fields(m, ri, nas, (const char**) &s);
5143 (*signature) += 1 + l;
5145 } else if (t == SD_BUS_TYPE_VARIANT) {
5148 r = message_peek_field_signature(m, ri, 0, &s);
5152 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5158 } else if (t == SD_BUS_TYPE_STRUCT ||
5159 t == SD_BUS_TYPE_DICT_ENTRY) {
5161 r = signature_element_length(*signature, &l);
5168 strncpy(sig, *signature + 1, l-1);
5171 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5182 int bus_message_parse_fields(sd_bus_message *m) {
5185 uint32_t unix_fds = 0;
5186 bool unix_fds_set = false;
5187 void *offsets = NULL;
5188 unsigned n_offsets = 0;
5194 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5197 /* Read the signature from the end of the body variant first */
5198 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5199 if (m->footer_accessible < 1 + sz)
5202 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5204 if (p < (char*) m->footer)
5211 /* We found the beginning of the signature
5212 * string, yay! We require the body to be a
5213 * structure, so verify it and then strip the
5214 * opening/closing brackets. */
5216 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5218 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5219 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5222 c = strndup(p + 1 + 1, l - 2);
5226 free(m->root_container.signature);
5227 m->root_container.signature = c;
5234 /* Calculate the actual user body size, by removing
5235 * the trailing variant signature and struct offset
5237 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5239 /* Pull out the offset table for the fields array */
5240 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5245 ri = m->fields_size - sz;
5246 r = message_peek_fields(m, &ri, 1, sz, &q);
5250 framing = bus_gvariant_read_word_le(q, sz);
5251 if (framing >= m->fields_size - sz)
5253 if ((m->fields_size - framing) % sz != 0)
5257 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5261 n_offsets = (m->fields_size - framing) / sz;
5264 m->user_body_size = m->body_size;
5267 while (ri < m->fields_size) {
5268 _cleanup_free_ char *sig = NULL;
5269 const char *signature;
5270 uint64_t field_type;
5271 size_t item_size = (size_t) -1;
5273 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5282 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5284 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5288 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5292 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5299 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5304 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5309 where = ri = ALIGN_TO(ri, 8);
5310 item_size = end - ri;
5311 r = message_peek_fields(m, &where, 1, item_size, &q);
5315 b = memrchr(q, 0, item_size);
5319 sig = strndup(b+1, item_size - (b+1-(char*) q));
5324 item_size = b - (char*) q;
5326 r = message_peek_field_signature(m, &ri, 0, &signature);
5331 switch (field_type) {
5333 case _BUS_MESSAGE_HEADER_INVALID:
5336 case BUS_MESSAGE_HEADER_PATH:
5341 if (!streq(signature, "o"))
5344 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5347 case BUS_MESSAGE_HEADER_INTERFACE:
5352 if (!streq(signature, "s"))
5355 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5358 case BUS_MESSAGE_HEADER_MEMBER:
5363 if (!streq(signature, "s"))
5366 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5369 case BUS_MESSAGE_HEADER_ERROR_NAME:
5374 if (!streq(signature, "s"))
5377 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5379 m->error._need_free = -1;
5383 case BUS_MESSAGE_HEADER_DESTINATION:
5388 if (!streq(signature, "s"))
5391 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5394 case BUS_MESSAGE_HEADER_SENDER:
5399 if (!streq(signature, "s"))
5402 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5404 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5405 m->creds.unique_name = (char*) m->sender;
5406 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5412 case BUS_MESSAGE_HEADER_SIGNATURE: {
5416 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5419 if (m->root_container.signature)
5422 if (!streq(signature, "g"))
5425 r = message_peek_field_signature(m, &ri, item_size, &s);
5433 free(m->root_container.signature);
5434 m->root_container.signature = c;
5438 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5440 if (m->reply_cookie != 0)
5443 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5444 /* 64bit on dbus2 */
5446 if (!streq(signature, "t"))
5449 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5453 /* 32bit on dbus1 */
5456 if (!streq(signature, "u"))
5459 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5463 m->reply_cookie = serial;
5466 if (m->reply_cookie == 0)
5471 case BUS_MESSAGE_HEADER_UNIX_FDS:
5475 if (!streq(signature, "u"))
5478 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5482 unix_fds_set = true;
5486 if (!BUS_MESSAGE_IS_GVARIANT(m))
5487 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5496 if (m->n_fds != unix_fds)
5499 switch (m->header->type) {
5501 case SD_BUS_MESSAGE_SIGNAL:
5502 if (!m->path || !m->interface || !m->member)
5505 if (m->reply_cookie != 0)
5510 case SD_BUS_MESSAGE_METHOD_CALL:
5512 if (!m->path || !m->member)
5515 if (m->reply_cookie != 0)
5520 case SD_BUS_MESSAGE_METHOD_RETURN:
5522 if (m->reply_cookie == 0)
5526 case SD_BUS_MESSAGE_METHOD_ERROR:
5528 if (m->reply_cookie == 0 || !m->error.name)
5533 /* Refuse non-local messages that claim they are local */
5534 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5536 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5538 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5541 m->root_container.end = m->user_body_size;
5543 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5544 r = build_struct_offsets(
5546 m->root_container.signature,
5548 &m->root_container.item_size,
5549 &m->root_container.offsets,
5550 &m->root_container.n_offsets);
5555 /* Try to read the error message, but if we can't it's a non-issue */
5556 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5557 (void) sd_bus_message_read(m, "s", &m->error.message);
5562 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5563 assert_return(m, -EINVAL);
5564 assert_return(destination, -EINVAL);
5565 assert_return(!m->sealed, -EPERM);
5566 assert_return(!m->destination, -EEXIST);
5568 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5571 /// UNNEEDED by elogind
5573 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5577 struct bus_body_part *part;
5583 total = BUS_MESSAGE_SIZE(m);
5589 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5590 MESSAGE_FOREACH_PART(part, i, m)
5591 e = mempcpy(e, part->data, part->size);
5593 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5602 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5609 r = sd_bus_message_enter_container(m, 'a', "s");
5613 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5614 r = strv_extend(l, s);
5621 r = sd_bus_message_exit_container(m);
5628 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5632 assert_return(m, -EINVAL);
5633 assert_return(m->sealed, -EPERM);
5634 assert_return(l, -EINVAL);
5636 r = bus_message_read_strv_extend(m, &strv);
5646 static int bus_message_get_arg_skip(
5650 const char **_contents) {
5655 r = sd_bus_message_rewind(m, true);
5660 const char *contents;
5663 r = sd_bus_message_peek_type(m, &type, &contents);
5669 /* Don't match against arguments after the first one we don't understand */
5670 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5671 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5676 *_contents = contents;
5682 r = sd_bus_message_skip(m, NULL);
5689 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5696 r = bus_message_get_arg_skip(m, i, &type, NULL);
5700 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5703 return sd_bus_message_read_basic(m, type, str);
5706 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5707 const char *contents;
5714 r = bus_message_get_arg_skip(m, i, &type, &contents);
5718 if (type != SD_BUS_TYPE_ARRAY)
5720 if (!STR_IN_SET(contents, "s", "o", "g"))
5723 return sd_bus_message_read_strv(m, strv);
5726 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5727 assert_return(m, EINVAL);
5729 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5732 return sd_bus_error_get_errno(&m->error);
5735 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5736 struct bus_container *c;
5738 assert_return(m, NULL);
5740 c = complete ? &m->root_container : message_get_container(m);
5741 return strempty(c->signature);
5744 /// UNNEEDED by elogind
5746 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5747 assert_return(m, -EINVAL);
5749 return isempty(m->root_container.signature);
5752 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5753 assert_return(m, -EINVAL);
5755 return streq(strempty(m->root_container.signature), strempty(signature));
5759 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5760 bool done_something = false;
5763 assert_return(m, -EINVAL);
5764 assert_return(source, -EINVAL);
5765 assert_return(!m->sealed, -EPERM);
5766 assert_return(source->sealed, -EPERM);
5769 const char *contents;
5784 r = sd_bus_message_peek_type(source, &type, &contents);
5790 done_something = true;
5792 if (bus_type_is_container(type) > 0) {
5794 r = sd_bus_message_enter_container(source, type, contents);
5798 r = sd_bus_message_open_container(m, type, contents);
5802 r = sd_bus_message_copy(m, source, true);
5806 r = sd_bus_message_close_container(m);
5810 r = sd_bus_message_exit_container(source);
5817 r = sd_bus_message_read_basic(source, type, &basic);
5823 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5824 type == SD_BUS_TYPE_SIGNATURE ||
5825 type == SD_BUS_TYPE_STRING)
5826 r = sd_bus_message_append_basic(m, type, basic.string);
5828 r = sd_bus_message_append_basic(m, type, &basic);
5835 return done_something;
5838 /// UNNEEDED by elogind
5840 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5845 assert_return(m, -EINVAL);
5846 assert_return(m->sealed, -EPERM);
5847 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5848 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5849 assert_return(type || contents, -EINVAL);
5850 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5852 r = sd_bus_message_peek_type(m, &t, &c);
5856 if (type != 0 && type != t)
5859 if (contents && !streq_ptr(contents, c))
5866 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5867 assert_return(m, NULL);
5872 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5873 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5881 switch ((*m)->header->type) {
5883 case SD_BUS_MESSAGE_SIGNAL:
5884 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5890 case SD_BUS_MESSAGE_METHOD_CALL:
5891 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5897 case SD_BUS_MESSAGE_METHOD_RETURN:
5898 case SD_BUS_MESSAGE_METHOD_ERROR:
5900 n = message_new(bus, (*m)->header->type);
5904 n->reply_cookie = (*m)->reply_cookie;
5906 r = message_append_reply_cookie(n, n->reply_cookie);
5910 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5911 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5915 n->error._need_free = -1;
5924 if ((*m)->destination && !n->destination) {
5925 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5930 if ((*m)->sender && !n->sender) {
5931 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5936 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5938 r = sd_bus_message_copy(n, *m, true);
5942 timeout = (*m)->timeout;
5943 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5944 timeout = BUS_DEFAULT_TIMEOUT;
5946 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5950 sd_bus_message_unref(*m);
5957 /// UNNEEDED by elogind
5959 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5963 assert_return(!m->sealed, -EPERM);
5964 assert_return(!m->sender, -EPERM);
5966 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5969 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5970 assert_return(m, -EINVAL);
5971 assert_return(priority, -EINVAL);
5973 *priority = m->priority;
5977 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5978 assert_return(m, -EINVAL);
5979 assert_return(!m->sealed, -EPERM);
5981 m->priority = priority;