2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "alloc-util.h"
27 #include "bus-gvariant.h"
28 #include "bus-internal.h"
29 #include "bus-message.h"
30 #include "bus-signature.h"
35 #include "memfd-util.h"
36 #include "string-util.h"
38 #include "time-util.h"
42 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
44 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
49 if (old_base == new_base)
52 if ((uint8_t*) p < (uint8_t*) old_base)
55 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
58 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
61 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
66 close_and_munmap(part->memfd, part->mmap_begin, part->mapped);
67 else if (part->munmap_this)
68 munmap(part->mmap_begin, part->mapped);
69 else if (part->free_this)
76 static void message_reset_parts(sd_bus_message *m) {
77 struct bus_body_part *part;
82 while (m->n_body_parts > 0) {
83 struct bus_body_part *next = part->next;
84 message_free_part(m, part);
91 m->cached_rindex_part = NULL;
92 m->cached_rindex_part_begin = 0;
95 static void message_reset_containers(sd_bus_message *m) {
100 for (i = 0; i < m->n_containers; i++) {
101 free(m->containers[i].signature);
102 free(m->containers[i].offsets);
105 m->containers = mfree(m->containers);
107 m->n_containers = m->containers_allocated = 0;
108 m->root_container.index = 0;
111 static void message_free(sd_bus_message *m) {
117 message_reset_parts(m);
119 sd_bus_unref(m->bus);
122 close_many(m->fds, m->n_fds);
126 if (m->iovec != m->iovec_fixed)
129 m->destination_ptr = mfree(m->destination_ptr);
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 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
581 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
586 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
587 m->header->endian = BUS_NATIVE_ENDIAN;
588 m->header->type = type;
589 m->header->version = bus->message_version;
590 m->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING);
591 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
592 m->bus = sd_bus_ref(bus);
594 if (bus->allow_interactive_authorization)
595 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
600 _public_ int sd_bus_message_new_signal(
604 const char *interface,
605 const char *member) {
610 assert_return(bus, -ENOTCONN);
611 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
612 assert_return(object_path_is_valid(path), -EINVAL);
613 assert_return(interface_name_is_valid(interface), -EINVAL);
614 assert_return(member_name_is_valid(member), -EINVAL);
615 assert_return(m, -EINVAL);
617 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
621 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
623 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
626 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
629 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
637 sd_bus_message_unref(t);
641 _public_ int sd_bus_message_new_method_call(
644 const char *destination,
646 const char *interface,
647 const char *member) {
652 assert_return(bus, -ENOTCONN);
653 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
654 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
655 assert_return(object_path_is_valid(path), -EINVAL);
656 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
657 assert_return(member_name_is_valid(member), -EINVAL);
658 assert_return(m, -EINVAL);
660 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
664 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
667 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
672 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
678 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
691 static int message_new_reply(
692 sd_bus_message *call,
694 sd_bus_message **m) {
699 assert_return(call, -EINVAL);
700 assert_return(call->sealed, -EPERM);
701 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
702 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
703 assert_return(m, -EINVAL);
705 t = message_new(call->bus, type);
709 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
710 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
711 if (t->reply_cookie == 0)
714 r = message_append_reply_cookie(t, t->reply_cookie);
719 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
724 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
725 t->enforced_reply_signature = call->enforced_reply_signature;
735 _public_ int sd_bus_message_new_method_return(
736 sd_bus_message *call,
737 sd_bus_message **m) {
739 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
742 _public_ int sd_bus_message_new_method_error(
743 sd_bus_message *call,
745 const sd_bus_error *e) {
750 assert_return(sd_bus_error_is_set(e), -EINVAL);
751 assert_return(m, -EINVAL);
753 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
757 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
762 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
767 t->error._need_free = -1;
777 _public_ int sd_bus_message_new_method_errorf(
778 sd_bus_message *call,
784 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
787 assert_return(name, -EINVAL);
788 assert_return(m, -EINVAL);
790 va_start(ap, format);
791 bus_error_setfv(&error, name, format, ap);
794 return sd_bus_message_new_method_error(call, m, &error);
797 _public_ int sd_bus_message_new_method_errno(
798 sd_bus_message *call,
801 const sd_bus_error *p) {
803 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
805 if (sd_bus_error_is_set(p))
806 return sd_bus_message_new_method_error(call, m, p);
808 sd_bus_error_set_errno(&berror, error);
810 return sd_bus_message_new_method_error(call, m, &berror);
813 #if 0 /// UNNEEDED by elogind
814 _public_ int sd_bus_message_new_method_errnof(
815 sd_bus_message *call,
821 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
824 va_start(ap, format);
825 sd_bus_error_set_errnofv(&berror, error, format, ap);
828 return sd_bus_message_new_method_error(call, m, &berror);
832 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
836 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
837 m->creds.well_known_names_local = true;
838 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
841 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
845 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
846 m->creds.well_known_names_driver = true;
847 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
850 int bus_message_new_synthetic_error(
853 const sd_bus_error *e,
854 sd_bus_message **m) {
860 assert(sd_bus_error_is_set(e));
863 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
867 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
868 t->reply_cookie = cookie;
870 r = message_append_reply_cookie(t, t->reply_cookie);
874 if (bus && bus->unique_name) {
875 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
880 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
885 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
890 t->error._need_free = -1;
892 bus_message_set_sender_driver(bus, t);
902 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
907 assert(m->n_ref > 0);
913 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
918 assert(m->n_ref > 0);
928 #if 0 /// UNNEEDED by elogind
929 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
930 assert_return(m, -EINVAL);
931 assert_return(type, -EINVAL);
933 *type = m->header->type;
937 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
940 assert_return(m, -EINVAL);
941 assert_return(cookie, -EINVAL);
943 c = BUS_MESSAGE_COOKIE(m);
947 *cookie = BUS_MESSAGE_COOKIE(m);
951 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
952 assert_return(m, -EINVAL);
953 assert_return(cookie, -EINVAL);
955 if (m->reply_cookie == 0)
958 *cookie = m->reply_cookie;
962 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
963 assert_return(m, -EINVAL);
965 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
966 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
969 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
970 assert_return(m, -EINVAL);
972 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
976 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
977 assert_return(m, -EINVAL);
979 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
980 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
983 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
984 assert_return(m, NULL);
989 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
990 assert_return(m, NULL);
995 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
996 assert_return(m, NULL);
1001 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1002 assert_return(m, NULL);
1004 return m->destination;
1007 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1008 assert_return(m, NULL);
1013 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1014 assert_return(m, NULL);
1016 if (!sd_bus_error_is_set(&m->error))
1022 #if 0 /// UNNEEDED by elogind
1023 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1024 assert_return(m, -EINVAL);
1025 assert_return(usec, -EINVAL);
1027 if (m->monotonic <= 0)
1030 *usec = m->monotonic;
1034 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1035 assert_return(m, -EINVAL);
1036 assert_return(usec, -EINVAL);
1038 if (m->realtime <= 0)
1041 *usec = m->realtime;
1045 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1046 assert_return(m, -EINVAL);
1047 assert_return(seqnum, -EINVAL);
1052 *seqnum = m->seqnum;
1057 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1058 assert_return(m, NULL);
1060 if (m->creds.mask == 0)
1066 _public_ int sd_bus_message_is_signal(
1068 const char *interface,
1069 const char *member) {
1071 assert_return(m, -EINVAL);
1073 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1076 if (interface && (!m->interface || !streq(m->interface, interface)))
1079 if (member && (!m->member || !streq(m->member, member)))
1085 _public_ int sd_bus_message_is_method_call(
1087 const char *interface,
1088 const char *member) {
1090 assert_return(m, -EINVAL);
1092 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1095 if (interface && (!m->interface || !streq(m->interface, interface)))
1098 if (member && (!m->member || !streq(m->member, member)))
1104 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1105 assert_return(m, -EINVAL);
1107 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1110 if (name && (!m->error.name || !streq(m->error.name, name)))
1116 #if 0 /// UNNEEDED by elogind
1117 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1118 assert_return(m, -EINVAL);
1119 assert_return(!m->sealed, -EPERM);
1120 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1122 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
1127 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1128 assert_return(m, -EINVAL);
1129 assert_return(!m->sealed, -EPERM);
1131 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
1136 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1137 assert_return(m, -EINVAL);
1138 assert_return(!m->sealed, -EPERM);
1140 SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
1146 static struct bus_container *message_get_container(sd_bus_message *m) {
1149 if (m->n_containers == 0)
1150 return &m->root_container;
1152 assert(m->containers);
1153 return m->containers + m->n_containers - 1;
1156 struct bus_body_part *message_append_part(sd_bus_message *m) {
1157 struct bus_body_part *part;
1164 if (m->n_body_parts <= 0) {
1168 assert(m->body_end);
1170 part = new0(struct bus_body_part, 1);
1176 m->body_end->next = part;
1186 static void part_zero(struct bus_body_part *part, size_t sz) {
1191 /* All other fields can be left in their defaults */
1192 assert(!part->data);
1193 assert(part->memfd < 0);
1196 part->is_zero = true;
1197 part->sealed = true;
1200 static int part_make_space(
1201 struct sd_bus_message *m,
1202 struct bus_body_part *part,
1210 assert(!part->sealed);
1215 if (part->allocated == 0 || sz > part->allocated) {
1216 size_t new_allocated;
1218 new_allocated = sz > 0 ? 2 * sz : 64;
1219 n = realloc(part->data, new_allocated);
1226 part->allocated = new_allocated;
1227 part->free_this = true;
1231 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1237 static int message_add_offset(sd_bus_message *m, size_t offset) {
1238 struct bus_container *c;
1241 assert(BUS_MESSAGE_IS_GVARIANT(m));
1243 /* Add offset to current container, unless this is the first
1244 * item in it, which will have the 0 offset, which we can
1246 c = message_get_container(m);
1248 if (!c->need_offsets)
1251 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1254 c->offsets[c->n_offsets++] = offset;
1258 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1259 struct bus_container *c;
1266 /* Update counters */
1267 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1270 *c->array_size += expand;
1274 static void *message_extend_body(
1279 bool force_inline) {
1281 size_t start_body, end_body, padding, added;
1292 start_body = ALIGN_TO((size_t) m->body_size, align);
1293 end_body = start_body + sz;
1295 padding = start_body - m->body_size;
1296 added = padding + sz;
1298 /* Check for 32bit overflows */
1299 if (end_body > (size_t) ((uint32_t) -1) ||
1300 end_body < start_body) {
1306 struct bus_body_part *part = NULL;
1310 m->n_body_parts <= 0 ||
1311 m->body_end->sealed ||
1312 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1313 (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 */
1317 part = message_append_part(m);
1321 part_zero(part, padding);
1324 part = message_append_part(m);
1328 r = part_make_space(m, part, sz, &p);
1332 struct bus_container *c;
1334 size_t os, start_part, end_part;
1340 start_part = ALIGN_TO(part->size, align);
1341 end_part = start_part + sz;
1343 r = part_make_space(m, part, end_part, &p);
1348 memzero(p, padding);
1349 p = (uint8_t*) p + padding;
1352 /* Readjust pointers */
1353 for (c = m->containers; c < m->containers + m->n_containers; c++)
1354 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1356 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1359 /* Return something that is not NULL and is aligned */
1360 p = (uint8_t *) NULL + align;
1362 m->body_size = end_body;
1363 message_extend_containers(m, added);
1366 r = message_add_offset(m, end_body);
1376 static int message_push_fd(sd_bus_message *m, int fd) {
1387 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1391 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1399 m->fds[m->n_fds] = copy;
1405 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1406 _cleanup_close_ int fd = -1;
1407 struct bus_container *c;
1411 assert_return(m, -EINVAL);
1412 assert_return(!m->sealed, -EPERM);
1413 assert_return(bus_type_is_basic(type), -EINVAL);
1414 assert_return(!m->poisoned, -ESTALE);
1416 c = message_get_container(m);
1418 if (c->signature && c->signature[c->index]) {
1419 /* Container signature is already set */
1421 if (c->signature[c->index] != type)
1426 /* Maybe we can append to the signature? But only if this is the top-level container */
1427 if (c->enclosing != 0)
1430 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1437 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1443 case SD_BUS_TYPE_SIGNATURE:
1444 case SD_BUS_TYPE_STRING:
1447 /* Fall through... */
1448 case SD_BUS_TYPE_OBJECT_PATH:
1456 case SD_BUS_TYPE_BOOLEAN:
1458 u8 = p && *(int*) p;
1464 case SD_BUS_TYPE_UNIX_FD:
1469 fd = message_push_fd(m, *(int*) p);
1480 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1481 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1488 a = message_extend_body(m, align, sz, true, false);
1495 *stored = (const uint8_t*) a;
1502 case SD_BUS_TYPE_STRING:
1503 /* To make things easy we'll serialize a NULL string
1504 * into the empty string */
1507 /* Fall through... */
1508 case SD_BUS_TYPE_OBJECT_PATH:
1514 sz = 4 + strlen(p) + 1;
1517 case SD_BUS_TYPE_SIGNATURE:
1522 sz = 1 + strlen(p) + 1;
1525 case SD_BUS_TYPE_BOOLEAN:
1527 u32 = p && *(int*) p;
1533 case SD_BUS_TYPE_UNIX_FD:
1538 fd = message_push_fd(m, *(int*) p);
1549 align = bus_type_get_alignment(type);
1550 sz = bus_type_get_size(type);
1557 a = message_extend_body(m, align, sz, false, false);
1561 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
1562 *(uint32_t*) a = sz - 5;
1563 memcpy((uint8_t*) a + 4, p, sz - 4);
1566 *stored = (const uint8_t*) a + 4;
1568 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1569 *(uint8_t*) a = sz - 2;
1570 memcpy((uint8_t*) a + 1, p, sz - 1);
1573 *stored = (const uint8_t*) a + 1;
1582 if (type == SD_BUS_TYPE_UNIX_FD)
1585 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1592 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1593 return message_append_basic(m, type, p, NULL);
1596 #if 0 /// UNNEEDED by elogind
1597 _public_ int sd_bus_message_append_string_space(
1602 struct bus_container *c;
1605 assert_return(m, -EINVAL);
1606 assert_return(s, -EINVAL);
1607 assert_return(!m->sealed, -EPERM);
1608 assert_return(!m->poisoned, -ESTALE);
1610 c = message_get_container(m);
1612 if (c->signature && c->signature[c->index]) {
1613 /* Container signature is already set */
1615 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1620 /* Maybe we can append to the signature? But only if this is the top-level container */
1621 if (c->enclosing != 0)
1624 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1631 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1632 a = message_extend_body(m, 1, size + 1, true, false);
1638 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1642 *(uint32_t*) a = size;
1648 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1654 _public_ int sd_bus_message_append_string_iovec(
1656 const struct iovec *iov,
1664 assert_return(m, -EINVAL);
1665 assert_return(!m->sealed, -EPERM);
1666 assert_return(iov || n == 0, -EINVAL);
1667 assert_return(!m->poisoned, -ESTALE);
1669 size = IOVEC_TOTAL_SIZE(iov, n);
1671 r = sd_bus_message_append_string_space(m, size, &p);
1675 for (i = 0; i < n; i++) {
1677 if (iov[i].iov_base)
1678 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1680 memset(p, ' ', iov[i].iov_len);
1682 p += iov[i].iov_len;
1689 static int bus_message_open_array(
1691 struct bus_container *c,
1692 const char *contents,
1693 uint32_t **array_size,
1695 bool *need_offsets) {
1705 assert(need_offsets);
1707 if (!signature_is_single(contents, true))
1710 if (c->signature && c->signature[c->index]) {
1712 /* Verify the existing signature */
1714 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1717 if (!startswith(c->signature + c->index + 1, contents))
1720 nindex = c->index + 1 + strlen(contents);
1724 if (c->enclosing != 0)
1727 /* Extend the existing signature */
1729 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1735 nindex = e - c->signature;
1738 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1739 alignment = bus_gvariant_get_alignment(contents);
1743 /* Add alignment padding and add to offset list */
1744 if (!message_extend_body(m, alignment, 0, false, false))
1747 r = bus_gvariant_is_fixed_size(contents);
1751 *begin = m->body_size;
1752 *need_offsets = r == 0;
1756 struct bus_body_part *o;
1758 alignment = bus_type_get_alignment(contents[0]);
1762 a = message_extend_body(m, 4, 4, false, false);
1767 op = m->body_end->data;
1768 os = m->body_end->size;
1770 /* Add alignment between size and first element */
1771 if (!message_extend_body(m, alignment, 0, false, false))
1774 /* location of array size might have changed so let's readjust a */
1775 if (o == m->body_end)
1776 a = adjust_pointer(a, op, os, m->body_end->data);
1782 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1788 static int bus_message_open_variant(
1790 struct bus_container *c,
1791 const char *contents) {
1797 if (!signature_is_single(contents, false))
1800 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1803 if (c->signature && c->signature[c->index]) {
1805 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1811 if (c->enclosing != 0)
1814 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1821 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1822 /* Variants are always aligned to 8 */
1824 if (!message_extend_body(m, 8, 0, false, false))
1831 l = strlen(contents);
1832 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1837 memcpy((uint8_t*) a + 1, contents, l + 1);
1840 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1846 static int bus_message_open_struct(
1848 struct bus_container *c,
1849 const char *contents,
1851 bool *need_offsets) {
1860 assert(need_offsets);
1862 if (!signature_is_valid(contents, false))
1865 if (c->signature && c->signature[c->index]) {
1868 l = strlen(contents);
1870 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1871 !startswith(c->signature + c->index + 1, contents) ||
1872 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1875 nindex = c->index + 1 + l + 1;
1879 if (c->enclosing != 0)
1882 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1888 nindex = e - c->signature;
1891 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1894 alignment = bus_gvariant_get_alignment(contents);
1898 if (!message_extend_body(m, alignment, 0, false, false))
1901 r = bus_gvariant_is_fixed_size(contents);
1905 *begin = m->body_size;
1906 *need_offsets = r == 0;
1908 /* Align contents to 8 byte boundary */
1909 if (!message_extend_body(m, 8, 0, false, false))
1913 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1919 static int bus_message_open_dict_entry(
1921 struct bus_container *c,
1922 const char *contents,
1924 bool *need_offsets) {
1932 assert(need_offsets);
1934 if (!signature_is_pair(contents))
1937 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1940 if (c->signature && c->signature[c->index]) {
1943 l = strlen(contents);
1945 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1946 !startswith(c->signature + c->index + 1, contents) ||
1947 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1952 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1955 alignment = bus_gvariant_get_alignment(contents);
1959 if (!message_extend_body(m, alignment, 0, false, false))
1962 r = bus_gvariant_is_fixed_size(contents);
1966 *begin = m->body_size;
1967 *need_offsets = r == 0;
1969 /* Align contents to 8 byte boundary */
1970 if (!message_extend_body(m, 8, 0, false, false))
1977 _public_ int sd_bus_message_open_container(
1980 const char *contents) {
1982 struct bus_container *c, *w;
1983 uint32_t *array_size = NULL;
1985 size_t before, begin = 0;
1986 bool need_offsets = false;
1989 assert_return(m, -EINVAL);
1990 assert_return(!m->sealed, -EPERM);
1991 assert_return(contents, -EINVAL);
1992 assert_return(!m->poisoned, -ESTALE);
1994 /* Make sure we have space for one more container */
1995 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2000 c = message_get_container(m);
2002 signature = strdup(contents);
2008 /* Save old index in the parent container, in case we have to
2009 * abort this container */
2010 c->saved_index = c->index;
2011 before = m->body_size;
2013 if (type == SD_BUS_TYPE_ARRAY)
2014 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2015 else if (type == SD_BUS_TYPE_VARIANT)
2016 r = bus_message_open_variant(m, c, contents);
2017 else if (type == SD_BUS_TYPE_STRUCT)
2018 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2019 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2020 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2029 /* OK, let's fill it in */
2030 w = m->containers + m->n_containers++;
2031 w->enclosing = type;
2032 w->signature = signature;
2034 w->array_size = array_size;
2037 w->n_offsets = w->offsets_allocated = 0;
2039 w->need_offsets = need_offsets;
2044 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2049 if (!BUS_MESSAGE_IS_GVARIANT(m))
2052 if (c->need_offsets) {
2053 size_t payload, sz, i;
2056 /* Variable-width arrays */
2058 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2059 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2061 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2065 for (i = 0; i < c->n_offsets; i++)
2066 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2070 /* Fixed-width or empty arrays */
2072 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2080 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2086 assert(c->signature);
2088 if (!BUS_MESSAGE_IS_GVARIANT(m))
2091 l = strlen(c->signature);
2093 a = message_extend_body(m, 1, 1 + l, true, false);
2098 memcpy(a+1, c->signature, l);
2103 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2104 bool fixed_size = true;
2105 size_t n_variable = 0;
2114 if (!BUS_MESSAGE_IS_GVARIANT(m))
2117 p = strempty(c->signature);
2121 r = signature_element_length(p, &n);
2130 r = bus_gvariant_is_fixed_size(t);
2135 assert(!c->need_offsets || i <= c->n_offsets);
2137 /* We need to add an offset for each item that has a
2138 * variable size and that is not the last one in the
2142 if (r == 0 && p[n] != 0)
2149 assert(!c->need_offsets || i == c->n_offsets);
2150 assert(c->need_offsets || n_variable == 0);
2152 if (isempty(c->signature)) {
2153 /* The unary type is encoded as fixed 1 byte padding */
2154 a = message_extend_body(m, 1, 1, add_offset, false);
2159 } else if (n_variable <= 0) {
2162 /* Structures with fixed-size members only have to be
2163 * fixed-size themselves. But gvariant requires all fixed-size
2164 * elements to be sized a multiple of their alignment. Hence,
2165 * we must *always* add final padding after the last member so
2166 * the overall size of the structure is properly aligned. */
2168 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2170 assert(alignment > 0);
2172 a = message_extend_body(m, alignment, 0, add_offset, false);
2179 assert(c->offsets[c->n_offsets-1] == m->body_size);
2181 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2183 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2187 p = strempty(c->signature);
2188 for (i = 0, j = 0; i < c->n_offsets; i++) {
2192 r = signature_element_length(p, &n);
2203 r = bus_gvariant_is_fixed_size(t);
2206 if (r > 0 || p[0] == 0)
2210 k = n_variable - 1 - j;
2212 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2221 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2222 struct bus_container *c;
2225 assert_return(m, -EINVAL);
2226 assert_return(!m->sealed, -EPERM);
2227 assert_return(m->n_containers > 0, -EINVAL);
2228 assert_return(!m->poisoned, -ESTALE);
2230 c = message_get_container(m);
2232 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2233 if (c->signature && c->signature[c->index] != 0)
2238 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2239 r = bus_message_close_array(m, c);
2240 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2241 r = bus_message_close_variant(m, c);
2242 else if (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY))
2243 r = bus_message_close_struct(m, c, true);
2245 assert_not_reached("Unknown container type");
2259 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2266 stack[*i].types = types;
2267 stack[*i].n_struct = n_struct;
2268 stack[*i].n_array = n_array;
2274 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2285 *types = stack[*i].types;
2286 *n_struct = stack[*i].n_struct;
2287 *n_array = stack[*i].n_array;
2292 _public_ int sd_bus_message_appendv(
2297 unsigned n_array, n_struct;
2298 TypeStack stack[BUS_CONTAINER_DEPTH];
2299 unsigned stack_ptr = 0;
2302 assert_return(m, -EINVAL);
2303 assert_return(types, -EINVAL);
2304 assert_return(!m->sealed, -EPERM);
2305 assert_return(!m->poisoned, -ESTALE);
2307 n_array = (unsigned) -1;
2308 n_struct = strlen(types);
2313 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2314 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2320 r = sd_bus_message_close_container(m);
2328 if (n_array != (unsigned) -1)
2337 case SD_BUS_TYPE_BYTE: {
2340 x = (uint8_t) va_arg(ap, int);
2341 r = sd_bus_message_append_basic(m, *t, &x);
2345 case SD_BUS_TYPE_BOOLEAN:
2346 case SD_BUS_TYPE_INT32:
2347 case SD_BUS_TYPE_UINT32:
2348 case SD_BUS_TYPE_UNIX_FD: {
2351 /* We assume a boolean is the same as int32_t */
2352 assert_cc(sizeof(int32_t) == sizeof(int));
2354 x = va_arg(ap, uint32_t);
2355 r = sd_bus_message_append_basic(m, *t, &x);
2359 case SD_BUS_TYPE_INT16:
2360 case SD_BUS_TYPE_UINT16: {
2363 x = (uint16_t) va_arg(ap, int);
2364 r = sd_bus_message_append_basic(m, *t, &x);
2368 case SD_BUS_TYPE_INT64:
2369 case SD_BUS_TYPE_UINT64: {
2372 x = va_arg(ap, uint64_t);
2373 r = sd_bus_message_append_basic(m, *t, &x);
2377 case SD_BUS_TYPE_DOUBLE: {
2380 x = va_arg(ap, double);
2381 r = sd_bus_message_append_basic(m, *t, &x);
2385 case SD_BUS_TYPE_STRING:
2386 case SD_BUS_TYPE_OBJECT_PATH:
2387 case SD_BUS_TYPE_SIGNATURE: {
2390 x = va_arg(ap, const char*);
2391 r = sd_bus_message_append_basic(m, *t, x);
2395 case SD_BUS_TYPE_ARRAY: {
2398 r = signature_element_length(t + 1, &k);
2404 memcpy(s, t + 1, k);
2407 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2412 if (n_array == (unsigned) -1) {
2417 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2423 n_array = va_arg(ap, unsigned);
2428 case SD_BUS_TYPE_VARIANT: {
2431 s = va_arg(ap, const char*);
2435 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2439 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2444 n_struct = strlen(s);
2445 n_array = (unsigned) -1;
2450 case SD_BUS_TYPE_STRUCT_BEGIN:
2451 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2454 r = signature_element_length(t, &k);
2461 memcpy(s, t + 1, k - 2);
2464 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2469 if (n_array == (unsigned) -1) {
2474 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2480 n_array = (unsigned) -1;
2496 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2500 assert_return(m, -EINVAL);
2501 assert_return(types, -EINVAL);
2502 assert_return(!m->sealed, -EPERM);
2503 assert_return(!m->poisoned, -ESTALE);
2505 va_start(ap, types);
2506 r = sd_bus_message_appendv(m, types, ap);
2512 _public_ int sd_bus_message_append_array_space(
2522 assert_return(m, -EINVAL);
2523 assert_return(!m->sealed, -EPERM);
2524 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2525 assert_return(ptr || size == 0, -EINVAL);
2526 assert_return(!m->poisoned, -ESTALE);
2528 /* alignment and size of the trivial types (except bool) is
2529 * identical for gvariant and dbus1 marshalling */
2530 align = bus_type_get_alignment(type);
2531 sz = bus_type_get_size(type);
2533 assert_se(align > 0);
2539 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2543 a = message_extend_body(m, align, size, false, false);
2547 r = sd_bus_message_close_container(m);
2555 #if 0 /// UNNEEDED by elogind
2556 _public_ int sd_bus_message_append_array(
2564 assert_return(m, -EINVAL);
2565 assert_return(!m->sealed, -EPERM);
2566 assert_return(bus_type_is_trivial(type), -EINVAL);
2567 assert_return(ptr || size == 0, -EINVAL);
2568 assert_return(!m->poisoned, -ESTALE);
2570 r = sd_bus_message_append_array_space(m, type, size, &p);
2574 memcpy_safe(p, ptr, size);
2579 _public_ int sd_bus_message_append_array_iovec(
2582 const struct iovec *iov,
2590 assert_return(m, -EINVAL);
2591 assert_return(!m->sealed, -EPERM);
2592 assert_return(bus_type_is_trivial(type), -EINVAL);
2593 assert_return(iov || n == 0, -EINVAL);
2594 assert_return(!m->poisoned, -ESTALE);
2596 size = IOVEC_TOTAL_SIZE(iov, n);
2598 r = sd_bus_message_append_array_space(m, type, size, &p);
2602 for (i = 0; i < n; i++) {
2604 if (iov[i].iov_base)
2605 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2607 memzero(p, iov[i].iov_len);
2609 p = (uint8_t*) p + iov[i].iov_len;
2615 _public_ int sd_bus_message_append_array_memfd(
2622 _cleanup_close_ int copy_fd = -1;
2623 struct bus_body_part *part;
2629 assert_return(m, -EINVAL);
2630 assert_return(memfd >= 0, -EBADF);
2631 assert_return(bus_type_is_trivial(type), -EINVAL);
2632 assert_return(size > 0, -EINVAL);
2633 assert_return(!m->sealed, -EPERM);
2634 assert_return(!m->poisoned, -ESTALE);
2636 r = memfd_set_sealed(memfd);
2640 copy_fd = dup(memfd);
2644 r = memfd_get_size(memfd, &real_size);
2648 if (offset == 0 && size == (uint64_t) -1)
2650 else if (offset + size > real_size)
2653 align = bus_type_get_alignment(type);
2654 sz = bus_type_get_size(type);
2656 assert_se(align > 0);
2659 if (offset % align != 0)
2665 if (size > (uint64_t) (uint32_t) -1)
2668 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2672 a = message_extend_body(m, align, 0, false, false);
2676 part = message_append_part(m);
2680 part->memfd = copy_fd;
2681 part->memfd_offset = offset;
2682 part->sealed = true;
2686 m->body_size += size;
2687 message_extend_containers(m, size);
2689 return sd_bus_message_close_container(m);
2692 _public_ int sd_bus_message_append_string_memfd(
2698 _cleanup_close_ int copy_fd = -1;
2699 struct bus_body_part *part;
2700 struct bus_container *c;
2705 assert_return(m, -EINVAL);
2706 assert_return(memfd >= 0, -EBADF);
2707 assert_return(size > 0, -EINVAL);
2708 assert_return(!m->sealed, -EPERM);
2709 assert_return(!m->poisoned, -ESTALE);
2711 r = memfd_set_sealed(memfd);
2715 copy_fd = dup(memfd);
2719 r = memfd_get_size(memfd, &real_size);
2723 if (offset == 0 && size == (uint64_t) -1)
2725 else if (offset + size > real_size)
2728 /* We require this to be NUL terminated */
2732 if (size > (uint64_t) (uint32_t) -1)
2735 c = message_get_container(m);
2736 if (c->signature && c->signature[c->index]) {
2737 /* Container signature is already set */
2739 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2744 /* Maybe we can append to the signature? But only if this is the top-level container */
2745 if (c->enclosing != 0)
2748 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2755 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2756 a = message_extend_body(m, 4, 4, false, false);
2760 *(uint32_t*) a = size - 1;
2763 part = message_append_part(m);
2767 part->memfd = copy_fd;
2768 part->memfd_offset = offset;
2769 part->sealed = true;
2773 m->body_size += size;
2774 message_extend_containers(m, size);
2776 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2777 r = message_add_offset(m, m->body_size);
2784 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2791 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2795 assert_return(m, -EINVAL);
2796 assert_return(!m->sealed, -EPERM);
2797 assert_return(!m->poisoned, -ESTALE);
2799 r = sd_bus_message_open_container(m, 'a', "s");
2803 STRV_FOREACH(i, l) {
2804 r = sd_bus_message_append_basic(m, 's', *i);
2809 return sd_bus_message_close_container(m);
2812 static int bus_message_close_header(sd_bus_message *m) {
2816 /* The actual user data is finished now, we just complete the
2817 variant and struct now (at least on gvariant). Remember
2818 this position, so that during parsing we know where to
2819 put the outer container end. */
2820 m->user_body_size = m->body_size;
2822 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2823 const char *signature;
2827 /* Add offset table to end of fields array */
2828 if (m->n_header_offsets >= 1) {
2832 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2834 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2835 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2839 for (i = 0; i < m->n_header_offsets; i++)
2840 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2843 /* Add gvariant NUL byte plus signature to the end of
2844 * the body, followed by the final offset pointing to
2845 * the end of the fields array */
2847 signature = strempty(m->root_container.signature);
2848 l = strlen(signature);
2850 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2851 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2856 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2857 memcpy((uint8_t*) d + 2, signature, l);
2858 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2860 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2863 m->footer_accessible = 1 + l + 2 + sz;
2865 m->header->dbus1.fields_size = m->fields_size;
2866 m->header->dbus1.body_size = m->body_size;
2872 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2873 struct bus_body_part *part;
2883 if (m->n_containers > 0)
2889 if (cookie > 0xffffffffULL &&
2890 !BUS_MESSAGE_IS_GVARIANT(m))
2893 /* In vtables the return signature of method calls is listed,
2894 * let's check if they match if this is a response */
2895 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2896 m->enforced_reply_signature &&
2897 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2900 /* If gvariant marshalling is used we need to close the body structure */
2901 r = bus_message_close_struct(m, &m->root_container, false);
2905 /* If there's a non-trivial signature set, then add it in
2906 * here, but only on dbus1 */
2907 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2908 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2914 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2919 r = bus_message_close_header(m);
2923 if (BUS_MESSAGE_IS_GVARIANT(m))
2924 m->header->dbus2.cookie = cookie;
2926 m->header->dbus1.serial = (uint32_t) cookie;
2928 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2930 /* Add padding at the end of the fields part, since we know
2931 * the body needs to start at an 8 byte alignment. We made
2932 * sure we allocated enough space for this, so all we need to
2933 * do here is to zero it out. */
2934 a = ALIGN8(m->fields_size) - m->fields_size;
2936 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2938 /* If this is something we can send as memfd, then let's seal
2939 the memfd now. Note that we can send memfds as payload only
2940 for directed messages, and not for broadcasts. */
2941 if (m->destination && m->bus->use_memfd) {
2942 MESSAGE_FOREACH_PART(part, i, m)
2943 if (part->memfd >= 0 &&
2945 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2946 part != m->body_end) { /* The last part may never be sent as memfd */
2949 /* Try to seal it if that makes
2950 * sense. First, unmap our own map to
2951 * make sure we don't keep it busy. */
2952 bus_body_part_unmap(part);
2954 /* Then, sync up real memfd size */
2956 r = memfd_set_size(part->memfd, sz);
2960 /* Finally, try to seal */
2961 if (memfd_set_sealed(part->memfd) >= 0)
2962 part->sealed = true;
2966 m->root_container.end = m->user_body_size;
2967 m->root_container.index = 0;
2968 m->root_container.offset_index = 0;
2969 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2976 int bus_body_part_map(struct bus_body_part *part) {
2985 if (part->size <= 0)
2988 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2989 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2990 static const uint8_t zeroes[7] = { };
2991 part->data = (void*) zeroes;
2995 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
2996 psz = PAGE_ALIGN(part->size + shift);
2998 if (part->memfd >= 0)
2999 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3000 else if (part->is_zero)
3001 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3005 if (p == MAP_FAILED)
3009 part->mmap_begin = p;
3010 part->data = (uint8_t*) p + shift;
3011 part->munmap_this = true;
3016 void bus_body_part_unmap(struct bus_body_part *part) {
3020 if (part->memfd < 0)
3023 if (!part->mmap_begin)
3026 if (!part->munmap_this)
3029 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3031 part->mmap_begin = NULL;
3034 part->munmap_this = false;
3039 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3040 size_t k, start, end;
3045 start = ALIGN_TO((size_t) *rindex, align);
3046 end = start + nbytes;
3051 /* Verify that padding is 0 */
3052 for (k = *rindex; k < start; k++)
3053 if (((const uint8_t*) p)[k] != 0)
3057 *r = (uint8_t*) p + start;
3064 static bool message_end_of_signature(sd_bus_message *m) {
3065 struct bus_container *c;
3069 c = message_get_container(m);
3070 return !c->signature || c->signature[c->index] == 0;
3073 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3074 struct bus_container *c;
3078 c = message_get_container(m);
3079 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3082 if (BUS_MESSAGE_IS_GVARIANT(m))
3083 return index >= c->end;
3085 assert(c->array_size);
3086 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3090 #if 0 /// UNNEEDED by elogind
3091 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3092 assert_return(m, -EINVAL);
3093 assert_return(m->sealed, -EPERM);
3095 if (complete && m->n_containers > 0)
3098 if (message_end_of_signature(m))
3101 if (message_end_of_array(m, m->rindex))
3108 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3109 struct bus_body_part *part;
3115 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3116 part = m->cached_rindex_part;
3117 begin = m->cached_rindex_part_begin;
3127 if (index + sz <= begin + part->size) {
3129 r = bus_body_part_map(part);
3134 *p = (uint8_t*) part->data + index - begin;
3136 m->cached_rindex_part = part;
3137 m->cached_rindex_part_begin = begin;
3142 begin += part->size;
3149 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3156 if (!BUS_MESSAGE_IS_GVARIANT(m))
3159 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3162 sz = bus_gvariant_get_size(c->signature);
3166 if (c->offset_index+1 >= c->n_offsets)
3169 /* Variable-size array */
3171 alignment = bus_gvariant_get_alignment(c->signature);
3172 assert(alignment > 0);
3174 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3175 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3178 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3181 /* Fixed-size array */
3182 *rindex = c->begin + (c->offset_index+1) * sz;
3188 } else if (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
3193 if (c->offset_index+1 >= c->n_offsets)
3196 r = signature_element_length(c->signature + c->index, &n);
3200 r = signature_element_length(c->signature + c->index + n, &j);
3205 memcpy(t, c->signature + c->index + n, j);
3208 alignment = bus_gvariant_get_alignment(t);
3211 assert(alignment > 0);
3213 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3214 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3218 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3221 assert_not_reached("Unknown container type");
3226 /* Reached the end */
3233 static int message_peek_body(
3240 size_t k, start, end, padding;
3241 struct bus_body_part *part;
3248 start = ALIGN_TO((size_t) *rindex, align);
3249 padding = start - *rindex;
3250 end = start + nbytes;
3252 if (end > m->user_body_size)
3255 part = find_part(m, *rindex, padding, (void**) &q);
3260 /* Verify padding */
3261 for (k = 0; k < padding; k++)
3266 part = find_part(m, start, nbytes, (void**) &q);
3267 if (!part || (nbytes > 0 && !q))
3278 static bool validate_nul(const char *s, size_t l) {
3280 /* Check for NUL chars in the string */
3281 if (memchr(s, 0, l))
3284 /* Check for NUL termination */
3291 static bool validate_string(const char *s, size_t l) {
3293 if (!validate_nul(s, l))
3296 /* Check if valid UTF8 */
3297 if (!utf8_is_valid(s))
3303 static bool validate_signature(const char *s, size_t l) {
3305 if (!validate_nul(s, l))
3308 /* Check if valid signature */
3309 if (!signature_is_valid(s, true))
3315 static bool validate_object_path(const char *s, size_t l) {
3317 if (!validate_nul(s, l))
3320 if (!object_path_is_valid(s))
3326 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3327 struct bus_container *c;
3332 assert_return(m, -EINVAL);
3333 assert_return(m->sealed, -EPERM);
3334 assert_return(bus_type_is_basic(type), -EINVAL);
3336 if (message_end_of_signature(m))
3339 if (message_end_of_array(m, m->rindex))
3342 c = message_get_container(m);
3343 if (c->signature[c->index] != type)
3348 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3350 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3353 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3357 if (type == SD_BUS_TYPE_STRING)
3358 ok = validate_string(q, c->item_size-1);
3359 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3360 ok = validate_object_path(q, c->item_size-1);
3362 ok = validate_signature(q, c->item_size-1);
3368 *(const char**) p = q;
3372 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3374 if ((size_t) sz != c->item_size)
3377 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3380 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3386 case SD_BUS_TYPE_BYTE:
3388 *(uint8_t*) p = *(uint8_t*) q;
3391 case SD_BUS_TYPE_BOOLEAN:
3393 *(int*) p = !!*(uint8_t*) q;
3396 case SD_BUS_TYPE_INT16:
3397 case SD_BUS_TYPE_UINT16:
3399 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3402 case SD_BUS_TYPE_INT32:
3403 case SD_BUS_TYPE_UINT32:
3405 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3408 case SD_BUS_TYPE_INT64:
3409 case SD_BUS_TYPE_UINT64:
3410 case SD_BUS_TYPE_DOUBLE:
3412 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3415 case SD_BUS_TYPE_UNIX_FD: {
3418 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3423 *(int*) p = m->fds[j];
3429 assert_not_reached("unexpected type");
3433 r = container_next_item(m, c, &rindex);
3438 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3442 r = message_peek_body(m, &rindex, 4, 4, &q);
3446 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3447 r = message_peek_body(m, &rindex, 1, l+1, &q);
3451 if (type == SD_BUS_TYPE_OBJECT_PATH)
3452 ok = validate_object_path(q, l);
3454 ok = validate_string(q, l);
3459 *(const char**) p = q;
3461 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3464 r = message_peek_body(m, &rindex, 1, 1, &q);
3469 r = message_peek_body(m, &rindex, 1, l+1, &q);
3473 if (!validate_signature(q, l))
3477 *(const char**) p = q;
3482 align = bus_type_get_alignment(type);
3485 sz = bus_type_get_size(type);
3488 r = message_peek_body(m, &rindex, align, sz, &q);
3494 case SD_BUS_TYPE_BYTE:
3496 *(uint8_t*) p = *(uint8_t*) q;
3499 case SD_BUS_TYPE_BOOLEAN:
3501 *(int*) p = !!*(uint32_t*) q;
3504 case SD_BUS_TYPE_INT16:
3505 case SD_BUS_TYPE_UINT16:
3507 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3510 case SD_BUS_TYPE_INT32:
3511 case SD_BUS_TYPE_UINT32:
3513 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3516 case SD_BUS_TYPE_INT64:
3517 case SD_BUS_TYPE_UINT64:
3518 case SD_BUS_TYPE_DOUBLE:
3520 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3523 case SD_BUS_TYPE_UNIX_FD: {
3526 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3531 *(int*) p = m->fds[j];
3536 assert_not_reached("Unknown basic type...");
3543 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3549 static int bus_message_enter_array(
3551 struct bus_container *c,
3552 const char *contents,
3553 uint32_t **array_size,
3556 size_t *n_offsets) {
3570 if (!signature_is_single(contents, true))
3573 if (!c->signature || c->signature[c->index] == 0)
3576 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3579 if (!startswith(c->signature + c->index + 1, contents))
3584 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3587 r = message_peek_body(m, &rindex, 4, 4, &q);
3591 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3594 alignment = bus_type_get_alignment(contents[0]);
3598 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3602 *array_size = (uint32_t*) q;
3604 } else if (c->item_size <= 0) {
3606 /* gvariant: empty array */
3611 } else if (bus_gvariant_is_fixed_size(contents)) {
3613 /* gvariant: fixed length array */
3614 *item_size = bus_gvariant_get_size(contents);
3619 size_t where, p = 0, framing, sz;
3622 /* gvariant: variable length array */
3623 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3625 where = rindex + c->item_size - sz;
3626 r = message_peek_body(m, &where, 1, sz, &q);
3630 framing = bus_gvariant_read_word_le(q, sz);
3631 if (framing > c->item_size - sz)
3633 if ((c->item_size - framing) % sz != 0)
3636 *n_offsets = (c->item_size - framing) / sz;
3638 where = rindex + framing;
3639 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3643 *offsets = new(size_t, *n_offsets);
3647 for (i = 0; i < *n_offsets; i++) {
3650 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3651 if (x > c->item_size - sz)
3656 (*offsets)[i] = rindex + x;
3660 *item_size = (*offsets)[0] - rindex;
3665 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3666 c->index += 1 + strlen(contents);
3671 static int bus_message_enter_variant(
3673 struct bus_container *c,
3674 const char *contents,
3675 size_t *item_size) {
3687 if (!signature_is_single(contents, false))
3690 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3693 if (!c->signature || c->signature[c->index] == 0)
3696 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3701 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3704 k = strlen(contents);
3705 if (1+k > c->item_size)
3708 where = rindex + c->item_size - (1+k);
3709 r = message_peek_body(m, &where, 1, 1+k, &q);
3713 if (*(char*) q != 0)
3716 if (memcmp((uint8_t*) q+1, contents, k))
3719 *item_size = c->item_size - (1+k);
3722 r = message_peek_body(m, &rindex, 1, 1, &q);
3727 r = message_peek_body(m, &rindex, 1, l+1, &q);
3731 if (!validate_signature(q, l))
3734 if (!streq(q, contents))
3740 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3746 static int build_struct_offsets(
3748 const char *signature,
3752 size_t *n_offsets) {
3754 unsigned n_variable = 0, n_total = 0, v;
3755 size_t previous = 0, where;
3766 if (isempty(signature)) {
3767 /* Unary type is encoded as *fixed* 1 byte padding */
3768 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3772 if (*(uint8_t *) q != 0)
3781 sz = bus_gvariant_determine_word_size(size, 0);
3785 /* First, loop over signature and count variable elements and
3786 * elements in general. We use this to know how large the
3787 * offset array is at the end of the structure. Note that
3788 * GVariant only stores offsets for all variable size elements
3789 * that are not the last item. */
3795 r = signature_element_length(p, &n);
3804 r = bus_gvariant_is_fixed_size(t);
3809 if (r == 0 && p[n] != 0) /* except the last item */
3816 if (size < n_variable * sz)
3819 where = m->rindex + size - (n_variable * sz);
3820 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3826 *offsets = new(size_t, n_total);
3832 /* Second, loop again and build an offset table */
3838 r = signature_element_length(p, &n);
3847 k = bus_gvariant_get_size(t);
3855 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3858 if (m->rindex + x < previous)
3861 /* The last item's end
3862 * is determined from
3865 x = size - (n_variable * sz);
3867 offset = m->rindex + x;
3873 align = bus_gvariant_get_alignment(t);
3876 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3880 previous = (*offsets)[(*n_offsets)++] = offset;
3885 assert(*n_offsets == n_total);
3887 *item_size = (*offsets)[0] - m->rindex;
3891 static int enter_struct_or_dict_entry(
3893 struct bus_container *c,
3894 const char *contents,
3897 size_t *n_offsets) {
3908 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3911 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3916 /* gvariant with contents */
3917 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3922 static int bus_message_enter_struct(
3924 struct bus_container *c,
3925 const char *contents,
3928 size_t *n_offsets) {
3940 if (!signature_is_valid(contents, false))
3943 if (!c->signature || c->signature[c->index] == 0)
3946 l = strlen(contents);
3948 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3949 !startswith(c->signature + c->index + 1, contents) ||
3950 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3953 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3957 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3958 c->index += 1 + l + 1;
3963 static int bus_message_enter_dict_entry(
3965 struct bus_container *c,
3966 const char *contents,
3969 size_t *n_offsets) {
3978 if (!signature_is_pair(contents))
3981 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3984 if (!c->signature || c->signature[c->index] == 0)
3987 l = strlen(contents);
3989 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3990 !startswith(c->signature + c->index + 1, contents) ||
3991 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3994 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3998 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3999 c->index += 1 + l + 1;
4004 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4006 const char *contents) {
4007 struct bus_container *c, *w;
4008 uint32_t *array_size = NULL;
4011 size_t *offsets = NULL;
4012 size_t n_offsets = 0, item_size = 0;
4015 assert_return(m, -EINVAL);
4016 assert_return(m->sealed, -EPERM);
4017 assert_return(type != 0 || !contents, -EINVAL);
4019 if (type == 0 || !contents) {
4023 /* Allow entering into anonymous containers */
4024 r = sd_bus_message_peek_type(m, &tt, &cc);
4028 if (type != 0 && type != tt)
4031 if (contents && !streq(contents, cc))
4039 * We enforce a global limit on container depth, that is much
4040 * higher than the 32 structs and 32 arrays the specification
4041 * mandates. This is simpler to implement for us, and we need
4042 * this only to ensure our container array doesn't grow
4043 * without bounds. We are happy to return any data from a
4044 * message as long as the data itself is valid, even if the
4045 * overall message might be not.
4047 * Note that the message signature is validated when
4048 * parsing the headers, and that validation does check the
4051 * Note that the specification defines no limits on the depth
4052 * of stacked variants, but we do.
4054 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4057 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4060 if (message_end_of_signature(m))
4063 if (message_end_of_array(m, m->rindex))
4066 c = message_get_container(m);
4068 signature = strdup(contents);
4072 c->saved_index = c->index;
4075 if (type == SD_BUS_TYPE_ARRAY)
4076 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4077 else if (type == SD_BUS_TYPE_VARIANT)
4078 r = bus_message_enter_variant(m, c, contents, &item_size);
4079 else if (type == SD_BUS_TYPE_STRUCT)
4080 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4081 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4082 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4092 /* OK, let's fill it in */
4093 w = m->containers + m->n_containers++;
4094 w->enclosing = type;
4095 w->signature = signature;
4096 w->peeked_signature = NULL;
4100 w->begin = m->rindex;
4102 /* Unary type has fixed size of 1, but virtual size of 0 */
4103 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4104 type == SD_BUS_TYPE_STRUCT &&
4106 w->end = m->rindex + 0;
4108 w->end = m->rindex + c->item_size;
4110 w->array_size = array_size;
4111 w->item_size = item_size;
4112 w->offsets = offsets;
4113 w->n_offsets = n_offsets;
4114 w->offset_index = 0;
4119 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4120 struct bus_container *c;
4124 assert_return(m, -EINVAL);
4125 assert_return(m->sealed, -EPERM);
4126 assert_return(m->n_containers > 0, -ENXIO);
4128 c = message_get_container(m);
4130 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4131 if (c->signature && c->signature[c->index] != 0)
4135 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4136 if (m->rindex < c->end)
4139 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4142 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4143 if (c->begin + l != m->rindex)
4148 free(c->peeked_signature);
4152 c = message_get_container(m);
4155 c->index = c->saved_index;
4156 r = container_next_item(m, c, &m->rindex);
4164 static void message_quit_container(sd_bus_message *m) {
4165 struct bus_container *c;
4169 assert(m->n_containers > 0);
4171 c = message_get_container(m);
4174 assert(m->rindex >= c->before);
4175 m->rindex = c->before;
4177 /* Free container */
4182 /* Correct index of new top-level container */
4183 c = message_get_container(m);
4184 c->index = c->saved_index;
4187 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4188 struct bus_container *c;
4191 assert_return(m, -EINVAL);
4192 assert_return(m->sealed, -EPERM);
4194 if (message_end_of_signature(m))
4197 if (message_end_of_array(m, m->rindex))
4200 c = message_get_container(m);
4202 if (bus_type_is_basic(c->signature[c->index])) {
4206 *type = c->signature[c->index];
4210 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4216 r = signature_element_length(c->signature+c->index+1, &l);
4222 sig = strndup(c->signature + c->index + 1, l);
4226 free(c->peeked_signature);
4227 *contents = c->peeked_signature = sig;
4231 *type = SD_BUS_TYPE_ARRAY;
4236 if (IN_SET(c->signature[c->index], SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN)) {
4242 r = signature_element_length(c->signature+c->index, &l);
4247 sig = strndup(c->signature + c->index + 1, l - 2);
4251 free(c->peeked_signature);
4252 *contents = c->peeked_signature = sig;
4256 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4261 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4265 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4268 if (c->item_size < 2)
4271 /* Look for the NUL delimiter that
4272 separates the payload from the
4273 signature. Since the body might be
4274 in a different part that then the
4275 signature we map byte by byte. */
4277 for (k = 2; k <= c->item_size; k++) {
4280 where = m->rindex + c->item_size - k;
4281 r = message_peek_body(m, &where, 1, k, &q);
4285 if (*(char*) q == 0)
4289 if (k > c->item_size)
4292 free(c->peeked_signature);
4293 c->peeked_signature = strndup((char*) q + 1, k - 1);
4294 if (!c->peeked_signature)
4297 if (!signature_is_valid(c->peeked_signature, true))
4300 *contents = c->peeked_signature;
4305 r = message_peek_body(m, &rindex, 1, 1, &q);
4310 r = message_peek_body(m, &rindex, 1, l+1, &q);
4314 if (!validate_signature(q, l))
4322 *type = SD_BUS_TYPE_VARIANT;
4337 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4338 struct bus_container *c;
4340 assert_return(m, -EINVAL);
4341 assert_return(m->sealed, -EPERM);
4344 message_reset_containers(m);
4347 c = message_get_container(m);
4349 c = message_get_container(m);
4351 c->offset_index = 0;
4353 m->rindex = c->begin;
4356 c->offset_index = 0;
4357 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4359 return !isempty(c->signature);
4362 static int message_read_ap(
4367 unsigned n_array, n_struct;
4368 TypeStack stack[BUS_CONTAINER_DEPTH];
4369 unsigned stack_ptr = 0;
4370 unsigned n_loop = 0;
4378 /* Ideally, we'd just call ourselves recursively on every
4379 * complex type. However, the state of a va_list that is
4380 * passed to a function is undefined after that function
4381 * returns. This means we need to docode the va_list linearly
4382 * in a single stackframe. We hence implement our own
4383 * home-grown stack in an array. */
4385 n_array = (unsigned) -1; /* length of current array entries */
4386 n_struct = strlen(types); /* length of current struct contents signature */
4393 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4394 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4400 r = sd_bus_message_exit_container(m);
4408 if (n_array != (unsigned) -1)
4417 case SD_BUS_TYPE_BYTE:
4418 case SD_BUS_TYPE_BOOLEAN:
4419 case SD_BUS_TYPE_INT16:
4420 case SD_BUS_TYPE_UINT16:
4421 case SD_BUS_TYPE_INT32:
4422 case SD_BUS_TYPE_UINT32:
4423 case SD_BUS_TYPE_INT64:
4424 case SD_BUS_TYPE_UINT64:
4425 case SD_BUS_TYPE_DOUBLE:
4426 case SD_BUS_TYPE_STRING:
4427 case SD_BUS_TYPE_OBJECT_PATH:
4428 case SD_BUS_TYPE_SIGNATURE:
4429 case SD_BUS_TYPE_UNIX_FD: {
4432 p = va_arg(ap, void*);
4433 r = sd_bus_message_read_basic(m, *t, p);
4446 case SD_BUS_TYPE_ARRAY: {
4449 r = signature_element_length(t + 1, &k);
4455 memcpy(s, t + 1, k);
4458 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4469 if (n_array == (unsigned) -1) {
4474 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4480 n_array = va_arg(ap, unsigned);
4485 case SD_BUS_TYPE_VARIANT: {
4488 s = va_arg(ap, const char *);
4492 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4502 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4507 n_struct = strlen(s);
4508 n_array = (unsigned) -1;
4513 case SD_BUS_TYPE_STRUCT_BEGIN:
4514 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4517 r = signature_element_length(t, &k);
4523 memcpy(s, t + 1, k - 2);
4526 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4536 if (n_array == (unsigned) -1) {
4541 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4547 n_array = (unsigned) -1;
4560 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4564 assert_return(m, -EINVAL);
4565 assert_return(m->sealed, -EPERM);
4566 assert_return(types, -EINVAL);
4568 va_start(ap, types);
4569 r = message_read_ap(m, types, ap);
4575 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4578 assert_return(m, -EINVAL);
4579 assert_return(m->sealed, -EPERM);
4581 /* If types is NULL, read exactly one element */
4583 struct bus_container *c;
4586 if (message_end_of_signature(m))
4589 if (message_end_of_array(m, m->rindex))
4592 c = message_get_container(m);
4594 r = signature_element_length(c->signature + c->index, &l);
4598 types = strndupa(c->signature + c->index, l);
4603 case 0: /* Nothing to drop */
4606 case SD_BUS_TYPE_BYTE:
4607 case SD_BUS_TYPE_BOOLEAN:
4608 case SD_BUS_TYPE_INT16:
4609 case SD_BUS_TYPE_UINT16:
4610 case SD_BUS_TYPE_INT32:
4611 case SD_BUS_TYPE_UINT32:
4612 case SD_BUS_TYPE_INT64:
4613 case SD_BUS_TYPE_UINT64:
4614 case SD_BUS_TYPE_DOUBLE:
4615 case SD_BUS_TYPE_STRING:
4616 case SD_BUS_TYPE_OBJECT_PATH:
4617 case SD_BUS_TYPE_SIGNATURE:
4618 case SD_BUS_TYPE_UNIX_FD:
4620 r = sd_bus_message_read_basic(m, *types, NULL);
4624 r = sd_bus_message_skip(m, types + 1);
4630 case SD_BUS_TYPE_ARRAY: {
4633 r = signature_element_length(types + 1, &k);
4639 memcpy(s, types+1, k);
4642 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4647 r = sd_bus_message_skip(m, s);
4654 r = sd_bus_message_exit_container(m);
4659 r = sd_bus_message_skip(m, types + 1 + k);
4666 case SD_BUS_TYPE_VARIANT: {
4667 const char *contents;
4670 r = sd_bus_message_peek_type(m, &x, &contents);
4674 if (x != SD_BUS_TYPE_VARIANT)
4677 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4681 r = sd_bus_message_skip(m, contents);
4686 r = sd_bus_message_exit_container(m);
4690 r = sd_bus_message_skip(m, types + 1);
4697 case SD_BUS_TYPE_STRUCT_BEGIN:
4698 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4701 r = signature_element_length(types, &k);
4707 memcpy(s, types+1, k-2);
4710 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4714 r = sd_bus_message_skip(m, s);
4718 r = sd_bus_message_exit_container(m);
4723 r = sd_bus_message_skip(m, types + k);
4735 _public_ int sd_bus_message_read_array(
4741 struct bus_container *c;
4747 assert_return(m, -EINVAL);
4748 assert_return(m->sealed, -EPERM);
4749 assert_return(bus_type_is_trivial(type), -EINVAL);
4750 assert_return(ptr, -EINVAL);
4751 assert_return(size, -EINVAL);
4752 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4754 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4758 c = message_get_container(m);
4760 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4761 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4765 sz = c->end - c->begin;
4767 align = bus_type_get_alignment(type);
4771 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4775 /* Zero length array, let's return some aligned
4776 * pointer that is not NULL */
4777 p = (uint8_t*) NULL + align;
4779 r = message_peek_body(m, &m->rindex, align, sz, &p);
4784 r = sd_bus_message_exit_container(m);
4788 *ptr = (const void*) p;
4794 message_quit_container(m);
4798 static int message_peek_fields(
4809 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4812 static int message_peek_field_uint32(
4824 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4827 /* identical for gvariant and dbus1 */
4829 r = message_peek_fields(m, ri, 4, 4, &q);
4834 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4839 static int message_peek_field_uint64(
4851 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4854 /* identical for gvariant and dbus1 */
4856 r = message_peek_fields(m, ri, 8, 8, &q);
4861 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4866 static int message_peek_field_string(
4868 bool (*validate)(const char *p),
4880 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4885 r = message_peek_fields(m, ri, 1, item_size, &q);
4891 r = message_peek_field_uint32(m, ri, 4, &l);
4895 r = message_peek_fields(m, ri, 1, l+1, &q);
4901 if (!validate_nul(q, l))
4907 if (!validate_string(q, l))
4917 static int message_peek_field_signature(
4930 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4935 r = message_peek_fields(m, ri, 1, item_size, &q);
4941 r = message_peek_fields(m, ri, 1, 1, &q);
4946 r = message_peek_fields(m, ri, 1, l+1, &q);
4951 if (!validate_signature(q, l))
4960 static int message_skip_fields(
4963 uint32_t array_size,
4964 const char **signature) {
4966 size_t original_index;
4972 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4974 original_index = *ri;
4980 if (array_size != (uint32_t) -1 &&
4981 array_size <= *ri - original_index)
4988 if (t == SD_BUS_TYPE_STRING) {
4990 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4996 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4998 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5004 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5006 r = message_peek_field_signature(m, ri, 0, NULL);
5012 } else if (bus_type_is_basic(t)) {
5015 align = bus_type_get_alignment(t);
5016 k = bus_type_get_size(t);
5017 assert(align > 0 && k > 0);
5019 r = message_peek_fields(m, ri, align, k, NULL);
5025 } else if (t == SD_BUS_TYPE_ARRAY) {
5027 r = signature_element_length(*signature+1, &l);
5037 strncpy(sig, *signature + 1, l-1);
5040 alignment = bus_type_get_alignment(sig[0]);
5044 r = message_peek_field_uint32(m, ri, 0, &nas);
5047 if (nas > BUS_ARRAY_MAX_SIZE)
5050 r = message_peek_fields(m, ri, alignment, 0, NULL);
5054 r = message_skip_fields(m, ri, nas, (const char**) &s);
5059 (*signature) += 1 + l;
5061 } else if (t == SD_BUS_TYPE_VARIANT) {
5064 r = message_peek_field_signature(m, ri, 0, &s);
5068 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5074 } else if (IN_SET(t, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
5076 r = signature_element_length(*signature, &l);
5083 strncpy(sig, *signature + 1, l-1);
5086 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5097 int bus_message_parse_fields(sd_bus_message *m) {
5100 uint32_t unix_fds = 0;
5101 bool unix_fds_set = false;
5102 void *offsets = NULL;
5103 unsigned n_offsets = 0;
5109 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5112 /* Read the signature from the end of the body variant first */
5113 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5114 if (m->footer_accessible < 1 + sz)
5117 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5119 if (p < (char*) m->footer)
5126 /* We found the beginning of the signature
5127 * string, yay! We require the body to be a
5128 * structure, so verify it and then strip the
5129 * opening/closing brackets. */
5131 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5133 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5134 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5137 c = strndup(p + 1 + 1, l - 2);
5141 free(m->root_container.signature);
5142 m->root_container.signature = c;
5149 /* Calculate the actual user body size, by removing
5150 * the trailing variant signature and struct offset
5152 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5154 /* Pull out the offset table for the fields array */
5155 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5160 ri = m->fields_size - sz;
5161 r = message_peek_fields(m, &ri, 1, sz, &q);
5165 framing = bus_gvariant_read_word_le(q, sz);
5166 if (framing >= m->fields_size - sz)
5168 if ((m->fields_size - framing) % sz != 0)
5172 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5176 n_offsets = (m->fields_size - framing) / sz;
5179 m->user_body_size = m->body_size;
5182 while (ri < m->fields_size) {
5183 _cleanup_free_ char *sig = NULL;
5184 const char *signature;
5185 uint64_t field_type;
5186 size_t item_size = (size_t) -1;
5188 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5197 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5199 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5203 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5207 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5214 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5219 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5224 where = ri = ALIGN_TO(ri, 8);
5225 item_size = end - ri;
5226 r = message_peek_fields(m, &where, 1, item_size, &q);
5230 b = memrchr(q, 0, item_size);
5234 sig = strndup(b+1, item_size - (b+1-(char*) q));
5239 item_size = b - (char*) q;
5241 r = message_peek_field_signature(m, &ri, 0, &signature);
5246 switch (field_type) {
5248 case _BUS_MESSAGE_HEADER_INVALID:
5251 case BUS_MESSAGE_HEADER_PATH:
5256 if (!streq(signature, "o"))
5259 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5262 case BUS_MESSAGE_HEADER_INTERFACE:
5267 if (!streq(signature, "s"))
5270 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5273 case BUS_MESSAGE_HEADER_MEMBER:
5278 if (!streq(signature, "s"))
5281 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5284 case BUS_MESSAGE_HEADER_ERROR_NAME:
5289 if (!streq(signature, "s"))
5292 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5294 m->error._need_free = -1;
5298 case BUS_MESSAGE_HEADER_DESTINATION:
5303 if (!streq(signature, "s"))
5306 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5309 case BUS_MESSAGE_HEADER_SENDER:
5314 if (!streq(signature, "s"))
5317 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5319 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client) {
5320 m->creds.unique_name = (char*) m->sender;
5321 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5327 case BUS_MESSAGE_HEADER_SIGNATURE: {
5331 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5334 if (m->root_container.signature)
5337 if (!streq(signature, "g"))
5340 r = message_peek_field_signature(m, &ri, item_size, &s);
5348 free(m->root_container.signature);
5349 m->root_container.signature = c;
5353 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5355 if (m->reply_cookie != 0)
5358 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5359 /* 64bit on dbus2 */
5361 if (!streq(signature, "t"))
5364 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5368 /* 32bit on dbus1 */
5371 if (!streq(signature, "u"))
5374 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5378 m->reply_cookie = serial;
5381 if (m->reply_cookie == 0)
5386 case BUS_MESSAGE_HEADER_UNIX_FDS:
5390 if (!streq(signature, "u"))
5393 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5397 unix_fds_set = true;
5401 if (!BUS_MESSAGE_IS_GVARIANT(m))
5402 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5411 if (m->n_fds != unix_fds)
5414 switch (m->header->type) {
5416 case SD_BUS_MESSAGE_SIGNAL:
5417 if (!m->path || !m->interface || !m->member)
5420 if (m->reply_cookie != 0)
5425 case SD_BUS_MESSAGE_METHOD_CALL:
5427 if (!m->path || !m->member)
5430 if (m->reply_cookie != 0)
5435 case SD_BUS_MESSAGE_METHOD_RETURN:
5437 if (m->reply_cookie == 0)
5441 case SD_BUS_MESSAGE_METHOD_ERROR:
5443 if (m->reply_cookie == 0 || !m->error.name)
5448 /* Refuse non-local messages that claim they are local */
5449 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5451 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5453 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5456 m->root_container.end = m->user_body_size;
5458 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5459 r = build_struct_offsets(
5461 m->root_container.signature,
5463 &m->root_container.item_size,
5464 &m->root_container.offsets,
5465 &m->root_container.n_offsets);
5470 /* Try to read the error message, but if we can't it's a non-issue */
5471 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5472 (void) sd_bus_message_read(m, "s", &m->error.message);
5477 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5478 assert_return(m, -EINVAL);
5479 assert_return(destination, -EINVAL);
5480 assert_return(!m->sealed, -EPERM);
5481 assert_return(!m->destination, -EEXIST);
5483 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5486 #if 0 /// UNNEEDED by elogind
5487 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5491 struct bus_body_part *part;
5497 total = BUS_MESSAGE_SIZE(m);
5503 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5504 MESSAGE_FOREACH_PART(part, i, m)
5505 e = mempcpy(e, part->data, part->size);
5507 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5516 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5523 r = sd_bus_message_enter_container(m, 'a', "s");
5527 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5528 r = strv_extend(l, s);
5535 r = sd_bus_message_exit_container(m);
5542 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5546 assert_return(m, -EINVAL);
5547 assert_return(m->sealed, -EPERM);
5548 assert_return(l, -EINVAL);
5550 r = bus_message_read_strv_extend(m, &strv);
5560 static int bus_message_get_arg_skip(
5564 const char **_contents) {
5569 r = sd_bus_message_rewind(m, true);
5574 const char *contents;
5577 r = sd_bus_message_peek_type(m, &type, &contents);
5583 /* Don't match against arguments after the first one we don't understand */
5584 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5585 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5590 *_contents = contents;
5596 r = sd_bus_message_skip(m, NULL);
5603 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5610 r = bus_message_get_arg_skip(m, i, &type, NULL);
5614 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5617 return sd_bus_message_read_basic(m, type, str);
5620 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5621 const char *contents;
5628 r = bus_message_get_arg_skip(m, i, &type, &contents);
5632 if (type != SD_BUS_TYPE_ARRAY)
5634 if (!STR_IN_SET(contents, "s", "o", "g"))
5637 return sd_bus_message_read_strv(m, strv);
5640 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5641 assert_return(m, EINVAL);
5643 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5646 return sd_bus_error_get_errno(&m->error);
5649 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5650 struct bus_container *c;
5652 assert_return(m, NULL);
5654 c = complete ? &m->root_container : message_get_container(m);
5655 return strempty(c->signature);
5658 #if 0 /// UNNEEDED by elogind
5659 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5660 assert_return(m, -EINVAL);
5662 return isempty(m->root_container.signature);
5665 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5666 assert_return(m, -EINVAL);
5668 return streq(strempty(m->root_container.signature), strempty(signature));
5672 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5673 bool done_something = false;
5676 assert_return(m, -EINVAL);
5677 assert_return(source, -EINVAL);
5678 assert_return(!m->sealed, -EPERM);
5679 assert_return(source->sealed, -EPERM);
5682 const char *contents;
5697 r = sd_bus_message_peek_type(source, &type, &contents);
5703 done_something = true;
5705 if (bus_type_is_container(type) > 0) {
5707 r = sd_bus_message_enter_container(source, type, contents);
5711 r = sd_bus_message_open_container(m, type, contents);
5715 r = sd_bus_message_copy(m, source, true);
5719 r = sd_bus_message_close_container(m);
5723 r = sd_bus_message_exit_container(source);
5730 r = sd_bus_message_read_basic(source, type, &basic);
5736 if (IN_SET(type, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_STRING))
5737 r = sd_bus_message_append_basic(m, type, basic.string);
5739 r = sd_bus_message_append_basic(m, type, &basic);
5746 return done_something;
5749 #if 0 /// UNNEEDED by elogind
5750 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5755 assert_return(m, -EINVAL);
5756 assert_return(m->sealed, -EPERM);
5757 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5758 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5759 assert_return(type || contents, -EINVAL);
5760 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5762 r = sd_bus_message_peek_type(m, &t, &c);
5766 if (type != 0 && type != t)
5769 if (contents && !streq_ptr(contents, c))
5776 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5777 assert_return(m, NULL);
5782 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5783 _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5791 switch ((*m)->header->type) {
5793 case SD_BUS_MESSAGE_SIGNAL:
5794 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5800 case SD_BUS_MESSAGE_METHOD_CALL:
5801 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5807 case SD_BUS_MESSAGE_METHOD_RETURN:
5808 case SD_BUS_MESSAGE_METHOD_ERROR:
5810 n = message_new(bus, (*m)->header->type);
5814 n->reply_cookie = (*m)->reply_cookie;
5816 r = message_append_reply_cookie(n, n->reply_cookie);
5820 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5821 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5825 n->error._need_free = -1;
5834 if ((*m)->destination && !n->destination) {
5835 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5840 if ((*m)->sender && !n->sender) {
5841 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5846 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5848 r = sd_bus_message_copy(n, *m, true);
5852 timeout = (*m)->timeout;
5853 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5854 timeout = BUS_DEFAULT_TIMEOUT;
5856 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5860 sd_bus_message_unref(*m);
5867 #if 0 /// UNNEEDED by elogind
5868 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5872 assert_return(!m->sealed, -EPERM);
5873 assert_return(!m->sender, -EPERM);
5875 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5878 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5879 assert_return(m, -EINVAL);
5880 assert_return(priority, -EINVAL);
5882 *priority = m->priority;
5886 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5887 assert_return(m, -EINVAL);
5888 assert_return(!m->sealed, -EPERM);
5890 m->priority = priority;