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;
1152 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1153 assert_return(m, -EINVAL);
1154 assert_return(!m->sealed, -EPERM);
1157 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1159 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1164 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1165 assert_return(m, -EINVAL);
1166 assert_return(!m->sealed, -EPERM);
1169 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1171 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1177 static struct bus_container *message_get_container(sd_bus_message *m) {
1180 if (m->n_containers == 0)
1181 return &m->root_container;
1183 assert(m->containers);
1184 return m->containers + m->n_containers - 1;
1187 struct bus_body_part *message_append_part(sd_bus_message *m) {
1188 struct bus_body_part *part;
1195 if (m->n_body_parts <= 0) {
1199 assert(m->body_end);
1201 part = new0(struct bus_body_part, 1);
1207 m->body_end->next = part;
1217 static void part_zero(struct bus_body_part *part, size_t sz) {
1222 /* All other fields can be left in their defaults */
1223 assert(!part->data);
1224 assert(part->memfd < 0);
1227 part->is_zero = true;
1228 part->sealed = true;
1231 static int part_make_space(
1232 struct sd_bus_message *m,
1233 struct bus_body_part *part,
1242 assert(!part->sealed);
1247 if (!part->data && part->memfd < 0) {
1248 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1249 part->mmap_begin = part->data;
1252 if (part->memfd >= 0) {
1254 if (part->allocated == 0 || sz > part->allocated) {
1255 uint64_t new_allocated;
1257 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1258 r = memfd_set_size(part->memfd, new_allocated);
1264 part->allocated = new_allocated;
1267 if (!part->data || sz > part->mapped) {
1270 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1271 if (part->mapped <= 0)
1272 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1274 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1276 if (n == MAP_FAILED) {
1281 part->mmap_begin = part->data = n;
1283 part->memfd_offset = 0;
1286 part->munmap_this = true;
1288 if (part->allocated == 0 || sz > part->allocated) {
1289 size_t new_allocated;
1291 new_allocated = sz > 0 ? 2 * sz : 64;
1292 n = realloc(part->data, new_allocated);
1299 part->allocated = new_allocated;
1300 part->free_this = true;
1305 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1311 static int message_add_offset(sd_bus_message *m, size_t offset) {
1312 struct bus_container *c;
1315 assert(BUS_MESSAGE_IS_GVARIANT(m));
1317 /* Add offset to current container, unless this is the first
1318 * item in it, which will have the 0 offset, which we can
1320 c = message_get_container(m);
1322 if (!c->need_offsets)
1325 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1328 c->offsets[c->n_offsets++] = offset;
1332 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1333 struct bus_container *c;
1340 /* Update counters */
1341 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1344 *c->array_size += expand;
1348 static void *message_extend_body(
1353 bool force_inline) {
1355 size_t start_body, end_body, padding, added;
1366 start_body = ALIGN_TO((size_t) m->body_size, align);
1367 end_body = start_body + sz;
1369 padding = start_body - m->body_size;
1370 added = padding + sz;
1372 /* Check for 32bit overflows */
1373 if (end_body > (size_t) ((uint32_t) -1) ||
1374 end_body < start_body) {
1380 struct bus_body_part *part = NULL;
1384 m->n_body_parts <= 0 ||
1385 m->body_end->sealed ||
1386 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1387 (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 */
1391 part = message_append_part(m);
1395 part_zero(part, padding);
1398 part = message_append_part(m);
1402 r = part_make_space(m, part, sz, &p);
1406 struct bus_container *c;
1408 size_t os, start_part, end_part;
1414 start_part = ALIGN_TO(part->size, align);
1415 end_part = start_part + sz;
1417 r = part_make_space(m, part, end_part, &p);
1422 memzero(p, padding);
1423 p = (uint8_t*) p + padding;
1426 /* Readjust pointers */
1427 for (c = m->containers; c < m->containers + m->n_containers; c++)
1428 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1430 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1433 /* Return something that is not NULL and is aligned */
1434 p = (uint8_t *) NULL + align;
1436 m->body_size = end_body;
1437 message_extend_containers(m, added);
1440 r = message_add_offset(m, end_body);
1450 static int message_push_fd(sd_bus_message *m, int fd) {
1461 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1465 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1473 m->fds[m->n_fds] = copy;
1479 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1480 _cleanup_close_ int fd = -1;
1481 struct bus_container *c;
1485 assert_return(m, -EINVAL);
1486 assert_return(!m->sealed, -EPERM);
1487 assert_return(bus_type_is_basic(type), -EINVAL);
1488 assert_return(!m->poisoned, -ESTALE);
1490 c = message_get_container(m);
1492 if (c->signature && c->signature[c->index]) {
1493 /* Container signature is already set */
1495 if (c->signature[c->index] != type)
1500 /* Maybe we can append to the signature? But only if this is the top-level container */
1501 if (c->enclosing != 0)
1504 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1511 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1517 case SD_BUS_TYPE_SIGNATURE:
1518 case SD_BUS_TYPE_STRING:
1521 /* Fall through... */
1522 case SD_BUS_TYPE_OBJECT_PATH:
1530 case SD_BUS_TYPE_BOOLEAN:
1532 u8 = p && *(int*) p;
1538 case SD_BUS_TYPE_UNIX_FD:
1543 fd = message_push_fd(m, *(int*) p);
1554 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1555 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1562 a = message_extend_body(m, align, sz, true, false);
1569 *stored = (const uint8_t*) a;
1576 case SD_BUS_TYPE_STRING:
1577 /* To make things easy we'll serialize a NULL string
1578 * into the empty string */
1581 /* Fall through... */
1582 case SD_BUS_TYPE_OBJECT_PATH:
1588 sz = 4 + strlen(p) + 1;
1591 case SD_BUS_TYPE_SIGNATURE:
1596 sz = 1 + strlen(p) + 1;
1599 case SD_BUS_TYPE_BOOLEAN:
1601 u32 = p && *(int*) p;
1607 case SD_BUS_TYPE_UNIX_FD:
1612 fd = message_push_fd(m, *(int*) p);
1623 align = bus_type_get_alignment(type);
1624 sz = bus_type_get_size(type);
1631 a = message_extend_body(m, align, sz, false, false);
1635 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1636 *(uint32_t*) a = sz - 5;
1637 memcpy((uint8_t*) a + 4, p, sz - 4);
1640 *stored = (const uint8_t*) a + 4;
1642 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1643 *(uint8_t*) a = sz - 2;
1644 memcpy((uint8_t*) a + 1, p, sz - 1);
1647 *stored = (const uint8_t*) a + 1;
1656 if (type == SD_BUS_TYPE_UNIX_FD)
1659 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1666 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1667 return message_append_basic(m, type, p, NULL);
1670 /// UNNEEDED by elogind
1672 _public_ int sd_bus_message_append_string_space(
1677 struct bus_container *c;
1680 assert_return(m, -EINVAL);
1681 assert_return(s, -EINVAL);
1682 assert_return(!m->sealed, -EPERM);
1683 assert_return(!m->poisoned, -ESTALE);
1685 c = message_get_container(m);
1687 if (c->signature && c->signature[c->index]) {
1688 /* Container signature is already set */
1690 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1695 /* Maybe we can append to the signature? But only if this is the top-level container */
1696 if (c->enclosing != 0)
1699 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1706 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1707 a = message_extend_body(m, 1, size + 1, true, false);
1713 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1717 *(uint32_t*) a = size;
1723 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1729 _public_ int sd_bus_message_append_string_iovec(
1731 const struct iovec *iov,
1739 assert_return(m, -EINVAL);
1740 assert_return(!m->sealed, -EPERM);
1741 assert_return(iov || n == 0, -EINVAL);
1742 assert_return(!m->poisoned, -ESTALE);
1744 size = IOVEC_TOTAL_SIZE(iov, n);
1746 r = sd_bus_message_append_string_space(m, size, &p);
1750 for (i = 0; i < n; i++) {
1752 if (iov[i].iov_base)
1753 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1755 memset(p, ' ', iov[i].iov_len);
1757 p += iov[i].iov_len;
1764 static int bus_message_open_array(
1766 struct bus_container *c,
1767 const char *contents,
1768 uint32_t **array_size,
1770 bool *need_offsets) {
1780 assert(need_offsets);
1782 if (!signature_is_single(contents, true))
1785 if (c->signature && c->signature[c->index]) {
1787 /* Verify the existing signature */
1789 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1792 if (!startswith(c->signature + c->index + 1, contents))
1795 nindex = c->index + 1 + strlen(contents);
1799 if (c->enclosing != 0)
1802 /* Extend the existing signature */
1804 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1810 nindex = e - c->signature;
1813 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1814 alignment = bus_gvariant_get_alignment(contents);
1818 /* Add alignment padding and add to offset list */
1819 if (!message_extend_body(m, alignment, 0, false, false))
1822 r = bus_gvariant_is_fixed_size(contents);
1826 *begin = m->body_size;
1827 *need_offsets = r == 0;
1831 struct bus_body_part *o;
1833 alignment = bus_type_get_alignment(contents[0]);
1837 a = message_extend_body(m, 4, 4, false, false);
1842 op = m->body_end->data;
1843 os = m->body_end->size;
1845 /* Add alignment between size and first element */
1846 if (!message_extend_body(m, alignment, 0, false, false))
1849 /* location of array size might have changed so let's readjust a */
1850 if (o == m->body_end)
1851 a = adjust_pointer(a, op, os, m->body_end->data);
1857 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1863 static int bus_message_open_variant(
1865 struct bus_container *c,
1866 const char *contents) {
1872 if (!signature_is_single(contents, false))
1875 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1878 if (c->signature && c->signature[c->index]) {
1880 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1886 if (c->enclosing != 0)
1889 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1896 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1897 /* Variants are always aligned to 8 */
1899 if (!message_extend_body(m, 8, 0, false, false))
1906 l = strlen(contents);
1907 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1912 memcpy((uint8_t*) a + 1, contents, l + 1);
1915 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1921 static int bus_message_open_struct(
1923 struct bus_container *c,
1924 const char *contents,
1926 bool *need_offsets) {
1935 assert(need_offsets);
1937 if (!signature_is_valid(contents, false))
1940 if (c->signature && c->signature[c->index]) {
1943 l = strlen(contents);
1945 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1946 !startswith(c->signature + c->index + 1, contents) ||
1947 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1950 nindex = c->index + 1 + l + 1;
1954 if (c->enclosing != 0)
1957 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1963 nindex = e - c->signature;
1966 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1969 alignment = bus_gvariant_get_alignment(contents);
1973 if (!message_extend_body(m, alignment, 0, false, false))
1976 r = bus_gvariant_is_fixed_size(contents);
1980 *begin = m->body_size;
1981 *need_offsets = r == 0;
1983 /* Align contents to 8 byte boundary */
1984 if (!message_extend_body(m, 8, 0, false, false))
1988 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1994 static int bus_message_open_dict_entry(
1996 struct bus_container *c,
1997 const char *contents,
1999 bool *need_offsets) {
2007 assert(need_offsets);
2009 if (!signature_is_pair(contents))
2012 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2015 if (c->signature && c->signature[c->index]) {
2018 l = strlen(contents);
2020 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2021 !startswith(c->signature + c->index + 1, contents) ||
2022 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2027 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2030 alignment = bus_gvariant_get_alignment(contents);
2034 if (!message_extend_body(m, alignment, 0, false, false))
2037 r = bus_gvariant_is_fixed_size(contents);
2041 *begin = m->body_size;
2042 *need_offsets = r == 0;
2044 /* Align contents to 8 byte boundary */
2045 if (!message_extend_body(m, 8, 0, false, false))
2052 _public_ int sd_bus_message_open_container(
2055 const char *contents) {
2057 struct bus_container *c, *w;
2058 uint32_t *array_size = NULL;
2060 size_t before, begin = 0;
2061 bool need_offsets = false;
2064 assert_return(m, -EINVAL);
2065 assert_return(!m->sealed, -EPERM);
2066 assert_return(contents, -EINVAL);
2067 assert_return(!m->poisoned, -ESTALE);
2069 /* Make sure we have space for one more container */
2070 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2075 c = message_get_container(m);
2077 signature = strdup(contents);
2083 /* Save old index in the parent container, in case we have to
2084 * abort this container */
2085 c->saved_index = c->index;
2086 before = m->body_size;
2088 if (type == SD_BUS_TYPE_ARRAY)
2089 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2090 else if (type == SD_BUS_TYPE_VARIANT)
2091 r = bus_message_open_variant(m, c, contents);
2092 else if (type == SD_BUS_TYPE_STRUCT)
2093 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2094 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2095 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2104 /* OK, let's fill it in */
2105 w = m->containers + m->n_containers++;
2106 w->enclosing = type;
2107 w->signature = signature;
2109 w->array_size = array_size;
2112 w->n_offsets = w->offsets_allocated = 0;
2114 w->need_offsets = need_offsets;
2119 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2124 if (!BUS_MESSAGE_IS_GVARIANT(m))
2127 if (c->need_offsets) {
2128 size_t payload, sz, i;
2131 /* Variable-width arrays */
2133 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2134 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2136 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2140 for (i = 0; i < c->n_offsets; i++)
2141 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2145 /* Fixed-width or empty arrays */
2147 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2155 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2161 assert(c->signature);
2163 if (!BUS_MESSAGE_IS_GVARIANT(m))
2166 l = strlen(c->signature);
2168 a = message_extend_body(m, 1, 1 + l, true, false);
2173 memcpy(a+1, c->signature, l);
2178 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2179 bool fixed_size = true;
2180 size_t n_variable = 0;
2189 if (!BUS_MESSAGE_IS_GVARIANT(m))
2192 p = strempty(c->signature);
2196 r = signature_element_length(p, &n);
2205 r = bus_gvariant_is_fixed_size(t);
2210 assert(!c->need_offsets || i <= c->n_offsets);
2212 /* We need to add an offset for each item that has a
2213 * variable size and that is not the last one in the
2217 if (r == 0 && p[n] != 0)
2224 assert(!c->need_offsets || i == c->n_offsets);
2225 assert(c->need_offsets || n_variable == 0);
2227 if (isempty(c->signature)) {
2228 /* The unary type is encoded as fixed 1 byte padding */
2229 a = message_extend_body(m, 1, 1, add_offset, false);
2234 } else if (n_variable <= 0) {
2237 /* Structures with fixed-size members only have to be
2238 * fixed-size themselves. But gvariant requires all fixed-size
2239 * elements to be sized a multiple of their alignment. Hence,
2240 * we must *always* add final padding after the last member so
2241 * the overall size of the structure is properly aligned. */
2243 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2245 assert(alignment > 0);
2247 a = message_extend_body(m, alignment, 0, add_offset, false);
2254 assert(c->offsets[c->n_offsets-1] == m->body_size);
2256 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2258 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2262 p = strempty(c->signature);
2263 for (i = 0, j = 0; i < c->n_offsets; i++) {
2267 r = signature_element_length(p, &n);
2278 r = bus_gvariant_is_fixed_size(t);
2281 if (r > 0 || p[0] == 0)
2285 k = n_variable - 1 - j;
2287 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2296 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2297 struct bus_container *c;
2300 assert_return(m, -EINVAL);
2301 assert_return(!m->sealed, -EPERM);
2302 assert_return(m->n_containers > 0, -EINVAL);
2303 assert_return(!m->poisoned, -ESTALE);
2305 c = message_get_container(m);
2307 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2308 if (c->signature && c->signature[c->index] != 0)
2313 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2314 r = bus_message_close_array(m, c);
2315 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2316 r = bus_message_close_variant(m, c);
2317 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2318 r = bus_message_close_struct(m, c, true);
2320 assert_not_reached("Unknown container type");
2334 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2341 stack[*i].types = types;
2342 stack[*i].n_struct = n_struct;
2343 stack[*i].n_array = n_array;
2349 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2360 *types = stack[*i].types;
2361 *n_struct = stack[*i].n_struct;
2362 *n_array = stack[*i].n_array;
2367 int bus_message_append_ap(
2372 unsigned n_array, n_struct;
2373 TypeStack stack[BUS_CONTAINER_DEPTH];
2374 unsigned stack_ptr = 0;
2382 n_array = (unsigned) -1;
2383 n_struct = strlen(types);
2388 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2389 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2395 r = sd_bus_message_close_container(m);
2403 if (n_array != (unsigned) -1)
2412 case SD_BUS_TYPE_BYTE: {
2415 x = (uint8_t) va_arg(ap, int);
2416 r = sd_bus_message_append_basic(m, *t, &x);
2420 case SD_BUS_TYPE_BOOLEAN:
2421 case SD_BUS_TYPE_INT32:
2422 case SD_BUS_TYPE_UINT32:
2423 case SD_BUS_TYPE_UNIX_FD: {
2426 /* We assume a boolean is the same as int32_t */
2427 assert_cc(sizeof(int32_t) == sizeof(int));
2429 x = va_arg(ap, uint32_t);
2430 r = sd_bus_message_append_basic(m, *t, &x);
2434 case SD_BUS_TYPE_INT16:
2435 case SD_BUS_TYPE_UINT16: {
2438 x = (uint16_t) va_arg(ap, int);
2439 r = sd_bus_message_append_basic(m, *t, &x);
2443 case SD_BUS_TYPE_INT64:
2444 case SD_BUS_TYPE_UINT64: {
2447 x = va_arg(ap, uint64_t);
2448 r = sd_bus_message_append_basic(m, *t, &x);
2452 case SD_BUS_TYPE_DOUBLE: {
2455 x = va_arg(ap, double);
2456 r = sd_bus_message_append_basic(m, *t, &x);
2460 case SD_BUS_TYPE_STRING:
2461 case SD_BUS_TYPE_OBJECT_PATH:
2462 case SD_BUS_TYPE_SIGNATURE: {
2465 x = va_arg(ap, const char*);
2466 r = sd_bus_message_append_basic(m, *t, x);
2470 case SD_BUS_TYPE_ARRAY: {
2473 r = signature_element_length(t + 1, &k);
2479 memcpy(s, t + 1, k);
2482 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2487 if (n_array == (unsigned) -1) {
2492 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2498 n_array = va_arg(ap, unsigned);
2503 case SD_BUS_TYPE_VARIANT: {
2506 s = va_arg(ap, const char*);
2510 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2514 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2519 n_struct = strlen(s);
2520 n_array = (unsigned) -1;
2525 case SD_BUS_TYPE_STRUCT_BEGIN:
2526 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2529 r = signature_element_length(t, &k);
2536 memcpy(s, t + 1, k - 2);
2539 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2544 if (n_array == (unsigned) -1) {
2549 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2555 n_array = (unsigned) -1;
2571 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2575 assert_return(m, -EINVAL);
2576 assert_return(types, -EINVAL);
2577 assert_return(!m->sealed, -EPERM);
2578 assert_return(!m->poisoned, -ESTALE);
2580 va_start(ap, types);
2581 r = bus_message_append_ap(m, types, ap);
2587 /// UNNEEDED by elogind
2589 _public_ int sd_bus_message_append_array_space(
2599 assert_return(m, -EINVAL);
2600 assert_return(!m->sealed, -EPERM);
2601 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2602 assert_return(ptr || size == 0, -EINVAL);
2603 assert_return(!m->poisoned, -ESTALE);
2605 /* alignment and size of the trivial types (except bool) is
2606 * identical for gvariant and dbus1 marshalling */
2607 align = bus_type_get_alignment(type);
2608 sz = bus_type_get_size(type);
2610 assert_se(align > 0);
2616 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2620 a = message_extend_body(m, align, size, false, false);
2624 r = sd_bus_message_close_container(m);
2632 _public_ int sd_bus_message_append_array(
2640 assert_return(m, -EINVAL);
2641 assert_return(!m->sealed, -EPERM);
2642 assert_return(bus_type_is_trivial(type), -EINVAL);
2643 assert_return(ptr || size == 0, -EINVAL);
2644 assert_return(!m->poisoned, -ESTALE);
2646 r = sd_bus_message_append_array_space(m, type, size, &p);
2651 memcpy(p, ptr, size);
2656 _public_ int sd_bus_message_append_array_iovec(
2659 const struct iovec *iov,
2667 assert_return(m, -EINVAL);
2668 assert_return(!m->sealed, -EPERM);
2669 assert_return(bus_type_is_trivial(type), -EINVAL);
2670 assert_return(iov || n == 0, -EINVAL);
2671 assert_return(!m->poisoned, -ESTALE);
2673 size = IOVEC_TOTAL_SIZE(iov, n);
2675 r = sd_bus_message_append_array_space(m, type, size, &p);
2679 for (i = 0; i < n; i++) {
2681 if (iov[i].iov_base)
2682 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2684 memzero(p, iov[i].iov_len);
2686 p = (uint8_t*) p + iov[i].iov_len;
2692 _public_ int sd_bus_message_append_array_memfd(
2699 _cleanup_close_ int copy_fd = -1;
2700 struct bus_body_part *part;
2706 assert_return(m, -EINVAL);
2707 assert_return(memfd >= 0, -EBADF);
2708 assert_return(bus_type_is_trivial(type), -EINVAL);
2709 assert_return(size > 0, -EINVAL);
2710 assert_return(!m->sealed, -EPERM);
2711 assert_return(!m->poisoned, -ESTALE);
2713 r = memfd_set_sealed(memfd);
2717 copy_fd = dup(memfd);
2721 r = memfd_get_size(memfd, &real_size);
2725 if (offset == 0 && size == (uint64_t) -1)
2727 else if (offset + size > real_size)
2730 align = bus_type_get_alignment(type);
2731 sz = bus_type_get_size(type);
2733 assert_se(align > 0);
2736 if (offset % align != 0)
2742 if (size > (uint64_t) (uint32_t) -1)
2745 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2749 a = message_extend_body(m, align, 0, false, false);
2753 part = message_append_part(m);
2757 part->memfd = copy_fd;
2758 part->memfd_offset = offset;
2759 part->sealed = true;
2763 m->body_size += size;
2764 message_extend_containers(m, size);
2766 return sd_bus_message_close_container(m);
2769 _public_ int sd_bus_message_append_string_memfd(
2775 _cleanup_close_ int copy_fd = -1;
2776 struct bus_body_part *part;
2777 struct bus_container *c;
2782 assert_return(m, -EINVAL);
2783 assert_return(memfd >= 0, -EBADF);
2784 assert_return(size > 0, -EINVAL);
2785 assert_return(!m->sealed, -EPERM);
2786 assert_return(!m->poisoned, -ESTALE);
2788 r = memfd_set_sealed(memfd);
2792 copy_fd = dup(memfd);
2796 r = memfd_get_size(memfd, &real_size);
2800 if (offset == 0 && size == (uint64_t) -1)
2802 else if (offset + size > real_size)
2805 /* We require this to be NUL terminated */
2809 if (size > (uint64_t) (uint32_t) -1)
2812 c = message_get_container(m);
2813 if (c->signature && c->signature[c->index]) {
2814 /* Container signature is already set */
2816 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2821 /* Maybe we can append to the signature? But only if this is the top-level container */
2822 if (c->enclosing != 0)
2825 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2832 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2833 a = message_extend_body(m, 4, 4, false, false);
2837 *(uint32_t*) a = size - 1;
2840 part = message_append_part(m);
2844 part->memfd = copy_fd;
2845 part->memfd_offset = offset;
2846 part->sealed = true;
2850 m->body_size += size;
2851 message_extend_containers(m, size);
2853 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2854 r = message_add_offset(m, m->body_size);
2861 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2868 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2872 assert_return(m, -EINVAL);
2873 assert_return(!m->sealed, -EPERM);
2874 assert_return(!m->poisoned, -ESTALE);
2876 r = sd_bus_message_open_container(m, 'a', "s");
2880 STRV_FOREACH(i, l) {
2881 r = sd_bus_message_append_basic(m, 's', *i);
2886 return sd_bus_message_close_container(m);
2889 static int bus_message_close_header(sd_bus_message *m) {
2893 /* The actual user data is finished now, we just complete the
2894 variant and struct now (at least on gvariant). Remember
2895 this position, so that during parsing we know where to to
2896 put the outer container end. */
2897 m->user_body_size = m->body_size;
2899 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2900 const char *signature;
2904 /* Add offset table to end of fields array */
2905 if (m->n_header_offsets >= 1) {
2909 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2911 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2912 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2916 for (i = 0; i < m->n_header_offsets; i++)
2917 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2920 /* Add gvariant NUL byte plus signature to the end of
2921 * the body, followed by the final offset pointing to
2922 * the end of the fields array */
2924 signature = strempty(m->root_container.signature);
2925 l = strlen(signature);
2927 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2928 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2933 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2934 memcpy((uint8_t*) d + 2, signature, l);
2935 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2937 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2940 m->footer_accessible = 1 + l + 2 + sz;
2942 m->header->dbus1.fields_size = m->fields_size;
2943 m->header->dbus1.body_size = m->body_size;
2949 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2950 struct bus_body_part *part;
2960 if (m->n_containers > 0)
2966 if (cookie > 0xffffffffULL &&
2967 !BUS_MESSAGE_IS_GVARIANT(m))
2970 /* In vtables the return signature of method calls is listed,
2971 * let's check if they match if this is a response */
2972 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2973 m->enforced_reply_signature &&
2974 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2977 /* If gvariant marshalling is used we need to close the body structure */
2978 r = bus_message_close_struct(m, &m->root_container, false);
2982 /* If there's a non-trivial signature set, then add it in
2983 * here, but only on dbus1 */
2984 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2985 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2991 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2996 r = bus_message_close_header(m);
3000 if (BUS_MESSAGE_IS_GVARIANT(m))
3001 m->header->dbus2.cookie = cookie;
3003 m->header->dbus1.serial = (uint32_t) cookie;
3005 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
3007 /* Add padding at the end of the fields part, since we know
3008 * the body needs to start at an 8 byte alignment. We made
3009 * sure we allocated enough space for this, so all we need to
3010 * do here is to zero it out. */
3011 a = ALIGN8(m->fields_size) - m->fields_size;
3013 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
3015 /* If this is something we can send as memfd, then let's seal
3016 the memfd now. Note that we can send memfds as payload only
3017 for directed messages, and not for broadcasts. */
3018 if (m->destination && m->bus->use_memfd) {
3019 MESSAGE_FOREACH_PART(part, i, m)
3020 if (part->memfd >= 0 &&
3022 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3023 part != m->body_end) { /* The last part may never be sent as memfd */
3026 /* Try to seal it if that makes
3027 * sense. First, unmap our own map to
3028 * make sure we don't keep it busy. */
3029 bus_body_part_unmap(part);
3031 /* Then, sync up real memfd size */
3033 r = memfd_set_size(part->memfd, sz);
3037 /* Finally, try to seal */
3038 if (memfd_set_sealed(part->memfd) >= 0)
3039 part->sealed = true;
3043 m->root_container.end = m->user_body_size;
3044 m->root_container.index = 0;
3045 m->root_container.offset_index = 0;
3046 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3053 int bus_body_part_map(struct bus_body_part *part) {
3062 if (part->size <= 0)
3065 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3066 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3067 static const uint8_t zeroes[7] = { };
3068 part->data = (void*) zeroes;
3072 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3073 psz = PAGE_ALIGN(part->size + shift);
3075 if (part->memfd >= 0)
3076 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3077 else if (part->is_zero)
3078 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3082 if (p == MAP_FAILED)
3086 part->mmap_begin = p;
3087 part->data = (uint8_t*) p + shift;
3088 part->munmap_this = true;
3093 void bus_body_part_unmap(struct bus_body_part *part) {
3097 if (part->memfd < 0)
3100 if (!part->mmap_begin)
3103 if (!part->munmap_this)
3106 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3108 part->mmap_begin = NULL;
3111 part->munmap_this = false;
3116 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3117 size_t k, start, end;
3122 start = ALIGN_TO((size_t) *rindex, align);
3123 end = start + nbytes;
3128 /* Verify that padding is 0 */
3129 for (k = *rindex; k < start; k++)
3130 if (((const uint8_t*) p)[k] != 0)
3134 *r = (uint8_t*) p + start;
3141 static bool message_end_of_signature(sd_bus_message *m) {
3142 struct bus_container *c;
3146 c = message_get_container(m);
3147 return !c->signature || c->signature[c->index] == 0;
3150 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3151 struct bus_container *c;
3155 c = message_get_container(m);
3156 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3159 if (BUS_MESSAGE_IS_GVARIANT(m))
3160 return index >= c->end;
3162 assert(c->array_size);
3163 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3167 /// UNNEEDED by elogind
3169 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3170 assert_return(m, -EINVAL);
3171 assert_return(m->sealed, -EPERM);
3173 if (complete && m->n_containers > 0)
3176 if (message_end_of_signature(m))
3179 if (message_end_of_array(m, m->rindex))
3186 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3187 struct bus_body_part *part;
3193 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3194 part = m->cached_rindex_part;
3195 begin = m->cached_rindex_part_begin;
3205 if (index + sz <= begin + part->size) {
3207 r = bus_body_part_map(part);
3212 *p = (uint8_t*) part->data + index - begin;
3214 m->cached_rindex_part = part;
3215 m->cached_rindex_part_begin = begin;
3220 begin += part->size;
3227 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3234 if (!BUS_MESSAGE_IS_GVARIANT(m))
3237 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3240 sz = bus_gvariant_get_size(c->signature);
3244 if (c->offset_index+1 >= c->n_offsets)
3247 /* Variable-size array */
3249 alignment = bus_gvariant_get_alignment(c->signature);
3250 assert(alignment > 0);
3252 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3253 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3256 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3259 /* Fixed-size array */
3260 *rindex = c->begin + (c->offset_index+1) * sz;
3266 } else if (c->enclosing == 0 ||
3267 c->enclosing == SD_BUS_TYPE_STRUCT ||
3268 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3273 if (c->offset_index+1 >= c->n_offsets)
3276 r = signature_element_length(c->signature + c->index, &n);
3280 r = signature_element_length(c->signature + c->index + n, &j);
3285 memcpy(t, c->signature + c->index + n, j);
3288 alignment = bus_gvariant_get_alignment(t);
3291 assert(alignment > 0);
3293 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3294 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3298 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3301 assert_not_reached("Unknown container type");
3306 /* Reached the end */
3313 static int message_peek_body(
3320 size_t k, start, end, padding;
3321 struct bus_body_part *part;
3328 start = ALIGN_TO((size_t) *rindex, align);
3329 padding = start - *rindex;
3330 end = start + nbytes;
3332 if (end > m->user_body_size)
3335 part = find_part(m, *rindex, padding, (void**) &q);
3340 /* Verify padding */
3341 for (k = 0; k < padding; k++)
3346 part = find_part(m, start, nbytes, (void**) &q);
3347 if (!part || (nbytes > 0 && !q))
3358 static bool validate_nul(const char *s, size_t l) {
3360 /* Check for NUL chars in the string */
3361 if (memchr(s, 0, l))
3364 /* Check for NUL termination */
3371 static bool validate_string(const char *s, size_t l) {
3373 if (!validate_nul(s, l))
3376 /* Check if valid UTF8 */
3377 if (!utf8_is_valid(s))
3383 static bool validate_signature(const char *s, size_t l) {
3385 if (!validate_nul(s, l))
3388 /* Check if valid signature */
3389 if (!signature_is_valid(s, true))
3395 static bool validate_object_path(const char *s, size_t l) {
3397 if (!validate_nul(s, l))
3400 if (!object_path_is_valid(s))
3406 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3407 struct bus_container *c;
3412 assert_return(m, -EINVAL);
3413 assert_return(m->sealed, -EPERM);
3414 assert_return(bus_type_is_basic(type), -EINVAL);
3416 if (message_end_of_signature(m))
3419 if (message_end_of_array(m, m->rindex))
3422 c = message_get_container(m);
3423 if (c->signature[c->index] != type)
3428 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3430 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3433 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3437 if (type == SD_BUS_TYPE_STRING)
3438 ok = validate_string(q, c->item_size-1);
3439 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3440 ok = validate_object_path(q, c->item_size-1);
3442 ok = validate_signature(q, c->item_size-1);
3448 *(const char**) p = q;
3452 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3454 if ((size_t) sz != c->item_size)
3457 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3460 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3466 case SD_BUS_TYPE_BYTE:
3468 *(uint8_t*) p = *(uint8_t*) q;
3471 case SD_BUS_TYPE_BOOLEAN:
3473 *(int*) p = !!*(uint8_t*) q;
3476 case SD_BUS_TYPE_INT16:
3477 case SD_BUS_TYPE_UINT16:
3479 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3482 case SD_BUS_TYPE_INT32:
3483 case SD_BUS_TYPE_UINT32:
3485 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3488 case SD_BUS_TYPE_INT64:
3489 case SD_BUS_TYPE_UINT64:
3490 case SD_BUS_TYPE_DOUBLE:
3492 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3495 case SD_BUS_TYPE_UNIX_FD: {
3498 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3503 *(int*) p = m->fds[j];
3509 assert_not_reached("unexpected type");
3513 r = container_next_item(m, c, &rindex);
3518 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3522 r = message_peek_body(m, &rindex, 4, 4, &q);
3526 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3527 r = message_peek_body(m, &rindex, 1, l+1, &q);
3531 if (type == SD_BUS_TYPE_OBJECT_PATH)
3532 ok = validate_object_path(q, l);
3534 ok = validate_string(q, l);
3539 *(const char**) p = q;
3541 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3544 r = message_peek_body(m, &rindex, 1, 1, &q);
3549 r = message_peek_body(m, &rindex, 1, l+1, &q);
3553 if (!validate_signature(q, l))
3557 *(const char**) p = q;
3562 align = bus_type_get_alignment(type);
3565 sz = bus_type_get_size(type);
3568 r = message_peek_body(m, &rindex, align, sz, &q);
3574 case SD_BUS_TYPE_BYTE:
3576 *(uint8_t*) p = *(uint8_t*) q;
3579 case SD_BUS_TYPE_BOOLEAN:
3581 *(int*) p = !!*(uint32_t*) q;
3584 case SD_BUS_TYPE_INT16:
3585 case SD_BUS_TYPE_UINT16:
3587 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3590 case SD_BUS_TYPE_INT32:
3591 case SD_BUS_TYPE_UINT32:
3593 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3596 case SD_BUS_TYPE_INT64:
3597 case SD_BUS_TYPE_UINT64:
3598 case SD_BUS_TYPE_DOUBLE:
3600 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3603 case SD_BUS_TYPE_UNIX_FD: {
3606 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3611 *(int*) p = m->fds[j];
3616 assert_not_reached("Unknown basic type...");
3623 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3629 static int bus_message_enter_array(
3631 struct bus_container *c,
3632 const char *contents,
3633 uint32_t **array_size,
3636 size_t *n_offsets) {
3650 if (!signature_is_single(contents, true))
3653 if (!c->signature || c->signature[c->index] == 0)
3656 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3659 if (!startswith(c->signature + c->index + 1, contents))
3664 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3667 r = message_peek_body(m, &rindex, 4, 4, &q);
3671 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3674 alignment = bus_type_get_alignment(contents[0]);
3678 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3682 *array_size = (uint32_t*) q;
3684 } else if (c->item_size <= 0) {
3686 /* gvariant: empty array */
3691 } else if (bus_gvariant_is_fixed_size(contents)) {
3693 /* gvariant: fixed length array */
3694 *item_size = bus_gvariant_get_size(contents);
3699 size_t where, p = 0, framing, sz;
3702 /* gvariant: variable length array */
3703 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3705 where = rindex + c->item_size - sz;
3706 r = message_peek_body(m, &where, 1, sz, &q);
3710 framing = bus_gvariant_read_word_le(q, sz);
3711 if (framing > c->item_size - sz)
3713 if ((c->item_size - framing) % sz != 0)
3716 *n_offsets = (c->item_size - framing) / sz;
3718 where = rindex + framing;
3719 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3723 *offsets = new(size_t, *n_offsets);
3727 for (i = 0; i < *n_offsets; i++) {
3730 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3731 if (x > c->item_size - sz)
3736 (*offsets)[i] = rindex + x;
3740 *item_size = (*offsets)[0] - rindex;
3745 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3746 c->index += 1 + strlen(contents);
3751 static int bus_message_enter_variant(
3753 struct bus_container *c,
3754 const char *contents,
3755 size_t *item_size) {
3767 if (!signature_is_single(contents, false))
3770 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3773 if (!c->signature || c->signature[c->index] == 0)
3776 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3781 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3784 k = strlen(contents);
3785 if (1+k > c->item_size)
3788 where = rindex + c->item_size - (1+k);
3789 r = message_peek_body(m, &where, 1, 1+k, &q);
3793 if (*(char*) q != 0)
3796 if (memcmp((uint8_t*) q+1, contents, k))
3799 *item_size = c->item_size - (1+k);
3802 r = message_peek_body(m, &rindex, 1, 1, &q);
3807 r = message_peek_body(m, &rindex, 1, l+1, &q);
3811 if (!validate_signature(q, l))
3814 if (!streq(q, contents))
3820 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3826 static int build_struct_offsets(
3828 const char *signature,
3832 size_t *n_offsets) {
3834 unsigned n_variable = 0, n_total = 0, v;
3835 size_t previous = 0, where;
3846 if (isempty(signature)) {
3847 /* Unary type is encoded as *fixed* 1 byte padding */
3848 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3852 if (*(uint8_t *) q != 0)
3861 sz = bus_gvariant_determine_word_size(size, 0);
3865 /* First, loop over signature and count variable elements and
3866 * elements in general. We use this to know how large the
3867 * offset array is at the end of the structure. Note that
3868 * GVariant only stores offsets for all variable size elements
3869 * that are not the last item. */
3875 r = signature_element_length(p, &n);
3884 r = bus_gvariant_is_fixed_size(t);
3889 if (r == 0 && p[n] != 0) /* except the last item */
3896 if (size < n_variable * sz)
3899 where = m->rindex + size - (n_variable * sz);
3900 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3906 *offsets = new(size_t, n_total);
3912 /* Second, loop again and build an offset table */
3918 r = signature_element_length(p, &n);
3927 k = bus_gvariant_get_size(t);
3935 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3938 if (m->rindex + x < previous)
3941 /* The last item's end
3942 * is determined from
3945 x = size - (n_variable * sz);
3947 offset = m->rindex + x;
3953 align = bus_gvariant_get_alignment(t);
3956 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3960 previous = (*offsets)[(*n_offsets)++] = offset;
3965 assert(*n_offsets == n_total);
3967 *item_size = (*offsets)[0] - m->rindex;
3971 static int enter_struct_or_dict_entry(
3973 struct bus_container *c,
3974 const char *contents,
3977 size_t *n_offsets) {
3988 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3991 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3996 /* gvariant with contents */
3997 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
4002 static int bus_message_enter_struct(
4004 struct bus_container *c,
4005 const char *contents,
4008 size_t *n_offsets) {
4020 if (!signature_is_valid(contents, false))
4023 if (!c->signature || c->signature[c->index] == 0)
4026 l = strlen(contents);
4028 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4029 !startswith(c->signature + c->index + 1, contents) ||
4030 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4033 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4037 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4038 c->index += 1 + l + 1;
4043 static int bus_message_enter_dict_entry(
4045 struct bus_container *c,
4046 const char *contents,
4049 size_t *n_offsets) {
4058 if (!signature_is_pair(contents))
4061 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4064 if (!c->signature || c->signature[c->index] == 0)
4067 l = strlen(contents);
4069 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4070 !startswith(c->signature + c->index + 1, contents) ||
4071 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4074 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4078 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4079 c->index += 1 + l + 1;
4084 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4086 const char *contents) {
4087 struct bus_container *c, *w;
4088 uint32_t *array_size = NULL;
4091 size_t *offsets = NULL;
4092 size_t n_offsets = 0, item_size = 0;
4095 assert_return(m, -EINVAL);
4096 assert_return(m->sealed, -EPERM);
4097 assert_return(type != 0 || !contents, -EINVAL);
4099 if (type == 0 || !contents) {
4103 /* Allow entering into anonymous containers */
4104 r = sd_bus_message_peek_type(m, &tt, &cc);
4108 if (type != 0 && type != tt)
4111 if (contents && !streq(contents, cc))
4119 * We enforce a global limit on container depth, that is much
4120 * higher than the 32 structs and 32 arrays the specification
4121 * mandates. This is simpler to implement for us, and we need
4122 * this only to ensure our container array doesn't grow
4123 * without bounds. We are happy to return any data from a
4124 * message as long as the data itself is valid, even if the
4125 * overall message might be not.
4127 * Note that the message signature is validated when
4128 * parsing the headers, and that validation does check the
4131 * Note that the specification defines no limits on the depth
4132 * of stacked variants, but we do.
4134 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4137 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4140 if (message_end_of_signature(m))
4143 if (message_end_of_array(m, m->rindex))
4146 c = message_get_container(m);
4148 signature = strdup(contents);
4152 c->saved_index = c->index;
4155 if (type == SD_BUS_TYPE_ARRAY)
4156 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4157 else if (type == SD_BUS_TYPE_VARIANT)
4158 r = bus_message_enter_variant(m, c, contents, &item_size);
4159 else if (type == SD_BUS_TYPE_STRUCT)
4160 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4161 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4162 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4172 /* OK, let's fill it in */
4173 w = m->containers + m->n_containers++;
4174 w->enclosing = type;
4175 w->signature = signature;
4176 w->peeked_signature = NULL;
4180 w->begin = m->rindex;
4182 /* Unary type has fixed size of 1, but virtual size of 0 */
4183 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4184 type == SD_BUS_TYPE_STRUCT &&
4186 w->end = m->rindex + 0;
4188 w->end = m->rindex + c->item_size;
4190 w->array_size = array_size;
4191 w->item_size = item_size;
4192 w->offsets = offsets;
4193 w->n_offsets = n_offsets;
4194 w->offset_index = 0;
4199 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4200 struct bus_container *c;
4204 assert_return(m, -EINVAL);
4205 assert_return(m->sealed, -EPERM);
4206 assert_return(m->n_containers > 0, -ENXIO);
4208 c = message_get_container(m);
4210 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4211 if (c->signature && c->signature[c->index] != 0)
4215 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4216 if (m->rindex < c->end)
4219 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4222 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4223 if (c->begin + l != m->rindex)
4228 free(c->peeked_signature);
4232 c = message_get_container(m);
4235 c->index = c->saved_index;
4236 r = container_next_item(m, c, &m->rindex);
4244 static void message_quit_container(sd_bus_message *m) {
4245 struct bus_container *c;
4249 assert(m->n_containers > 0);
4251 c = message_get_container(m);
4254 assert(m->rindex >= c->before);
4255 m->rindex = c->before;
4257 /* Free container */
4262 /* Correct index of new top-level container */
4263 c = message_get_container(m);
4264 c->index = c->saved_index;
4267 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4268 struct bus_container *c;
4271 assert_return(m, -EINVAL);
4272 assert_return(m->sealed, -EPERM);
4274 if (message_end_of_signature(m))
4277 if (message_end_of_array(m, m->rindex))
4280 c = message_get_container(m);
4282 if (bus_type_is_basic(c->signature[c->index])) {
4286 *type = c->signature[c->index];
4290 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4296 r = signature_element_length(c->signature+c->index+1, &l);
4302 sig = strndup(c->signature + c->index + 1, l);
4306 free(c->peeked_signature);
4307 *contents = c->peeked_signature = sig;
4311 *type = SD_BUS_TYPE_ARRAY;
4316 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4317 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4323 r = signature_element_length(c->signature+c->index, &l);
4328 sig = strndup(c->signature + c->index + 1, l - 2);
4332 free(c->peeked_signature);
4333 *contents = c->peeked_signature = sig;
4337 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4342 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4346 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4349 if (c->item_size < 2)
4352 /* Look for the NUL delimiter that
4353 separates the payload from the
4354 signature. Since the body might be
4355 in a different part that then the
4356 signature we map byte by byte. */
4358 for (k = 2; k <= c->item_size; k++) {
4361 where = m->rindex + c->item_size - k;
4362 r = message_peek_body(m, &where, 1, k, &q);
4366 if (*(char*) q == 0)
4370 if (k > c->item_size)
4373 free(c->peeked_signature);
4374 c->peeked_signature = strndup((char*) q + 1, k - 1);
4375 if (!c->peeked_signature)
4378 if (!signature_is_valid(c->peeked_signature, true))
4381 *contents = c->peeked_signature;
4386 r = message_peek_body(m, &rindex, 1, 1, &q);
4391 r = message_peek_body(m, &rindex, 1, l+1, &q);
4395 if (!validate_signature(q, l))
4403 *type = SD_BUS_TYPE_VARIANT;
4418 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4419 struct bus_container *c;
4421 assert_return(m, -EINVAL);
4422 assert_return(m->sealed, -EPERM);
4425 message_reset_containers(m);
4428 c = message_get_container(m);
4430 c = message_get_container(m);
4432 c->offset_index = 0;
4434 m->rindex = c->begin;
4437 c->offset_index = 0;
4438 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4440 return !isempty(c->signature);
4443 static int message_read_ap(
4448 unsigned n_array, n_struct;
4449 TypeStack stack[BUS_CONTAINER_DEPTH];
4450 unsigned stack_ptr = 0;
4451 unsigned n_loop = 0;
4459 /* Ideally, we'd just call ourselves recursively on every
4460 * complex type. However, the state of a va_list that is
4461 * passed to a function is undefined after that function
4462 * returns. This means we need to docode the va_list linearly
4463 * in a single stackframe. We hence implement our own
4464 * home-grown stack in an array. */
4466 n_array = (unsigned) -1; /* length of current array entries */
4467 n_struct = strlen(types); /* length of current struct contents signature */
4474 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4475 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4481 r = sd_bus_message_exit_container(m);
4489 if (n_array != (unsigned) -1)
4498 case SD_BUS_TYPE_BYTE:
4499 case SD_BUS_TYPE_BOOLEAN:
4500 case SD_BUS_TYPE_INT16:
4501 case SD_BUS_TYPE_UINT16:
4502 case SD_BUS_TYPE_INT32:
4503 case SD_BUS_TYPE_UINT32:
4504 case SD_BUS_TYPE_INT64:
4505 case SD_BUS_TYPE_UINT64:
4506 case SD_BUS_TYPE_DOUBLE:
4507 case SD_BUS_TYPE_STRING:
4508 case SD_BUS_TYPE_OBJECT_PATH:
4509 case SD_BUS_TYPE_SIGNATURE:
4510 case SD_BUS_TYPE_UNIX_FD: {
4513 p = va_arg(ap, void*);
4514 r = sd_bus_message_read_basic(m, *t, p);
4527 case SD_BUS_TYPE_ARRAY: {
4530 r = signature_element_length(t + 1, &k);
4536 memcpy(s, t + 1, k);
4539 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4550 if (n_array == (unsigned) -1) {
4555 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4561 n_array = va_arg(ap, unsigned);
4566 case SD_BUS_TYPE_VARIANT: {
4569 s = va_arg(ap, const char *);
4573 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4583 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4588 n_struct = strlen(s);
4589 n_array = (unsigned) -1;
4594 case SD_BUS_TYPE_STRUCT_BEGIN:
4595 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4598 r = signature_element_length(t, &k);
4604 memcpy(s, t + 1, k - 2);
4607 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4617 if (n_array == (unsigned) -1) {
4622 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4628 n_array = (unsigned) -1;
4641 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4645 assert_return(m, -EINVAL);
4646 assert_return(m->sealed, -EPERM);
4647 assert_return(types, -EINVAL);
4649 va_start(ap, types);
4650 r = message_read_ap(m, types, ap);
4656 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4659 assert_return(m, -EINVAL);
4660 assert_return(m->sealed, -EPERM);
4662 /* If types is NULL, read exactly one element */
4664 struct bus_container *c;
4667 if (message_end_of_signature(m))
4670 if (message_end_of_array(m, m->rindex))
4673 c = message_get_container(m);
4675 r = signature_element_length(c->signature + c->index, &l);
4679 types = strndupa(c->signature + c->index, l);
4684 case 0: /* Nothing to drop */
4687 case SD_BUS_TYPE_BYTE:
4688 case SD_BUS_TYPE_BOOLEAN:
4689 case SD_BUS_TYPE_INT16:
4690 case SD_BUS_TYPE_UINT16:
4691 case SD_BUS_TYPE_INT32:
4692 case SD_BUS_TYPE_UINT32:
4693 case SD_BUS_TYPE_INT64:
4694 case SD_BUS_TYPE_UINT64:
4695 case SD_BUS_TYPE_DOUBLE:
4696 case SD_BUS_TYPE_STRING:
4697 case SD_BUS_TYPE_OBJECT_PATH:
4698 case SD_BUS_TYPE_SIGNATURE:
4699 case SD_BUS_TYPE_UNIX_FD:
4701 r = sd_bus_message_read_basic(m, *types, NULL);
4705 r = sd_bus_message_skip(m, types + 1);
4711 case SD_BUS_TYPE_ARRAY: {
4714 r = signature_element_length(types + 1, &k);
4720 memcpy(s, types+1, k);
4723 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4728 r = sd_bus_message_skip(m, s);
4735 r = sd_bus_message_exit_container(m);
4740 r = sd_bus_message_skip(m, types + 1 + k);
4747 case SD_BUS_TYPE_VARIANT: {
4748 const char *contents;
4751 r = sd_bus_message_peek_type(m, &x, &contents);
4755 if (x != SD_BUS_TYPE_VARIANT)
4758 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4762 r = sd_bus_message_skip(m, contents);
4767 r = sd_bus_message_exit_container(m);
4771 r = sd_bus_message_skip(m, types + 1);
4778 case SD_BUS_TYPE_STRUCT_BEGIN:
4779 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4782 r = signature_element_length(types, &k);
4788 memcpy(s, types+1, k-2);
4791 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4795 r = sd_bus_message_skip(m, s);
4799 r = sd_bus_message_exit_container(m);
4804 r = sd_bus_message_skip(m, types + k);
4816 _public_ int sd_bus_message_read_array(
4822 struct bus_container *c;
4828 assert_return(m, -EINVAL);
4829 assert_return(m->sealed, -EPERM);
4830 assert_return(bus_type_is_trivial(type), -EINVAL);
4831 assert_return(ptr, -EINVAL);
4832 assert_return(size, -EINVAL);
4833 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4835 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4839 c = message_get_container(m);
4841 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4842 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4846 sz = c->end - c->begin;
4848 align = bus_type_get_alignment(type);
4852 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4856 /* Zero length array, let's return some aligned
4857 * pointer that is not NULL */
4858 p = (uint8_t*) NULL + align;
4860 r = message_peek_body(m, &m->rindex, align, sz, &p);
4865 r = sd_bus_message_exit_container(m);
4869 *ptr = (const void*) p;
4875 message_quit_container(m);
4879 static int message_peek_fields(
4890 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4893 static int message_peek_field_uint32(
4905 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4908 /* identical for gvariant and dbus1 */
4910 r = message_peek_fields(m, ri, 4, 4, &q);
4915 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4920 static int message_peek_field_uint64(
4932 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4935 /* identical for gvariant and dbus1 */
4937 r = message_peek_fields(m, ri, 8, 8, &q);
4942 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4947 static int message_peek_field_string(
4949 bool (*validate)(const char *p),
4961 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4966 r = message_peek_fields(m, ri, 1, item_size, &q);
4972 r = message_peek_field_uint32(m, ri, 4, &l);
4976 r = message_peek_fields(m, ri, 1, l+1, &q);
4982 if (!validate_nul(q, l))
4988 if (!validate_string(q, l))
4998 static int message_peek_field_signature(
5011 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5016 r = message_peek_fields(m, ri, 1, item_size, &q);
5022 r = message_peek_fields(m, ri, 1, 1, &q);
5027 r = message_peek_fields(m, ri, 1, l+1, &q);
5032 if (!validate_signature(q, l))
5041 static int message_skip_fields(
5044 uint32_t array_size,
5045 const char **signature) {
5047 size_t original_index;
5053 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5055 original_index = *ri;
5061 if (array_size != (uint32_t) -1 &&
5062 array_size <= *ri - original_index)
5069 if (t == SD_BUS_TYPE_STRING) {
5071 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5077 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5079 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5085 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5087 r = message_peek_field_signature(m, ri, 0, NULL);
5093 } else if (bus_type_is_basic(t)) {
5096 align = bus_type_get_alignment(t);
5097 k = bus_type_get_size(t);
5098 assert(align > 0 && k > 0);
5100 r = message_peek_fields(m, ri, align, k, NULL);
5106 } else if (t == SD_BUS_TYPE_ARRAY) {
5108 r = signature_element_length(*signature+1, &l);
5118 strncpy(sig, *signature + 1, l-1);
5121 alignment = bus_type_get_alignment(sig[0]);
5125 r = message_peek_field_uint32(m, ri, 0, &nas);
5128 if (nas > BUS_ARRAY_MAX_SIZE)
5131 r = message_peek_fields(m, ri, alignment, 0, NULL);
5135 r = message_skip_fields(m, ri, nas, (const char**) &s);
5140 (*signature) += 1 + l;
5142 } else if (t == SD_BUS_TYPE_VARIANT) {
5145 r = message_peek_field_signature(m, ri, 0, &s);
5149 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5155 } else if (t == SD_BUS_TYPE_STRUCT ||
5156 t == SD_BUS_TYPE_DICT_ENTRY) {
5158 r = signature_element_length(*signature, &l);
5165 strncpy(sig, *signature + 1, l-1);
5168 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5179 int bus_message_parse_fields(sd_bus_message *m) {
5182 uint32_t unix_fds = 0;
5183 bool unix_fds_set = false;
5184 void *offsets = NULL;
5185 unsigned n_offsets = 0;
5191 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5194 /* Read the signature from the end of the body variant first */
5195 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5196 if (m->footer_accessible < 1 + sz)
5199 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5201 if (p < (char*) m->footer)
5208 /* We found the beginning of the signature
5209 * string, yay! We require the body to be a
5210 * structure, so verify it and then strip the
5211 * opening/closing brackets. */
5213 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5215 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5216 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5219 c = strndup(p + 1 + 1, l - 2);
5223 free(m->root_container.signature);
5224 m->root_container.signature = c;
5231 /* Calculate the actual user body size, by removing
5232 * the trailing variant signature and struct offset
5234 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5236 /* Pull out the offset table for the fields array */
5237 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5242 ri = m->fields_size - sz;
5243 r = message_peek_fields(m, &ri, 1, sz, &q);
5247 framing = bus_gvariant_read_word_le(q, sz);
5248 if (framing >= m->fields_size - sz)
5250 if ((m->fields_size - framing) % sz != 0)
5254 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5258 n_offsets = (m->fields_size - framing) / sz;
5261 m->user_body_size = m->body_size;
5264 while (ri < m->fields_size) {
5265 _cleanup_free_ char *sig = NULL;
5266 const char *signature;
5267 uint64_t field_type;
5268 size_t item_size = (size_t) -1;
5270 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5279 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5281 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5285 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5289 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5296 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5301 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5306 where = ri = ALIGN_TO(ri, 8);
5307 item_size = end - ri;
5308 r = message_peek_fields(m, &where, 1, item_size, &q);
5312 b = memrchr(q, 0, item_size);
5316 sig = strndup(b+1, item_size - (b+1-(char*) q));
5321 item_size = b - (char*) q;
5323 r = message_peek_field_signature(m, &ri, 0, &signature);
5328 switch (field_type) {
5330 case _BUS_MESSAGE_HEADER_INVALID:
5333 case BUS_MESSAGE_HEADER_PATH:
5338 if (!streq(signature, "o"))
5341 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5344 case BUS_MESSAGE_HEADER_INTERFACE:
5349 if (!streq(signature, "s"))
5352 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5355 case BUS_MESSAGE_HEADER_MEMBER:
5360 if (!streq(signature, "s"))
5363 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5366 case BUS_MESSAGE_HEADER_ERROR_NAME:
5371 if (!streq(signature, "s"))
5374 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5376 m->error._need_free = -1;
5380 case BUS_MESSAGE_HEADER_DESTINATION:
5385 if (!streq(signature, "s"))
5388 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5391 case BUS_MESSAGE_HEADER_SENDER:
5396 if (!streq(signature, "s"))
5399 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5401 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5402 m->creds.unique_name = (char*) m->sender;
5403 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5409 case BUS_MESSAGE_HEADER_SIGNATURE: {
5413 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5416 if (m->root_container.signature)
5419 if (!streq(signature, "g"))
5422 r = message_peek_field_signature(m, &ri, item_size, &s);
5430 free(m->root_container.signature);
5431 m->root_container.signature = c;
5435 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5437 if (m->reply_cookie != 0)
5440 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5441 /* 64bit on dbus2 */
5443 if (!streq(signature, "t"))
5446 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5450 /* 32bit on dbus1 */
5453 if (!streq(signature, "u"))
5456 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5460 m->reply_cookie = serial;
5463 if (m->reply_cookie == 0)
5468 case BUS_MESSAGE_HEADER_UNIX_FDS:
5472 if (!streq(signature, "u"))
5475 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5479 unix_fds_set = true;
5483 if (!BUS_MESSAGE_IS_GVARIANT(m))
5484 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5493 if (m->n_fds != unix_fds)
5496 switch (m->header->type) {
5498 case SD_BUS_MESSAGE_SIGNAL:
5499 if (!m->path || !m->interface || !m->member)
5502 if (m->reply_cookie != 0)
5507 case SD_BUS_MESSAGE_METHOD_CALL:
5509 if (!m->path || !m->member)
5512 if (m->reply_cookie != 0)
5517 case SD_BUS_MESSAGE_METHOD_RETURN:
5519 if (m->reply_cookie == 0)
5523 case SD_BUS_MESSAGE_METHOD_ERROR:
5525 if (m->reply_cookie == 0 || !m->error.name)
5530 /* Refuse non-local messages that claim they are local */
5531 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5533 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5535 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5538 m->root_container.end = m->user_body_size;
5540 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5541 r = build_struct_offsets(
5543 m->root_container.signature,
5545 &m->root_container.item_size,
5546 &m->root_container.offsets,
5547 &m->root_container.n_offsets);
5552 /* Try to read the error message, but if we can't it's a non-issue */
5553 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5554 (void) sd_bus_message_read(m, "s", &m->error.message);
5559 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5560 assert_return(m, -EINVAL);
5561 assert_return(destination, -EINVAL);
5562 assert_return(!m->sealed, -EPERM);
5563 assert_return(!m->destination, -EEXIST);
5565 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5568 /// UNNEEDED by elogind
5570 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5574 struct bus_body_part *part;
5580 total = BUS_MESSAGE_SIZE(m);
5586 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5587 MESSAGE_FOREACH_PART(part, i, m)
5588 e = mempcpy(e, part->data, part->size);
5590 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5599 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5606 r = sd_bus_message_enter_container(m, 'a', "s");
5610 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5611 r = strv_extend(l, s);
5618 r = sd_bus_message_exit_container(m);
5625 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5629 assert_return(m, -EINVAL);
5630 assert_return(m->sealed, -EPERM);
5631 assert_return(l, -EINVAL);
5633 r = bus_message_read_strv_extend(m, &strv);
5643 static int bus_message_get_arg_skip(
5647 const char **_contents) {
5652 r = sd_bus_message_rewind(m, true);
5657 const char *contents;
5660 r = sd_bus_message_peek_type(m, &type, &contents);
5666 /* Don't match against arguments after the first one we don't understand */
5667 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5668 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5673 *_contents = contents;
5679 r = sd_bus_message_skip(m, NULL);
5686 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5693 r = bus_message_get_arg_skip(m, i, &type, NULL);
5697 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5700 return sd_bus_message_read_basic(m, type, str);
5703 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5704 const char *contents;
5711 r = bus_message_get_arg_skip(m, i, &type, &contents);
5715 if (type != SD_BUS_TYPE_ARRAY)
5717 if (!STR_IN_SET(contents, "s", "o", "g"))
5720 return sd_bus_message_read_strv(m, strv);
5723 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5724 assert_return(m, EINVAL);
5726 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5729 return sd_bus_error_get_errno(&m->error);
5732 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5733 struct bus_container *c;
5735 assert_return(m, NULL);
5737 c = complete ? &m->root_container : message_get_container(m);
5738 return strempty(c->signature);
5741 /// UNNEEDED by elogind
5743 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5744 assert_return(m, -EINVAL);
5746 return isempty(m->root_container.signature);
5749 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5750 assert_return(m, -EINVAL);
5752 return streq(strempty(m->root_container.signature), strempty(signature));
5756 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5757 bool done_something = false;
5760 assert_return(m, -EINVAL);
5761 assert_return(source, -EINVAL);
5762 assert_return(!m->sealed, -EPERM);
5763 assert_return(source->sealed, -EPERM);
5766 const char *contents;
5781 r = sd_bus_message_peek_type(source, &type, &contents);
5787 done_something = true;
5789 if (bus_type_is_container(type) > 0) {
5791 r = sd_bus_message_enter_container(source, type, contents);
5795 r = sd_bus_message_open_container(m, type, contents);
5799 r = sd_bus_message_copy(m, source, true);
5803 r = sd_bus_message_close_container(m);
5807 r = sd_bus_message_exit_container(source);
5814 r = sd_bus_message_read_basic(source, type, &basic);
5820 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5821 type == SD_BUS_TYPE_SIGNATURE ||
5822 type == SD_BUS_TYPE_STRING)
5823 r = sd_bus_message_append_basic(m, type, basic.string);
5825 r = sd_bus_message_append_basic(m, type, &basic);
5832 return done_something;
5835 /// UNNEEDED by elogind
5837 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5842 assert_return(m, -EINVAL);
5843 assert_return(m->sealed, -EPERM);
5844 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5845 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5846 assert_return(type || contents, -EINVAL);
5847 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5849 r = sd_bus_message_peek_type(m, &t, &c);
5853 if (type != 0 && type != t)
5856 if (contents && !streq_ptr(contents, c))
5863 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5864 assert_return(m, NULL);
5869 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5870 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5878 switch ((*m)->header->type) {
5880 case SD_BUS_MESSAGE_SIGNAL:
5881 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5887 case SD_BUS_MESSAGE_METHOD_CALL:
5888 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5894 case SD_BUS_MESSAGE_METHOD_RETURN:
5895 case SD_BUS_MESSAGE_METHOD_ERROR:
5897 n = message_new(bus, (*m)->header->type);
5901 n->reply_cookie = (*m)->reply_cookie;
5903 r = message_append_reply_cookie(n, n->reply_cookie);
5907 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5908 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5912 n->error._need_free = -1;
5921 if ((*m)->destination && !n->destination) {
5922 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5927 if ((*m)->sender && !n->sender) {
5928 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5933 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5935 r = sd_bus_message_copy(n, *m, true);
5939 timeout = (*m)->timeout;
5940 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5941 timeout = BUS_DEFAULT_TIMEOUT;
5943 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5947 sd_bus_message_unref(*m);
5954 /// UNNEEDED by elogind
5956 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5960 assert_return(!m->sealed, -EPERM);
5961 assert_return(!m->sender, -EPERM);
5963 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5966 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5967 assert_return(m, -EINVAL);
5968 assert_return(priority, -EINVAL);
5970 *priority = m->priority;
5974 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5975 assert_return(m, -EINVAL);
5976 assert_return(!m->sealed, -EPERM);
5978 m->priority = priority;