1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "alloc-util.h"
28 #include "bus-gvariant.h"
29 #include "bus-internal.h"
30 #include "bus-message.h"
31 #include "bus-signature.h"
36 #include "memfd-util.h"
37 #include "string-util.h"
39 #include "time-util.h"
43 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
45 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
50 if (old_base == new_base)
53 if ((uint8_t*) p < (uint8_t*) old_base)
56 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
59 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
62 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
67 close_and_munmap(part->memfd, part->mmap_begin, part->mapped);
68 else if (part->munmap_this)
69 munmap(part->mmap_begin, part->mapped);
70 else if (part->free_this)
77 static void message_reset_parts(sd_bus_message *m) {
78 struct bus_body_part *part;
83 while (m->n_body_parts > 0) {
84 struct bus_body_part *next = part->next;
85 message_free_part(m, part);
92 m->cached_rindex_part = NULL;
93 m->cached_rindex_part_begin = 0;
96 static void message_reset_containers(sd_bus_message *m) {
101 for (i = 0; i < m->n_containers; i++) {
102 free(m->containers[i].signature);
103 free(m->containers[i].offsets);
106 m->containers = mfree(m->containers);
108 m->n_containers = m->containers_allocated = 0;
109 m->root_container.index = 0;
112 static void message_free(sd_bus_message *m) {
118 message_reset_parts(m);
120 sd_bus_unref(m->bus);
123 close_many(m->fds, m->n_fds);
127 if (m->iovec != m->iovec_fixed)
130 message_reset_containers(m);
131 free(m->root_container.signature);
132 free(m->root_container.offsets);
134 free(m->root_container.peeked_signature);
136 bus_creds_done(&m->creds);
140 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
142 size_t old_size, new_size, start;
149 old_size = sizeof(struct bus_header) + m->fields_size;
150 start = ALIGN_TO(old_size, align);
151 new_size = start + sz;
153 if (new_size < start ||
154 new_size > (size_t) ((uint32_t) -1))
157 if (old_size == new_size)
158 return (uint8_t*) m->header + old_size;
160 if (m->free_header) {
161 np = realloc(m->header, ALIGN8(new_size));
165 /* Initially, the header is allocated as part of
166 * the sd_bus_message itself, let's replace it by
169 np = malloc(ALIGN8(new_size));
173 memcpy(np, m->header, sizeof(struct bus_header));
176 /* Zero out padding */
177 if (start > old_size)
178 memzero((uint8_t*) np + old_size, start - old_size);
182 m->fields_size = new_size - sizeof(struct bus_header);
184 /* Adjust quick access pointers */
185 m->path = adjust_pointer(m->path, op, old_size, m->header);
186 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
187 m->member = adjust_pointer(m->member, op, old_size, m->header);
188 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
189 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
190 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
192 m->free_header = true;
195 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
198 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
201 return (uint8_t*) np + start;
208 static int message_append_field_string(
220 /* dbus1 only allows 8bit header field ids */
224 /* dbus1 doesn't allow strings over 32bit, let's enforce this
225 * globally, to not risk convertability */
227 if (l > (size_t) (uint32_t) -1)
230 /* Signature "(yv)" where the variant contains "s" */
232 if (BUS_MESSAGE_IS_GVARIANT(m)) {
234 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
235 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
239 *((uint64_t*) p) = h;
246 *ret = (char*) p + 8;
249 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
250 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
259 ((uint32_t*) p)[1] = l;
260 memcpy(p + 8, s, l + 1);
263 *ret = (char*) p + 8;
269 static int message_append_field_signature(
280 /* dbus1 only allows 8bit header field ids */
284 /* dbus1 doesn't allow signatures over 8bit, let's enforce
285 * this globally, to not risk convertability */
290 /* Signature "(yv)" where the variant contains "g" */
292 if (BUS_MESSAGE_IS_GVARIANT(m))
293 /* For gvariant the serialization is the same as for normal strings */
294 return message_append_field_string(m, h, 'g', s, ret);
296 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
297 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
303 p[2] = SD_BUS_TYPE_SIGNATURE;
306 memcpy(p + 5, s, l + 1);
309 *ret = (const char*) p + 5;
315 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
320 /* dbus1 only allows 8bit header field ids */
324 if (BUS_MESSAGE_IS_GVARIANT(m)) {
325 /* (field id 64bit + ((value + NUL + signature string 'u') */
327 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
331 *((uint64_t*) p) = h;
332 *((uint32_t*) (p + 8)) = x;
336 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
337 p = message_extend_fields(m, 8, 4 + 4, false);
346 ((uint32_t*) p)[1] = x;
352 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
357 /* dbus1 only allows 8bit header field ids */
361 if (BUS_MESSAGE_IS_GVARIANT(m)) {
362 /* (field id 64bit + ((value + NUL + signature string 't') */
364 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
368 *((uint64_t*) p) = h;
369 *((uint64_t*) (p + 8)) = x;
373 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
374 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
387 ((uint64_t*) p)[1] = x;
393 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
396 if (BUS_MESSAGE_IS_GVARIANT(m))
397 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
399 /* 64bit cookies are not supported on dbus1 */
400 if (cookie > 0xffffffffUL)
403 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
407 int bus_message_from_header(
410 size_t header_accessible,
412 size_t footer_accessible,
418 sd_bus_message **ret) {
420 _cleanup_free_ sd_bus_message *m = NULL;
421 struct bus_header *h;
425 assert(header || header_accessible <= 0);
426 assert(footer || footer_accessible <= 0);
427 assert(fds || n_fds <= 0);
430 if (header_accessible < sizeof(struct bus_header))
433 if (header_accessible > message_size)
435 if (footer_accessible > message_size)
439 if (!IN_SET(h->version, 1, 2))
442 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
445 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
448 /* Note that we are happy with unknown flags in the flags header! */
450 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
453 label_sz = strlen(label);
464 m->header_accessible = header_accessible;
466 m->footer_accessible = footer_accessible;
468 if (BUS_MESSAGE_IS_GVARIANT(m)) {
471 if (h->dbus2.cookie == 0)
474 /* dbus2 derives the sizes from the message size and
475 the offset table at the end, since it is formatted as
476 gvariant "yyyyuta{tv}v". Since the message itself is a
477 structure with precisely to variable sized entries,
478 there's only one offset in the table, which marks the
479 end of the fields array. */
481 ws = bus_gvariant_determine_word_size(message_size, 0);
482 if (footer_accessible < ws)
485 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
486 if (ALIGN8(m->fields_size) > message_size - ws)
488 if (m->fields_size < sizeof(struct bus_header))
491 m->fields_size -= sizeof(struct bus_header);
492 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
494 if (h->dbus1.serial == 0)
497 /* dbus1 has the sizes in the header */
498 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
499 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
501 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
509 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
510 memcpy(m->creds.label, label, label_sz + 1);
512 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
515 m->bus = sd_bus_ref(bus);
522 int bus_message_from_malloc(
529 sd_bus_message **ret) {
535 r = bus_message_from_header(
537 buffer, length, /* in this case the initial bytes and the final bytes are the same */
546 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
549 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
551 m->body.sealed = true;
556 m->iovec = m->iovec_fixed;
557 m->iovec[0].iov_base = buffer;
558 m->iovec[0].iov_len = length;
560 r = bus_message_parse_fields(m);
564 /* We take possession of the memory and fds now */
565 m->free_header = true;
576 _public_ int sd_bus_message_new(
583 assert_return(bus, -ENOTCONN);
584 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
585 assert_return(m, -EINVAL);
586 assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
588 t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
593 t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message)));
594 t->header->endian = BUS_NATIVE_ENDIAN;
595 t->header->type = type;
596 t->header->version = bus->message_version;
597 t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING);
598 t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t);
599 t->bus = sd_bus_ref(bus);
601 if (bus->allow_interactive_authorization)
602 t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
608 _public_ int sd_bus_message_new_signal(
612 const char *interface,
613 const char *member) {
618 assert_return(bus, -ENOTCONN);
619 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
620 assert_return(object_path_is_valid(path), -EINVAL);
621 assert_return(interface_name_is_valid(interface), -EINVAL);
622 assert_return(member_name_is_valid(member), -EINVAL);
623 assert_return(m, -EINVAL);
625 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_SIGNAL);
631 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
633 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
636 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
639 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
647 sd_bus_message_unref(t);
651 _public_ int sd_bus_message_new_method_call(
654 const char *destination,
656 const char *interface,
657 const char *member) {
662 assert_return(bus, -ENOTCONN);
663 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
664 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
665 assert_return(object_path_is_valid(path), -EINVAL);
666 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
667 assert_return(member_name_is_valid(member), -EINVAL);
668 assert_return(m, -EINVAL);
670 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_CALL);
676 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
679 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
684 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
690 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
703 static int message_new_reply(
704 sd_bus_message *call,
706 sd_bus_message **m) {
712 assert_return(call, -EINVAL);
713 assert_return(call->sealed, -EPERM);
714 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
715 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
716 assert_return(m, -EINVAL);
718 cookie = BUS_MESSAGE_COOKIE(call);
722 r = sd_bus_message_new(call->bus, &t, type);
728 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
729 t->reply_cookie = cookie;
730 r = message_append_reply_cookie(t, t->reply_cookie);
735 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
740 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
741 t->enforced_reply_signature = call->enforced_reply_signature;
751 _public_ int sd_bus_message_new_method_return(
752 sd_bus_message *call,
753 sd_bus_message **m) {
755 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
758 _public_ int sd_bus_message_new_method_error(
759 sd_bus_message *call,
761 const sd_bus_error *e) {
766 assert_return(sd_bus_error_is_set(e), -EINVAL);
767 assert_return(m, -EINVAL);
769 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
773 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
778 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
783 t->error._need_free = -1;
793 _public_ int sd_bus_message_new_method_errorf(
794 sd_bus_message *call,
800 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
803 assert_return(name, -EINVAL);
804 assert_return(m, -EINVAL);
806 va_start(ap, format);
807 bus_error_setfv(&error, name, format, ap);
810 return sd_bus_message_new_method_error(call, m, &error);
813 _public_ int sd_bus_message_new_method_errno(
814 sd_bus_message *call,
817 const sd_bus_error *p) {
819 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
821 if (sd_bus_error_is_set(p))
822 return sd_bus_message_new_method_error(call, m, p);
824 sd_bus_error_set_errno(&berror, error);
826 return sd_bus_message_new_method_error(call, m, &berror);
829 _public_ int sd_bus_message_new_method_errnof(
830 sd_bus_message *call,
836 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
839 va_start(ap, format);
840 sd_bus_error_set_errnofv(&berror, error, format, ap);
843 return sd_bus_message_new_method_error(call, m, &berror);
846 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
850 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
851 m->creds.well_known_names_local = true;
852 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
855 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
859 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
860 m->creds.well_known_names_driver = true;
861 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
864 int bus_message_new_synthetic_error(
867 const sd_bus_error *e,
868 sd_bus_message **m) {
874 assert(sd_bus_error_is_set(e));
877 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_ERROR);
883 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
884 t->reply_cookie = cookie;
886 r = message_append_reply_cookie(t, t->reply_cookie);
890 if (bus && bus->unique_name) {
891 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
896 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
901 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
906 t->error._need_free = -1;
908 bus_message_set_sender_driver(bus, t);
918 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
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 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
945 assert_return(m, -EINVAL);
946 assert_return(type, -EINVAL);
948 *type = m->header->type;
952 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
955 assert_return(m, -EINVAL);
956 assert_return(cookie, -EINVAL);
958 c = BUS_MESSAGE_COOKIE(m);
962 *cookie = BUS_MESSAGE_COOKIE(m);
966 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
967 assert_return(m, -EINVAL);
968 assert_return(cookie, -EINVAL);
970 if (m->reply_cookie == 0)
973 *cookie = m->reply_cookie;
977 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
978 assert_return(m, -EINVAL);
980 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
981 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
984 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
985 assert_return(m, -EINVAL);
987 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
990 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
991 assert_return(m, -EINVAL);
993 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
994 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
997 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
998 assert_return(m, NULL);
1003 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1004 assert_return(m, NULL);
1006 return m->interface;
1009 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1010 assert_return(m, NULL);
1015 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1016 assert_return(m, NULL);
1018 return m->destination;
1021 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1022 assert_return(m, NULL);
1027 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1028 assert_return(m, NULL);
1030 if (!sd_bus_error_is_set(&m->error))
1036 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1037 assert_return(m, -EINVAL);
1038 assert_return(usec, -EINVAL);
1040 if (m->monotonic <= 0)
1043 *usec = m->monotonic;
1047 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1048 assert_return(m, -EINVAL);
1049 assert_return(usec, -EINVAL);
1051 if (m->realtime <= 0)
1054 *usec = m->realtime;
1058 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1059 assert_return(m, -EINVAL);
1060 assert_return(seqnum, -EINVAL);
1065 *seqnum = m->seqnum;
1069 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1070 assert_return(m, NULL);
1072 if (m->creds.mask == 0)
1078 _public_ int sd_bus_message_is_signal(
1080 const char *interface,
1081 const char *member) {
1083 assert_return(m, -EINVAL);
1085 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1088 if (interface && (!m->interface || !streq(m->interface, interface)))
1091 if (member && (!m->member || !streq(m->member, member)))
1097 _public_ int sd_bus_message_is_method_call(
1099 const char *interface,
1100 const char *member) {
1102 assert_return(m, -EINVAL);
1104 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1107 if (interface && (!m->interface || !streq(m->interface, interface)))
1110 if (member && (!m->member || !streq(m->member, member)))
1116 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1117 assert_return(m, -EINVAL);
1119 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1122 if (name && (!m->error.name || !streq(m->error.name, name)))
1128 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1129 assert_return(m, -EINVAL);
1130 assert_return(!m->sealed, -EPERM);
1131 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1133 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
1138 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1139 assert_return(m, -EINVAL);
1140 assert_return(!m->sealed, -EPERM);
1142 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
1147 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1148 assert_return(m, -EINVAL);
1149 assert_return(!m->sealed, -EPERM);
1151 SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
1156 static struct bus_container *message_get_container(sd_bus_message *m) {
1159 if (m->n_containers == 0)
1160 return &m->root_container;
1162 assert(m->containers);
1163 return m->containers + m->n_containers - 1;
1166 struct bus_body_part *message_append_part(sd_bus_message *m) {
1167 struct bus_body_part *part;
1174 if (m->n_body_parts <= 0) {
1178 assert(m->body_end);
1180 part = new0(struct bus_body_part, 1);
1186 m->body_end->next = part;
1196 static void part_zero(struct bus_body_part *part, size_t sz) {
1201 /* All other fields can be left in their defaults */
1202 assert(!part->data);
1203 assert(part->memfd < 0);
1206 part->is_zero = true;
1207 part->sealed = true;
1210 static int part_make_space(
1211 struct sd_bus_message *m,
1212 struct bus_body_part *part,
1220 assert(!part->sealed);
1225 if (part->allocated == 0 || sz > part->allocated) {
1226 size_t new_allocated;
1228 new_allocated = sz > 0 ? 2 * sz : 64;
1229 n = realloc(part->data, new_allocated);
1236 part->allocated = new_allocated;
1237 part->free_this = true;
1241 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1247 static int message_add_offset(sd_bus_message *m, size_t offset) {
1248 struct bus_container *c;
1251 assert(BUS_MESSAGE_IS_GVARIANT(m));
1253 /* Add offset to current container, unless this is the first
1254 * item in it, which will have the 0 offset, which we can
1256 c = message_get_container(m);
1258 if (!c->need_offsets)
1261 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1264 c->offsets[c->n_offsets++] = offset;
1268 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1269 struct bus_container *c;
1276 /* Update counters */
1277 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1280 *c->array_size += expand;
1284 static void *message_extend_body(
1289 bool force_inline) {
1291 size_t start_body, end_body, padding, added;
1302 start_body = ALIGN_TO((size_t) m->body_size, align);
1303 end_body = start_body + sz;
1305 padding = start_body - m->body_size;
1306 added = padding + sz;
1308 /* Check for 32bit overflows */
1309 if (end_body > (size_t) ((uint32_t) -1) ||
1310 end_body < start_body) {
1316 struct bus_body_part *part = NULL;
1320 m->n_body_parts <= 0 ||
1321 m->body_end->sealed ||
1322 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1323 (force_inline && m->body_end->size > MEMFD_MIN_SIZE);
1324 /* If this must be an inlined extension, let's create a new part if
1325 * the previous part is large enough to be inlined. */
1329 part = message_append_part(m);
1333 part_zero(part, padding);
1336 part = message_append_part(m);
1340 r = part_make_space(m, part, sz, &p);
1344 struct bus_container *c;
1346 size_t os, start_part, end_part;
1352 start_part = ALIGN_TO(part->size, align);
1353 end_part = start_part + sz;
1355 r = part_make_space(m, part, end_part, &p);
1360 memzero(p, padding);
1361 p = (uint8_t*) p + padding;
1364 /* Readjust pointers */
1365 for (c = m->containers; c < m->containers + m->n_containers; c++)
1366 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1368 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1371 /* Return something that is not NULL and is aligned */
1372 p = (uint8_t*) align;
1374 m->body_size = end_body;
1375 message_extend_containers(m, added);
1378 r = message_add_offset(m, end_body);
1388 static int message_push_fd(sd_bus_message *m, int fd) {
1399 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1403 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1411 m->fds[m->n_fds] = copy;
1417 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1418 _cleanup_close_ int fd = -1;
1419 struct bus_container *c;
1423 assert_return(m, -EINVAL);
1424 assert_return(!m->sealed, -EPERM);
1425 assert_return(bus_type_is_basic(type), -EINVAL);
1426 assert_return(!m->poisoned, -ESTALE);
1428 c = message_get_container(m);
1430 if (c->signature && c->signature[c->index]) {
1431 /* Container signature is already set */
1433 if (c->signature[c->index] != type)
1438 /* Maybe we can append to the signature? But only if this is the top-level container */
1439 if (c->enclosing != 0)
1442 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1449 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1455 case SD_BUS_TYPE_SIGNATURE:
1456 case SD_BUS_TYPE_STRING:
1460 case SD_BUS_TYPE_OBJECT_PATH:
1468 case SD_BUS_TYPE_BOOLEAN:
1470 u8 = p && *(int*) p;
1476 case SD_BUS_TYPE_UNIX_FD:
1481 fd = message_push_fd(m, *(int*) p);
1492 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1493 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1500 a = message_extend_body(m, align, sz, true, false);
1507 *stored = (const uint8_t*) a;
1514 case SD_BUS_TYPE_STRING:
1515 /* To make things easy we'll serialize a NULL string
1516 * into the empty string */
1520 case SD_BUS_TYPE_OBJECT_PATH:
1526 sz = 4 + strlen(p) + 1;
1529 case SD_BUS_TYPE_SIGNATURE:
1534 sz = 1 + strlen(p) + 1;
1537 case SD_BUS_TYPE_BOOLEAN:
1539 u32 = p && *(int*) p;
1545 case SD_BUS_TYPE_UNIX_FD:
1550 fd = message_push_fd(m, *(int*) p);
1561 align = bus_type_get_alignment(type);
1562 sz = bus_type_get_size(type);
1569 a = message_extend_body(m, align, sz, false, false);
1573 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
1574 *(uint32_t*) a = sz - 5;
1575 memcpy((uint8_t*) a + 4, p, sz - 4);
1578 *stored = (const uint8_t*) a + 4;
1580 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1581 *(uint8_t*) a = sz - 2;
1582 memcpy((uint8_t*) a + 1, p, sz - 1);
1585 *stored = (const uint8_t*) a + 1;
1594 if (type == SD_BUS_TYPE_UNIX_FD)
1597 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1604 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1605 return message_append_basic(m, type, p, NULL);
1608 _public_ int sd_bus_message_append_string_space(
1613 struct bus_container *c;
1616 assert_return(m, -EINVAL);
1617 assert_return(s, -EINVAL);
1618 assert_return(!m->sealed, -EPERM);
1619 assert_return(!m->poisoned, -ESTALE);
1621 c = message_get_container(m);
1623 if (c->signature && c->signature[c->index]) {
1624 /* Container signature is already set */
1626 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1631 /* Maybe we can append to the signature? But only if this is the top-level container */
1632 if (c->enclosing != 0)
1635 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1642 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1643 a = message_extend_body(m, 1, size + 1, true, false);
1649 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1653 *(uint32_t*) a = size;
1659 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1665 _public_ int sd_bus_message_append_string_iovec(
1667 const struct iovec *iov,
1675 assert_return(m, -EINVAL);
1676 assert_return(!m->sealed, -EPERM);
1677 assert_return(iov || n == 0, -EINVAL);
1678 assert_return(!m->poisoned, -ESTALE);
1680 size = IOVEC_TOTAL_SIZE(iov, n);
1682 r = sd_bus_message_append_string_space(m, size, &p);
1686 for (i = 0; i < n; i++) {
1688 if (iov[i].iov_base)
1689 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1691 memset(p, ' ', iov[i].iov_len);
1693 p += iov[i].iov_len;
1699 static int bus_message_open_array(
1701 struct bus_container *c,
1702 const char *contents,
1703 uint32_t **array_size,
1705 bool *need_offsets) {
1715 assert(need_offsets);
1717 if (!signature_is_single(contents, true))
1720 if (c->signature && c->signature[c->index]) {
1722 /* Verify the existing signature */
1724 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1727 if (!startswith(c->signature + c->index + 1, contents))
1730 nindex = c->index + 1 + strlen(contents);
1734 if (c->enclosing != 0)
1737 /* Extend the existing signature */
1739 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1745 nindex = e - c->signature;
1748 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1749 alignment = bus_gvariant_get_alignment(contents);
1753 /* Add alignment padding and add to offset list */
1754 if (!message_extend_body(m, alignment, 0, false, false))
1757 r = bus_gvariant_is_fixed_size(contents);
1761 *begin = m->body_size;
1762 *need_offsets = r == 0;
1766 struct bus_body_part *o;
1768 alignment = bus_type_get_alignment(contents[0]);
1772 a = message_extend_body(m, 4, 4, false, false);
1777 op = m->body_end->data;
1778 os = m->body_end->size;
1780 /* Add alignment between size and first element */
1781 if (!message_extend_body(m, alignment, 0, false, false))
1784 /* location of array size might have changed so let's readjust a */
1785 if (o == m->body_end)
1786 a = adjust_pointer(a, op, os, m->body_end->data);
1792 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1798 static int bus_message_open_variant(
1800 struct bus_container *c,
1801 const char *contents) {
1807 if (!signature_is_single(contents, false))
1810 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1813 if (c->signature && c->signature[c->index]) {
1815 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1821 if (c->enclosing != 0)
1824 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1831 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1832 /* Variants are always aligned to 8 */
1834 if (!message_extend_body(m, 8, 0, false, false))
1841 l = strlen(contents);
1842 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1847 memcpy((uint8_t*) a + 1, contents, l + 1);
1850 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1856 static int bus_message_open_struct(
1858 struct bus_container *c,
1859 const char *contents,
1861 bool *need_offsets) {
1870 assert(need_offsets);
1872 if (!signature_is_valid(contents, false))
1875 if (c->signature && c->signature[c->index]) {
1878 l = strlen(contents);
1880 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1881 !startswith(c->signature + c->index + 1, contents) ||
1882 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1885 nindex = c->index + 1 + l + 1;
1889 if (c->enclosing != 0)
1892 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1898 nindex = e - c->signature;
1901 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1904 alignment = bus_gvariant_get_alignment(contents);
1908 if (!message_extend_body(m, alignment, 0, false, false))
1911 r = bus_gvariant_is_fixed_size(contents);
1915 *begin = m->body_size;
1916 *need_offsets = r == 0;
1918 /* Align contents to 8 byte boundary */
1919 if (!message_extend_body(m, 8, 0, false, false))
1923 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1929 static int bus_message_open_dict_entry(
1931 struct bus_container *c,
1932 const char *contents,
1934 bool *need_offsets) {
1942 assert(need_offsets);
1944 if (!signature_is_pair(contents))
1947 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1950 if (c->signature && c->signature[c->index]) {
1953 l = strlen(contents);
1955 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1956 !startswith(c->signature + c->index + 1, contents) ||
1957 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1962 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1965 alignment = bus_gvariant_get_alignment(contents);
1969 if (!message_extend_body(m, alignment, 0, false, false))
1972 r = bus_gvariant_is_fixed_size(contents);
1976 *begin = m->body_size;
1977 *need_offsets = r == 0;
1979 /* Align contents to 8 byte boundary */
1980 if (!message_extend_body(m, 8, 0, false, false))
1987 _public_ int sd_bus_message_open_container(
1990 const char *contents) {
1992 struct bus_container *c, *w;
1993 uint32_t *array_size = NULL;
1995 size_t before, begin = 0;
1996 bool need_offsets = false;
1999 assert_return(m, -EINVAL);
2000 assert_return(!m->sealed, -EPERM);
2001 assert_return(contents, -EINVAL);
2002 assert_return(!m->poisoned, -ESTALE);
2004 /* Make sure we have space for one more container */
2005 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2010 c = message_get_container(m);
2012 signature = strdup(contents);
2018 /* Save old index in the parent container, in case we have to
2019 * abort this container */
2020 c->saved_index = c->index;
2021 before = m->body_size;
2023 if (type == SD_BUS_TYPE_ARRAY)
2024 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2025 else if (type == SD_BUS_TYPE_VARIANT)
2026 r = bus_message_open_variant(m, c, contents);
2027 else if (type == SD_BUS_TYPE_STRUCT)
2028 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2029 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2030 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2039 /* OK, let's fill it in */
2040 w = m->containers + m->n_containers++;
2041 w->enclosing = type;
2042 w->signature = signature;
2044 w->array_size = array_size;
2047 w->n_offsets = w->offsets_allocated = 0;
2049 w->need_offsets = need_offsets;
2054 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2059 if (!BUS_MESSAGE_IS_GVARIANT(m))
2062 if (c->need_offsets) {
2063 size_t payload, sz, i;
2066 /* Variable-width arrays */
2068 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2069 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2071 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2075 for (i = 0; i < c->n_offsets; i++)
2076 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2080 /* Fixed-width or empty arrays */
2082 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2090 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2096 assert(c->signature);
2098 if (!BUS_MESSAGE_IS_GVARIANT(m))
2101 l = strlen(c->signature);
2103 a = message_extend_body(m, 1, 1 + l, true, false);
2108 memcpy(a+1, c->signature, l);
2113 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2114 bool fixed_size = true;
2115 size_t n_variable = 0;
2124 if (!BUS_MESSAGE_IS_GVARIANT(m))
2127 p = strempty(c->signature);
2131 r = signature_element_length(p, &n);
2140 r = bus_gvariant_is_fixed_size(t);
2145 assert(!c->need_offsets || i <= c->n_offsets);
2147 /* We need to add an offset for each item that has a
2148 * variable size and that is not the last one in the
2152 if (r == 0 && p[n] != 0)
2159 assert(!c->need_offsets || i == c->n_offsets);
2160 assert(c->need_offsets || n_variable == 0);
2162 if (isempty(c->signature)) {
2163 /* The unary type is encoded as fixed 1 byte padding */
2164 a = message_extend_body(m, 1, 1, add_offset, false);
2169 } else if (n_variable <= 0) {
2172 /* Structures with fixed-size members only have to be
2173 * fixed-size themselves. But gvariant requires all fixed-size
2174 * elements to be sized a multiple of their alignment. Hence,
2175 * we must *always* add final padding after the last member so
2176 * the overall size of the structure is properly aligned. */
2178 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2180 assert(alignment > 0);
2182 a = message_extend_body(m, alignment, 0, add_offset, false);
2189 assert(c->offsets[c->n_offsets-1] == m->body_size);
2191 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2193 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2197 p = strempty(c->signature);
2198 for (i = 0, j = 0; i < c->n_offsets; i++) {
2202 r = signature_element_length(p, &n);
2213 r = bus_gvariant_is_fixed_size(t);
2216 if (r > 0 || p[0] == 0)
2220 k = n_variable - 1 - j;
2222 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2231 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2232 struct bus_container *c;
2235 assert_return(m, -EINVAL);
2236 assert_return(!m->sealed, -EPERM);
2237 assert_return(m->n_containers > 0, -EINVAL);
2238 assert_return(!m->poisoned, -ESTALE);
2240 c = message_get_container(m);
2242 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2243 if (c->signature && c->signature[c->index] != 0)
2248 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2249 r = bus_message_close_array(m, c);
2250 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2251 r = bus_message_close_variant(m, c);
2252 else if (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY))
2253 r = bus_message_close_struct(m, c, true);
2255 assert_not_reached("Unknown container type");
2269 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2276 stack[*i].types = types;
2277 stack[*i].n_struct = n_struct;
2278 stack[*i].n_array = n_array;
2284 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2295 *types = stack[*i].types;
2296 *n_struct = stack[*i].n_struct;
2297 *n_array = stack[*i].n_array;
2302 _public_ int sd_bus_message_appendv(
2307 unsigned n_array, n_struct;
2308 TypeStack stack[BUS_CONTAINER_DEPTH];
2309 unsigned stack_ptr = 0;
2312 assert_return(m, -EINVAL);
2313 assert_return(types, -EINVAL);
2314 assert_return(!m->sealed, -EPERM);
2315 assert_return(!m->poisoned, -ESTALE);
2317 n_array = (unsigned) -1;
2318 n_struct = strlen(types);
2323 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2324 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2330 r = sd_bus_message_close_container(m);
2338 if (n_array != (unsigned) -1)
2347 case SD_BUS_TYPE_BYTE: {
2350 x = (uint8_t) va_arg(ap, int);
2351 r = sd_bus_message_append_basic(m, *t, &x);
2355 case SD_BUS_TYPE_BOOLEAN:
2356 case SD_BUS_TYPE_INT32:
2357 case SD_BUS_TYPE_UINT32:
2358 case SD_BUS_TYPE_UNIX_FD: {
2361 /* We assume a boolean is the same as int32_t */
2362 assert_cc(sizeof(int32_t) == sizeof(int));
2364 x = va_arg(ap, uint32_t);
2365 r = sd_bus_message_append_basic(m, *t, &x);
2369 case SD_BUS_TYPE_INT16:
2370 case SD_BUS_TYPE_UINT16: {
2373 x = (uint16_t) va_arg(ap, int);
2374 r = sd_bus_message_append_basic(m, *t, &x);
2378 case SD_BUS_TYPE_INT64:
2379 case SD_BUS_TYPE_UINT64: {
2382 x = va_arg(ap, uint64_t);
2383 r = sd_bus_message_append_basic(m, *t, &x);
2387 case SD_BUS_TYPE_DOUBLE: {
2390 x = va_arg(ap, double);
2391 r = sd_bus_message_append_basic(m, *t, &x);
2395 case SD_BUS_TYPE_STRING:
2396 case SD_BUS_TYPE_OBJECT_PATH:
2397 case SD_BUS_TYPE_SIGNATURE: {
2400 x = va_arg(ap, const char*);
2401 r = sd_bus_message_append_basic(m, *t, x);
2405 case SD_BUS_TYPE_ARRAY: {
2408 r = signature_element_length(t + 1, &k);
2414 memcpy(s, t + 1, k);
2417 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2422 if (n_array == (unsigned) -1) {
2427 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2433 n_array = va_arg(ap, unsigned);
2438 case SD_BUS_TYPE_VARIANT: {
2441 s = va_arg(ap, const char*);
2445 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2449 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2454 n_struct = strlen(s);
2455 n_array = (unsigned) -1;
2460 case SD_BUS_TYPE_STRUCT_BEGIN:
2461 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2464 r = signature_element_length(t, &k);
2471 memcpy(s, t + 1, k - 2);
2474 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2479 if (n_array == (unsigned) -1) {
2484 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2490 n_array = (unsigned) -1;
2506 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2510 assert_return(m, -EINVAL);
2511 assert_return(types, -EINVAL);
2512 assert_return(!m->sealed, -EPERM);
2513 assert_return(!m->poisoned, -ESTALE);
2515 va_start(ap, types);
2516 r = sd_bus_message_appendv(m, types, ap);
2522 _public_ int sd_bus_message_append_array_space(
2532 assert_return(m, -EINVAL);
2533 assert_return(!m->sealed, -EPERM);
2534 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2535 assert_return(ptr || size == 0, -EINVAL);
2536 assert_return(!m->poisoned, -ESTALE);
2538 /* alignment and size of the trivial types (except bool) is
2539 * identical for gvariant and dbus1 marshalling */
2540 align = bus_type_get_alignment(type);
2541 sz = bus_type_get_size(type);
2543 assert_se(align > 0);
2549 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2553 a = message_extend_body(m, align, size, false, false);
2557 r = sd_bus_message_close_container(m);
2565 _public_ int sd_bus_message_append_array(
2573 assert_return(m, -EINVAL);
2574 assert_return(!m->sealed, -EPERM);
2575 assert_return(bus_type_is_trivial(type), -EINVAL);
2576 assert_return(ptr || size == 0, -EINVAL);
2577 assert_return(!m->poisoned, -ESTALE);
2579 r = sd_bus_message_append_array_space(m, type, size, &p);
2583 memcpy_safe(p, ptr, size);
2588 _public_ int sd_bus_message_append_array_iovec(
2591 const struct iovec *iov,
2599 assert_return(m, -EINVAL);
2600 assert_return(!m->sealed, -EPERM);
2601 assert_return(bus_type_is_trivial(type), -EINVAL);
2602 assert_return(iov || n == 0, -EINVAL);
2603 assert_return(!m->poisoned, -ESTALE);
2605 size = IOVEC_TOTAL_SIZE(iov, n);
2607 r = sd_bus_message_append_array_space(m, type, size, &p);
2611 for (i = 0; i < n; i++) {
2613 if (iov[i].iov_base)
2614 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2616 memzero(p, iov[i].iov_len);
2618 p = (uint8_t*) p + iov[i].iov_len;
2624 _public_ int sd_bus_message_append_array_memfd(
2631 _cleanup_close_ int copy_fd = -1;
2632 struct bus_body_part *part;
2638 assert_return(m, -EINVAL);
2639 assert_return(memfd >= 0, -EBADF);
2640 assert_return(bus_type_is_trivial(type), -EINVAL);
2641 assert_return(size > 0, -EINVAL);
2642 assert_return(!m->sealed, -EPERM);
2643 assert_return(!m->poisoned, -ESTALE);
2645 r = memfd_set_sealed(memfd);
2649 copy_fd = dup(memfd);
2653 r = memfd_get_size(memfd, &real_size);
2657 if (offset == 0 && size == (uint64_t) -1)
2659 else if (offset + size > real_size)
2662 align = bus_type_get_alignment(type);
2663 sz = bus_type_get_size(type);
2665 assert_se(align > 0);
2668 if (offset % align != 0)
2674 if (size > (uint64_t) (uint32_t) -1)
2677 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2681 a = message_extend_body(m, align, 0, false, false);
2685 part = message_append_part(m);
2689 part->memfd = copy_fd;
2690 part->memfd_offset = offset;
2691 part->sealed = true;
2695 m->body_size += size;
2696 message_extend_containers(m, size);
2698 return sd_bus_message_close_container(m);
2701 _public_ int sd_bus_message_append_string_memfd(
2707 _cleanup_close_ int copy_fd = -1;
2708 struct bus_body_part *part;
2709 struct bus_container *c;
2714 assert_return(m, -EINVAL);
2715 assert_return(memfd >= 0, -EBADF);
2716 assert_return(size > 0, -EINVAL);
2717 assert_return(!m->sealed, -EPERM);
2718 assert_return(!m->poisoned, -ESTALE);
2720 r = memfd_set_sealed(memfd);
2724 copy_fd = dup(memfd);
2728 r = memfd_get_size(memfd, &real_size);
2732 if (offset == 0 && size == (uint64_t) -1)
2734 else if (offset + size > real_size)
2737 /* We require this to be NUL terminated */
2741 if (size > (uint64_t) (uint32_t) -1)
2744 c = message_get_container(m);
2745 if (c->signature && c->signature[c->index]) {
2746 /* Container signature is already set */
2748 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2753 /* Maybe we can append to the signature? But only if this is the top-level container */
2754 if (c->enclosing != 0)
2757 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2764 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2765 a = message_extend_body(m, 4, 4, false, false);
2769 *(uint32_t*) a = size - 1;
2772 part = message_append_part(m);
2776 part->memfd = copy_fd;
2777 part->memfd_offset = offset;
2778 part->sealed = true;
2782 m->body_size += size;
2783 message_extend_containers(m, size);
2785 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2786 r = message_add_offset(m, m->body_size);
2793 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2799 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2803 assert_return(m, -EINVAL);
2804 assert_return(!m->sealed, -EPERM);
2805 assert_return(!m->poisoned, -ESTALE);
2807 r = sd_bus_message_open_container(m, 'a', "s");
2811 STRV_FOREACH(i, l) {
2812 r = sd_bus_message_append_basic(m, 's', *i);
2817 return sd_bus_message_close_container(m);
2820 static int bus_message_close_header(sd_bus_message *m) {
2824 /* The actual user data is finished now, we just complete the
2825 variant and struct now (at least on gvariant). Remember
2826 this position, so that during parsing we know where to
2827 put the outer container end. */
2828 m->user_body_size = m->body_size;
2830 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2831 const char *signature;
2835 /* Add offset table to end of fields array */
2836 if (m->n_header_offsets >= 1) {
2840 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2842 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2843 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2847 for (i = 0; i < m->n_header_offsets; i++)
2848 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2851 /* Add gvariant NUL byte plus signature to the end of
2852 * the body, followed by the final offset pointing to
2853 * the end of the fields array */
2855 signature = strempty(m->root_container.signature);
2856 l = strlen(signature);
2858 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2859 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2864 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2865 memcpy((uint8_t*) d + 2, signature, l);
2866 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2868 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2871 m->footer_accessible = 1 + l + 2 + sz;
2873 m->header->dbus1.fields_size = m->fields_size;
2874 m->header->dbus1.body_size = m->body_size;
2880 _public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t timeout_usec) {
2881 struct bus_body_part *part;
2886 assert_return(m, -EINVAL);
2891 if (m->n_containers > 0)
2897 if (cookie > 0xffffffffULL &&
2898 !BUS_MESSAGE_IS_GVARIANT(m))
2901 /* In vtables the return signature of method calls is listed,
2902 * let's check if they match if this is a response */
2903 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2904 m->enforced_reply_signature &&
2905 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2908 /* If gvariant marshalling is used we need to close the body structure */
2909 r = bus_message_close_struct(m, &m->root_container, false);
2913 /* If there's a non-trivial signature set, then add it in
2914 * here, but only on dbus1 */
2915 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2916 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2922 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2927 r = bus_message_close_header(m);
2931 if (BUS_MESSAGE_IS_GVARIANT(m))
2932 m->header->dbus2.cookie = cookie;
2934 m->header->dbus1.serial = (uint32_t) cookie;
2936 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout_usec;
2938 /* Add padding at the end of the fields part, since we know
2939 * the body needs to start at an 8 byte alignment. We made
2940 * sure we allocated enough space for this, so all we need to
2941 * do here is to zero it out. */
2942 a = ALIGN8(m->fields_size) - m->fields_size;
2944 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2946 /* If this is something we can send as memfd, then let's seal
2947 the memfd now. Note that we can send memfds as payload only
2948 for directed messages, and not for broadcasts. */
2949 if (m->destination && m->bus->use_memfd) {
2950 MESSAGE_FOREACH_PART(part, i, m)
2951 if (part->memfd >= 0 &&
2953 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2954 part != m->body_end) { /* The last part may never be sent as memfd */
2957 /* Try to seal it if that makes
2958 * sense. First, unmap our own map to
2959 * make sure we don't keep it busy. */
2960 bus_body_part_unmap(part);
2962 /* Then, sync up real memfd size */
2964 r = memfd_set_size(part->memfd, sz);
2968 /* Finally, try to seal */
2969 if (memfd_set_sealed(part->memfd) >= 0)
2970 part->sealed = true;
2974 m->root_container.end = m->user_body_size;
2975 m->root_container.index = 0;
2976 m->root_container.offset_index = 0;
2977 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2984 int bus_body_part_map(struct bus_body_part *part) {
2993 if (part->size <= 0)
2996 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2997 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2998 static const uint8_t zeroes[7] = { };
2999 part->data = (void*) zeroes;
3003 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3004 psz = PAGE_ALIGN(part->size + shift);
3006 if (part->memfd >= 0)
3007 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3008 else if (part->is_zero)
3009 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3013 if (p == MAP_FAILED)
3017 part->mmap_begin = p;
3018 part->data = (uint8_t*) p + shift;
3019 part->munmap_this = true;
3024 void bus_body_part_unmap(struct bus_body_part *part) {
3028 if (part->memfd < 0)
3031 if (!part->mmap_begin)
3034 if (!part->munmap_this)
3037 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3039 part->mmap_begin = NULL;
3042 part->munmap_this = false;
3047 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3048 size_t k, start, end;
3053 start = ALIGN_TO((size_t) *rindex, align);
3054 end = start + nbytes;
3059 /* Verify that padding is 0 */
3060 for (k = *rindex; k < start; k++)
3061 if (((const uint8_t*) p)[k] != 0)
3065 *r = (uint8_t*) p + start;
3072 static bool message_end_of_signature(sd_bus_message *m) {
3073 struct bus_container *c;
3077 c = message_get_container(m);
3078 return !c->signature || c->signature[c->index] == 0;
3081 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3082 struct bus_container *c;
3086 c = message_get_container(m);
3087 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3090 if (BUS_MESSAGE_IS_GVARIANT(m))
3091 return index >= c->end;
3093 assert(c->array_size);
3094 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3098 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3099 assert_return(m, -EINVAL);
3100 assert_return(m->sealed, -EPERM);
3102 if (complete && m->n_containers > 0)
3105 if (message_end_of_signature(m))
3108 if (message_end_of_array(m, m->rindex))
3114 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3115 struct bus_body_part *part;
3121 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3122 part = m->cached_rindex_part;
3123 begin = m->cached_rindex_part_begin;
3133 if (index + sz <= begin + part->size) {
3135 r = bus_body_part_map(part);
3140 *p = (uint8_t*) part->data + index - begin;
3142 m->cached_rindex_part = part;
3143 m->cached_rindex_part_begin = begin;
3148 begin += part->size;
3155 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3162 if (!BUS_MESSAGE_IS_GVARIANT(m))
3165 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3168 sz = bus_gvariant_get_size(c->signature);
3172 if (c->offset_index+1 >= c->n_offsets)
3175 /* Variable-size array */
3177 alignment = bus_gvariant_get_alignment(c->signature);
3178 assert(alignment > 0);
3180 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3181 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3184 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3187 /* Fixed-size array */
3188 *rindex = c->begin + (c->offset_index+1) * sz;
3194 } else if (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
3199 if (c->offset_index+1 >= c->n_offsets)
3202 r = signature_element_length(c->signature + c->index, &n);
3206 r = signature_element_length(c->signature + c->index + n, &j);
3211 memcpy(t, c->signature + c->index + n, j);
3214 alignment = bus_gvariant_get_alignment(t);
3217 assert(alignment > 0);
3219 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3220 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3224 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3227 assert_not_reached("Unknown container type");
3232 /* Reached the end */
3239 static int message_peek_body(
3246 size_t k, start, end, padding;
3247 struct bus_body_part *part;
3254 start = ALIGN_TO((size_t) *rindex, align);
3255 padding = start - *rindex;
3256 end = start + nbytes;
3258 if (end > m->user_body_size)
3261 part = find_part(m, *rindex, padding, (void**) &q);
3266 /* Verify padding */
3267 for (k = 0; k < padding; k++)
3272 part = find_part(m, start, nbytes, (void**) &q);
3273 if (!part || (nbytes > 0 && !q))
3284 static bool validate_nul(const char *s, size_t l) {
3286 /* Check for NUL chars in the string */
3287 if (memchr(s, 0, l))
3290 /* Check for NUL termination */
3297 static bool validate_string(const char *s, size_t l) {
3299 if (!validate_nul(s, l))
3302 /* Check if valid UTF8 */
3303 if (!utf8_is_valid(s))
3309 static bool validate_signature(const char *s, size_t l) {
3311 if (!validate_nul(s, l))
3314 /* Check if valid signature */
3315 if (!signature_is_valid(s, true))
3321 static bool validate_object_path(const char *s, size_t l) {
3323 if (!validate_nul(s, l))
3326 if (!object_path_is_valid(s))
3332 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3333 struct bus_container *c;
3338 assert_return(m, -EINVAL);
3339 assert_return(m->sealed, -EPERM);
3340 assert_return(bus_type_is_basic(type), -EINVAL);
3342 if (message_end_of_signature(m))
3345 if (message_end_of_array(m, m->rindex))
3348 c = message_get_container(m);
3349 if (c->signature[c->index] != type)
3354 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3356 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3359 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3363 if (type == SD_BUS_TYPE_STRING)
3364 ok = validate_string(q, c->item_size-1);
3365 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3366 ok = validate_object_path(q, c->item_size-1);
3368 ok = validate_signature(q, c->item_size-1);
3374 *(const char**) p = q;
3378 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3380 if ((size_t) sz != c->item_size)
3383 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3386 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3392 case SD_BUS_TYPE_BYTE:
3394 *(uint8_t*) p = *(uint8_t*) q;
3397 case SD_BUS_TYPE_BOOLEAN:
3399 *(int*) p = !!*(uint8_t*) q;
3402 case SD_BUS_TYPE_INT16:
3403 case SD_BUS_TYPE_UINT16:
3405 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3408 case SD_BUS_TYPE_INT32:
3409 case SD_BUS_TYPE_UINT32:
3411 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3414 case SD_BUS_TYPE_INT64:
3415 case SD_BUS_TYPE_UINT64:
3416 case SD_BUS_TYPE_DOUBLE:
3418 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3421 case SD_BUS_TYPE_UNIX_FD: {
3424 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3429 *(int*) p = m->fds[j];
3435 assert_not_reached("unexpected type");
3439 r = container_next_item(m, c, &rindex);
3444 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3448 r = message_peek_body(m, &rindex, 4, 4, &q);
3452 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3453 r = message_peek_body(m, &rindex, 1, l+1, &q);
3457 if (type == SD_BUS_TYPE_OBJECT_PATH)
3458 ok = validate_object_path(q, l);
3460 ok = validate_string(q, l);
3465 *(const char**) p = q;
3467 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3470 r = message_peek_body(m, &rindex, 1, 1, &q);
3475 r = message_peek_body(m, &rindex, 1, l+1, &q);
3479 if (!validate_signature(q, l))
3483 *(const char**) p = q;
3488 align = bus_type_get_alignment(type);
3491 sz = bus_type_get_size(type);
3494 r = message_peek_body(m, &rindex, align, sz, &q);
3500 case SD_BUS_TYPE_BYTE:
3502 *(uint8_t*) p = *(uint8_t*) q;
3505 case SD_BUS_TYPE_BOOLEAN:
3507 *(int*) p = !!*(uint32_t*) q;
3510 case SD_BUS_TYPE_INT16:
3511 case SD_BUS_TYPE_UINT16:
3513 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3516 case SD_BUS_TYPE_INT32:
3517 case SD_BUS_TYPE_UINT32:
3519 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3522 case SD_BUS_TYPE_INT64:
3523 case SD_BUS_TYPE_UINT64:
3524 case SD_BUS_TYPE_DOUBLE:
3526 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3529 case SD_BUS_TYPE_UNIX_FD: {
3532 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3537 *(int*) p = m->fds[j];
3542 assert_not_reached("Unknown basic type...");
3549 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3555 static int bus_message_enter_array(
3557 struct bus_container *c,
3558 const char *contents,
3559 uint32_t **array_size,
3562 size_t *n_offsets) {
3576 if (!signature_is_single(contents, true))
3579 if (!c->signature || c->signature[c->index] == 0)
3582 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3585 if (!startswith(c->signature + c->index + 1, contents))
3590 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3593 r = message_peek_body(m, &rindex, 4, 4, &q);
3597 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3600 alignment = bus_type_get_alignment(contents[0]);
3604 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3608 *array_size = (uint32_t*) q;
3610 } else if (c->item_size <= 0) {
3612 /* gvariant: empty array */
3617 } else if (bus_gvariant_is_fixed_size(contents)) {
3619 /* gvariant: fixed length array */
3620 *item_size = bus_gvariant_get_size(contents);
3625 size_t where, p = 0, framing, sz;
3628 /* gvariant: variable length array */
3629 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3631 where = rindex + c->item_size - sz;
3632 r = message_peek_body(m, &where, 1, sz, &q);
3636 framing = bus_gvariant_read_word_le(q, sz);
3637 if (framing > c->item_size - sz)
3639 if ((c->item_size - framing) % sz != 0)
3642 *n_offsets = (c->item_size - framing) / sz;
3644 where = rindex + framing;
3645 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3649 *offsets = new(size_t, *n_offsets);
3653 for (i = 0; i < *n_offsets; i++) {
3656 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3657 if (x > c->item_size - sz)
3662 (*offsets)[i] = rindex + x;
3666 *item_size = (*offsets)[0] - rindex;
3671 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3672 c->index += 1 + strlen(contents);
3677 static int bus_message_enter_variant(
3679 struct bus_container *c,
3680 const char *contents,
3681 size_t *item_size) {
3693 if (!signature_is_single(contents, false))
3696 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3699 if (!c->signature || c->signature[c->index] == 0)
3702 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3707 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3710 k = strlen(contents);
3711 if (1+k > c->item_size)
3714 where = rindex + c->item_size - (1+k);
3715 r = message_peek_body(m, &where, 1, 1+k, &q);
3719 if (*(char*) q != 0)
3722 if (memcmp((uint8_t*) q+1, contents, k))
3725 *item_size = c->item_size - (1+k);
3728 r = message_peek_body(m, &rindex, 1, 1, &q);
3733 r = message_peek_body(m, &rindex, 1, l+1, &q);
3737 if (!validate_signature(q, l))
3740 if (!streq(q, contents))
3746 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3752 static int build_struct_offsets(
3754 const char *signature,
3758 size_t *n_offsets) {
3760 unsigned n_variable = 0, n_total = 0, v;
3761 size_t previous = 0, where;
3772 if (isempty(signature)) {
3773 /* Unary type is encoded as *fixed* 1 byte padding */
3774 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3778 if (*(uint8_t *) q != 0)
3787 sz = bus_gvariant_determine_word_size(size, 0);
3791 /* First, loop over signature and count variable elements and
3792 * elements in general. We use this to know how large the
3793 * offset array is at the end of the structure. Note that
3794 * GVariant only stores offsets for all variable size elements
3795 * that are not the last item. */
3801 r = signature_element_length(p, &n);
3810 r = bus_gvariant_is_fixed_size(t);
3815 if (r == 0 && p[n] != 0) /* except the last item */
3822 if (size < n_variable * sz)
3825 where = m->rindex + size - (n_variable * sz);
3826 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3832 *offsets = new(size_t, n_total);
3838 /* Second, loop again and build an offset table */
3844 r = signature_element_length(p, &n);
3853 k = bus_gvariant_get_size(t);
3861 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3864 if (m->rindex + x < previous)
3867 /* The last item's end
3868 * is determined from
3871 x = size - (n_variable * sz);
3873 offset = m->rindex + x;
3879 align = bus_gvariant_get_alignment(t);
3882 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3886 previous = (*offsets)[(*n_offsets)++] = offset;
3891 assert(*n_offsets == n_total);
3893 *item_size = (*offsets)[0] - m->rindex;
3897 static int enter_struct_or_dict_entry(
3899 struct bus_container *c,
3900 const char *contents,
3903 size_t *n_offsets) {
3914 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3917 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3922 /* gvariant with contents */
3923 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3928 static int bus_message_enter_struct(
3930 struct bus_container *c,
3931 const char *contents,
3934 size_t *n_offsets) {
3946 if (!signature_is_valid(contents, false))
3949 if (!c->signature || c->signature[c->index] == 0)
3952 l = strlen(contents);
3954 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3955 !startswith(c->signature + c->index + 1, contents) ||
3956 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3959 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3963 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3964 c->index += 1 + l + 1;
3969 static int bus_message_enter_dict_entry(
3971 struct bus_container *c,
3972 const char *contents,
3975 size_t *n_offsets) {
3984 if (!signature_is_pair(contents))
3987 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3990 if (!c->signature || c->signature[c->index] == 0)
3993 l = strlen(contents);
3995 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3996 !startswith(c->signature + c->index + 1, contents) ||
3997 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4000 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4004 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4005 c->index += 1 + l + 1;
4010 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4012 const char *contents) {
4013 struct bus_container *c, *w;
4014 uint32_t *array_size = NULL;
4017 size_t *offsets = NULL;
4018 size_t n_offsets = 0, item_size = 0;
4021 assert_return(m, -EINVAL);
4022 assert_return(m->sealed, -EPERM);
4023 assert_return(type != 0 || !contents, -EINVAL);
4025 if (type == 0 || !contents) {
4029 /* Allow entering into anonymous containers */
4030 r = sd_bus_message_peek_type(m, &tt, &cc);
4034 if (type != 0 && type != tt)
4037 if (contents && !streq(contents, cc))
4045 * We enforce a global limit on container depth, that is much
4046 * higher than the 32 structs and 32 arrays the specification
4047 * mandates. This is simpler to implement for us, and we need
4048 * this only to ensure our container array doesn't grow
4049 * without bounds. We are happy to return any data from a
4050 * message as long as the data itself is valid, even if the
4051 * overall message might be not.
4053 * Note that the message signature is validated when
4054 * parsing the headers, and that validation does check the
4057 * Note that the specification defines no limits on the depth
4058 * of stacked variants, but we do.
4060 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4063 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4066 if (message_end_of_signature(m))
4069 if (message_end_of_array(m, m->rindex))
4072 c = message_get_container(m);
4074 signature = strdup(contents);
4078 c->saved_index = c->index;
4081 if (type == SD_BUS_TYPE_ARRAY)
4082 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4083 else if (type == SD_BUS_TYPE_VARIANT)
4084 r = bus_message_enter_variant(m, c, contents, &item_size);
4085 else if (type == SD_BUS_TYPE_STRUCT)
4086 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4087 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4088 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4098 /* OK, let's fill it in */
4099 w = m->containers + m->n_containers++;
4100 w->enclosing = type;
4101 w->signature = signature;
4102 w->peeked_signature = NULL;
4106 w->begin = m->rindex;
4108 /* Unary type has fixed size of 1, but virtual size of 0 */
4109 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4110 type == SD_BUS_TYPE_STRUCT &&
4112 w->end = m->rindex + 0;
4114 w->end = m->rindex + c->item_size;
4116 w->array_size = array_size;
4117 w->item_size = item_size;
4118 w->offsets = offsets;
4119 w->n_offsets = n_offsets;
4120 w->offset_index = 0;
4125 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4126 struct bus_container *c;
4130 assert_return(m, -EINVAL);
4131 assert_return(m->sealed, -EPERM);
4132 assert_return(m->n_containers > 0, -ENXIO);
4134 c = message_get_container(m);
4136 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4137 if (c->signature && c->signature[c->index] != 0)
4141 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4142 if (m->rindex < c->end)
4145 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4148 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4149 if (c->begin + l != m->rindex)
4154 free(c->peeked_signature);
4158 c = message_get_container(m);
4161 c->index = c->saved_index;
4162 r = container_next_item(m, c, &m->rindex);
4170 static void message_quit_container(sd_bus_message *m) {
4171 struct bus_container *c;
4175 assert(m->n_containers > 0);
4177 c = message_get_container(m);
4180 assert(m->rindex >= c->before);
4181 m->rindex = c->before;
4183 /* Free container */
4188 /* Correct index of new top-level container */
4189 c = message_get_container(m);
4190 c->index = c->saved_index;
4193 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4194 struct bus_container *c;
4197 assert_return(m, -EINVAL);
4198 assert_return(m->sealed, -EPERM);
4200 if (message_end_of_signature(m))
4203 if (message_end_of_array(m, m->rindex))
4206 c = message_get_container(m);
4208 if (bus_type_is_basic(c->signature[c->index])) {
4212 *type = c->signature[c->index];
4216 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4222 r = signature_element_length(c->signature+c->index+1, &l);
4228 sig = strndup(c->signature + c->index + 1, l);
4232 free(c->peeked_signature);
4233 *contents = c->peeked_signature = sig;
4237 *type = SD_BUS_TYPE_ARRAY;
4242 if (IN_SET(c->signature[c->index], SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN)) {
4248 r = signature_element_length(c->signature+c->index, &l);
4253 sig = strndup(c->signature + c->index + 1, l - 2);
4257 free(c->peeked_signature);
4258 *contents = c->peeked_signature = sig;
4262 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4267 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4271 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4274 if (c->item_size < 2)
4277 /* Look for the NUL delimiter that
4278 separates the payload from the
4279 signature. Since the body might be
4280 in a different part that then the
4281 signature we map byte by byte. */
4283 for (k = 2; k <= c->item_size; k++) {
4286 where = m->rindex + c->item_size - k;
4287 r = message_peek_body(m, &where, 1, k, &q);
4291 if (*(char*) q == 0)
4295 if (k > c->item_size)
4298 free(c->peeked_signature);
4299 c->peeked_signature = strndup((char*) q + 1, k - 1);
4300 if (!c->peeked_signature)
4303 if (!signature_is_valid(c->peeked_signature, true))
4306 *contents = c->peeked_signature;
4311 r = message_peek_body(m, &rindex, 1, 1, &q);
4316 r = message_peek_body(m, &rindex, 1, l+1, &q);
4320 if (!validate_signature(q, l))
4328 *type = SD_BUS_TYPE_VARIANT;
4343 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4344 struct bus_container *c;
4346 assert_return(m, -EINVAL);
4347 assert_return(m->sealed, -EPERM);
4350 message_reset_containers(m);
4353 c = message_get_container(m);
4355 c = message_get_container(m);
4357 c->offset_index = 0;
4359 m->rindex = c->begin;
4362 c->offset_index = 0;
4363 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4365 return !isempty(c->signature);
4368 static int message_read_ap(
4373 unsigned n_array, n_struct;
4374 TypeStack stack[BUS_CONTAINER_DEPTH];
4375 unsigned stack_ptr = 0;
4376 unsigned n_loop = 0;
4384 /* Ideally, we'd just call ourselves recursively on every
4385 * complex type. However, the state of a va_list that is
4386 * passed to a function is undefined after that function
4387 * returns. This means we need to docode the va_list linearly
4388 * in a single stackframe. We hence implement our own
4389 * home-grown stack in an array. */
4391 n_array = (unsigned) -1; /* length of current array entries */
4392 n_struct = strlen(types); /* length of current struct contents signature */
4399 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4400 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4406 r = sd_bus_message_exit_container(m);
4414 if (n_array != (unsigned) -1)
4423 case SD_BUS_TYPE_BYTE:
4424 case SD_BUS_TYPE_BOOLEAN:
4425 case SD_BUS_TYPE_INT16:
4426 case SD_BUS_TYPE_UINT16:
4427 case SD_BUS_TYPE_INT32:
4428 case SD_BUS_TYPE_UINT32:
4429 case SD_BUS_TYPE_INT64:
4430 case SD_BUS_TYPE_UINT64:
4431 case SD_BUS_TYPE_DOUBLE:
4432 case SD_BUS_TYPE_STRING:
4433 case SD_BUS_TYPE_OBJECT_PATH:
4434 case SD_BUS_TYPE_SIGNATURE:
4435 case SD_BUS_TYPE_UNIX_FD: {
4438 p = va_arg(ap, void*);
4439 r = sd_bus_message_read_basic(m, *t, p);
4452 case SD_BUS_TYPE_ARRAY: {
4455 r = signature_element_length(t + 1, &k);
4461 memcpy(s, t + 1, k);
4464 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4475 if (n_array == (unsigned) -1) {
4480 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4486 n_array = va_arg(ap, unsigned);
4491 case SD_BUS_TYPE_VARIANT: {
4494 s = va_arg(ap, const char *);
4498 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4508 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4513 n_struct = strlen(s);
4514 n_array = (unsigned) -1;
4519 case SD_BUS_TYPE_STRUCT_BEGIN:
4520 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4523 r = signature_element_length(t, &k);
4529 memcpy(s, t + 1, k - 2);
4532 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4542 if (n_array == (unsigned) -1) {
4547 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4553 n_array = (unsigned) -1;
4566 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4570 assert_return(m, -EINVAL);
4571 assert_return(m->sealed, -EPERM);
4572 assert_return(types, -EINVAL);
4574 va_start(ap, types);
4575 r = message_read_ap(m, types, ap);
4581 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4584 assert_return(m, -EINVAL);
4585 assert_return(m->sealed, -EPERM);
4587 /* If types is NULL, read exactly one element */
4589 struct bus_container *c;
4592 if (message_end_of_signature(m))
4595 if (message_end_of_array(m, m->rindex))
4598 c = message_get_container(m);
4600 r = signature_element_length(c->signature + c->index, &l);
4604 types = strndupa(c->signature + c->index, l);
4609 case 0: /* Nothing to drop */
4612 case SD_BUS_TYPE_BYTE:
4613 case SD_BUS_TYPE_BOOLEAN:
4614 case SD_BUS_TYPE_INT16:
4615 case SD_BUS_TYPE_UINT16:
4616 case SD_BUS_TYPE_INT32:
4617 case SD_BUS_TYPE_UINT32:
4618 case SD_BUS_TYPE_INT64:
4619 case SD_BUS_TYPE_UINT64:
4620 case SD_BUS_TYPE_DOUBLE:
4621 case SD_BUS_TYPE_STRING:
4622 case SD_BUS_TYPE_OBJECT_PATH:
4623 case SD_BUS_TYPE_SIGNATURE:
4624 case SD_BUS_TYPE_UNIX_FD:
4626 r = sd_bus_message_read_basic(m, *types, NULL);
4630 r = sd_bus_message_skip(m, types + 1);
4636 case SD_BUS_TYPE_ARRAY: {
4639 r = signature_element_length(types + 1, &k);
4645 memcpy(s, types+1, k);
4648 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4653 r = sd_bus_message_skip(m, s);
4660 r = sd_bus_message_exit_container(m);
4665 r = sd_bus_message_skip(m, types + 1 + k);
4672 case SD_BUS_TYPE_VARIANT: {
4673 const char *contents;
4676 r = sd_bus_message_peek_type(m, &x, &contents);
4680 if (x != SD_BUS_TYPE_VARIANT)
4683 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4687 r = sd_bus_message_skip(m, contents);
4692 r = sd_bus_message_exit_container(m);
4696 r = sd_bus_message_skip(m, types + 1);
4703 case SD_BUS_TYPE_STRUCT_BEGIN:
4704 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4707 r = signature_element_length(types, &k);
4713 memcpy(s, types+1, k-2);
4716 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4720 r = sd_bus_message_skip(m, s);
4724 r = sd_bus_message_exit_container(m);
4729 r = sd_bus_message_skip(m, types + k);
4741 _public_ int sd_bus_message_read_array(
4747 struct bus_container *c;
4753 assert_return(m, -EINVAL);
4754 assert_return(m->sealed, -EPERM);
4755 assert_return(bus_type_is_trivial(type), -EINVAL);
4756 assert_return(ptr, -EINVAL);
4757 assert_return(size, -EINVAL);
4758 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4760 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4764 c = message_get_container(m);
4766 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4767 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4771 sz = c->end - c->begin;
4773 align = bus_type_get_alignment(type);
4777 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4781 /* Zero length array, let's return some aligned
4782 * pointer that is not NULL */
4783 p = (uint8_t*) align;
4785 r = message_peek_body(m, &m->rindex, align, sz, &p);
4790 r = sd_bus_message_exit_container(m);
4794 *ptr = (const void*) p;
4800 message_quit_container(m);
4804 static int message_peek_fields(
4815 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4818 static int message_peek_field_uint32(
4830 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4833 /* identical for gvariant and dbus1 */
4835 r = message_peek_fields(m, ri, 4, 4, &q);
4840 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4845 static int message_peek_field_uint64(
4857 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4860 /* identical for gvariant and dbus1 */
4862 r = message_peek_fields(m, ri, 8, 8, &q);
4867 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4872 static int message_peek_field_string(
4874 bool (*validate)(const char *p),
4886 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4891 r = message_peek_fields(m, ri, 1, item_size, &q);
4897 r = message_peek_field_uint32(m, ri, 4, &l);
4901 r = message_peek_fields(m, ri, 1, l+1, &q);
4907 if (!validate_nul(q, l))
4913 if (!validate_string(q, l))
4923 static int message_peek_field_signature(
4936 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4941 r = message_peek_fields(m, ri, 1, item_size, &q);
4947 r = message_peek_fields(m, ri, 1, 1, &q);
4952 r = message_peek_fields(m, ri, 1, l+1, &q);
4957 if (!validate_signature(q, l))
4966 static int message_skip_fields(
4969 uint32_t array_size,
4970 const char **signature) {
4972 size_t original_index;
4978 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4980 original_index = *ri;
4986 if (array_size != (uint32_t) -1 &&
4987 array_size <= *ri - original_index)
4994 if (t == SD_BUS_TYPE_STRING) {
4996 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5002 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5004 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5010 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5012 r = message_peek_field_signature(m, ri, 0, NULL);
5018 } else if (bus_type_is_basic(t)) {
5021 align = bus_type_get_alignment(t);
5022 k = bus_type_get_size(t);
5023 assert(align > 0 && k > 0);
5025 r = message_peek_fields(m, ri, align, k, NULL);
5031 } else if (t == SD_BUS_TYPE_ARRAY) {
5033 r = signature_element_length(*signature+1, &l);
5043 strncpy(sig, *signature + 1, l-1);
5046 alignment = bus_type_get_alignment(sig[0]);
5050 r = message_peek_field_uint32(m, ri, 0, &nas);
5053 if (nas > BUS_ARRAY_MAX_SIZE)
5056 r = message_peek_fields(m, ri, alignment, 0, NULL);
5060 r = message_skip_fields(m, ri, nas, (const char**) &s);
5065 (*signature) += 1 + l;
5067 } else if (t == SD_BUS_TYPE_VARIANT) {
5070 r = message_peek_field_signature(m, ri, 0, &s);
5074 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5080 } else if (IN_SET(t, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
5082 r = signature_element_length(*signature, &l);
5089 strncpy(sig, *signature + 1, l-1);
5092 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5103 int bus_message_parse_fields(sd_bus_message *m) {
5106 uint32_t unix_fds = 0;
5107 bool unix_fds_set = false;
5108 void *offsets = NULL;
5109 unsigned n_offsets = 0;
5115 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5118 /* Read the signature from the end of the body variant first */
5119 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5120 if (m->footer_accessible < 1 + sz)
5123 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5125 if (p < (char*) m->footer)
5132 /* We found the beginning of the signature
5133 * string, yay! We require the body to be a
5134 * structure, so verify it and then strip the
5135 * opening/closing brackets. */
5137 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5139 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5140 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5143 c = strndup(p + 1 + 1, l - 2);
5147 free(m->root_container.signature);
5148 m->root_container.signature = c;
5155 /* Calculate the actual user body size, by removing
5156 * the trailing variant signature and struct offset
5158 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5160 /* Pull out the offset table for the fields array */
5161 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5166 ri = m->fields_size - sz;
5167 r = message_peek_fields(m, &ri, 1, sz, &q);
5171 framing = bus_gvariant_read_word_le(q, sz);
5172 if (framing >= m->fields_size - sz)
5174 if ((m->fields_size - framing) % sz != 0)
5178 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5182 n_offsets = (m->fields_size - framing) / sz;
5185 m->user_body_size = m->body_size;
5188 while (ri < m->fields_size) {
5189 _cleanup_free_ char *sig = NULL;
5190 const char *signature;
5191 uint64_t field_type;
5192 size_t item_size = (size_t) -1;
5194 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5203 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5205 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5209 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5213 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5220 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5225 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5230 where = ri = ALIGN_TO(ri, 8);
5231 item_size = end - ri;
5232 r = message_peek_fields(m, &where, 1, item_size, &q);
5236 b = memrchr(q, 0, item_size);
5240 sig = strndup(b+1, item_size - (b+1-(char*) q));
5245 item_size = b - (char*) q;
5247 r = message_peek_field_signature(m, &ri, 0, &signature);
5252 switch (field_type) {
5254 case _BUS_MESSAGE_HEADER_INVALID:
5257 case BUS_MESSAGE_HEADER_PATH:
5262 if (!streq(signature, "o"))
5265 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5268 case BUS_MESSAGE_HEADER_INTERFACE:
5273 if (!streq(signature, "s"))
5276 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5279 case BUS_MESSAGE_HEADER_MEMBER:
5284 if (!streq(signature, "s"))
5287 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5290 case BUS_MESSAGE_HEADER_ERROR_NAME:
5295 if (!streq(signature, "s"))
5298 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5300 m->error._need_free = -1;
5304 case BUS_MESSAGE_HEADER_DESTINATION:
5309 if (!streq(signature, "s"))
5312 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5315 case BUS_MESSAGE_HEADER_SENDER:
5320 if (!streq(signature, "s"))
5323 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5325 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client) {
5326 m->creds.unique_name = (char*) m->sender;
5327 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5333 case BUS_MESSAGE_HEADER_SIGNATURE: {
5337 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5340 if (m->root_container.signature)
5343 if (!streq(signature, "g"))
5346 r = message_peek_field_signature(m, &ri, item_size, &s);
5354 free(m->root_container.signature);
5355 m->root_container.signature = c;
5359 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5361 if (m->reply_cookie != 0)
5364 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5365 /* 64bit on dbus2 */
5367 if (!streq(signature, "t"))
5370 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5374 /* 32bit on dbus1 */
5377 if (!streq(signature, "u"))
5380 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5384 m->reply_cookie = serial;
5387 if (m->reply_cookie == 0)
5392 case BUS_MESSAGE_HEADER_UNIX_FDS:
5396 if (!streq(signature, "u"))
5399 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5403 unix_fds_set = true;
5407 if (!BUS_MESSAGE_IS_GVARIANT(m))
5408 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5417 if (m->n_fds != unix_fds)
5420 switch (m->header->type) {
5422 case SD_BUS_MESSAGE_SIGNAL:
5423 if (!m->path || !m->interface || !m->member)
5426 if (m->reply_cookie != 0)
5431 case SD_BUS_MESSAGE_METHOD_CALL:
5433 if (!m->path || !m->member)
5436 if (m->reply_cookie != 0)
5441 case SD_BUS_MESSAGE_METHOD_RETURN:
5443 if (m->reply_cookie == 0)
5447 case SD_BUS_MESSAGE_METHOD_ERROR:
5449 if (m->reply_cookie == 0 || !m->error.name)
5454 /* Refuse non-local messages that claim they are local */
5455 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5457 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5459 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5462 m->root_container.end = m->user_body_size;
5464 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5465 r = build_struct_offsets(
5467 m->root_container.signature,
5469 &m->root_container.item_size,
5470 &m->root_container.offsets,
5471 &m->root_container.n_offsets);
5476 /* Try to read the error message, but if we can't it's a non-issue */
5477 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5478 (void) sd_bus_message_read(m, "s", &m->error.message);
5483 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5484 assert_return(m, -EINVAL);
5485 assert_return(destination, -EINVAL);
5486 assert_return(!m->sealed, -EPERM);
5487 assert_return(!m->destination, -EEXIST);
5489 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5492 _public_ int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) {
5493 assert_return(m, -EINVAL);
5494 assert_return(sender, -EINVAL);
5495 assert_return(!m->sealed, -EPERM);
5496 assert_return(!m->sender, -EEXIST);
5498 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5501 #if 0 /// UNNEEDED by elogind
5502 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5506 struct bus_body_part *part;
5512 total = BUS_MESSAGE_SIZE(m);
5518 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5519 MESSAGE_FOREACH_PART(part, i, m)
5520 e = mempcpy(e, part->data, part->size);
5522 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5531 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5538 r = sd_bus_message_enter_container(m, 'a', "s");
5542 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5543 r = strv_extend(l, s);
5550 r = sd_bus_message_exit_container(m);
5557 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5561 assert_return(m, -EINVAL);
5562 assert_return(m->sealed, -EPERM);
5563 assert_return(l, -EINVAL);
5565 r = bus_message_read_strv_extend(m, &strv);
5575 static int bus_message_get_arg_skip(
5579 const char **_contents) {
5584 r = sd_bus_message_rewind(m, true);
5589 const char *contents;
5592 r = sd_bus_message_peek_type(m, &type, &contents);
5598 /* Don't match against arguments after the first one we don't understand */
5599 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5600 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5605 *_contents = contents;
5611 r = sd_bus_message_skip(m, NULL);
5618 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5625 r = bus_message_get_arg_skip(m, i, &type, NULL);
5629 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5632 return sd_bus_message_read_basic(m, type, str);
5635 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5636 const char *contents;
5643 r = bus_message_get_arg_skip(m, i, &type, &contents);
5647 if (type != SD_BUS_TYPE_ARRAY)
5649 if (!STR_IN_SET(contents, "s", "o", "g"))
5652 return sd_bus_message_read_strv(m, strv);
5655 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5656 assert_return(m, EINVAL);
5658 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5661 return sd_bus_error_get_errno(&m->error);
5664 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5665 struct bus_container *c;
5667 assert_return(m, NULL);
5669 c = complete ? &m->root_container : message_get_container(m);
5670 return strempty(c->signature);
5673 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5674 assert_return(m, -EINVAL);
5676 return isempty(m->root_container.signature);
5679 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5680 assert_return(m, -EINVAL);
5682 return streq(strempty(m->root_container.signature), strempty(signature));
5685 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5686 bool done_something = false;
5689 assert_return(m, -EINVAL);
5690 assert_return(source, -EINVAL);
5691 assert_return(!m->sealed, -EPERM);
5692 assert_return(source->sealed, -EPERM);
5695 const char *contents;
5710 r = sd_bus_message_peek_type(source, &type, &contents);
5716 done_something = true;
5718 if (bus_type_is_container(type) > 0) {
5720 r = sd_bus_message_enter_container(source, type, contents);
5724 r = sd_bus_message_open_container(m, type, contents);
5728 r = sd_bus_message_copy(m, source, true);
5732 r = sd_bus_message_close_container(m);
5736 r = sd_bus_message_exit_container(source);
5743 r = sd_bus_message_read_basic(source, type, &basic);
5749 if (IN_SET(type, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_STRING))
5750 r = sd_bus_message_append_basic(m, type, basic.string);
5752 r = sd_bus_message_append_basic(m, type, &basic);
5759 return done_something;
5762 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5767 assert_return(m, -EINVAL);
5768 assert_return(m->sealed, -EPERM);
5769 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5770 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5771 assert_return(type || contents, -EINVAL);
5772 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5774 r = sd_bus_message_peek_type(m, &t, &c);
5778 if (type != 0 && type != t)
5781 if (contents && !streq_ptr(contents, c))
5787 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5788 assert_return(m, NULL);
5793 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5794 _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5802 switch ((*m)->header->type) {
5804 case SD_BUS_MESSAGE_SIGNAL:
5805 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5811 case SD_BUS_MESSAGE_METHOD_CALL:
5812 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5818 case SD_BUS_MESSAGE_METHOD_RETURN:
5819 case SD_BUS_MESSAGE_METHOD_ERROR:
5821 r = sd_bus_message_new(bus, &n, (*m)->header->type);
5827 n->reply_cookie = (*m)->reply_cookie;
5829 r = message_append_reply_cookie(n, n->reply_cookie);
5833 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5834 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5838 n->error._need_free = -1;
5847 if ((*m)->destination && !n->destination) {
5848 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5853 if ((*m)->sender && !n->sender) {
5854 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5859 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5861 r = sd_bus_message_copy(n, *m, true);
5865 timeout = (*m)->timeout;
5866 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5867 timeout = BUS_DEFAULT_TIMEOUT;
5869 r = sd_bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5873 sd_bus_message_unref(*m);
5880 #if 0 /// UNNEEDED by elogind
5881 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5885 assert_return(!m->sealed, -EPERM);
5886 assert_return(!m->sender, -EPERM);
5888 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5892 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5893 assert_return(m, -EINVAL);
5894 assert_return(priority, -EINVAL);
5896 *priority = m->priority;
5900 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5901 assert_return(m, -EINVAL);
5902 assert_return(!m->sealed, -EPERM);
5904 m->priority = priority;