1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "alloc-util.h"
29 #include "bus-gvariant.h"
30 #include "bus-internal.h"
31 #include "bus-message.h"
32 #include "bus-signature.h"
37 #include "memfd-util.h"
38 #include "string-util.h"
40 #include "time-util.h"
44 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
46 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
51 if (old_base == new_base)
54 if ((uint8_t*) p < (uint8_t*) old_base)
57 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
60 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
63 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
67 if (part->memfd >= 0) {
68 /* If we can reuse the memfd, try that. For that it
69 * can't be sealed yet. */
72 assert(part->memfd_offset == 0);
73 assert(part->data == part->mmap_begin);
74 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
77 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
79 safe_close(part->memfd);
82 } else if (part->munmap_this)
83 munmap(part->mmap_begin, part->mapped);
84 else if (part->free_this)
91 static void message_reset_parts(sd_bus_message *m) {
92 struct bus_body_part *part;
97 while (m->n_body_parts > 0) {
98 struct bus_body_part *next = part->next;
99 message_free_part(m, part);
106 m->cached_rindex_part = NULL;
107 m->cached_rindex_part_begin = 0;
110 static void message_reset_containers(sd_bus_message *m) {
115 for (i = 0; i < m->n_containers; i++) {
116 free(m->containers[i].signature);
117 free(m->containers[i].offsets);
120 m->containers = mfree(m->containers);
122 m->n_containers = m->containers_allocated = 0;
123 m->root_container.index = 0;
126 static void message_free(sd_bus_message *m) {
132 message_reset_parts(m);
134 if (m->release_kdbus)
135 bus_kernel_cmd_free(m->bus, (uint8_t *) m->kdbus - (uint8_t *) m->bus->kdbus_buffer);
140 sd_bus_unref(m->bus);
143 close_many(m->fds, m->n_fds);
147 if (m->iovec != m->iovec_fixed)
150 m->destination_ptr = mfree(m->destination_ptr);
151 message_reset_containers(m);
152 free(m->root_container.signature);
153 free(m->root_container.offsets);
155 free(m->root_container.peeked_signature);
157 bus_creds_done(&m->creds);
161 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
163 size_t old_size, new_size, start;
170 old_size = sizeof(struct bus_header) + m->fields_size;
171 start = ALIGN_TO(old_size, align);
172 new_size = start + sz;
174 if (new_size < start ||
175 new_size > (size_t) ((uint32_t) -1))
178 if (old_size == new_size)
179 return (uint8_t*) m->header + old_size;
181 if (m->free_header) {
182 np = realloc(m->header, ALIGN8(new_size));
186 /* Initially, the header is allocated as part of of
187 * the sd_bus_message itself, let's replace it by
190 np = malloc(ALIGN8(new_size));
194 memcpy(np, m->header, sizeof(struct bus_header));
197 /* Zero out padding */
198 if (start > old_size)
199 memzero((uint8_t*) np + old_size, start - old_size);
203 m->fields_size = new_size - sizeof(struct bus_header);
205 /* Adjust quick access pointers */
206 m->path = adjust_pointer(m->path, op, old_size, m->header);
207 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
208 m->member = adjust_pointer(m->member, op, old_size, m->header);
209 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
210 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
211 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
213 m->free_header = true;
216 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
219 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
222 return (uint8_t*) np + start;
229 static int message_append_field_string(
241 /* dbus1 only allows 8bit header field ids */
245 /* dbus1 doesn't allow strings over 32bit, let's enforce this
246 * globally, to not risk convertability */
248 if (l > (size_t) (uint32_t) -1)
251 /* Signature "(yv)" where the variant contains "s" */
253 if (BUS_MESSAGE_IS_GVARIANT(m)) {
255 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
256 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
260 *((uint64_t*) p) = h;
267 *ret = (char*) p + 8;
270 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
271 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
280 ((uint32_t*) p)[1] = l;
281 memcpy(p + 8, s, l + 1);
284 *ret = (char*) p + 8;
290 static int message_append_field_signature(
301 /* dbus1 only allows 8bit header field ids */
305 /* dbus1 doesn't allow signatures over 8bit, let's enforce
306 * this globally, to not risk convertability */
311 /* Signature "(yv)" where the variant contains "g" */
313 if (BUS_MESSAGE_IS_GVARIANT(m))
314 /* For gvariant the serialization is the same as for normal strings */
315 return message_append_field_string(m, h, 'g', s, ret);
317 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
318 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
324 p[2] = SD_BUS_TYPE_SIGNATURE;
327 memcpy(p + 5, s, l + 1);
330 *ret = (const char*) p + 5;
336 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
341 /* dbus1 only allows 8bit header field ids */
345 if (BUS_MESSAGE_IS_GVARIANT(m)) {
346 /* (field id 64bit + ((value + NUL + signature string 'u') */
348 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
352 *((uint64_t*) p) = h;
353 *((uint32_t*) (p + 8)) = x;
357 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
358 p = message_extend_fields(m, 8, 4 + 4, false);
367 ((uint32_t*) p)[1] = x;
373 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
378 /* dbus1 only allows 8bit header field ids */
382 if (BUS_MESSAGE_IS_GVARIANT(m)) {
383 /* (field id 64bit + ((value + NUL + signature string 't') */
385 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
389 *((uint64_t*) p) = h;
390 *((uint64_t*) (p + 8)) = x;
394 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
395 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
408 ((uint64_t*) p)[1] = x;
414 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
417 if (BUS_MESSAGE_IS_GVARIANT(m))
418 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
420 /* 64bit cookies are not supported on dbus1 */
421 if (cookie > 0xffffffffUL)
424 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
428 int bus_message_from_header(
431 size_t header_accessible,
433 size_t footer_accessible,
439 sd_bus_message **ret) {
441 _cleanup_free_ sd_bus_message *m = NULL;
442 struct bus_header *h;
446 assert(header || header_accessible <= 0);
447 assert(footer || footer_accessible <= 0);
448 assert(fds || n_fds <= 0);
451 if (header_accessible < sizeof(struct bus_header))
454 if (header_accessible > message_size)
456 if (footer_accessible > message_size)
460 if (!IN_SET(h->version, 1, 2))
463 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
466 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
469 /* Note that we are happy with unknown flags in the flags header! */
471 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
474 label_sz = strlen(label);
485 m->header_accessible = header_accessible;
487 m->footer_accessible = footer_accessible;
489 if (BUS_MESSAGE_IS_GVARIANT(m)) {
492 if (h->dbus2.cookie == 0)
495 /* dbus2 derives the sizes from the message size and
496 the offset table at the end, since it is formatted as
497 gvariant "yyyyuta{tv}v". Since the message itself is a
498 structure with precisely to variable sized entries,
499 there's only one offset in the table, which marks the
500 end of the fields array. */
502 ws = bus_gvariant_determine_word_size(message_size, 0);
503 if (footer_accessible < ws)
506 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
507 if (ALIGN8(m->fields_size) > message_size - ws)
509 if (m->fields_size < sizeof(struct bus_header))
512 m->fields_size -= sizeof(struct bus_header);
513 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
515 if (h->dbus1.serial == 0)
518 /* dbus1 has the sizes in the header */
519 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
520 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
522 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
530 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
531 memcpy(m->creds.label, label, label_sz + 1);
533 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
536 m->bus = sd_bus_ref(bus);
543 int bus_message_from_malloc(
550 sd_bus_message **ret) {
556 r = bus_message_from_header(
558 buffer, length, /* in this case the initial bytes and the final bytes are the same */
567 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
570 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
572 m->body.sealed = true;
577 m->iovec = m->iovec_fixed;
578 m->iovec[0].iov_base = buffer;
579 m->iovec[0].iov_len = length;
581 r = bus_message_parse_fields(m);
585 /* We take possession of the memory and fds now */
586 m->free_header = true;
597 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
602 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
607 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
608 m->header->endian = BUS_NATIVE_ENDIAN;
609 m->header->type = type;
610 m->header->version = bus->message_version;
611 m->allow_fds = bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
612 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
613 m->bus = sd_bus_ref(bus);
615 if (bus->allow_interactive_authorization)
616 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
621 _public_ int sd_bus_message_new_signal(
625 const char *interface,
626 const char *member) {
631 assert_return(bus, -ENOTCONN);
632 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
633 assert_return(object_path_is_valid(path), -EINVAL);
634 assert_return(interface_name_is_valid(interface), -EINVAL);
635 assert_return(member_name_is_valid(member), -EINVAL);
636 assert_return(m, -EINVAL);
638 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
642 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
644 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
647 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
650 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
658 sd_bus_message_unref(t);
662 _public_ int sd_bus_message_new_method_call(
665 const char *destination,
667 const char *interface,
668 const char *member) {
673 assert_return(bus, -ENOTCONN);
674 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
675 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
676 assert_return(object_path_is_valid(path), -EINVAL);
677 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
678 assert_return(member_name_is_valid(member), -EINVAL);
679 assert_return(m, -EINVAL);
681 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
685 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
688 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
693 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
699 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
712 static int message_new_reply(
713 sd_bus_message *call,
715 sd_bus_message **m) {
720 assert_return(call, -EINVAL);
721 assert_return(call->sealed, -EPERM);
722 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
723 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
724 assert_return(m, -EINVAL);
726 t = message_new(call->bus, type);
730 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
731 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
732 if (t->reply_cookie == 0)
735 r = message_append_reply_cookie(t, t->reply_cookie);
740 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
745 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
746 t->enforced_reply_signature = call->enforced_reply_signature;
756 _public_ int sd_bus_message_new_method_return(
757 sd_bus_message *call,
758 sd_bus_message **m) {
760 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
763 _public_ int sd_bus_message_new_method_error(
764 sd_bus_message *call,
766 const sd_bus_error *e) {
771 assert_return(sd_bus_error_is_set(e), -EINVAL);
772 assert_return(m, -EINVAL);
774 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
778 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
783 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
788 t->error._need_free = -1;
798 _public_ int sd_bus_message_new_method_errorf(
799 sd_bus_message *call,
805 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
808 assert_return(name, -EINVAL);
809 assert_return(m, -EINVAL);
811 va_start(ap, format);
812 bus_error_setfv(&error, name, format, ap);
815 return sd_bus_message_new_method_error(call, m, &error);
818 _public_ int sd_bus_message_new_method_errno(
819 sd_bus_message *call,
822 const sd_bus_error *p) {
824 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
826 if (sd_bus_error_is_set(p))
827 return sd_bus_message_new_method_error(call, m, p);
829 sd_bus_error_set_errno(&berror, error);
831 return sd_bus_message_new_method_error(call, m, &berror);
834 /// UNNEEDED by elogind
836 _public_ int sd_bus_message_new_method_errnof(
837 sd_bus_message *call,
843 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
846 va_start(ap, format);
847 sd_bus_error_set_errnofv(&berror, error, format, ap);
850 return sd_bus_message_new_method_error(call, m, &berror);
854 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
858 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
859 m->creds.well_known_names_local = true;
860 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
863 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
867 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
868 m->creds.well_known_names_driver = true;
869 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
872 int bus_message_new_synthetic_error(
875 const sd_bus_error *e,
876 sd_bus_message **m) {
882 assert(sd_bus_error_is_set(e));
885 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
889 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
890 t->reply_cookie = cookie;
892 r = message_append_reply_cookie(t, t->reply_cookie);
896 if (bus && bus->unique_name) {
897 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
902 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
907 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
912 t->error._need_free = -1;
914 bus_message_set_sender_driver(bus, t);
924 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
925 assert_return(m, NULL);
927 assert(m->n_ref > 0);
933 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
938 assert(m->n_ref > 0);
948 /// UNNEEDED by elogind
950 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
951 assert_return(m, -EINVAL);
952 assert_return(type, -EINVAL);
954 *type = m->header->type;
958 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
961 assert_return(m, -EINVAL);
962 assert_return(cookie, -EINVAL);
964 c = BUS_MESSAGE_COOKIE(m);
968 *cookie = BUS_MESSAGE_COOKIE(m);
972 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
973 assert_return(m, -EINVAL);
974 assert_return(cookie, -EINVAL);
976 if (m->reply_cookie == 0)
979 *cookie = m->reply_cookie;
983 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
984 assert_return(m, -EINVAL);
986 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
987 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
990 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
991 assert_return(m, -EINVAL);
993 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
997 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
998 assert_return(m, -EINVAL);
1000 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
1001 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
1004 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1005 assert_return(m, NULL);
1010 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1011 assert_return(m, NULL);
1013 return m->interface;
1016 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1017 assert_return(m, NULL);
1022 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1023 assert_return(m, NULL);
1025 return m->destination;
1028 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1029 assert_return(m, NULL);
1034 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1035 assert_return(m, NULL);
1037 if (!sd_bus_error_is_set(&m->error))
1043 /// UNNEEDED by elogind
1045 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1046 assert_return(m, -EINVAL);
1047 assert_return(usec, -EINVAL);
1049 if (m->monotonic <= 0)
1052 *usec = m->monotonic;
1056 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1057 assert_return(m, -EINVAL);
1058 assert_return(usec, -EINVAL);
1060 if (m->realtime <= 0)
1063 *usec = m->realtime;
1067 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1068 assert_return(m, -EINVAL);
1069 assert_return(seqnum, -EINVAL);
1074 *seqnum = m->seqnum;
1079 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1080 assert_return(m, NULL);
1082 if (m->creds.mask == 0)
1088 /// UNNEEDED by elogind
1090 _public_ int sd_bus_message_is_signal(
1092 const char *interface,
1093 const char *member) {
1095 assert_return(m, -EINVAL);
1097 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1100 if (interface && (!m->interface || !streq(m->interface, interface)))
1103 if (member && (!m->member || !streq(m->member, member)))
1110 _public_ int sd_bus_message_is_method_call(
1112 const char *interface,
1113 const char *member) {
1115 assert_return(m, -EINVAL);
1117 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1120 if (interface && (!m->interface || !streq(m->interface, interface)))
1123 if (member && (!m->member || !streq(m->member, member)))
1129 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1130 assert_return(m, -EINVAL);
1132 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1135 if (name && (!m->error.name || !streq(m->error.name, name)))
1141 /// UNNEEDED by elogind
1143 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1144 assert_return(m, -EINVAL);
1145 assert_return(!m->sealed, -EPERM);
1146 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1149 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1151 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1156 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1157 assert_return(m, -EINVAL);
1158 assert_return(!m->sealed, -EPERM);
1161 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1163 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1168 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1169 assert_return(m, -EINVAL);
1170 assert_return(!m->sealed, -EPERM);
1173 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1175 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1181 static struct bus_container *message_get_container(sd_bus_message *m) {
1184 if (m->n_containers == 0)
1185 return &m->root_container;
1187 assert(m->containers);
1188 return m->containers + m->n_containers - 1;
1191 struct bus_body_part *message_append_part(sd_bus_message *m) {
1192 struct bus_body_part *part;
1199 if (m->n_body_parts <= 0) {
1203 assert(m->body_end);
1205 part = new0(struct bus_body_part, 1);
1211 m->body_end->next = part;
1221 static void part_zero(struct bus_body_part *part, size_t sz) {
1226 /* All other fields can be left in their defaults */
1227 assert(!part->data);
1228 assert(part->memfd < 0);
1231 part->is_zero = true;
1232 part->sealed = true;
1235 static int part_make_space(
1236 struct sd_bus_message *m,
1237 struct bus_body_part *part,
1246 assert(!part->sealed);
1251 if (!part->data && part->memfd < 0) {
1252 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1253 part->mmap_begin = part->data;
1256 if (part->memfd >= 0) {
1258 if (part->allocated == 0 || sz > part->allocated) {
1259 uint64_t new_allocated;
1261 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1262 r = memfd_set_size(part->memfd, new_allocated);
1268 part->allocated = new_allocated;
1271 if (!part->data || sz > part->mapped) {
1274 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1275 if (part->mapped <= 0)
1276 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1278 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1280 if (n == MAP_FAILED) {
1285 part->mmap_begin = part->data = n;
1287 part->memfd_offset = 0;
1290 part->munmap_this = true;
1292 if (part->allocated == 0 || sz > part->allocated) {
1293 size_t new_allocated;
1295 new_allocated = sz > 0 ? 2 * sz : 64;
1296 n = realloc(part->data, new_allocated);
1303 part->allocated = new_allocated;
1304 part->free_this = true;
1309 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1315 static int message_add_offset(sd_bus_message *m, size_t offset) {
1316 struct bus_container *c;
1319 assert(BUS_MESSAGE_IS_GVARIANT(m));
1321 /* Add offset to current container, unless this is the first
1322 * item in it, which will have the 0 offset, which we can
1324 c = message_get_container(m);
1326 if (!c->need_offsets)
1329 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1332 c->offsets[c->n_offsets++] = offset;
1336 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1337 struct bus_container *c;
1344 /* Update counters */
1345 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1348 *c->array_size += expand;
1352 static void *message_extend_body(
1357 bool force_inline) {
1359 size_t start_body, end_body, padding, added;
1370 start_body = ALIGN_TO((size_t) m->body_size, align);
1371 end_body = start_body + sz;
1373 padding = start_body - m->body_size;
1374 added = padding + sz;
1376 /* Check for 32bit overflows */
1377 if (end_body > (size_t) ((uint32_t) -1) ||
1378 end_body < start_body) {
1384 struct bus_body_part *part = NULL;
1388 m->n_body_parts <= 0 ||
1389 m->body_end->sealed ||
1390 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1391 (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 */
1395 part = message_append_part(m);
1399 part_zero(part, padding);
1402 part = message_append_part(m);
1406 r = part_make_space(m, part, sz, &p);
1410 struct bus_container *c;
1412 size_t os, start_part, end_part;
1418 start_part = ALIGN_TO(part->size, align);
1419 end_part = start_part + sz;
1421 r = part_make_space(m, part, end_part, &p);
1426 memzero(p, padding);
1427 p = (uint8_t*) p + padding;
1430 /* Readjust pointers */
1431 for (c = m->containers; c < m->containers + m->n_containers; c++)
1432 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1434 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1437 /* Return something that is not NULL and is aligned */
1438 p = (uint8_t *) NULL + align;
1440 m->body_size = end_body;
1441 message_extend_containers(m, added);
1444 r = message_add_offset(m, end_body);
1454 static int message_push_fd(sd_bus_message *m, int fd) {
1465 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1469 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1477 m->fds[m->n_fds] = copy;
1483 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1484 _cleanup_close_ int fd = -1;
1485 struct bus_container *c;
1489 assert_return(m, -EINVAL);
1490 assert_return(!m->sealed, -EPERM);
1491 assert_return(bus_type_is_basic(type), -EINVAL);
1492 assert_return(!m->poisoned, -ESTALE);
1494 c = message_get_container(m);
1496 if (c->signature && c->signature[c->index]) {
1497 /* Container signature is already set */
1499 if (c->signature[c->index] != type)
1504 /* Maybe we can append to the signature? But only if this is the top-level container */
1505 if (c->enclosing != 0)
1508 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1515 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1521 case SD_BUS_TYPE_SIGNATURE:
1522 case SD_BUS_TYPE_STRING:
1525 /* Fall through... */
1526 case SD_BUS_TYPE_OBJECT_PATH:
1534 case SD_BUS_TYPE_BOOLEAN:
1536 u8 = p && *(int*) p;
1542 case SD_BUS_TYPE_UNIX_FD:
1547 fd = message_push_fd(m, *(int*) p);
1558 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1559 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1566 a = message_extend_body(m, align, sz, true, false);
1573 *stored = (const uint8_t*) a;
1580 case SD_BUS_TYPE_STRING:
1581 /* To make things easy we'll serialize a NULL string
1582 * into the empty string */
1585 /* Fall through... */
1586 case SD_BUS_TYPE_OBJECT_PATH:
1592 sz = 4 + strlen(p) + 1;
1595 case SD_BUS_TYPE_SIGNATURE:
1600 sz = 1 + strlen(p) + 1;
1603 case SD_BUS_TYPE_BOOLEAN:
1605 u32 = p && *(int*) p;
1611 case SD_BUS_TYPE_UNIX_FD:
1616 fd = message_push_fd(m, *(int*) p);
1627 align = bus_type_get_alignment(type);
1628 sz = bus_type_get_size(type);
1635 a = message_extend_body(m, align, sz, false, false);
1639 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1640 *(uint32_t*) a = sz - 5;
1641 memcpy((uint8_t*) a + 4, p, sz - 4);
1644 *stored = (const uint8_t*) a + 4;
1646 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1647 *(uint8_t*) a = sz - 2;
1648 memcpy((uint8_t*) a + 1, p, sz - 1);
1651 *stored = (const uint8_t*) a + 1;
1660 if (type == SD_BUS_TYPE_UNIX_FD)
1663 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1670 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1671 return message_append_basic(m, type, p, NULL);
1674 /// UNNEEDED by elogind
1676 _public_ int sd_bus_message_append_string_space(
1681 struct bus_container *c;
1684 assert_return(m, -EINVAL);
1685 assert_return(s, -EINVAL);
1686 assert_return(!m->sealed, -EPERM);
1687 assert_return(!m->poisoned, -ESTALE);
1689 c = message_get_container(m);
1691 if (c->signature && c->signature[c->index]) {
1692 /* Container signature is already set */
1694 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1699 /* Maybe we can append to the signature? But only if this is the top-level container */
1700 if (c->enclosing != 0)
1703 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1710 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1711 a = message_extend_body(m, 1, size + 1, true, false);
1717 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1721 *(uint32_t*) a = size;
1727 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1733 _public_ int sd_bus_message_append_string_iovec(
1735 const struct iovec *iov,
1743 assert_return(m, -EINVAL);
1744 assert_return(!m->sealed, -EPERM);
1745 assert_return(iov || n == 0, -EINVAL);
1746 assert_return(!m->poisoned, -ESTALE);
1748 size = IOVEC_TOTAL_SIZE(iov, n);
1750 r = sd_bus_message_append_string_space(m, size, &p);
1754 for (i = 0; i < n; i++) {
1756 if (iov[i].iov_base)
1757 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1759 memset(p, ' ', iov[i].iov_len);
1761 p += iov[i].iov_len;
1768 static int bus_message_open_array(
1770 struct bus_container *c,
1771 const char *contents,
1772 uint32_t **array_size,
1774 bool *need_offsets) {
1784 assert(need_offsets);
1786 if (!signature_is_single(contents, true))
1789 if (c->signature && c->signature[c->index]) {
1791 /* Verify the existing signature */
1793 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1796 if (!startswith(c->signature + c->index + 1, contents))
1799 nindex = c->index + 1 + strlen(contents);
1803 if (c->enclosing != 0)
1806 /* Extend the existing signature */
1808 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1814 nindex = e - c->signature;
1817 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1818 alignment = bus_gvariant_get_alignment(contents);
1822 /* Add alignment padding and add to offset list */
1823 if (!message_extend_body(m, alignment, 0, false, false))
1826 r = bus_gvariant_is_fixed_size(contents);
1830 *begin = m->body_size;
1831 *need_offsets = r == 0;
1835 struct bus_body_part *o;
1837 alignment = bus_type_get_alignment(contents[0]);
1841 a = message_extend_body(m, 4, 4, false, false);
1846 op = m->body_end->data;
1847 os = m->body_end->size;
1849 /* Add alignment between size and first element */
1850 if (!message_extend_body(m, alignment, 0, false, false))
1853 /* location of array size might have changed so let's readjust a */
1854 if (o == m->body_end)
1855 a = adjust_pointer(a, op, os, m->body_end->data);
1861 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1867 static int bus_message_open_variant(
1869 struct bus_container *c,
1870 const char *contents) {
1876 if (!signature_is_single(contents, false))
1879 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1882 if (c->signature && c->signature[c->index]) {
1884 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1890 if (c->enclosing != 0)
1893 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1900 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1901 /* Variants are always aligned to 8 */
1903 if (!message_extend_body(m, 8, 0, false, false))
1910 l = strlen(contents);
1911 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1916 memcpy((uint8_t*) a + 1, contents, l + 1);
1919 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1925 static int bus_message_open_struct(
1927 struct bus_container *c,
1928 const char *contents,
1930 bool *need_offsets) {
1939 assert(need_offsets);
1941 if (!signature_is_valid(contents, false))
1944 if (c->signature && c->signature[c->index]) {
1947 l = strlen(contents);
1949 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1950 !startswith(c->signature + c->index + 1, contents) ||
1951 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1954 nindex = c->index + 1 + l + 1;
1958 if (c->enclosing != 0)
1961 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1967 nindex = e - c->signature;
1970 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1973 alignment = bus_gvariant_get_alignment(contents);
1977 if (!message_extend_body(m, alignment, 0, false, false))
1980 r = bus_gvariant_is_fixed_size(contents);
1984 *begin = m->body_size;
1985 *need_offsets = r == 0;
1987 /* Align contents to 8 byte boundary */
1988 if (!message_extend_body(m, 8, 0, false, false))
1992 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1998 static int bus_message_open_dict_entry(
2000 struct bus_container *c,
2001 const char *contents,
2003 bool *need_offsets) {
2011 assert(need_offsets);
2013 if (!signature_is_pair(contents))
2016 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2019 if (c->signature && c->signature[c->index]) {
2022 l = strlen(contents);
2024 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2025 !startswith(c->signature + c->index + 1, contents) ||
2026 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2031 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2034 alignment = bus_gvariant_get_alignment(contents);
2038 if (!message_extend_body(m, alignment, 0, false, false))
2041 r = bus_gvariant_is_fixed_size(contents);
2045 *begin = m->body_size;
2046 *need_offsets = r == 0;
2048 /* Align contents to 8 byte boundary */
2049 if (!message_extend_body(m, 8, 0, false, false))
2056 _public_ int sd_bus_message_open_container(
2059 const char *contents) {
2061 struct bus_container *c, *w;
2062 uint32_t *array_size = NULL;
2064 size_t before, begin = 0;
2065 bool need_offsets = false;
2068 assert_return(m, -EINVAL);
2069 assert_return(!m->sealed, -EPERM);
2070 assert_return(contents, -EINVAL);
2071 assert_return(!m->poisoned, -ESTALE);
2073 /* Make sure we have space for one more container */
2074 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2079 c = message_get_container(m);
2081 signature = strdup(contents);
2087 /* Save old index in the parent container, in case we have to
2088 * abort this container */
2089 c->saved_index = c->index;
2090 before = m->body_size;
2092 if (type == SD_BUS_TYPE_ARRAY)
2093 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2094 else if (type == SD_BUS_TYPE_VARIANT)
2095 r = bus_message_open_variant(m, c, contents);
2096 else if (type == SD_BUS_TYPE_STRUCT)
2097 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2098 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2099 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2108 /* OK, let's fill it in */
2109 w = m->containers + m->n_containers++;
2110 w->enclosing = type;
2111 w->signature = signature;
2113 w->array_size = array_size;
2116 w->n_offsets = w->offsets_allocated = 0;
2118 w->need_offsets = need_offsets;
2123 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2128 if (!BUS_MESSAGE_IS_GVARIANT(m))
2131 if (c->need_offsets) {
2132 size_t payload, sz, i;
2135 /* Variable-width arrays */
2137 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2138 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2140 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2144 for (i = 0; i < c->n_offsets; i++)
2145 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2149 /* Fixed-width or empty arrays */
2151 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2159 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2165 assert(c->signature);
2167 if (!BUS_MESSAGE_IS_GVARIANT(m))
2170 l = strlen(c->signature);
2172 a = message_extend_body(m, 1, 1 + l, true, false);
2177 memcpy(a+1, c->signature, l);
2182 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2183 bool fixed_size = true;
2184 size_t n_variable = 0;
2193 if (!BUS_MESSAGE_IS_GVARIANT(m))
2196 p = strempty(c->signature);
2200 r = signature_element_length(p, &n);
2209 r = bus_gvariant_is_fixed_size(t);
2214 assert(!c->need_offsets || i <= c->n_offsets);
2216 /* We need to add an offset for each item that has a
2217 * variable size and that is not the last one in the
2221 if (r == 0 && p[n] != 0)
2228 assert(!c->need_offsets || i == c->n_offsets);
2229 assert(c->need_offsets || n_variable == 0);
2231 if (isempty(c->signature)) {
2232 /* The unary type is encoded as fixed 1 byte padding */
2233 a = message_extend_body(m, 1, 1, add_offset, false);
2238 } else if (n_variable <= 0) {
2241 /* Structures with fixed-size members only have to be
2242 * fixed-size themselves. But gvariant requires all fixed-size
2243 * elements to be sized a multiple of their alignment. Hence,
2244 * we must *always* add final padding after the last member so
2245 * the overall size of the structure is properly aligned. */
2247 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2249 assert(alignment > 0);
2251 a = message_extend_body(m, alignment, 0, add_offset, false);
2258 assert(c->offsets[c->n_offsets-1] == m->body_size);
2260 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2262 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2266 p = strempty(c->signature);
2267 for (i = 0, j = 0; i < c->n_offsets; i++) {
2271 r = signature_element_length(p, &n);
2282 r = bus_gvariant_is_fixed_size(t);
2285 if (r > 0 || p[0] == 0)
2289 k = n_variable - 1 - j;
2291 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2300 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2301 struct bus_container *c;
2304 assert_return(m, -EINVAL);
2305 assert_return(!m->sealed, -EPERM);
2306 assert_return(m->n_containers > 0, -EINVAL);
2307 assert_return(!m->poisoned, -ESTALE);
2309 c = message_get_container(m);
2311 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2312 if (c->signature && c->signature[c->index] != 0)
2317 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2318 r = bus_message_close_array(m, c);
2319 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2320 r = bus_message_close_variant(m, c);
2321 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2322 r = bus_message_close_struct(m, c, true);
2324 assert_not_reached("Unknown container type");
2338 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2345 stack[*i].types = types;
2346 stack[*i].n_struct = n_struct;
2347 stack[*i].n_array = n_array;
2353 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2364 *types = stack[*i].types;
2365 *n_struct = stack[*i].n_struct;
2366 *n_array = stack[*i].n_array;
2371 int bus_message_append_ap(
2376 unsigned n_array, n_struct;
2377 TypeStack stack[BUS_CONTAINER_DEPTH];
2378 unsigned stack_ptr = 0;
2386 n_array = (unsigned) -1;
2387 n_struct = strlen(types);
2392 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2393 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2399 r = sd_bus_message_close_container(m);
2407 if (n_array != (unsigned) -1)
2416 case SD_BUS_TYPE_BYTE: {
2419 x = (uint8_t) va_arg(ap, int);
2420 r = sd_bus_message_append_basic(m, *t, &x);
2424 case SD_BUS_TYPE_BOOLEAN:
2425 case SD_BUS_TYPE_INT32:
2426 case SD_BUS_TYPE_UINT32:
2427 case SD_BUS_TYPE_UNIX_FD: {
2430 /* We assume a boolean is the same as int32_t */
2431 assert_cc(sizeof(int32_t) == sizeof(int));
2433 x = va_arg(ap, uint32_t);
2434 r = sd_bus_message_append_basic(m, *t, &x);
2438 case SD_BUS_TYPE_INT16:
2439 case SD_BUS_TYPE_UINT16: {
2442 x = (uint16_t) va_arg(ap, int);
2443 r = sd_bus_message_append_basic(m, *t, &x);
2447 case SD_BUS_TYPE_INT64:
2448 case SD_BUS_TYPE_UINT64: {
2451 x = va_arg(ap, uint64_t);
2452 r = sd_bus_message_append_basic(m, *t, &x);
2456 case SD_BUS_TYPE_DOUBLE: {
2459 x = va_arg(ap, double);
2460 r = sd_bus_message_append_basic(m, *t, &x);
2464 case SD_BUS_TYPE_STRING:
2465 case SD_BUS_TYPE_OBJECT_PATH:
2466 case SD_BUS_TYPE_SIGNATURE: {
2469 x = va_arg(ap, const char*);
2470 r = sd_bus_message_append_basic(m, *t, x);
2474 case SD_BUS_TYPE_ARRAY: {
2477 r = signature_element_length(t + 1, &k);
2483 memcpy(s, t + 1, k);
2486 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2491 if (n_array == (unsigned) -1) {
2496 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2502 n_array = va_arg(ap, unsigned);
2507 case SD_BUS_TYPE_VARIANT: {
2510 s = va_arg(ap, const char*);
2514 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2518 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2523 n_struct = strlen(s);
2524 n_array = (unsigned) -1;
2529 case SD_BUS_TYPE_STRUCT_BEGIN:
2530 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2533 r = signature_element_length(t, &k);
2540 memcpy(s, t + 1, k - 2);
2543 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2548 if (n_array == (unsigned) -1) {
2553 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2559 n_array = (unsigned) -1;
2575 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2579 assert_return(m, -EINVAL);
2580 assert_return(types, -EINVAL);
2581 assert_return(!m->sealed, -EPERM);
2582 assert_return(!m->poisoned, -ESTALE);
2584 va_start(ap, types);
2585 r = bus_message_append_ap(m, types, ap);
2591 /// UNNEEDED by elogind
2593 _public_ int sd_bus_message_append_array_space(
2603 assert_return(m, -EINVAL);
2604 assert_return(!m->sealed, -EPERM);
2605 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2606 assert_return(ptr || size == 0, -EINVAL);
2607 assert_return(!m->poisoned, -ESTALE);
2609 /* alignment and size of the trivial types (except bool) is
2610 * identical for gvariant and dbus1 marshalling */
2611 align = bus_type_get_alignment(type);
2612 sz = bus_type_get_size(type);
2614 assert_se(align > 0);
2620 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2624 a = message_extend_body(m, align, size, false, false);
2628 r = sd_bus_message_close_container(m);
2636 _public_ int sd_bus_message_append_array(
2644 assert_return(m, -EINVAL);
2645 assert_return(!m->sealed, -EPERM);
2646 assert_return(bus_type_is_trivial(type), -EINVAL);
2647 assert_return(ptr || size == 0, -EINVAL);
2648 assert_return(!m->poisoned, -ESTALE);
2650 r = sd_bus_message_append_array_space(m, type, size, &p);
2655 memcpy(p, ptr, size);
2660 _public_ int sd_bus_message_append_array_iovec(
2663 const struct iovec *iov,
2671 assert_return(m, -EINVAL);
2672 assert_return(!m->sealed, -EPERM);
2673 assert_return(bus_type_is_trivial(type), -EINVAL);
2674 assert_return(iov || n == 0, -EINVAL);
2675 assert_return(!m->poisoned, -ESTALE);
2677 size = IOVEC_TOTAL_SIZE(iov, n);
2679 r = sd_bus_message_append_array_space(m, type, size, &p);
2683 for (i = 0; i < n; i++) {
2685 if (iov[i].iov_base)
2686 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2688 memzero(p, iov[i].iov_len);
2690 p = (uint8_t*) p + iov[i].iov_len;
2696 _public_ int sd_bus_message_append_array_memfd(
2703 _cleanup_close_ int copy_fd = -1;
2704 struct bus_body_part *part;
2710 assert_return(m, -EINVAL);
2711 assert_return(memfd >= 0, -EBADF);
2712 assert_return(bus_type_is_trivial(type), -EINVAL);
2713 assert_return(size > 0, -EINVAL);
2714 assert_return(!m->sealed, -EPERM);
2715 assert_return(!m->poisoned, -ESTALE);
2717 r = memfd_set_sealed(memfd);
2721 copy_fd = dup(memfd);
2725 r = memfd_get_size(memfd, &real_size);
2729 if (offset == 0 && size == (uint64_t) -1)
2731 else if (offset + size > real_size)
2734 align = bus_type_get_alignment(type);
2735 sz = bus_type_get_size(type);
2737 assert_se(align > 0);
2740 if (offset % align != 0)
2746 if (size > (uint64_t) (uint32_t) -1)
2749 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2753 a = message_extend_body(m, align, 0, false, false);
2757 part = message_append_part(m);
2761 part->memfd = copy_fd;
2762 part->memfd_offset = offset;
2763 part->sealed = true;
2767 m->body_size += size;
2768 message_extend_containers(m, size);
2770 return sd_bus_message_close_container(m);
2773 _public_ int sd_bus_message_append_string_memfd(
2779 _cleanup_close_ int copy_fd = -1;
2780 struct bus_body_part *part;
2781 struct bus_container *c;
2786 assert_return(m, -EINVAL);
2787 assert_return(memfd >= 0, -EBADF);
2788 assert_return(size > 0, -EINVAL);
2789 assert_return(!m->sealed, -EPERM);
2790 assert_return(!m->poisoned, -ESTALE);
2792 r = memfd_set_sealed(memfd);
2796 copy_fd = dup(memfd);
2800 r = memfd_get_size(memfd, &real_size);
2804 if (offset == 0 && size == (uint64_t) -1)
2806 else if (offset + size > real_size)
2809 /* We require this to be NUL terminated */
2813 if (size > (uint64_t) (uint32_t) -1)
2816 c = message_get_container(m);
2817 if (c->signature && c->signature[c->index]) {
2818 /* Container signature is already set */
2820 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2825 /* Maybe we can append to the signature? But only if this is the top-level container */
2826 if (c->enclosing != 0)
2829 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2836 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2837 a = message_extend_body(m, 4, 4, false, false);
2841 *(uint32_t*) a = size - 1;
2844 part = message_append_part(m);
2848 part->memfd = copy_fd;
2849 part->memfd_offset = offset;
2850 part->sealed = true;
2854 m->body_size += size;
2855 message_extend_containers(m, size);
2857 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2858 r = message_add_offset(m, m->body_size);
2865 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2872 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2876 assert_return(m, -EINVAL);
2877 assert_return(!m->sealed, -EPERM);
2878 assert_return(!m->poisoned, -ESTALE);
2880 r = sd_bus_message_open_container(m, 'a', "s");
2884 STRV_FOREACH(i, l) {
2885 r = sd_bus_message_append_basic(m, 's', *i);
2890 return sd_bus_message_close_container(m);
2893 static int bus_message_close_header(sd_bus_message *m) {
2897 /* The actual user data is finished now, we just complete the
2898 variant and struct now (at least on gvariant). Remember
2899 this position, so that during parsing we know where to to
2900 put the outer container end. */
2901 m->user_body_size = m->body_size;
2903 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2904 const char *signature;
2908 /* Add offset table to end of fields array */
2909 if (m->n_header_offsets >= 1) {
2913 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2915 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2916 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2920 for (i = 0; i < m->n_header_offsets; i++)
2921 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2924 /* Add gvariant NUL byte plus signature to the end of
2925 * the body, followed by the final offset pointing to
2926 * the end of the fields array */
2928 signature = strempty(m->root_container.signature);
2929 l = strlen(signature);
2931 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2932 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2937 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2938 memcpy((uint8_t*) d + 2, signature, l);
2939 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2941 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2944 m->footer_accessible = 1 + l + 2 + sz;
2946 m->header->dbus1.fields_size = m->fields_size;
2947 m->header->dbus1.body_size = m->body_size;
2953 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2954 struct bus_body_part *part;
2964 if (m->n_containers > 0)
2970 if (cookie > 0xffffffffULL &&
2971 !BUS_MESSAGE_IS_GVARIANT(m))
2974 /* In vtables the return signature of method calls is listed,
2975 * let's check if they match if this is a response */
2976 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2977 m->enforced_reply_signature &&
2978 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2981 /* If gvariant marshalling is used we need to close the body structure */
2982 r = bus_message_close_struct(m, &m->root_container, false);
2986 /* If there's a non-trivial signature set, then add it in
2987 * here, but only on dbus1 */
2988 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2989 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2995 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
3000 r = bus_message_close_header(m);
3004 if (BUS_MESSAGE_IS_GVARIANT(m))
3005 m->header->dbus2.cookie = cookie;
3007 m->header->dbus1.serial = (uint32_t) cookie;
3009 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
3011 /* Add padding at the end of the fields part, since we know
3012 * the body needs to start at an 8 byte alignment. We made
3013 * sure we allocated enough space for this, so all we need to
3014 * do here is to zero it out. */
3015 a = ALIGN8(m->fields_size) - m->fields_size;
3017 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
3019 /* If this is something we can send as memfd, then let's seal
3020 the memfd now. Note that we can send memfds as payload only
3021 for directed messages, and not for broadcasts. */
3022 if (m->destination && m->bus->use_memfd) {
3023 MESSAGE_FOREACH_PART(part, i, m)
3024 if (part->memfd >= 0 &&
3026 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3027 part != m->body_end) { /* The last part may never be sent as memfd */
3030 /* Try to seal it if that makes
3031 * sense. First, unmap our own map to
3032 * make sure we don't keep it busy. */
3033 bus_body_part_unmap(part);
3035 /* Then, sync up real memfd size */
3037 r = memfd_set_size(part->memfd, sz);
3041 /* Finally, try to seal */
3042 if (memfd_set_sealed(part->memfd) >= 0)
3043 part->sealed = true;
3047 m->root_container.end = m->user_body_size;
3048 m->root_container.index = 0;
3049 m->root_container.offset_index = 0;
3050 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3057 int bus_body_part_map(struct bus_body_part *part) {
3066 if (part->size <= 0)
3069 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3070 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3071 static const uint8_t zeroes[7] = { };
3072 part->data = (void*) zeroes;
3076 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3077 psz = PAGE_ALIGN(part->size + shift);
3079 if (part->memfd >= 0)
3080 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3081 else if (part->is_zero)
3082 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3086 if (p == MAP_FAILED)
3090 part->mmap_begin = p;
3091 part->data = (uint8_t*) p + shift;
3092 part->munmap_this = true;
3097 void bus_body_part_unmap(struct bus_body_part *part) {
3101 if (part->memfd < 0)
3104 if (!part->mmap_begin)
3107 if (!part->munmap_this)
3110 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3112 part->mmap_begin = NULL;
3115 part->munmap_this = false;
3120 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3121 size_t k, start, end;
3126 start = ALIGN_TO((size_t) *rindex, align);
3127 end = start + nbytes;
3132 /* Verify that padding is 0 */
3133 for (k = *rindex; k < start; k++)
3134 if (((const uint8_t*) p)[k] != 0)
3138 *r = (uint8_t*) p + start;
3145 static bool message_end_of_signature(sd_bus_message *m) {
3146 struct bus_container *c;
3150 c = message_get_container(m);
3151 return !c->signature || c->signature[c->index] == 0;
3154 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3155 struct bus_container *c;
3159 c = message_get_container(m);
3160 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3163 if (BUS_MESSAGE_IS_GVARIANT(m))
3164 return index >= c->end;
3166 assert(c->array_size);
3167 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3171 /// UNNEEDED by elogind
3173 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3174 assert_return(m, -EINVAL);
3175 assert_return(m->sealed, -EPERM);
3177 if (complete && m->n_containers > 0)
3180 if (message_end_of_signature(m))
3183 if (message_end_of_array(m, m->rindex))
3190 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3191 struct bus_body_part *part;
3197 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3198 part = m->cached_rindex_part;
3199 begin = m->cached_rindex_part_begin;
3209 if (index + sz <= begin + part->size) {
3211 r = bus_body_part_map(part);
3216 *p = (uint8_t*) part->data + index - begin;
3218 m->cached_rindex_part = part;
3219 m->cached_rindex_part_begin = begin;
3224 begin += part->size;
3231 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3238 if (!BUS_MESSAGE_IS_GVARIANT(m))
3241 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3244 sz = bus_gvariant_get_size(c->signature);
3248 if (c->offset_index+1 >= c->n_offsets)
3251 /* Variable-size array */
3253 alignment = bus_gvariant_get_alignment(c->signature);
3254 assert(alignment > 0);
3256 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3257 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3260 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3263 /* Fixed-size array */
3264 *rindex = c->begin + (c->offset_index+1) * sz;
3270 } else if (c->enclosing == 0 ||
3271 c->enclosing == SD_BUS_TYPE_STRUCT ||
3272 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3277 if (c->offset_index+1 >= c->n_offsets)
3280 r = signature_element_length(c->signature + c->index, &n);
3284 r = signature_element_length(c->signature + c->index + n, &j);
3289 memcpy(t, c->signature + c->index + n, j);
3292 alignment = bus_gvariant_get_alignment(t);
3295 assert(alignment > 0);
3297 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3298 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3302 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3305 assert_not_reached("Unknown container type");
3310 /* Reached the end */
3317 static int message_peek_body(
3324 size_t k, start, end, padding;
3325 struct bus_body_part *part;
3332 start = ALIGN_TO((size_t) *rindex, align);
3333 padding = start - *rindex;
3334 end = start + nbytes;
3336 if (end > m->user_body_size)
3339 part = find_part(m, *rindex, padding, (void**) &q);
3344 /* Verify padding */
3345 for (k = 0; k < padding; k++)
3350 part = find_part(m, start, nbytes, (void**) &q);
3351 if (!part || (nbytes > 0 && !q))
3362 static bool validate_nul(const char *s, size_t l) {
3364 /* Check for NUL chars in the string */
3365 if (memchr(s, 0, l))
3368 /* Check for NUL termination */
3375 static bool validate_string(const char *s, size_t l) {
3377 if (!validate_nul(s, l))
3380 /* Check if valid UTF8 */
3381 if (!utf8_is_valid(s))
3387 static bool validate_signature(const char *s, size_t l) {
3389 if (!validate_nul(s, l))
3392 /* Check if valid signature */
3393 if (!signature_is_valid(s, true))
3399 static bool validate_object_path(const char *s, size_t l) {
3401 if (!validate_nul(s, l))
3404 if (!object_path_is_valid(s))
3410 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3411 struct bus_container *c;
3416 assert_return(m, -EINVAL);
3417 assert_return(m->sealed, -EPERM);
3418 assert_return(bus_type_is_basic(type), -EINVAL);
3420 if (message_end_of_signature(m))
3423 if (message_end_of_array(m, m->rindex))
3426 c = message_get_container(m);
3427 if (c->signature[c->index] != type)
3432 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3434 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3437 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3441 if (type == SD_BUS_TYPE_STRING)
3442 ok = validate_string(q, c->item_size-1);
3443 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3444 ok = validate_object_path(q, c->item_size-1);
3446 ok = validate_signature(q, c->item_size-1);
3452 *(const char**) p = q;
3456 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3458 if ((size_t) sz != c->item_size)
3461 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3464 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3470 case SD_BUS_TYPE_BYTE:
3472 *(uint8_t*) p = *(uint8_t*) q;
3475 case SD_BUS_TYPE_BOOLEAN:
3477 *(int*) p = !!*(uint8_t*) q;
3480 case SD_BUS_TYPE_INT16:
3481 case SD_BUS_TYPE_UINT16:
3483 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3486 case SD_BUS_TYPE_INT32:
3487 case SD_BUS_TYPE_UINT32:
3489 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3492 case SD_BUS_TYPE_INT64:
3493 case SD_BUS_TYPE_UINT64:
3494 case SD_BUS_TYPE_DOUBLE:
3496 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3499 case SD_BUS_TYPE_UNIX_FD: {
3502 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3507 *(int*) p = m->fds[j];
3513 assert_not_reached("unexpected type");
3517 r = container_next_item(m, c, &rindex);
3522 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3526 r = message_peek_body(m, &rindex, 4, 4, &q);
3530 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3531 r = message_peek_body(m, &rindex, 1, l+1, &q);
3535 if (type == SD_BUS_TYPE_OBJECT_PATH)
3536 ok = validate_object_path(q, l);
3538 ok = validate_string(q, l);
3543 *(const char**) p = q;
3545 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3548 r = message_peek_body(m, &rindex, 1, 1, &q);
3553 r = message_peek_body(m, &rindex, 1, l+1, &q);
3557 if (!validate_signature(q, l))
3561 *(const char**) p = q;
3566 align = bus_type_get_alignment(type);
3569 sz = bus_type_get_size(type);
3572 r = message_peek_body(m, &rindex, align, sz, &q);
3578 case SD_BUS_TYPE_BYTE:
3580 *(uint8_t*) p = *(uint8_t*) q;
3583 case SD_BUS_TYPE_BOOLEAN:
3585 *(int*) p = !!*(uint32_t*) q;
3588 case SD_BUS_TYPE_INT16:
3589 case SD_BUS_TYPE_UINT16:
3591 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3594 case SD_BUS_TYPE_INT32:
3595 case SD_BUS_TYPE_UINT32:
3597 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3600 case SD_BUS_TYPE_INT64:
3601 case SD_BUS_TYPE_UINT64:
3602 case SD_BUS_TYPE_DOUBLE:
3604 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3607 case SD_BUS_TYPE_UNIX_FD: {
3610 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3615 *(int*) p = m->fds[j];
3620 assert_not_reached("Unknown basic type...");
3627 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3633 static int bus_message_enter_array(
3635 struct bus_container *c,
3636 const char *contents,
3637 uint32_t **array_size,
3640 size_t *n_offsets) {
3654 if (!signature_is_single(contents, true))
3657 if (!c->signature || c->signature[c->index] == 0)
3660 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3663 if (!startswith(c->signature + c->index + 1, contents))
3668 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3671 r = message_peek_body(m, &rindex, 4, 4, &q);
3675 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3678 alignment = bus_type_get_alignment(contents[0]);
3682 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3686 *array_size = (uint32_t*) q;
3688 } else if (c->item_size <= 0) {
3690 /* gvariant: empty array */
3695 } else if (bus_gvariant_is_fixed_size(contents)) {
3697 /* gvariant: fixed length array */
3698 *item_size = bus_gvariant_get_size(contents);
3703 size_t where, p = 0, framing, sz;
3706 /* gvariant: variable length array */
3707 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3709 where = rindex + c->item_size - sz;
3710 r = message_peek_body(m, &where, 1, sz, &q);
3714 framing = bus_gvariant_read_word_le(q, sz);
3715 if (framing > c->item_size - sz)
3717 if ((c->item_size - framing) % sz != 0)
3720 *n_offsets = (c->item_size - framing) / sz;
3722 where = rindex + framing;
3723 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3727 *offsets = new(size_t, *n_offsets);
3731 for (i = 0; i < *n_offsets; i++) {
3734 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3735 if (x > c->item_size - sz)
3740 (*offsets)[i] = rindex + x;
3744 *item_size = (*offsets)[0] - rindex;
3749 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3750 c->index += 1 + strlen(contents);
3755 static int bus_message_enter_variant(
3757 struct bus_container *c,
3758 const char *contents,
3759 size_t *item_size) {
3771 if (!signature_is_single(contents, false))
3774 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3777 if (!c->signature || c->signature[c->index] == 0)
3780 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3785 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3788 k = strlen(contents);
3789 if (1+k > c->item_size)
3792 where = rindex + c->item_size - (1+k);
3793 r = message_peek_body(m, &where, 1, 1+k, &q);
3797 if (*(char*) q != 0)
3800 if (memcmp((uint8_t*) q+1, contents, k))
3803 *item_size = c->item_size - (1+k);
3806 r = message_peek_body(m, &rindex, 1, 1, &q);
3811 r = message_peek_body(m, &rindex, 1, l+1, &q);
3815 if (!validate_signature(q, l))
3818 if (!streq(q, contents))
3824 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3830 static int build_struct_offsets(
3832 const char *signature,
3836 size_t *n_offsets) {
3838 unsigned n_variable = 0, n_total = 0, v;
3839 size_t previous = 0, where;
3850 if (isempty(signature)) {
3851 /* Unary type is encoded as *fixed* 1 byte padding */
3852 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3856 if (*(uint8_t *) q != 0)
3865 sz = bus_gvariant_determine_word_size(size, 0);
3869 /* First, loop over signature and count variable elements and
3870 * elements in general. We use this to know how large the
3871 * offset array is at the end of the structure. Note that
3872 * GVariant only stores offsets for all variable size elements
3873 * that are not the last item. */
3879 r = signature_element_length(p, &n);
3888 r = bus_gvariant_is_fixed_size(t);
3893 if (r == 0 && p[n] != 0) /* except the last item */
3900 if (size < n_variable * sz)
3903 where = m->rindex + size - (n_variable * sz);
3904 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3910 *offsets = new(size_t, n_total);
3916 /* Second, loop again and build an offset table */
3922 r = signature_element_length(p, &n);
3931 k = bus_gvariant_get_size(t);
3939 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3942 if (m->rindex + x < previous)
3945 /* The last item's end
3946 * is determined from
3949 x = size - (n_variable * sz);
3951 offset = m->rindex + x;
3957 align = bus_gvariant_get_alignment(t);
3960 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3964 previous = (*offsets)[(*n_offsets)++] = offset;
3969 assert(*n_offsets == n_total);
3971 *item_size = (*offsets)[0] - m->rindex;
3975 static int enter_struct_or_dict_entry(
3977 struct bus_container *c,
3978 const char *contents,
3981 size_t *n_offsets) {
3992 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3995 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
4000 /* gvariant with contents */
4001 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
4006 static int bus_message_enter_struct(
4008 struct bus_container *c,
4009 const char *contents,
4012 size_t *n_offsets) {
4024 if (!signature_is_valid(contents, false))
4027 if (!c->signature || c->signature[c->index] == 0)
4030 l = strlen(contents);
4032 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4033 !startswith(c->signature + c->index + 1, contents) ||
4034 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4037 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4041 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4042 c->index += 1 + l + 1;
4047 static int bus_message_enter_dict_entry(
4049 struct bus_container *c,
4050 const char *contents,
4053 size_t *n_offsets) {
4062 if (!signature_is_pair(contents))
4065 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4068 if (!c->signature || c->signature[c->index] == 0)
4071 l = strlen(contents);
4073 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4074 !startswith(c->signature + c->index + 1, contents) ||
4075 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4078 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4082 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4083 c->index += 1 + l + 1;
4088 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4090 const char *contents) {
4091 struct bus_container *c, *w;
4092 uint32_t *array_size = NULL;
4095 size_t *offsets = NULL;
4096 size_t n_offsets = 0, item_size = 0;
4099 assert_return(m, -EINVAL);
4100 assert_return(m->sealed, -EPERM);
4101 assert_return(type != 0 || !contents, -EINVAL);
4103 if (type == 0 || !contents) {
4107 /* Allow entering into anonymous containers */
4108 r = sd_bus_message_peek_type(m, &tt, &cc);
4112 if (type != 0 && type != tt)
4115 if (contents && !streq(contents, cc))
4123 * We enforce a global limit on container depth, that is much
4124 * higher than the 32 structs and 32 arrays the specification
4125 * mandates. This is simpler to implement for us, and we need
4126 * this only to ensure our container array doesn't grow
4127 * without bounds. We are happy to return any data from a
4128 * message as long as the data itself is valid, even if the
4129 * overall message might be not.
4131 * Note that the message signature is validated when
4132 * parsing the headers, and that validation does check the
4135 * Note that the specification defines no limits on the depth
4136 * of stacked variants, but we do.
4138 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4141 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4144 if (message_end_of_signature(m))
4147 if (message_end_of_array(m, m->rindex))
4150 c = message_get_container(m);
4152 signature = strdup(contents);
4156 c->saved_index = c->index;
4159 if (type == SD_BUS_TYPE_ARRAY)
4160 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4161 else if (type == SD_BUS_TYPE_VARIANT)
4162 r = bus_message_enter_variant(m, c, contents, &item_size);
4163 else if (type == SD_BUS_TYPE_STRUCT)
4164 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4165 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4166 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4176 /* OK, let's fill it in */
4177 w = m->containers + m->n_containers++;
4178 w->enclosing = type;
4179 w->signature = signature;
4180 w->peeked_signature = NULL;
4184 w->begin = m->rindex;
4186 /* Unary type has fixed size of 1, but virtual size of 0 */
4187 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4188 type == SD_BUS_TYPE_STRUCT &&
4190 w->end = m->rindex + 0;
4192 w->end = m->rindex + c->item_size;
4194 w->array_size = array_size;
4195 w->item_size = item_size;
4196 w->offsets = offsets;
4197 w->n_offsets = n_offsets;
4198 w->offset_index = 0;
4203 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4204 struct bus_container *c;
4208 assert_return(m, -EINVAL);
4209 assert_return(m->sealed, -EPERM);
4210 assert_return(m->n_containers > 0, -ENXIO);
4212 c = message_get_container(m);
4214 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4215 if (c->signature && c->signature[c->index] != 0)
4219 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4220 if (m->rindex < c->end)
4223 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4226 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4227 if (c->begin + l != m->rindex)
4232 free(c->peeked_signature);
4236 c = message_get_container(m);
4239 c->index = c->saved_index;
4240 r = container_next_item(m, c, &m->rindex);
4248 static void message_quit_container(sd_bus_message *m) {
4249 struct bus_container *c;
4253 assert(m->n_containers > 0);
4255 c = message_get_container(m);
4258 assert(m->rindex >= c->before);
4259 m->rindex = c->before;
4261 /* Free container */
4266 /* Correct index of new top-level container */
4267 c = message_get_container(m);
4268 c->index = c->saved_index;
4271 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4272 struct bus_container *c;
4275 assert_return(m, -EINVAL);
4276 assert_return(m->sealed, -EPERM);
4278 if (message_end_of_signature(m))
4281 if (message_end_of_array(m, m->rindex))
4284 c = message_get_container(m);
4286 if (bus_type_is_basic(c->signature[c->index])) {
4290 *type = c->signature[c->index];
4294 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4300 r = signature_element_length(c->signature+c->index+1, &l);
4306 sig = strndup(c->signature + c->index + 1, l);
4310 free(c->peeked_signature);
4311 *contents = c->peeked_signature = sig;
4315 *type = SD_BUS_TYPE_ARRAY;
4320 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4321 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4327 r = signature_element_length(c->signature+c->index, &l);
4332 sig = strndup(c->signature + c->index + 1, l - 2);
4336 free(c->peeked_signature);
4337 *contents = c->peeked_signature = sig;
4341 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4346 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4350 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4353 if (c->item_size < 2)
4356 /* Look for the NUL delimiter that
4357 separates the payload from the
4358 signature. Since the body might be
4359 in a different part that then the
4360 signature we map byte by byte. */
4362 for (k = 2; k <= c->item_size; k++) {
4365 where = m->rindex + c->item_size - k;
4366 r = message_peek_body(m, &where, 1, k, &q);
4370 if (*(char*) q == 0)
4374 if (k > c->item_size)
4377 free(c->peeked_signature);
4378 c->peeked_signature = strndup((char*) q + 1, k - 1);
4379 if (!c->peeked_signature)
4382 if (!signature_is_valid(c->peeked_signature, true))
4385 *contents = c->peeked_signature;
4390 r = message_peek_body(m, &rindex, 1, 1, &q);
4395 r = message_peek_body(m, &rindex, 1, l+1, &q);
4399 if (!validate_signature(q, l))
4407 *type = SD_BUS_TYPE_VARIANT;
4422 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4423 struct bus_container *c;
4425 assert_return(m, -EINVAL);
4426 assert_return(m->sealed, -EPERM);
4429 message_reset_containers(m);
4432 c = message_get_container(m);
4434 c = message_get_container(m);
4436 c->offset_index = 0;
4438 m->rindex = c->begin;
4441 c->offset_index = 0;
4442 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4444 return !isempty(c->signature);
4447 static int message_read_ap(
4452 unsigned n_array, n_struct;
4453 TypeStack stack[BUS_CONTAINER_DEPTH];
4454 unsigned stack_ptr = 0;
4455 unsigned n_loop = 0;
4463 /* Ideally, we'd just call ourselves recursively on every
4464 * complex type. However, the state of a va_list that is
4465 * passed to a function is undefined after that function
4466 * returns. This means we need to docode the va_list linearly
4467 * in a single stackframe. We hence implement our own
4468 * home-grown stack in an array. */
4470 n_array = (unsigned) -1; /* length of current array entries */
4471 n_struct = strlen(types); /* length of current struct contents signature */
4478 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4479 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4485 r = sd_bus_message_exit_container(m);
4493 if (n_array != (unsigned) -1)
4502 case SD_BUS_TYPE_BYTE:
4503 case SD_BUS_TYPE_BOOLEAN:
4504 case SD_BUS_TYPE_INT16:
4505 case SD_BUS_TYPE_UINT16:
4506 case SD_BUS_TYPE_INT32:
4507 case SD_BUS_TYPE_UINT32:
4508 case SD_BUS_TYPE_INT64:
4509 case SD_BUS_TYPE_UINT64:
4510 case SD_BUS_TYPE_DOUBLE:
4511 case SD_BUS_TYPE_STRING:
4512 case SD_BUS_TYPE_OBJECT_PATH:
4513 case SD_BUS_TYPE_SIGNATURE:
4514 case SD_BUS_TYPE_UNIX_FD: {
4517 p = va_arg(ap, void*);
4518 r = sd_bus_message_read_basic(m, *t, p);
4531 case SD_BUS_TYPE_ARRAY: {
4534 r = signature_element_length(t + 1, &k);
4540 memcpy(s, t + 1, k);
4543 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4554 if (n_array == (unsigned) -1) {
4559 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4565 n_array = va_arg(ap, unsigned);
4570 case SD_BUS_TYPE_VARIANT: {
4573 s = va_arg(ap, const char *);
4577 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4587 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4592 n_struct = strlen(s);
4593 n_array = (unsigned) -1;
4598 case SD_BUS_TYPE_STRUCT_BEGIN:
4599 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4602 r = signature_element_length(t, &k);
4608 memcpy(s, t + 1, k - 2);
4611 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4621 if (n_array == (unsigned) -1) {
4626 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4632 n_array = (unsigned) -1;
4645 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4649 assert_return(m, -EINVAL);
4650 assert_return(m->sealed, -EPERM);
4651 assert_return(types, -EINVAL);
4653 va_start(ap, types);
4654 r = message_read_ap(m, types, ap);
4660 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4663 assert_return(m, -EINVAL);
4664 assert_return(m->sealed, -EPERM);
4666 /* If types is NULL, read exactly one element */
4668 struct bus_container *c;
4671 if (message_end_of_signature(m))
4674 if (message_end_of_array(m, m->rindex))
4677 c = message_get_container(m);
4679 r = signature_element_length(c->signature + c->index, &l);
4683 types = strndupa(c->signature + c->index, l);
4688 case 0: /* Nothing to drop */
4691 case SD_BUS_TYPE_BYTE:
4692 case SD_BUS_TYPE_BOOLEAN:
4693 case SD_BUS_TYPE_INT16:
4694 case SD_BUS_TYPE_UINT16:
4695 case SD_BUS_TYPE_INT32:
4696 case SD_BUS_TYPE_UINT32:
4697 case SD_BUS_TYPE_INT64:
4698 case SD_BUS_TYPE_UINT64:
4699 case SD_BUS_TYPE_DOUBLE:
4700 case SD_BUS_TYPE_STRING:
4701 case SD_BUS_TYPE_OBJECT_PATH:
4702 case SD_BUS_TYPE_SIGNATURE:
4703 case SD_BUS_TYPE_UNIX_FD:
4705 r = sd_bus_message_read_basic(m, *types, NULL);
4709 r = sd_bus_message_skip(m, types + 1);
4715 case SD_BUS_TYPE_ARRAY: {
4718 r = signature_element_length(types + 1, &k);
4724 memcpy(s, types+1, k);
4727 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4732 r = sd_bus_message_skip(m, s);
4739 r = sd_bus_message_exit_container(m);
4744 r = sd_bus_message_skip(m, types + 1 + k);
4751 case SD_BUS_TYPE_VARIANT: {
4752 const char *contents;
4755 r = sd_bus_message_peek_type(m, &x, &contents);
4759 if (x != SD_BUS_TYPE_VARIANT)
4762 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4766 r = sd_bus_message_skip(m, contents);
4771 r = sd_bus_message_exit_container(m);
4775 r = sd_bus_message_skip(m, types + 1);
4782 case SD_BUS_TYPE_STRUCT_BEGIN:
4783 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4786 r = signature_element_length(types, &k);
4792 memcpy(s, types+1, k-2);
4795 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4799 r = sd_bus_message_skip(m, s);
4803 r = sd_bus_message_exit_container(m);
4808 r = sd_bus_message_skip(m, types + k);
4820 _public_ int sd_bus_message_read_array(
4826 struct bus_container *c;
4832 assert_return(m, -EINVAL);
4833 assert_return(m->sealed, -EPERM);
4834 assert_return(bus_type_is_trivial(type), -EINVAL);
4835 assert_return(ptr, -EINVAL);
4836 assert_return(size, -EINVAL);
4837 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4839 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4843 c = message_get_container(m);
4845 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4846 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4850 sz = c->end - c->begin;
4852 align = bus_type_get_alignment(type);
4856 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4860 /* Zero length array, let's return some aligned
4861 * pointer that is not NULL */
4862 p = (uint8_t*) NULL + align;
4864 r = message_peek_body(m, &m->rindex, align, sz, &p);
4869 r = sd_bus_message_exit_container(m);
4873 *ptr = (const void*) p;
4879 message_quit_container(m);
4883 static int message_peek_fields(
4894 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4897 static int message_peek_field_uint32(
4909 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4912 /* identical for gvariant and dbus1 */
4914 r = message_peek_fields(m, ri, 4, 4, &q);
4919 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4924 static int message_peek_field_uint64(
4936 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4939 /* identical for gvariant and dbus1 */
4941 r = message_peek_fields(m, ri, 8, 8, &q);
4946 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4951 static int message_peek_field_string(
4953 bool (*validate)(const char *p),
4965 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4970 r = message_peek_fields(m, ri, 1, item_size, &q);
4976 r = message_peek_field_uint32(m, ri, 4, &l);
4980 r = message_peek_fields(m, ri, 1, l+1, &q);
4986 if (!validate_nul(q, l))
4992 if (!validate_string(q, l))
5002 static int message_peek_field_signature(
5015 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5020 r = message_peek_fields(m, ri, 1, item_size, &q);
5026 r = message_peek_fields(m, ri, 1, 1, &q);
5031 r = message_peek_fields(m, ri, 1, l+1, &q);
5036 if (!validate_signature(q, l))
5045 static int message_skip_fields(
5048 uint32_t array_size,
5049 const char **signature) {
5051 size_t original_index;
5057 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5059 original_index = *ri;
5065 if (array_size != (uint32_t) -1 &&
5066 array_size <= *ri - original_index)
5073 if (t == SD_BUS_TYPE_STRING) {
5075 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5081 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5083 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5089 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5091 r = message_peek_field_signature(m, ri, 0, NULL);
5097 } else if (bus_type_is_basic(t)) {
5100 align = bus_type_get_alignment(t);
5101 k = bus_type_get_size(t);
5102 assert(align > 0 && k > 0);
5104 r = message_peek_fields(m, ri, align, k, NULL);
5110 } else if (t == SD_BUS_TYPE_ARRAY) {
5112 r = signature_element_length(*signature+1, &l);
5122 strncpy(sig, *signature + 1, l-1);
5125 alignment = bus_type_get_alignment(sig[0]);
5129 r = message_peek_field_uint32(m, ri, 0, &nas);
5132 if (nas > BUS_ARRAY_MAX_SIZE)
5135 r = message_peek_fields(m, ri, alignment, 0, NULL);
5139 r = message_skip_fields(m, ri, nas, (const char**) &s);
5144 (*signature) += 1 + l;
5146 } else if (t == SD_BUS_TYPE_VARIANT) {
5149 r = message_peek_field_signature(m, ri, 0, &s);
5153 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5159 } else if (t == SD_BUS_TYPE_STRUCT ||
5160 t == SD_BUS_TYPE_DICT_ENTRY) {
5162 r = signature_element_length(*signature, &l);
5169 strncpy(sig, *signature + 1, l-1);
5172 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5183 int bus_message_parse_fields(sd_bus_message *m) {
5186 uint32_t unix_fds = 0;
5187 bool unix_fds_set = false;
5188 void *offsets = NULL;
5189 unsigned n_offsets = 0;
5195 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5198 /* Read the signature from the end of the body variant first */
5199 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5200 if (m->footer_accessible < 1 + sz)
5203 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5205 if (p < (char*) m->footer)
5212 /* We found the beginning of the signature
5213 * string, yay! We require the body to be a
5214 * structure, so verify it and then strip the
5215 * opening/closing brackets. */
5217 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5219 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5220 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5223 c = strndup(p + 1 + 1, l - 2);
5227 free(m->root_container.signature);
5228 m->root_container.signature = c;
5235 /* Calculate the actual user body size, by removing
5236 * the trailing variant signature and struct offset
5238 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5240 /* Pull out the offset table for the fields array */
5241 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5246 ri = m->fields_size - sz;
5247 r = message_peek_fields(m, &ri, 1, sz, &q);
5251 framing = bus_gvariant_read_word_le(q, sz);
5252 if (framing >= m->fields_size - sz)
5254 if ((m->fields_size - framing) % sz != 0)
5258 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5262 n_offsets = (m->fields_size - framing) / sz;
5265 m->user_body_size = m->body_size;
5268 while (ri < m->fields_size) {
5269 _cleanup_free_ char *sig = NULL;
5270 const char *signature;
5271 uint64_t field_type;
5272 size_t item_size = (size_t) -1;
5274 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5283 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5285 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5289 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5293 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5300 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5305 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5310 where = ri = ALIGN_TO(ri, 8);
5311 item_size = end - ri;
5312 r = message_peek_fields(m, &where, 1, item_size, &q);
5316 b = memrchr(q, 0, item_size);
5320 sig = strndup(b+1, item_size - (b+1-(char*) q));
5325 item_size = b - (char*) q;
5327 r = message_peek_field_signature(m, &ri, 0, &signature);
5332 switch (field_type) {
5334 case _BUS_MESSAGE_HEADER_INVALID:
5337 case BUS_MESSAGE_HEADER_PATH:
5342 if (!streq(signature, "o"))
5345 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5348 case BUS_MESSAGE_HEADER_INTERFACE:
5353 if (!streq(signature, "s"))
5356 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5359 case BUS_MESSAGE_HEADER_MEMBER:
5364 if (!streq(signature, "s"))
5367 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5370 case BUS_MESSAGE_HEADER_ERROR_NAME:
5375 if (!streq(signature, "s"))
5378 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5380 m->error._need_free = -1;
5384 case BUS_MESSAGE_HEADER_DESTINATION:
5389 if (!streq(signature, "s"))
5392 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5395 case BUS_MESSAGE_HEADER_SENDER:
5400 if (!streq(signature, "s"))
5403 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5405 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5406 m->creds.unique_name = (char*) m->sender;
5407 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5413 case BUS_MESSAGE_HEADER_SIGNATURE: {
5417 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5420 if (m->root_container.signature)
5423 if (!streq(signature, "g"))
5426 r = message_peek_field_signature(m, &ri, item_size, &s);
5434 free(m->root_container.signature);
5435 m->root_container.signature = c;
5439 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5441 if (m->reply_cookie != 0)
5444 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5445 /* 64bit on dbus2 */
5447 if (!streq(signature, "t"))
5450 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5454 /* 32bit on dbus1 */
5457 if (!streq(signature, "u"))
5460 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5464 m->reply_cookie = serial;
5467 if (m->reply_cookie == 0)
5472 case BUS_MESSAGE_HEADER_UNIX_FDS:
5476 if (!streq(signature, "u"))
5479 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5483 unix_fds_set = true;
5487 if (!BUS_MESSAGE_IS_GVARIANT(m))
5488 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5497 if (m->n_fds != unix_fds)
5500 switch (m->header->type) {
5502 case SD_BUS_MESSAGE_SIGNAL:
5503 if (!m->path || !m->interface || !m->member)
5506 if (m->reply_cookie != 0)
5511 case SD_BUS_MESSAGE_METHOD_CALL:
5513 if (!m->path || !m->member)
5516 if (m->reply_cookie != 0)
5521 case SD_BUS_MESSAGE_METHOD_RETURN:
5523 if (m->reply_cookie == 0)
5527 case SD_BUS_MESSAGE_METHOD_ERROR:
5529 if (m->reply_cookie == 0 || !m->error.name)
5534 /* Refuse non-local messages that claim they are local */
5535 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5537 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5539 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5542 m->root_container.end = m->user_body_size;
5544 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5545 r = build_struct_offsets(
5547 m->root_container.signature,
5549 &m->root_container.item_size,
5550 &m->root_container.offsets,
5551 &m->root_container.n_offsets);
5556 /* Try to read the error message, but if we can't it's a non-issue */
5557 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5558 (void) sd_bus_message_read(m, "s", &m->error.message);
5563 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5564 assert_return(m, -EINVAL);
5565 assert_return(destination, -EINVAL);
5566 assert_return(!m->sealed, -EPERM);
5567 assert_return(!m->destination, -EEXIST);
5569 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5572 /// UNNEEDED by elogind
5574 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5578 struct bus_body_part *part;
5584 total = BUS_MESSAGE_SIZE(m);
5590 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5591 MESSAGE_FOREACH_PART(part, i, m)
5592 e = mempcpy(e, part->data, part->size);
5594 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5603 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5610 r = sd_bus_message_enter_container(m, 'a', "s");
5614 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5615 r = strv_extend(l, s);
5622 r = sd_bus_message_exit_container(m);
5629 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5633 assert_return(m, -EINVAL);
5634 assert_return(m->sealed, -EPERM);
5635 assert_return(l, -EINVAL);
5637 r = bus_message_read_strv_extend(m, &strv);
5647 static int bus_message_get_arg_skip(
5651 const char **_contents) {
5656 r = sd_bus_message_rewind(m, true);
5661 const char *contents;
5664 r = sd_bus_message_peek_type(m, &type, &contents);
5670 /* Don't match against arguments after the first one we don't understand */
5671 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5672 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5677 *_contents = contents;
5683 r = sd_bus_message_skip(m, NULL);
5690 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5697 r = bus_message_get_arg_skip(m, i, &type, NULL);
5701 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5704 return sd_bus_message_read_basic(m, type, str);
5707 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5708 const char *contents;
5715 r = bus_message_get_arg_skip(m, i, &type, &contents);
5719 if (type != SD_BUS_TYPE_ARRAY)
5721 if (!STR_IN_SET(contents, "s", "o", "g"))
5724 return sd_bus_message_read_strv(m, strv);
5727 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5728 assert_return(m, EINVAL);
5730 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5733 return sd_bus_error_get_errno(&m->error);
5736 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5737 struct bus_container *c;
5739 assert_return(m, NULL);
5741 c = complete ? &m->root_container : message_get_container(m);
5742 return strempty(c->signature);
5745 /// UNNEEDED by elogind
5747 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5748 assert_return(m, -EINVAL);
5750 return isempty(m->root_container.signature);
5753 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5754 assert_return(m, -EINVAL);
5756 return streq(strempty(m->root_container.signature), strempty(signature));
5760 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5761 bool done_something = false;
5764 assert_return(m, -EINVAL);
5765 assert_return(source, -EINVAL);
5766 assert_return(!m->sealed, -EPERM);
5767 assert_return(source->sealed, -EPERM);
5770 const char *contents;
5785 r = sd_bus_message_peek_type(source, &type, &contents);
5791 done_something = true;
5793 if (bus_type_is_container(type) > 0) {
5795 r = sd_bus_message_enter_container(source, type, contents);
5799 r = sd_bus_message_open_container(m, type, contents);
5803 r = sd_bus_message_copy(m, source, true);
5807 r = sd_bus_message_close_container(m);
5811 r = sd_bus_message_exit_container(source);
5818 r = sd_bus_message_read_basic(source, type, &basic);
5824 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5825 type == SD_BUS_TYPE_SIGNATURE ||
5826 type == SD_BUS_TYPE_STRING)
5827 r = sd_bus_message_append_basic(m, type, basic.string);
5829 r = sd_bus_message_append_basic(m, type, &basic);
5836 return done_something;
5839 /// UNNEEDED by elogind
5841 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5846 assert_return(m, -EINVAL);
5847 assert_return(m->sealed, -EPERM);
5848 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5849 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5850 assert_return(type || contents, -EINVAL);
5851 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5853 r = sd_bus_message_peek_type(m, &t, &c);
5857 if (type != 0 && type != t)
5860 if (contents && !streq_ptr(contents, c))
5867 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5868 assert_return(m, NULL);
5873 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5874 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5882 switch ((*m)->header->type) {
5884 case SD_BUS_MESSAGE_SIGNAL:
5885 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5891 case SD_BUS_MESSAGE_METHOD_CALL:
5892 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5898 case SD_BUS_MESSAGE_METHOD_RETURN:
5899 case SD_BUS_MESSAGE_METHOD_ERROR:
5901 n = message_new(bus, (*m)->header->type);
5905 n->reply_cookie = (*m)->reply_cookie;
5907 r = message_append_reply_cookie(n, n->reply_cookie);
5911 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5912 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5916 n->error._need_free = -1;
5925 if ((*m)->destination && !n->destination) {
5926 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5931 if ((*m)->sender && !n->sender) {
5932 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5937 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5939 r = sd_bus_message_copy(n, *m, true);
5943 timeout = (*m)->timeout;
5944 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5945 timeout = BUS_DEFAULT_TIMEOUT;
5947 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5951 sd_bus_message_unref(*m);
5958 /// UNNEEDED by elogind
5960 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5964 assert_return(!m->sealed, -EPERM);
5965 assert_return(!m->sender, -EPERM);
5967 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5970 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5971 assert_return(m, -EINVAL);
5972 assert_return(priority, -EINVAL);
5974 *priority = m->priority;
5978 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5979 assert_return(m, -EINVAL);
5980 assert_return(!m->sealed, -EPERM);
5982 m->priority = priority;