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); /* if this must be an inlined extension, let's create a new part if the previous part is large enough to be inlined */
1327 part = message_append_part(m);
1331 part_zero(part, padding);
1334 part = message_append_part(m);
1338 r = part_make_space(m, part, sz, &p);
1342 struct bus_container *c;
1344 size_t os, start_part, end_part;
1350 start_part = ALIGN_TO(part->size, align);
1351 end_part = start_part + sz;
1353 r = part_make_space(m, part, end_part, &p);
1358 memzero(p, padding);
1359 p = (uint8_t*) p + padding;
1362 /* Readjust pointers */
1363 for (c = m->containers; c < m->containers + m->n_containers; c++)
1364 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1366 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1369 /* Return something that is not NULL and is aligned */
1370 p = (uint8_t *) NULL + align;
1372 m->body_size = end_body;
1373 message_extend_containers(m, added);
1376 r = message_add_offset(m, end_body);
1386 static int message_push_fd(sd_bus_message *m, int fd) {
1397 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1401 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1409 m->fds[m->n_fds] = copy;
1415 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1416 _cleanup_close_ int fd = -1;
1417 struct bus_container *c;
1421 assert_return(m, -EINVAL);
1422 assert_return(!m->sealed, -EPERM);
1423 assert_return(bus_type_is_basic(type), -EINVAL);
1424 assert_return(!m->poisoned, -ESTALE);
1426 c = message_get_container(m);
1428 if (c->signature && c->signature[c->index]) {
1429 /* Container signature is already set */
1431 if (c->signature[c->index] != type)
1436 /* Maybe we can append to the signature? But only if this is the top-level container */
1437 if (c->enclosing != 0)
1440 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1447 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1453 case SD_BUS_TYPE_SIGNATURE:
1454 case SD_BUS_TYPE_STRING:
1458 case SD_BUS_TYPE_OBJECT_PATH:
1466 case SD_BUS_TYPE_BOOLEAN:
1468 u8 = p && *(int*) p;
1474 case SD_BUS_TYPE_UNIX_FD:
1479 fd = message_push_fd(m, *(int*) p);
1490 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1491 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1498 a = message_extend_body(m, align, sz, true, false);
1505 *stored = (const uint8_t*) a;
1512 case SD_BUS_TYPE_STRING:
1513 /* To make things easy we'll serialize a NULL string
1514 * into the empty string */
1518 case SD_BUS_TYPE_OBJECT_PATH:
1524 sz = 4 + strlen(p) + 1;
1527 case SD_BUS_TYPE_SIGNATURE:
1532 sz = 1 + strlen(p) + 1;
1535 case SD_BUS_TYPE_BOOLEAN:
1537 u32 = p && *(int*) p;
1543 case SD_BUS_TYPE_UNIX_FD:
1548 fd = message_push_fd(m, *(int*) p);
1559 align = bus_type_get_alignment(type);
1560 sz = bus_type_get_size(type);
1567 a = message_extend_body(m, align, sz, false, false);
1571 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
1572 *(uint32_t*) a = sz - 5;
1573 memcpy((uint8_t*) a + 4, p, sz - 4);
1576 *stored = (const uint8_t*) a + 4;
1578 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1579 *(uint8_t*) a = sz - 2;
1580 memcpy((uint8_t*) a + 1, p, sz - 1);
1583 *stored = (const uint8_t*) a + 1;
1592 if (type == SD_BUS_TYPE_UNIX_FD)
1595 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1602 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1603 return message_append_basic(m, type, p, NULL);
1606 _public_ int sd_bus_message_append_string_space(
1611 struct bus_container *c;
1614 assert_return(m, -EINVAL);
1615 assert_return(s, -EINVAL);
1616 assert_return(!m->sealed, -EPERM);
1617 assert_return(!m->poisoned, -ESTALE);
1619 c = message_get_container(m);
1621 if (c->signature && c->signature[c->index]) {
1622 /* Container signature is already set */
1624 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1629 /* Maybe we can append to the signature? But only if this is the top-level container */
1630 if (c->enclosing != 0)
1633 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1640 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1641 a = message_extend_body(m, 1, size + 1, true, false);
1647 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1651 *(uint32_t*) a = size;
1657 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1663 _public_ int sd_bus_message_append_string_iovec(
1665 const struct iovec *iov,
1673 assert_return(m, -EINVAL);
1674 assert_return(!m->sealed, -EPERM);
1675 assert_return(iov || n == 0, -EINVAL);
1676 assert_return(!m->poisoned, -ESTALE);
1678 size = IOVEC_TOTAL_SIZE(iov, n);
1680 r = sd_bus_message_append_string_space(m, size, &p);
1684 for (i = 0; i < n; i++) {
1686 if (iov[i].iov_base)
1687 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1689 memset(p, ' ', iov[i].iov_len);
1691 p += iov[i].iov_len;
1697 static int bus_message_open_array(
1699 struct bus_container *c,
1700 const char *contents,
1701 uint32_t **array_size,
1703 bool *need_offsets) {
1713 assert(need_offsets);
1715 if (!signature_is_single(contents, true))
1718 if (c->signature && c->signature[c->index]) {
1720 /* Verify the existing signature */
1722 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1725 if (!startswith(c->signature + c->index + 1, contents))
1728 nindex = c->index + 1 + strlen(contents);
1732 if (c->enclosing != 0)
1735 /* Extend the existing signature */
1737 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1743 nindex = e - c->signature;
1746 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1747 alignment = bus_gvariant_get_alignment(contents);
1751 /* Add alignment padding and add to offset list */
1752 if (!message_extend_body(m, alignment, 0, false, false))
1755 r = bus_gvariant_is_fixed_size(contents);
1759 *begin = m->body_size;
1760 *need_offsets = r == 0;
1764 struct bus_body_part *o;
1766 alignment = bus_type_get_alignment(contents[0]);
1770 a = message_extend_body(m, 4, 4, false, false);
1775 op = m->body_end->data;
1776 os = m->body_end->size;
1778 /* Add alignment between size and first element */
1779 if (!message_extend_body(m, alignment, 0, false, false))
1782 /* location of array size might have changed so let's readjust a */
1783 if (o == m->body_end)
1784 a = adjust_pointer(a, op, os, m->body_end->data);
1790 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1796 static int bus_message_open_variant(
1798 struct bus_container *c,
1799 const char *contents) {
1805 if (!signature_is_single(contents, false))
1808 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1811 if (c->signature && c->signature[c->index]) {
1813 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1819 if (c->enclosing != 0)
1822 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1829 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1830 /* Variants are always aligned to 8 */
1832 if (!message_extend_body(m, 8, 0, false, false))
1839 l = strlen(contents);
1840 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1845 memcpy((uint8_t*) a + 1, contents, l + 1);
1848 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1854 static int bus_message_open_struct(
1856 struct bus_container *c,
1857 const char *contents,
1859 bool *need_offsets) {
1868 assert(need_offsets);
1870 if (!signature_is_valid(contents, false))
1873 if (c->signature && c->signature[c->index]) {
1876 l = strlen(contents);
1878 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1879 !startswith(c->signature + c->index + 1, contents) ||
1880 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1883 nindex = c->index + 1 + l + 1;
1887 if (c->enclosing != 0)
1890 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1896 nindex = e - c->signature;
1899 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1902 alignment = bus_gvariant_get_alignment(contents);
1906 if (!message_extend_body(m, alignment, 0, false, false))
1909 r = bus_gvariant_is_fixed_size(contents);
1913 *begin = m->body_size;
1914 *need_offsets = r == 0;
1916 /* Align contents to 8 byte boundary */
1917 if (!message_extend_body(m, 8, 0, false, false))
1921 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1927 static int bus_message_open_dict_entry(
1929 struct bus_container *c,
1930 const char *contents,
1932 bool *need_offsets) {
1940 assert(need_offsets);
1942 if (!signature_is_pair(contents))
1945 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1948 if (c->signature && c->signature[c->index]) {
1951 l = strlen(contents);
1953 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1954 !startswith(c->signature + c->index + 1, contents) ||
1955 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1960 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1963 alignment = bus_gvariant_get_alignment(contents);
1967 if (!message_extend_body(m, alignment, 0, false, false))
1970 r = bus_gvariant_is_fixed_size(contents);
1974 *begin = m->body_size;
1975 *need_offsets = r == 0;
1977 /* Align contents to 8 byte boundary */
1978 if (!message_extend_body(m, 8, 0, false, false))
1985 _public_ int sd_bus_message_open_container(
1988 const char *contents) {
1990 struct bus_container *c, *w;
1991 uint32_t *array_size = NULL;
1993 size_t before, begin = 0;
1994 bool need_offsets = false;
1997 assert_return(m, -EINVAL);
1998 assert_return(!m->sealed, -EPERM);
1999 assert_return(contents, -EINVAL);
2000 assert_return(!m->poisoned, -ESTALE);
2002 /* Make sure we have space for one more container */
2003 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2008 c = message_get_container(m);
2010 signature = strdup(contents);
2016 /* Save old index in the parent container, in case we have to
2017 * abort this container */
2018 c->saved_index = c->index;
2019 before = m->body_size;
2021 if (type == SD_BUS_TYPE_ARRAY)
2022 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2023 else if (type == SD_BUS_TYPE_VARIANT)
2024 r = bus_message_open_variant(m, c, contents);
2025 else if (type == SD_BUS_TYPE_STRUCT)
2026 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2027 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2028 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2037 /* OK, let's fill it in */
2038 w = m->containers + m->n_containers++;
2039 w->enclosing = type;
2040 w->signature = signature;
2042 w->array_size = array_size;
2045 w->n_offsets = w->offsets_allocated = 0;
2047 w->need_offsets = need_offsets;
2052 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2057 if (!BUS_MESSAGE_IS_GVARIANT(m))
2060 if (c->need_offsets) {
2061 size_t payload, sz, i;
2064 /* Variable-width arrays */
2066 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2067 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2069 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2073 for (i = 0; i < c->n_offsets; i++)
2074 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2078 /* Fixed-width or empty arrays */
2080 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2088 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2094 assert(c->signature);
2096 if (!BUS_MESSAGE_IS_GVARIANT(m))
2099 l = strlen(c->signature);
2101 a = message_extend_body(m, 1, 1 + l, true, false);
2106 memcpy(a+1, c->signature, l);
2111 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2112 bool fixed_size = true;
2113 size_t n_variable = 0;
2122 if (!BUS_MESSAGE_IS_GVARIANT(m))
2125 p = strempty(c->signature);
2129 r = signature_element_length(p, &n);
2138 r = bus_gvariant_is_fixed_size(t);
2143 assert(!c->need_offsets || i <= c->n_offsets);
2145 /* We need to add an offset for each item that has a
2146 * variable size and that is not the last one in the
2150 if (r == 0 && p[n] != 0)
2157 assert(!c->need_offsets || i == c->n_offsets);
2158 assert(c->need_offsets || n_variable == 0);
2160 if (isempty(c->signature)) {
2161 /* The unary type is encoded as fixed 1 byte padding */
2162 a = message_extend_body(m, 1, 1, add_offset, false);
2167 } else if (n_variable <= 0) {
2170 /* Structures with fixed-size members only have to be
2171 * fixed-size themselves. But gvariant requires all fixed-size
2172 * elements to be sized a multiple of their alignment. Hence,
2173 * we must *always* add final padding after the last member so
2174 * the overall size of the structure is properly aligned. */
2176 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2178 assert(alignment > 0);
2180 a = message_extend_body(m, alignment, 0, add_offset, false);
2187 assert(c->offsets[c->n_offsets-1] == m->body_size);
2189 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2191 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2195 p = strempty(c->signature);
2196 for (i = 0, j = 0; i < c->n_offsets; i++) {
2200 r = signature_element_length(p, &n);
2211 r = bus_gvariant_is_fixed_size(t);
2214 if (r > 0 || p[0] == 0)
2218 k = n_variable - 1 - j;
2220 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2229 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2230 struct bus_container *c;
2233 assert_return(m, -EINVAL);
2234 assert_return(!m->sealed, -EPERM);
2235 assert_return(m->n_containers > 0, -EINVAL);
2236 assert_return(!m->poisoned, -ESTALE);
2238 c = message_get_container(m);
2240 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2241 if (c->signature && c->signature[c->index] != 0)
2246 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2247 r = bus_message_close_array(m, c);
2248 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2249 r = bus_message_close_variant(m, c);
2250 else if (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY))
2251 r = bus_message_close_struct(m, c, true);
2253 assert_not_reached("Unknown container type");
2267 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2274 stack[*i].types = types;
2275 stack[*i].n_struct = n_struct;
2276 stack[*i].n_array = n_array;
2282 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2293 *types = stack[*i].types;
2294 *n_struct = stack[*i].n_struct;
2295 *n_array = stack[*i].n_array;
2300 _public_ int sd_bus_message_appendv(
2305 unsigned n_array, n_struct;
2306 TypeStack stack[BUS_CONTAINER_DEPTH];
2307 unsigned stack_ptr = 0;
2310 assert_return(m, -EINVAL);
2311 assert_return(types, -EINVAL);
2312 assert_return(!m->sealed, -EPERM);
2313 assert_return(!m->poisoned, -ESTALE);
2315 n_array = (unsigned) -1;
2316 n_struct = strlen(types);
2321 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2322 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2328 r = sd_bus_message_close_container(m);
2336 if (n_array != (unsigned) -1)
2345 case SD_BUS_TYPE_BYTE: {
2348 x = (uint8_t) va_arg(ap, int);
2349 r = sd_bus_message_append_basic(m, *t, &x);
2353 case SD_BUS_TYPE_BOOLEAN:
2354 case SD_BUS_TYPE_INT32:
2355 case SD_BUS_TYPE_UINT32:
2356 case SD_BUS_TYPE_UNIX_FD: {
2359 /* We assume a boolean is the same as int32_t */
2360 assert_cc(sizeof(int32_t) == sizeof(int));
2362 x = va_arg(ap, uint32_t);
2363 r = sd_bus_message_append_basic(m, *t, &x);
2367 case SD_BUS_TYPE_INT16:
2368 case SD_BUS_TYPE_UINT16: {
2371 x = (uint16_t) va_arg(ap, int);
2372 r = sd_bus_message_append_basic(m, *t, &x);
2376 case SD_BUS_TYPE_INT64:
2377 case SD_BUS_TYPE_UINT64: {
2380 x = va_arg(ap, uint64_t);
2381 r = sd_bus_message_append_basic(m, *t, &x);
2385 case SD_BUS_TYPE_DOUBLE: {
2388 x = va_arg(ap, double);
2389 r = sd_bus_message_append_basic(m, *t, &x);
2393 case SD_BUS_TYPE_STRING:
2394 case SD_BUS_TYPE_OBJECT_PATH:
2395 case SD_BUS_TYPE_SIGNATURE: {
2398 x = va_arg(ap, const char*);
2399 r = sd_bus_message_append_basic(m, *t, x);
2403 case SD_BUS_TYPE_ARRAY: {
2406 r = signature_element_length(t + 1, &k);
2412 memcpy(s, t + 1, k);
2415 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2420 if (n_array == (unsigned) -1) {
2425 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2431 n_array = va_arg(ap, unsigned);
2436 case SD_BUS_TYPE_VARIANT: {
2439 s = va_arg(ap, const char*);
2443 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2447 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2452 n_struct = strlen(s);
2453 n_array = (unsigned) -1;
2458 case SD_BUS_TYPE_STRUCT_BEGIN:
2459 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2462 r = signature_element_length(t, &k);
2469 memcpy(s, t + 1, k - 2);
2472 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2477 if (n_array == (unsigned) -1) {
2482 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2488 n_array = (unsigned) -1;
2504 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2508 assert_return(m, -EINVAL);
2509 assert_return(types, -EINVAL);
2510 assert_return(!m->sealed, -EPERM);
2511 assert_return(!m->poisoned, -ESTALE);
2513 va_start(ap, types);
2514 r = sd_bus_message_appendv(m, types, ap);
2520 _public_ int sd_bus_message_append_array_space(
2530 assert_return(m, -EINVAL);
2531 assert_return(!m->sealed, -EPERM);
2532 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2533 assert_return(ptr || size == 0, -EINVAL);
2534 assert_return(!m->poisoned, -ESTALE);
2536 /* alignment and size of the trivial types (except bool) is
2537 * identical for gvariant and dbus1 marshalling */
2538 align = bus_type_get_alignment(type);
2539 sz = bus_type_get_size(type);
2541 assert_se(align > 0);
2547 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2551 a = message_extend_body(m, align, size, false, false);
2555 r = sd_bus_message_close_container(m);
2563 _public_ int sd_bus_message_append_array(
2571 assert_return(m, -EINVAL);
2572 assert_return(!m->sealed, -EPERM);
2573 assert_return(bus_type_is_trivial(type), -EINVAL);
2574 assert_return(ptr || size == 0, -EINVAL);
2575 assert_return(!m->poisoned, -ESTALE);
2577 r = sd_bus_message_append_array_space(m, type, size, &p);
2581 memcpy_safe(p, ptr, size);
2586 _public_ int sd_bus_message_append_array_iovec(
2589 const struct iovec *iov,
2597 assert_return(m, -EINVAL);
2598 assert_return(!m->sealed, -EPERM);
2599 assert_return(bus_type_is_trivial(type), -EINVAL);
2600 assert_return(iov || n == 0, -EINVAL);
2601 assert_return(!m->poisoned, -ESTALE);
2603 size = IOVEC_TOTAL_SIZE(iov, n);
2605 r = sd_bus_message_append_array_space(m, type, size, &p);
2609 for (i = 0; i < n; i++) {
2611 if (iov[i].iov_base)
2612 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2614 memzero(p, iov[i].iov_len);
2616 p = (uint8_t*) p + iov[i].iov_len;
2622 _public_ int sd_bus_message_append_array_memfd(
2629 _cleanup_close_ int copy_fd = -1;
2630 struct bus_body_part *part;
2636 assert_return(m, -EINVAL);
2637 assert_return(memfd >= 0, -EBADF);
2638 assert_return(bus_type_is_trivial(type), -EINVAL);
2639 assert_return(size > 0, -EINVAL);
2640 assert_return(!m->sealed, -EPERM);
2641 assert_return(!m->poisoned, -ESTALE);
2643 r = memfd_set_sealed(memfd);
2647 copy_fd = dup(memfd);
2651 r = memfd_get_size(memfd, &real_size);
2655 if (offset == 0 && size == (uint64_t) -1)
2657 else if (offset + size > real_size)
2660 align = bus_type_get_alignment(type);
2661 sz = bus_type_get_size(type);
2663 assert_se(align > 0);
2666 if (offset % align != 0)
2672 if (size > (uint64_t) (uint32_t) -1)
2675 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2679 a = message_extend_body(m, align, 0, false, false);
2683 part = message_append_part(m);
2687 part->memfd = copy_fd;
2688 part->memfd_offset = offset;
2689 part->sealed = true;
2693 m->body_size += size;
2694 message_extend_containers(m, size);
2696 return sd_bus_message_close_container(m);
2699 _public_ int sd_bus_message_append_string_memfd(
2705 _cleanup_close_ int copy_fd = -1;
2706 struct bus_body_part *part;
2707 struct bus_container *c;
2712 assert_return(m, -EINVAL);
2713 assert_return(memfd >= 0, -EBADF);
2714 assert_return(size > 0, -EINVAL);
2715 assert_return(!m->sealed, -EPERM);
2716 assert_return(!m->poisoned, -ESTALE);
2718 r = memfd_set_sealed(memfd);
2722 copy_fd = dup(memfd);
2726 r = memfd_get_size(memfd, &real_size);
2730 if (offset == 0 && size == (uint64_t) -1)
2732 else if (offset + size > real_size)
2735 /* We require this to be NUL terminated */
2739 if (size > (uint64_t) (uint32_t) -1)
2742 c = message_get_container(m);
2743 if (c->signature && c->signature[c->index]) {
2744 /* Container signature is already set */
2746 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2751 /* Maybe we can append to the signature? But only if this is the top-level container */
2752 if (c->enclosing != 0)
2755 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2762 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2763 a = message_extend_body(m, 4, 4, false, false);
2767 *(uint32_t*) a = size - 1;
2770 part = message_append_part(m);
2774 part->memfd = copy_fd;
2775 part->memfd_offset = offset;
2776 part->sealed = true;
2780 m->body_size += size;
2781 message_extend_containers(m, size);
2783 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2784 r = message_add_offset(m, m->body_size);
2791 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2797 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2801 assert_return(m, -EINVAL);
2802 assert_return(!m->sealed, -EPERM);
2803 assert_return(!m->poisoned, -ESTALE);
2805 r = sd_bus_message_open_container(m, 'a', "s");
2809 STRV_FOREACH(i, l) {
2810 r = sd_bus_message_append_basic(m, 's', *i);
2815 return sd_bus_message_close_container(m);
2818 static int bus_message_close_header(sd_bus_message *m) {
2822 /* The actual user data is finished now, we just complete the
2823 variant and struct now (at least on gvariant). Remember
2824 this position, so that during parsing we know where to
2825 put the outer container end. */
2826 m->user_body_size = m->body_size;
2828 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2829 const char *signature;
2833 /* Add offset table to end of fields array */
2834 if (m->n_header_offsets >= 1) {
2838 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2840 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2841 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2845 for (i = 0; i < m->n_header_offsets; i++)
2846 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2849 /* Add gvariant NUL byte plus signature to the end of
2850 * the body, followed by the final offset pointing to
2851 * the end of the fields array */
2853 signature = strempty(m->root_container.signature);
2854 l = strlen(signature);
2856 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2857 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2862 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2863 memcpy((uint8_t*) d + 2, signature, l);
2864 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2866 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2869 m->footer_accessible = 1 + l + 2 + sz;
2871 m->header->dbus1.fields_size = m->fields_size;
2872 m->header->dbus1.body_size = m->body_size;
2878 _public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t timeout_usec) {
2879 struct bus_body_part *part;
2884 assert_return(m, -EINVAL);
2889 if (m->n_containers > 0)
2895 if (cookie > 0xffffffffULL &&
2896 !BUS_MESSAGE_IS_GVARIANT(m))
2899 /* In vtables the return signature of method calls is listed,
2900 * let's check if they match if this is a response */
2901 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2902 m->enforced_reply_signature &&
2903 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2906 /* If gvariant marshalling is used we need to close the body structure */
2907 r = bus_message_close_struct(m, &m->root_container, false);
2911 /* If there's a non-trivial signature set, then add it in
2912 * here, but only on dbus1 */
2913 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2914 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2920 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2925 r = bus_message_close_header(m);
2929 if (BUS_MESSAGE_IS_GVARIANT(m))
2930 m->header->dbus2.cookie = cookie;
2932 m->header->dbus1.serial = (uint32_t) cookie;
2934 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout_usec;
2936 /* Add padding at the end of the fields part, since we know
2937 * the body needs to start at an 8 byte alignment. We made
2938 * sure we allocated enough space for this, so all we need to
2939 * do here is to zero it out. */
2940 a = ALIGN8(m->fields_size) - m->fields_size;
2942 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2944 /* If this is something we can send as memfd, then let's seal
2945 the memfd now. Note that we can send memfds as payload only
2946 for directed messages, and not for broadcasts. */
2947 if (m->destination && m->bus->use_memfd) {
2948 MESSAGE_FOREACH_PART(part, i, m)
2949 if (part->memfd >= 0 &&
2951 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2952 part != m->body_end) { /* The last part may never be sent as memfd */
2955 /* Try to seal it if that makes
2956 * sense. First, unmap our own map to
2957 * make sure we don't keep it busy. */
2958 bus_body_part_unmap(part);
2960 /* Then, sync up real memfd size */
2962 r = memfd_set_size(part->memfd, sz);
2966 /* Finally, try to seal */
2967 if (memfd_set_sealed(part->memfd) >= 0)
2968 part->sealed = true;
2972 m->root_container.end = m->user_body_size;
2973 m->root_container.index = 0;
2974 m->root_container.offset_index = 0;
2975 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2982 int bus_body_part_map(struct bus_body_part *part) {
2991 if (part->size <= 0)
2994 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2995 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2996 static const uint8_t zeroes[7] = { };
2997 part->data = (void*) zeroes;
3001 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3002 psz = PAGE_ALIGN(part->size + shift);
3004 if (part->memfd >= 0)
3005 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3006 else if (part->is_zero)
3007 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3011 if (p == MAP_FAILED)
3015 part->mmap_begin = p;
3016 part->data = (uint8_t*) p + shift;
3017 part->munmap_this = true;
3022 void bus_body_part_unmap(struct bus_body_part *part) {
3026 if (part->memfd < 0)
3029 if (!part->mmap_begin)
3032 if (!part->munmap_this)
3035 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3037 part->mmap_begin = NULL;
3040 part->munmap_this = false;
3045 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3046 size_t k, start, end;
3051 start = ALIGN_TO((size_t) *rindex, align);
3052 end = start + nbytes;
3057 /* Verify that padding is 0 */
3058 for (k = *rindex; k < start; k++)
3059 if (((const uint8_t*) p)[k] != 0)
3063 *r = (uint8_t*) p + start;
3070 static bool message_end_of_signature(sd_bus_message *m) {
3071 struct bus_container *c;
3075 c = message_get_container(m);
3076 return !c->signature || c->signature[c->index] == 0;
3079 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3080 struct bus_container *c;
3084 c = message_get_container(m);
3085 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3088 if (BUS_MESSAGE_IS_GVARIANT(m))
3089 return index >= c->end;
3091 assert(c->array_size);
3092 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3096 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3097 assert_return(m, -EINVAL);
3098 assert_return(m->sealed, -EPERM);
3100 if (complete && m->n_containers > 0)
3103 if (message_end_of_signature(m))
3106 if (message_end_of_array(m, m->rindex))
3112 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3113 struct bus_body_part *part;
3119 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3120 part = m->cached_rindex_part;
3121 begin = m->cached_rindex_part_begin;
3131 if (index + sz <= begin + part->size) {
3133 r = bus_body_part_map(part);
3138 *p = (uint8_t*) part->data + index - begin;
3140 m->cached_rindex_part = part;
3141 m->cached_rindex_part_begin = begin;
3146 begin += part->size;
3153 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3160 if (!BUS_MESSAGE_IS_GVARIANT(m))
3163 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3166 sz = bus_gvariant_get_size(c->signature);
3170 if (c->offset_index+1 >= c->n_offsets)
3173 /* Variable-size array */
3175 alignment = bus_gvariant_get_alignment(c->signature);
3176 assert(alignment > 0);
3178 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3179 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3182 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3185 /* Fixed-size array */
3186 *rindex = c->begin + (c->offset_index+1) * sz;
3192 } else if (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
3197 if (c->offset_index+1 >= c->n_offsets)
3200 r = signature_element_length(c->signature + c->index, &n);
3204 r = signature_element_length(c->signature + c->index + n, &j);
3209 memcpy(t, c->signature + c->index + n, j);
3212 alignment = bus_gvariant_get_alignment(t);
3215 assert(alignment > 0);
3217 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3218 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3222 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3225 assert_not_reached("Unknown container type");
3230 /* Reached the end */
3237 static int message_peek_body(
3244 size_t k, start, end, padding;
3245 struct bus_body_part *part;
3252 start = ALIGN_TO((size_t) *rindex, align);
3253 padding = start - *rindex;
3254 end = start + nbytes;
3256 if (end > m->user_body_size)
3259 part = find_part(m, *rindex, padding, (void**) &q);
3264 /* Verify padding */
3265 for (k = 0; k < padding; k++)
3270 part = find_part(m, start, nbytes, (void**) &q);
3271 if (!part || (nbytes > 0 && !q))
3282 static bool validate_nul(const char *s, size_t l) {
3284 /* Check for NUL chars in the string */
3285 if (memchr(s, 0, l))
3288 /* Check for NUL termination */
3295 static bool validate_string(const char *s, size_t l) {
3297 if (!validate_nul(s, l))
3300 /* Check if valid UTF8 */
3301 if (!utf8_is_valid(s))
3307 static bool validate_signature(const char *s, size_t l) {
3309 if (!validate_nul(s, l))
3312 /* Check if valid signature */
3313 if (!signature_is_valid(s, true))
3319 static bool validate_object_path(const char *s, size_t l) {
3321 if (!validate_nul(s, l))
3324 if (!object_path_is_valid(s))
3330 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3331 struct bus_container *c;
3336 assert_return(m, -EINVAL);
3337 assert_return(m->sealed, -EPERM);
3338 assert_return(bus_type_is_basic(type), -EINVAL);
3340 if (message_end_of_signature(m))
3343 if (message_end_of_array(m, m->rindex))
3346 c = message_get_container(m);
3347 if (c->signature[c->index] != type)
3352 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3354 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3357 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3361 if (type == SD_BUS_TYPE_STRING)
3362 ok = validate_string(q, c->item_size-1);
3363 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3364 ok = validate_object_path(q, c->item_size-1);
3366 ok = validate_signature(q, c->item_size-1);
3372 *(const char**) p = q;
3376 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3378 if ((size_t) sz != c->item_size)
3381 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3384 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3390 case SD_BUS_TYPE_BYTE:
3392 *(uint8_t*) p = *(uint8_t*) q;
3395 case SD_BUS_TYPE_BOOLEAN:
3397 *(int*) p = !!*(uint8_t*) q;
3400 case SD_BUS_TYPE_INT16:
3401 case SD_BUS_TYPE_UINT16:
3403 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3406 case SD_BUS_TYPE_INT32:
3407 case SD_BUS_TYPE_UINT32:
3409 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3412 case SD_BUS_TYPE_INT64:
3413 case SD_BUS_TYPE_UINT64:
3414 case SD_BUS_TYPE_DOUBLE:
3416 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3419 case SD_BUS_TYPE_UNIX_FD: {
3422 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3427 *(int*) p = m->fds[j];
3433 assert_not_reached("unexpected type");
3437 r = container_next_item(m, c, &rindex);
3442 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3446 r = message_peek_body(m, &rindex, 4, 4, &q);
3450 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3451 r = message_peek_body(m, &rindex, 1, l+1, &q);
3455 if (type == SD_BUS_TYPE_OBJECT_PATH)
3456 ok = validate_object_path(q, l);
3458 ok = validate_string(q, l);
3463 *(const char**) p = q;
3465 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3468 r = message_peek_body(m, &rindex, 1, 1, &q);
3473 r = message_peek_body(m, &rindex, 1, l+1, &q);
3477 if (!validate_signature(q, l))
3481 *(const char**) p = q;
3486 align = bus_type_get_alignment(type);
3489 sz = bus_type_get_size(type);
3492 r = message_peek_body(m, &rindex, align, sz, &q);
3498 case SD_BUS_TYPE_BYTE:
3500 *(uint8_t*) p = *(uint8_t*) q;
3503 case SD_BUS_TYPE_BOOLEAN:
3505 *(int*) p = !!*(uint32_t*) q;
3508 case SD_BUS_TYPE_INT16:
3509 case SD_BUS_TYPE_UINT16:
3511 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3514 case SD_BUS_TYPE_INT32:
3515 case SD_BUS_TYPE_UINT32:
3517 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3520 case SD_BUS_TYPE_INT64:
3521 case SD_BUS_TYPE_UINT64:
3522 case SD_BUS_TYPE_DOUBLE:
3524 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3527 case SD_BUS_TYPE_UNIX_FD: {
3530 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3535 *(int*) p = m->fds[j];
3540 assert_not_reached("Unknown basic type...");
3547 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3553 static int bus_message_enter_array(
3555 struct bus_container *c,
3556 const char *contents,
3557 uint32_t **array_size,
3560 size_t *n_offsets) {
3574 if (!signature_is_single(contents, true))
3577 if (!c->signature || c->signature[c->index] == 0)
3580 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3583 if (!startswith(c->signature + c->index + 1, contents))
3588 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3591 r = message_peek_body(m, &rindex, 4, 4, &q);
3595 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3598 alignment = bus_type_get_alignment(contents[0]);
3602 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3606 *array_size = (uint32_t*) q;
3608 } else if (c->item_size <= 0) {
3610 /* gvariant: empty array */
3615 } else if (bus_gvariant_is_fixed_size(contents)) {
3617 /* gvariant: fixed length array */
3618 *item_size = bus_gvariant_get_size(contents);
3623 size_t where, p = 0, framing, sz;
3626 /* gvariant: variable length array */
3627 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3629 where = rindex + c->item_size - sz;
3630 r = message_peek_body(m, &where, 1, sz, &q);
3634 framing = bus_gvariant_read_word_le(q, sz);
3635 if (framing > c->item_size - sz)
3637 if ((c->item_size - framing) % sz != 0)
3640 *n_offsets = (c->item_size - framing) / sz;
3642 where = rindex + framing;
3643 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3647 *offsets = new(size_t, *n_offsets);
3651 for (i = 0; i < *n_offsets; i++) {
3654 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3655 if (x > c->item_size - sz)
3660 (*offsets)[i] = rindex + x;
3664 *item_size = (*offsets)[0] - rindex;
3669 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3670 c->index += 1 + strlen(contents);
3675 static int bus_message_enter_variant(
3677 struct bus_container *c,
3678 const char *contents,
3679 size_t *item_size) {
3691 if (!signature_is_single(contents, false))
3694 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3697 if (!c->signature || c->signature[c->index] == 0)
3700 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3705 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3708 k = strlen(contents);
3709 if (1+k > c->item_size)
3712 where = rindex + c->item_size - (1+k);
3713 r = message_peek_body(m, &where, 1, 1+k, &q);
3717 if (*(char*) q != 0)
3720 if (memcmp((uint8_t*) q+1, contents, k))
3723 *item_size = c->item_size - (1+k);
3726 r = message_peek_body(m, &rindex, 1, 1, &q);
3731 r = message_peek_body(m, &rindex, 1, l+1, &q);
3735 if (!validate_signature(q, l))
3738 if (!streq(q, contents))
3744 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3750 static int build_struct_offsets(
3752 const char *signature,
3756 size_t *n_offsets) {
3758 unsigned n_variable = 0, n_total = 0, v;
3759 size_t previous = 0, where;
3770 if (isempty(signature)) {
3771 /* Unary type is encoded as *fixed* 1 byte padding */
3772 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3776 if (*(uint8_t *) q != 0)
3785 sz = bus_gvariant_determine_word_size(size, 0);
3789 /* First, loop over signature and count variable elements and
3790 * elements in general. We use this to know how large the
3791 * offset array is at the end of the structure. Note that
3792 * GVariant only stores offsets for all variable size elements
3793 * that are not the last item. */
3799 r = signature_element_length(p, &n);
3808 r = bus_gvariant_is_fixed_size(t);
3813 if (r == 0 && p[n] != 0) /* except the last item */
3820 if (size < n_variable * sz)
3823 where = m->rindex + size - (n_variable * sz);
3824 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3830 *offsets = new(size_t, n_total);
3836 /* Second, loop again and build an offset table */
3842 r = signature_element_length(p, &n);
3851 k = bus_gvariant_get_size(t);
3859 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3862 if (m->rindex + x < previous)
3865 /* The last item's end
3866 * is determined from
3869 x = size - (n_variable * sz);
3871 offset = m->rindex + x;
3877 align = bus_gvariant_get_alignment(t);
3880 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3884 previous = (*offsets)[(*n_offsets)++] = offset;
3889 assert(*n_offsets == n_total);
3891 *item_size = (*offsets)[0] - m->rindex;
3895 static int enter_struct_or_dict_entry(
3897 struct bus_container *c,
3898 const char *contents,
3901 size_t *n_offsets) {
3912 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3915 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3920 /* gvariant with contents */
3921 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3926 static int bus_message_enter_struct(
3928 struct bus_container *c,
3929 const char *contents,
3932 size_t *n_offsets) {
3944 if (!signature_is_valid(contents, false))
3947 if (!c->signature || c->signature[c->index] == 0)
3950 l = strlen(contents);
3952 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3953 !startswith(c->signature + c->index + 1, contents) ||
3954 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3957 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3961 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3962 c->index += 1 + l + 1;
3967 static int bus_message_enter_dict_entry(
3969 struct bus_container *c,
3970 const char *contents,
3973 size_t *n_offsets) {
3982 if (!signature_is_pair(contents))
3985 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3988 if (!c->signature || c->signature[c->index] == 0)
3991 l = strlen(contents);
3993 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3994 !startswith(c->signature + c->index + 1, contents) ||
3995 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3998 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4002 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4003 c->index += 1 + l + 1;
4008 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4010 const char *contents) {
4011 struct bus_container *c, *w;
4012 uint32_t *array_size = NULL;
4015 size_t *offsets = NULL;
4016 size_t n_offsets = 0, item_size = 0;
4019 assert_return(m, -EINVAL);
4020 assert_return(m->sealed, -EPERM);
4021 assert_return(type != 0 || !contents, -EINVAL);
4023 if (type == 0 || !contents) {
4027 /* Allow entering into anonymous containers */
4028 r = sd_bus_message_peek_type(m, &tt, &cc);
4032 if (type != 0 && type != tt)
4035 if (contents && !streq(contents, cc))
4043 * We enforce a global limit on container depth, that is much
4044 * higher than the 32 structs and 32 arrays the specification
4045 * mandates. This is simpler to implement for us, and we need
4046 * this only to ensure our container array doesn't grow
4047 * without bounds. We are happy to return any data from a
4048 * message as long as the data itself is valid, even if the
4049 * overall message might be not.
4051 * Note that the message signature is validated when
4052 * parsing the headers, and that validation does check the
4055 * Note that the specification defines no limits on the depth
4056 * of stacked variants, but we do.
4058 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4061 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4064 if (message_end_of_signature(m))
4067 if (message_end_of_array(m, m->rindex))
4070 c = message_get_container(m);
4072 signature = strdup(contents);
4076 c->saved_index = c->index;
4079 if (type == SD_BUS_TYPE_ARRAY)
4080 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4081 else if (type == SD_BUS_TYPE_VARIANT)
4082 r = bus_message_enter_variant(m, c, contents, &item_size);
4083 else if (type == SD_BUS_TYPE_STRUCT)
4084 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4085 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4086 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4096 /* OK, let's fill it in */
4097 w = m->containers + m->n_containers++;
4098 w->enclosing = type;
4099 w->signature = signature;
4100 w->peeked_signature = NULL;
4104 w->begin = m->rindex;
4106 /* Unary type has fixed size of 1, but virtual size of 0 */
4107 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4108 type == SD_BUS_TYPE_STRUCT &&
4110 w->end = m->rindex + 0;
4112 w->end = m->rindex + c->item_size;
4114 w->array_size = array_size;
4115 w->item_size = item_size;
4116 w->offsets = offsets;
4117 w->n_offsets = n_offsets;
4118 w->offset_index = 0;
4123 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4124 struct bus_container *c;
4128 assert_return(m, -EINVAL);
4129 assert_return(m->sealed, -EPERM);
4130 assert_return(m->n_containers > 0, -ENXIO);
4132 c = message_get_container(m);
4134 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4135 if (c->signature && c->signature[c->index] != 0)
4139 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4140 if (m->rindex < c->end)
4143 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4146 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4147 if (c->begin + l != m->rindex)
4152 free(c->peeked_signature);
4156 c = message_get_container(m);
4159 c->index = c->saved_index;
4160 r = container_next_item(m, c, &m->rindex);
4168 static void message_quit_container(sd_bus_message *m) {
4169 struct bus_container *c;
4173 assert(m->n_containers > 0);
4175 c = message_get_container(m);
4178 assert(m->rindex >= c->before);
4179 m->rindex = c->before;
4181 /* Free container */
4186 /* Correct index of new top-level container */
4187 c = message_get_container(m);
4188 c->index = c->saved_index;
4191 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4192 struct bus_container *c;
4195 assert_return(m, -EINVAL);
4196 assert_return(m->sealed, -EPERM);
4198 if (message_end_of_signature(m))
4201 if (message_end_of_array(m, m->rindex))
4204 c = message_get_container(m);
4206 if (bus_type_is_basic(c->signature[c->index])) {
4210 *type = c->signature[c->index];
4214 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4220 r = signature_element_length(c->signature+c->index+1, &l);
4226 sig = strndup(c->signature + c->index + 1, l);
4230 free(c->peeked_signature);
4231 *contents = c->peeked_signature = sig;
4235 *type = SD_BUS_TYPE_ARRAY;
4240 if (IN_SET(c->signature[c->index], SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN)) {
4246 r = signature_element_length(c->signature+c->index, &l);
4251 sig = strndup(c->signature + c->index + 1, l - 2);
4255 free(c->peeked_signature);
4256 *contents = c->peeked_signature = sig;
4260 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4265 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4269 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4272 if (c->item_size < 2)
4275 /* Look for the NUL delimiter that
4276 separates the payload from the
4277 signature. Since the body might be
4278 in a different part that then the
4279 signature we map byte by byte. */
4281 for (k = 2; k <= c->item_size; k++) {
4284 where = m->rindex + c->item_size - k;
4285 r = message_peek_body(m, &where, 1, k, &q);
4289 if (*(char*) q == 0)
4293 if (k > c->item_size)
4296 free(c->peeked_signature);
4297 c->peeked_signature = strndup((char*) q + 1, k - 1);
4298 if (!c->peeked_signature)
4301 if (!signature_is_valid(c->peeked_signature, true))
4304 *contents = c->peeked_signature;
4309 r = message_peek_body(m, &rindex, 1, 1, &q);
4314 r = message_peek_body(m, &rindex, 1, l+1, &q);
4318 if (!validate_signature(q, l))
4326 *type = SD_BUS_TYPE_VARIANT;
4341 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4342 struct bus_container *c;
4344 assert_return(m, -EINVAL);
4345 assert_return(m->sealed, -EPERM);
4348 message_reset_containers(m);
4351 c = message_get_container(m);
4353 c = message_get_container(m);
4355 c->offset_index = 0;
4357 m->rindex = c->begin;
4360 c->offset_index = 0;
4361 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4363 return !isempty(c->signature);
4366 static int message_read_ap(
4371 unsigned n_array, n_struct;
4372 TypeStack stack[BUS_CONTAINER_DEPTH];
4373 unsigned stack_ptr = 0;
4374 unsigned n_loop = 0;
4382 /* Ideally, we'd just call ourselves recursively on every
4383 * complex type. However, the state of a va_list that is
4384 * passed to a function is undefined after that function
4385 * returns. This means we need to docode the va_list linearly
4386 * in a single stackframe. We hence implement our own
4387 * home-grown stack in an array. */
4389 n_array = (unsigned) -1; /* length of current array entries */
4390 n_struct = strlen(types); /* length of current struct contents signature */
4397 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4398 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4404 r = sd_bus_message_exit_container(m);
4412 if (n_array != (unsigned) -1)
4421 case SD_BUS_TYPE_BYTE:
4422 case SD_BUS_TYPE_BOOLEAN:
4423 case SD_BUS_TYPE_INT16:
4424 case SD_BUS_TYPE_UINT16:
4425 case SD_BUS_TYPE_INT32:
4426 case SD_BUS_TYPE_UINT32:
4427 case SD_BUS_TYPE_INT64:
4428 case SD_BUS_TYPE_UINT64:
4429 case SD_BUS_TYPE_DOUBLE:
4430 case SD_BUS_TYPE_STRING:
4431 case SD_BUS_TYPE_OBJECT_PATH:
4432 case SD_BUS_TYPE_SIGNATURE:
4433 case SD_BUS_TYPE_UNIX_FD: {
4436 p = va_arg(ap, void*);
4437 r = sd_bus_message_read_basic(m, *t, p);
4450 case SD_BUS_TYPE_ARRAY: {
4453 r = signature_element_length(t + 1, &k);
4459 memcpy(s, t + 1, k);
4462 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4473 if (n_array == (unsigned) -1) {
4478 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4484 n_array = va_arg(ap, unsigned);
4489 case SD_BUS_TYPE_VARIANT: {
4492 s = va_arg(ap, const char *);
4496 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4506 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4511 n_struct = strlen(s);
4512 n_array = (unsigned) -1;
4517 case SD_BUS_TYPE_STRUCT_BEGIN:
4518 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4521 r = signature_element_length(t, &k);
4527 memcpy(s, t + 1, k - 2);
4530 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4540 if (n_array == (unsigned) -1) {
4545 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4551 n_array = (unsigned) -1;
4564 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4568 assert_return(m, -EINVAL);
4569 assert_return(m->sealed, -EPERM);
4570 assert_return(types, -EINVAL);
4572 va_start(ap, types);
4573 r = message_read_ap(m, types, ap);
4579 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4582 assert_return(m, -EINVAL);
4583 assert_return(m->sealed, -EPERM);
4585 /* If types is NULL, read exactly one element */
4587 struct bus_container *c;
4590 if (message_end_of_signature(m))
4593 if (message_end_of_array(m, m->rindex))
4596 c = message_get_container(m);
4598 r = signature_element_length(c->signature + c->index, &l);
4602 types = strndupa(c->signature + c->index, l);
4607 case 0: /* Nothing to drop */
4610 case SD_BUS_TYPE_BYTE:
4611 case SD_BUS_TYPE_BOOLEAN:
4612 case SD_BUS_TYPE_INT16:
4613 case SD_BUS_TYPE_UINT16:
4614 case SD_BUS_TYPE_INT32:
4615 case SD_BUS_TYPE_UINT32:
4616 case SD_BUS_TYPE_INT64:
4617 case SD_BUS_TYPE_UINT64:
4618 case SD_BUS_TYPE_DOUBLE:
4619 case SD_BUS_TYPE_STRING:
4620 case SD_BUS_TYPE_OBJECT_PATH:
4621 case SD_BUS_TYPE_SIGNATURE:
4622 case SD_BUS_TYPE_UNIX_FD:
4624 r = sd_bus_message_read_basic(m, *types, NULL);
4628 r = sd_bus_message_skip(m, types + 1);
4634 case SD_BUS_TYPE_ARRAY: {
4637 r = signature_element_length(types + 1, &k);
4643 memcpy(s, types+1, k);
4646 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4651 r = sd_bus_message_skip(m, s);
4658 r = sd_bus_message_exit_container(m);
4663 r = sd_bus_message_skip(m, types + 1 + k);
4670 case SD_BUS_TYPE_VARIANT: {
4671 const char *contents;
4674 r = sd_bus_message_peek_type(m, &x, &contents);
4678 if (x != SD_BUS_TYPE_VARIANT)
4681 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4685 r = sd_bus_message_skip(m, contents);
4690 r = sd_bus_message_exit_container(m);
4694 r = sd_bus_message_skip(m, types + 1);
4701 case SD_BUS_TYPE_STRUCT_BEGIN:
4702 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4705 r = signature_element_length(types, &k);
4711 memcpy(s, types+1, k-2);
4714 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4718 r = sd_bus_message_skip(m, s);
4722 r = sd_bus_message_exit_container(m);
4727 r = sd_bus_message_skip(m, types + k);
4739 _public_ int sd_bus_message_read_array(
4745 struct bus_container *c;
4751 assert_return(m, -EINVAL);
4752 assert_return(m->sealed, -EPERM);
4753 assert_return(bus_type_is_trivial(type), -EINVAL);
4754 assert_return(ptr, -EINVAL);
4755 assert_return(size, -EINVAL);
4756 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4758 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4762 c = message_get_container(m);
4764 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4765 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4769 sz = c->end - c->begin;
4771 align = bus_type_get_alignment(type);
4775 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4779 /* Zero length array, let's return some aligned
4780 * pointer that is not NULL */
4781 p = (uint8_t*) NULL + align;
4783 r = message_peek_body(m, &m->rindex, align, sz, &p);
4788 r = sd_bus_message_exit_container(m);
4792 *ptr = (const void*) p;
4798 message_quit_container(m);
4802 static int message_peek_fields(
4813 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4816 static int message_peek_field_uint32(
4828 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4831 /* identical for gvariant and dbus1 */
4833 r = message_peek_fields(m, ri, 4, 4, &q);
4838 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4843 static int message_peek_field_uint64(
4855 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4858 /* identical for gvariant and dbus1 */
4860 r = message_peek_fields(m, ri, 8, 8, &q);
4865 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4870 static int message_peek_field_string(
4872 bool (*validate)(const char *p),
4884 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4889 r = message_peek_fields(m, ri, 1, item_size, &q);
4895 r = message_peek_field_uint32(m, ri, 4, &l);
4899 r = message_peek_fields(m, ri, 1, l+1, &q);
4905 if (!validate_nul(q, l))
4911 if (!validate_string(q, l))
4921 static int message_peek_field_signature(
4934 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4939 r = message_peek_fields(m, ri, 1, item_size, &q);
4945 r = message_peek_fields(m, ri, 1, 1, &q);
4950 r = message_peek_fields(m, ri, 1, l+1, &q);
4955 if (!validate_signature(q, l))
4964 static int message_skip_fields(
4967 uint32_t array_size,
4968 const char **signature) {
4970 size_t original_index;
4976 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4978 original_index = *ri;
4984 if (array_size != (uint32_t) -1 &&
4985 array_size <= *ri - original_index)
4992 if (t == SD_BUS_TYPE_STRING) {
4994 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5000 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5002 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5008 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5010 r = message_peek_field_signature(m, ri, 0, NULL);
5016 } else if (bus_type_is_basic(t)) {
5019 align = bus_type_get_alignment(t);
5020 k = bus_type_get_size(t);
5021 assert(align > 0 && k > 0);
5023 r = message_peek_fields(m, ri, align, k, NULL);
5029 } else if (t == SD_BUS_TYPE_ARRAY) {
5031 r = signature_element_length(*signature+1, &l);
5041 strncpy(sig, *signature + 1, l-1);
5044 alignment = bus_type_get_alignment(sig[0]);
5048 r = message_peek_field_uint32(m, ri, 0, &nas);
5051 if (nas > BUS_ARRAY_MAX_SIZE)
5054 r = message_peek_fields(m, ri, alignment, 0, NULL);
5058 r = message_skip_fields(m, ri, nas, (const char**) &s);
5063 (*signature) += 1 + l;
5065 } else if (t == SD_BUS_TYPE_VARIANT) {
5068 r = message_peek_field_signature(m, ri, 0, &s);
5072 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5078 } else if (IN_SET(t, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
5080 r = signature_element_length(*signature, &l);
5087 strncpy(sig, *signature + 1, l-1);
5090 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5101 int bus_message_parse_fields(sd_bus_message *m) {
5104 uint32_t unix_fds = 0;
5105 bool unix_fds_set = false;
5106 void *offsets = NULL;
5107 unsigned n_offsets = 0;
5113 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5116 /* Read the signature from the end of the body variant first */
5117 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5118 if (m->footer_accessible < 1 + sz)
5121 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5123 if (p < (char*) m->footer)
5130 /* We found the beginning of the signature
5131 * string, yay! We require the body to be a
5132 * structure, so verify it and then strip the
5133 * opening/closing brackets. */
5135 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5137 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5138 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5141 c = strndup(p + 1 + 1, l - 2);
5145 free(m->root_container.signature);
5146 m->root_container.signature = c;
5153 /* Calculate the actual user body size, by removing
5154 * the trailing variant signature and struct offset
5156 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5158 /* Pull out the offset table for the fields array */
5159 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5164 ri = m->fields_size - sz;
5165 r = message_peek_fields(m, &ri, 1, sz, &q);
5169 framing = bus_gvariant_read_word_le(q, sz);
5170 if (framing >= m->fields_size - sz)
5172 if ((m->fields_size - framing) % sz != 0)
5176 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5180 n_offsets = (m->fields_size - framing) / sz;
5183 m->user_body_size = m->body_size;
5186 while (ri < m->fields_size) {
5187 _cleanup_free_ char *sig = NULL;
5188 const char *signature;
5189 uint64_t field_type;
5190 size_t item_size = (size_t) -1;
5192 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5201 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5203 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5207 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5211 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5218 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5223 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5228 where = ri = ALIGN_TO(ri, 8);
5229 item_size = end - ri;
5230 r = message_peek_fields(m, &where, 1, item_size, &q);
5234 b = memrchr(q, 0, item_size);
5238 sig = strndup(b+1, item_size - (b+1-(char*) q));
5243 item_size = b - (char*) q;
5245 r = message_peek_field_signature(m, &ri, 0, &signature);
5250 switch (field_type) {
5252 case _BUS_MESSAGE_HEADER_INVALID:
5255 case BUS_MESSAGE_HEADER_PATH:
5260 if (!streq(signature, "o"))
5263 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5266 case BUS_MESSAGE_HEADER_INTERFACE:
5271 if (!streq(signature, "s"))
5274 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5277 case BUS_MESSAGE_HEADER_MEMBER:
5282 if (!streq(signature, "s"))
5285 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5288 case BUS_MESSAGE_HEADER_ERROR_NAME:
5293 if (!streq(signature, "s"))
5296 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5298 m->error._need_free = -1;
5302 case BUS_MESSAGE_HEADER_DESTINATION:
5307 if (!streq(signature, "s"))
5310 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5313 case BUS_MESSAGE_HEADER_SENDER:
5318 if (!streq(signature, "s"))
5321 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5323 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client) {
5324 m->creds.unique_name = (char*) m->sender;
5325 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5331 case BUS_MESSAGE_HEADER_SIGNATURE: {
5335 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5338 if (m->root_container.signature)
5341 if (!streq(signature, "g"))
5344 r = message_peek_field_signature(m, &ri, item_size, &s);
5352 free(m->root_container.signature);
5353 m->root_container.signature = c;
5357 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5359 if (m->reply_cookie != 0)
5362 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5363 /* 64bit on dbus2 */
5365 if (!streq(signature, "t"))
5368 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5372 /* 32bit on dbus1 */
5375 if (!streq(signature, "u"))
5378 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5382 m->reply_cookie = serial;
5385 if (m->reply_cookie == 0)
5390 case BUS_MESSAGE_HEADER_UNIX_FDS:
5394 if (!streq(signature, "u"))
5397 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5401 unix_fds_set = true;
5405 if (!BUS_MESSAGE_IS_GVARIANT(m))
5406 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5415 if (m->n_fds != unix_fds)
5418 switch (m->header->type) {
5420 case SD_BUS_MESSAGE_SIGNAL:
5421 if (!m->path || !m->interface || !m->member)
5424 if (m->reply_cookie != 0)
5429 case SD_BUS_MESSAGE_METHOD_CALL:
5431 if (!m->path || !m->member)
5434 if (m->reply_cookie != 0)
5439 case SD_BUS_MESSAGE_METHOD_RETURN:
5441 if (m->reply_cookie == 0)
5445 case SD_BUS_MESSAGE_METHOD_ERROR:
5447 if (m->reply_cookie == 0 || !m->error.name)
5452 /* Refuse non-local messages that claim they are local */
5453 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5455 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5457 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5460 m->root_container.end = m->user_body_size;
5462 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5463 r = build_struct_offsets(
5465 m->root_container.signature,
5467 &m->root_container.item_size,
5468 &m->root_container.offsets,
5469 &m->root_container.n_offsets);
5474 /* Try to read the error message, but if we can't it's a non-issue */
5475 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5476 (void) sd_bus_message_read(m, "s", &m->error.message);
5481 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5482 assert_return(m, -EINVAL);
5483 assert_return(destination, -EINVAL);
5484 assert_return(!m->sealed, -EPERM);
5485 assert_return(!m->destination, -EEXIST);
5487 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5490 _public_ int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) {
5491 assert_return(m, -EINVAL);
5492 assert_return(sender, -EINVAL);
5493 assert_return(!m->sealed, -EPERM);
5494 assert_return(!m->sender, -EEXIST);
5496 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5499 #if 0 /// UNNEEDED by elogind
5500 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5504 struct bus_body_part *part;
5510 total = BUS_MESSAGE_SIZE(m);
5516 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5517 MESSAGE_FOREACH_PART(part, i, m)
5518 e = mempcpy(e, part->data, part->size);
5520 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5529 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5536 r = sd_bus_message_enter_container(m, 'a', "s");
5540 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5541 r = strv_extend(l, s);
5548 r = sd_bus_message_exit_container(m);
5555 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5559 assert_return(m, -EINVAL);
5560 assert_return(m->sealed, -EPERM);
5561 assert_return(l, -EINVAL);
5563 r = bus_message_read_strv_extend(m, &strv);
5573 static int bus_message_get_arg_skip(
5577 const char **_contents) {
5582 r = sd_bus_message_rewind(m, true);
5587 const char *contents;
5590 r = sd_bus_message_peek_type(m, &type, &contents);
5596 /* Don't match against arguments after the first one we don't understand */
5597 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5598 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5603 *_contents = contents;
5609 r = sd_bus_message_skip(m, NULL);
5616 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5623 r = bus_message_get_arg_skip(m, i, &type, NULL);
5627 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5630 return sd_bus_message_read_basic(m, type, str);
5633 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5634 const char *contents;
5641 r = bus_message_get_arg_skip(m, i, &type, &contents);
5645 if (type != SD_BUS_TYPE_ARRAY)
5647 if (!STR_IN_SET(contents, "s", "o", "g"))
5650 return sd_bus_message_read_strv(m, strv);
5653 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5654 assert_return(m, EINVAL);
5656 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5659 return sd_bus_error_get_errno(&m->error);
5662 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5663 struct bus_container *c;
5665 assert_return(m, NULL);
5667 c = complete ? &m->root_container : message_get_container(m);
5668 return strempty(c->signature);
5671 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5672 assert_return(m, -EINVAL);
5674 return isempty(m->root_container.signature);
5677 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5678 assert_return(m, -EINVAL);
5680 return streq(strempty(m->root_container.signature), strempty(signature));
5683 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5684 bool done_something = false;
5687 assert_return(m, -EINVAL);
5688 assert_return(source, -EINVAL);
5689 assert_return(!m->sealed, -EPERM);
5690 assert_return(source->sealed, -EPERM);
5693 const char *contents;
5708 r = sd_bus_message_peek_type(source, &type, &contents);
5714 done_something = true;
5716 if (bus_type_is_container(type) > 0) {
5718 r = sd_bus_message_enter_container(source, type, contents);
5722 r = sd_bus_message_open_container(m, type, contents);
5726 r = sd_bus_message_copy(m, source, true);
5730 r = sd_bus_message_close_container(m);
5734 r = sd_bus_message_exit_container(source);
5741 r = sd_bus_message_read_basic(source, type, &basic);
5747 if (IN_SET(type, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_STRING))
5748 r = sd_bus_message_append_basic(m, type, basic.string);
5750 r = sd_bus_message_append_basic(m, type, &basic);
5757 return done_something;
5760 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5765 assert_return(m, -EINVAL);
5766 assert_return(m->sealed, -EPERM);
5767 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5768 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5769 assert_return(type || contents, -EINVAL);
5770 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5772 r = sd_bus_message_peek_type(m, &t, &c);
5776 if (type != 0 && type != t)
5779 if (contents && !streq_ptr(contents, c))
5785 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5786 assert_return(m, NULL);
5791 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5792 _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5800 switch ((*m)->header->type) {
5802 case SD_BUS_MESSAGE_SIGNAL:
5803 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5809 case SD_BUS_MESSAGE_METHOD_CALL:
5810 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5816 case SD_BUS_MESSAGE_METHOD_RETURN:
5817 case SD_BUS_MESSAGE_METHOD_ERROR:
5819 r = sd_bus_message_new(bus, &n, (*m)->header->type);
5825 n->reply_cookie = (*m)->reply_cookie;
5827 r = message_append_reply_cookie(n, n->reply_cookie);
5831 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5832 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5836 n->error._need_free = -1;
5845 if ((*m)->destination && !n->destination) {
5846 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5851 if ((*m)->sender && !n->sender) {
5852 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5857 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5859 r = sd_bus_message_copy(n, *m, true);
5863 timeout = (*m)->timeout;
5864 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5865 timeout = BUS_DEFAULT_TIMEOUT;
5867 r = sd_bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5871 sd_bus_message_unref(*m);
5878 #if 0 /// UNNEEDED by elogind
5879 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5883 assert_return(!m->sealed, -EPERM);
5884 assert_return(!m->sender, -EPERM);
5886 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5890 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5891 assert_return(m, -EINVAL);
5892 assert_return(priority, -EINVAL);
5894 *priority = m->priority;
5898 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5899 assert_return(m, -EINVAL);
5900 assert_return(!m->sealed, -EPERM);
5902 m->priority = priority;