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 #if 0 /// UNNEEDED by elogind
835 _public_ int sd_bus_message_new_method_errnof(
836 sd_bus_message *call,
842 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
845 va_start(ap, format);
846 sd_bus_error_set_errnofv(&berror, error, format, ap);
849 return sd_bus_message_new_method_error(call, m, &berror);
853 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
857 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
858 m->creds.well_known_names_local = true;
859 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
862 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
866 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
867 m->creds.well_known_names_driver = true;
868 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
871 int bus_message_new_synthetic_error(
874 const sd_bus_error *e,
875 sd_bus_message **m) {
881 assert(sd_bus_error_is_set(e));
884 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
888 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
889 t->reply_cookie = cookie;
891 r = message_append_reply_cookie(t, t->reply_cookie);
895 if (bus && bus->unique_name) {
896 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
901 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
906 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
911 t->error._need_free = -1;
913 bus_message_set_sender_driver(bus, t);
923 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
924 assert_return(m, NULL);
926 assert(m->n_ref > 0);
932 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
937 assert(m->n_ref > 0);
947 #if 0 /// UNNEEDED by elogind
948 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
949 assert_return(m, -EINVAL);
950 assert_return(type, -EINVAL);
952 *type = m->header->type;
956 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
959 assert_return(m, -EINVAL);
960 assert_return(cookie, -EINVAL);
962 c = BUS_MESSAGE_COOKIE(m);
966 *cookie = BUS_MESSAGE_COOKIE(m);
970 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
971 assert_return(m, -EINVAL);
972 assert_return(cookie, -EINVAL);
974 if (m->reply_cookie == 0)
977 *cookie = m->reply_cookie;
981 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
982 assert_return(m, -EINVAL);
984 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
985 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
988 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
989 assert_return(m, -EINVAL);
991 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
995 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
996 assert_return(m, -EINVAL);
998 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
999 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
1002 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1003 assert_return(m, NULL);
1008 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1009 assert_return(m, NULL);
1011 return m->interface;
1014 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1015 assert_return(m, NULL);
1020 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1021 assert_return(m, NULL);
1023 return m->destination;
1026 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1027 assert_return(m, NULL);
1032 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1033 assert_return(m, NULL);
1035 if (!sd_bus_error_is_set(&m->error))
1041 #if 0 /// UNNEEDED by elogind
1042 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1043 assert_return(m, -EINVAL);
1044 assert_return(usec, -EINVAL);
1046 if (m->monotonic <= 0)
1049 *usec = m->monotonic;
1053 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1054 assert_return(m, -EINVAL);
1055 assert_return(usec, -EINVAL);
1057 if (m->realtime <= 0)
1060 *usec = m->realtime;
1064 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1065 assert_return(m, -EINVAL);
1066 assert_return(seqnum, -EINVAL);
1071 *seqnum = m->seqnum;
1076 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1077 assert_return(m, NULL);
1079 if (m->creds.mask == 0)
1085 #if 0 /// UNNEEDED by elogind
1086 _public_ int sd_bus_message_is_signal(
1088 const char *interface,
1089 const char *member) {
1091 assert_return(m, -EINVAL);
1093 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1096 if (interface && (!m->interface || !streq(m->interface, interface)))
1099 if (member && (!m->member || !streq(m->member, member)))
1106 _public_ int sd_bus_message_is_method_call(
1108 const char *interface,
1109 const char *member) {
1111 assert_return(m, -EINVAL);
1113 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1116 if (interface && (!m->interface || !streq(m->interface, interface)))
1119 if (member && (!m->member || !streq(m->member, member)))
1125 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1126 assert_return(m, -EINVAL);
1128 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1131 if (name && (!m->error.name || !streq(m->error.name, name)))
1137 #if 0 /// UNNEEDED by elogind
1138 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1139 assert_return(m, -EINVAL);
1140 assert_return(!m->sealed, -EPERM);
1141 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1144 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1146 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1151 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1152 assert_return(m, -EINVAL);
1153 assert_return(!m->sealed, -EPERM);
1156 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1158 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1163 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1164 assert_return(m, -EINVAL);
1165 assert_return(!m->sealed, -EPERM);
1168 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1170 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1176 static struct bus_container *message_get_container(sd_bus_message *m) {
1179 if (m->n_containers == 0)
1180 return &m->root_container;
1182 assert(m->containers);
1183 return m->containers + m->n_containers - 1;
1186 struct bus_body_part *message_append_part(sd_bus_message *m) {
1187 struct bus_body_part *part;
1194 if (m->n_body_parts <= 0) {
1198 assert(m->body_end);
1200 part = new0(struct bus_body_part, 1);
1206 m->body_end->next = part;
1216 static void part_zero(struct bus_body_part *part, size_t sz) {
1221 /* All other fields can be left in their defaults */
1222 assert(!part->data);
1223 assert(part->memfd < 0);
1226 part->is_zero = true;
1227 part->sealed = true;
1230 static int part_make_space(
1231 struct sd_bus_message *m,
1232 struct bus_body_part *part,
1241 assert(!part->sealed);
1246 if (!part->data && part->memfd < 0) {
1247 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1248 part->mmap_begin = part->data;
1251 if (part->memfd >= 0) {
1253 if (part->allocated == 0 || sz > part->allocated) {
1254 uint64_t new_allocated;
1256 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1257 r = memfd_set_size(part->memfd, new_allocated);
1263 part->allocated = new_allocated;
1266 if (!part->data || sz > part->mapped) {
1269 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1270 if (part->mapped <= 0)
1271 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1273 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1275 if (n == MAP_FAILED) {
1280 part->mmap_begin = part->data = n;
1282 part->memfd_offset = 0;
1285 part->munmap_this = true;
1287 if (part->allocated == 0 || sz > part->allocated) {
1288 size_t new_allocated;
1290 new_allocated = sz > 0 ? 2 * sz : 64;
1291 n = realloc(part->data, new_allocated);
1298 part->allocated = new_allocated;
1299 part->free_this = true;
1304 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1310 static int message_add_offset(sd_bus_message *m, size_t offset) {
1311 struct bus_container *c;
1314 assert(BUS_MESSAGE_IS_GVARIANT(m));
1316 /* Add offset to current container, unless this is the first
1317 * item in it, which will have the 0 offset, which we can
1319 c = message_get_container(m);
1321 if (!c->need_offsets)
1324 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1327 c->offsets[c->n_offsets++] = offset;
1331 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1332 struct bus_container *c;
1339 /* Update counters */
1340 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1343 *c->array_size += expand;
1347 static void *message_extend_body(
1352 bool force_inline) {
1354 size_t start_body, end_body, padding, added;
1365 start_body = ALIGN_TO((size_t) m->body_size, align);
1366 end_body = start_body + sz;
1368 padding = start_body - m->body_size;
1369 added = padding + sz;
1371 /* Check for 32bit overflows */
1372 if (end_body > (size_t) ((uint32_t) -1) ||
1373 end_body < start_body) {
1379 struct bus_body_part *part = NULL;
1383 m->n_body_parts <= 0 ||
1384 m->body_end->sealed ||
1385 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1386 (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 */
1390 part = message_append_part(m);
1394 part_zero(part, padding);
1397 part = message_append_part(m);
1401 r = part_make_space(m, part, sz, &p);
1405 struct bus_container *c;
1407 size_t os, start_part, end_part;
1413 start_part = ALIGN_TO(part->size, align);
1414 end_part = start_part + sz;
1416 r = part_make_space(m, part, end_part, &p);
1421 memzero(p, padding);
1422 p = (uint8_t*) p + padding;
1425 /* Readjust pointers */
1426 for (c = m->containers; c < m->containers + m->n_containers; c++)
1427 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1429 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1432 /* Return something that is not NULL and is aligned */
1433 p = (uint8_t *) NULL + align;
1435 m->body_size = end_body;
1436 message_extend_containers(m, added);
1439 r = message_add_offset(m, end_body);
1449 static int message_push_fd(sd_bus_message *m, int fd) {
1460 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1464 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1472 m->fds[m->n_fds] = copy;
1478 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1479 _cleanup_close_ int fd = -1;
1480 struct bus_container *c;
1484 assert_return(m, -EINVAL);
1485 assert_return(!m->sealed, -EPERM);
1486 assert_return(bus_type_is_basic(type), -EINVAL);
1487 assert_return(!m->poisoned, -ESTALE);
1489 c = message_get_container(m);
1491 if (c->signature && c->signature[c->index]) {
1492 /* Container signature is already set */
1494 if (c->signature[c->index] != type)
1499 /* Maybe we can append to the signature? But only if this is the top-level container */
1500 if (c->enclosing != 0)
1503 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1510 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1516 case SD_BUS_TYPE_SIGNATURE:
1517 case SD_BUS_TYPE_STRING:
1520 /* Fall through... */
1521 case SD_BUS_TYPE_OBJECT_PATH:
1529 case SD_BUS_TYPE_BOOLEAN:
1531 u8 = p && *(int*) p;
1537 case SD_BUS_TYPE_UNIX_FD:
1542 fd = message_push_fd(m, *(int*) p);
1553 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1554 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1561 a = message_extend_body(m, align, sz, true, false);
1568 *stored = (const uint8_t*) a;
1575 case SD_BUS_TYPE_STRING:
1576 /* To make things easy we'll serialize a NULL string
1577 * into the empty string */
1580 /* Fall through... */
1581 case SD_BUS_TYPE_OBJECT_PATH:
1587 sz = 4 + strlen(p) + 1;
1590 case SD_BUS_TYPE_SIGNATURE:
1595 sz = 1 + strlen(p) + 1;
1598 case SD_BUS_TYPE_BOOLEAN:
1600 u32 = p && *(int*) p;
1606 case SD_BUS_TYPE_UNIX_FD:
1611 fd = message_push_fd(m, *(int*) p);
1622 align = bus_type_get_alignment(type);
1623 sz = bus_type_get_size(type);
1630 a = message_extend_body(m, align, sz, false, false);
1634 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1635 *(uint32_t*) a = sz - 5;
1636 memcpy((uint8_t*) a + 4, p, sz - 4);
1639 *stored = (const uint8_t*) a + 4;
1641 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1642 *(uint8_t*) a = sz - 2;
1643 memcpy((uint8_t*) a + 1, p, sz - 1);
1646 *stored = (const uint8_t*) a + 1;
1655 if (type == SD_BUS_TYPE_UNIX_FD)
1658 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1665 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1666 return message_append_basic(m, type, p, NULL);
1669 #if 0 /// UNNEEDED by elogind
1670 _public_ int sd_bus_message_append_string_space(
1675 struct bus_container *c;
1678 assert_return(m, -EINVAL);
1679 assert_return(s, -EINVAL);
1680 assert_return(!m->sealed, -EPERM);
1681 assert_return(!m->poisoned, -ESTALE);
1683 c = message_get_container(m);
1685 if (c->signature && c->signature[c->index]) {
1686 /* Container signature is already set */
1688 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1693 /* Maybe we can append to the signature? But only if this is the top-level container */
1694 if (c->enclosing != 0)
1697 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1704 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1705 a = message_extend_body(m, 1, size + 1, true, false);
1711 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1715 *(uint32_t*) a = size;
1721 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1727 _public_ int sd_bus_message_append_string_iovec(
1729 const struct iovec *iov,
1737 assert_return(m, -EINVAL);
1738 assert_return(!m->sealed, -EPERM);
1739 assert_return(iov || n == 0, -EINVAL);
1740 assert_return(!m->poisoned, -ESTALE);
1742 size = IOVEC_TOTAL_SIZE(iov, n);
1744 r = sd_bus_message_append_string_space(m, size, &p);
1748 for (i = 0; i < n; i++) {
1750 if (iov[i].iov_base)
1751 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1753 memset(p, ' ', iov[i].iov_len);
1755 p += iov[i].iov_len;
1762 static int bus_message_open_array(
1764 struct bus_container *c,
1765 const char *contents,
1766 uint32_t **array_size,
1768 bool *need_offsets) {
1778 assert(need_offsets);
1780 if (!signature_is_single(contents, true))
1783 if (c->signature && c->signature[c->index]) {
1785 /* Verify the existing signature */
1787 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1790 if (!startswith(c->signature + c->index + 1, contents))
1793 nindex = c->index + 1 + strlen(contents);
1797 if (c->enclosing != 0)
1800 /* Extend the existing signature */
1802 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1808 nindex = e - c->signature;
1811 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1812 alignment = bus_gvariant_get_alignment(contents);
1816 /* Add alignment padding and add to offset list */
1817 if (!message_extend_body(m, alignment, 0, false, false))
1820 r = bus_gvariant_is_fixed_size(contents);
1824 *begin = m->body_size;
1825 *need_offsets = r == 0;
1829 struct bus_body_part *o;
1831 alignment = bus_type_get_alignment(contents[0]);
1835 a = message_extend_body(m, 4, 4, false, false);
1840 op = m->body_end->data;
1841 os = m->body_end->size;
1843 /* Add alignment between size and first element */
1844 if (!message_extend_body(m, alignment, 0, false, false))
1847 /* location of array size might have changed so let's readjust a */
1848 if (o == m->body_end)
1849 a = adjust_pointer(a, op, os, m->body_end->data);
1855 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1861 static int bus_message_open_variant(
1863 struct bus_container *c,
1864 const char *contents) {
1870 if (!signature_is_single(contents, false))
1873 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1876 if (c->signature && c->signature[c->index]) {
1878 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1884 if (c->enclosing != 0)
1887 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1894 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1895 /* Variants are always aligned to 8 */
1897 if (!message_extend_body(m, 8, 0, false, false))
1904 l = strlen(contents);
1905 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1910 memcpy((uint8_t*) a + 1, contents, l + 1);
1913 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1919 static int bus_message_open_struct(
1921 struct bus_container *c,
1922 const char *contents,
1924 bool *need_offsets) {
1933 assert(need_offsets);
1935 if (!signature_is_valid(contents, false))
1938 if (c->signature && c->signature[c->index]) {
1941 l = strlen(contents);
1943 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1944 !startswith(c->signature + c->index + 1, contents) ||
1945 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1948 nindex = c->index + 1 + l + 1;
1952 if (c->enclosing != 0)
1955 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1961 nindex = e - c->signature;
1964 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1967 alignment = bus_gvariant_get_alignment(contents);
1971 if (!message_extend_body(m, alignment, 0, false, false))
1974 r = bus_gvariant_is_fixed_size(contents);
1978 *begin = m->body_size;
1979 *need_offsets = r == 0;
1981 /* Align contents to 8 byte boundary */
1982 if (!message_extend_body(m, 8, 0, false, false))
1986 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1992 static int bus_message_open_dict_entry(
1994 struct bus_container *c,
1995 const char *contents,
1997 bool *need_offsets) {
2005 assert(need_offsets);
2007 if (!signature_is_pair(contents))
2010 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2013 if (c->signature && c->signature[c->index]) {
2016 l = strlen(contents);
2018 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2019 !startswith(c->signature + c->index + 1, contents) ||
2020 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2025 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2028 alignment = bus_gvariant_get_alignment(contents);
2032 if (!message_extend_body(m, alignment, 0, false, false))
2035 r = bus_gvariant_is_fixed_size(contents);
2039 *begin = m->body_size;
2040 *need_offsets = r == 0;
2042 /* Align contents to 8 byte boundary */
2043 if (!message_extend_body(m, 8, 0, false, false))
2050 _public_ int sd_bus_message_open_container(
2053 const char *contents) {
2055 struct bus_container *c, *w;
2056 uint32_t *array_size = NULL;
2058 size_t before, begin = 0;
2059 bool need_offsets = false;
2062 assert_return(m, -EINVAL);
2063 assert_return(!m->sealed, -EPERM);
2064 assert_return(contents, -EINVAL);
2065 assert_return(!m->poisoned, -ESTALE);
2067 /* Make sure we have space for one more container */
2068 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2073 c = message_get_container(m);
2075 signature = strdup(contents);
2081 /* Save old index in the parent container, in case we have to
2082 * abort this container */
2083 c->saved_index = c->index;
2084 before = m->body_size;
2086 if (type == SD_BUS_TYPE_ARRAY)
2087 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2088 else if (type == SD_BUS_TYPE_VARIANT)
2089 r = bus_message_open_variant(m, c, contents);
2090 else if (type == SD_BUS_TYPE_STRUCT)
2091 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2092 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2093 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2102 /* OK, let's fill it in */
2103 w = m->containers + m->n_containers++;
2104 w->enclosing = type;
2105 w->signature = signature;
2107 w->array_size = array_size;
2110 w->n_offsets = w->offsets_allocated = 0;
2112 w->need_offsets = need_offsets;
2117 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2122 if (!BUS_MESSAGE_IS_GVARIANT(m))
2125 if (c->need_offsets) {
2126 size_t payload, sz, i;
2129 /* Variable-width arrays */
2131 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2132 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2134 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2138 for (i = 0; i < c->n_offsets; i++)
2139 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2143 /* Fixed-width or empty arrays */
2145 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2153 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2159 assert(c->signature);
2161 if (!BUS_MESSAGE_IS_GVARIANT(m))
2164 l = strlen(c->signature);
2166 a = message_extend_body(m, 1, 1 + l, true, false);
2171 memcpy(a+1, c->signature, l);
2176 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2177 bool fixed_size = true;
2178 size_t n_variable = 0;
2187 if (!BUS_MESSAGE_IS_GVARIANT(m))
2190 p = strempty(c->signature);
2194 r = signature_element_length(p, &n);
2203 r = bus_gvariant_is_fixed_size(t);
2208 assert(!c->need_offsets || i <= c->n_offsets);
2210 /* We need to add an offset for each item that has a
2211 * variable size and that is not the last one in the
2215 if (r == 0 && p[n] != 0)
2222 assert(!c->need_offsets || i == c->n_offsets);
2223 assert(c->need_offsets || n_variable == 0);
2225 if (isempty(c->signature)) {
2226 /* The unary type is encoded as fixed 1 byte padding */
2227 a = message_extend_body(m, 1, 1, add_offset, false);
2232 } else if (n_variable <= 0) {
2235 /* Structures with fixed-size members only have to be
2236 * fixed-size themselves. But gvariant requires all fixed-size
2237 * elements to be sized a multiple of their alignment. Hence,
2238 * we must *always* add final padding after the last member so
2239 * the overall size of the structure is properly aligned. */
2241 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2243 assert(alignment > 0);
2245 a = message_extend_body(m, alignment, 0, add_offset, false);
2252 assert(c->offsets[c->n_offsets-1] == m->body_size);
2254 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2256 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2260 p = strempty(c->signature);
2261 for (i = 0, j = 0; i < c->n_offsets; i++) {
2265 r = signature_element_length(p, &n);
2276 r = bus_gvariant_is_fixed_size(t);
2279 if (r > 0 || p[0] == 0)
2283 k = n_variable - 1 - j;
2285 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2294 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2295 struct bus_container *c;
2298 assert_return(m, -EINVAL);
2299 assert_return(!m->sealed, -EPERM);
2300 assert_return(m->n_containers > 0, -EINVAL);
2301 assert_return(!m->poisoned, -ESTALE);
2303 c = message_get_container(m);
2305 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2306 if (c->signature && c->signature[c->index] != 0)
2311 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2312 r = bus_message_close_array(m, c);
2313 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2314 r = bus_message_close_variant(m, c);
2315 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2316 r = bus_message_close_struct(m, c, true);
2318 assert_not_reached("Unknown container type");
2332 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2339 stack[*i].types = types;
2340 stack[*i].n_struct = n_struct;
2341 stack[*i].n_array = n_array;
2347 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2358 *types = stack[*i].types;
2359 *n_struct = stack[*i].n_struct;
2360 *n_array = stack[*i].n_array;
2365 int bus_message_append_ap(
2370 unsigned n_array, n_struct;
2371 TypeStack stack[BUS_CONTAINER_DEPTH];
2372 unsigned stack_ptr = 0;
2380 n_array = (unsigned) -1;
2381 n_struct = strlen(types);
2386 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2387 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2393 r = sd_bus_message_close_container(m);
2401 if (n_array != (unsigned) -1)
2410 case SD_BUS_TYPE_BYTE: {
2413 x = (uint8_t) va_arg(ap, int);
2414 r = sd_bus_message_append_basic(m, *t, &x);
2418 case SD_BUS_TYPE_BOOLEAN:
2419 case SD_BUS_TYPE_INT32:
2420 case SD_BUS_TYPE_UINT32:
2421 case SD_BUS_TYPE_UNIX_FD: {
2424 /* We assume a boolean is the same as int32_t */
2425 assert_cc(sizeof(int32_t) == sizeof(int));
2427 x = va_arg(ap, uint32_t);
2428 r = sd_bus_message_append_basic(m, *t, &x);
2432 case SD_BUS_TYPE_INT16:
2433 case SD_BUS_TYPE_UINT16: {
2436 x = (uint16_t) va_arg(ap, int);
2437 r = sd_bus_message_append_basic(m, *t, &x);
2441 case SD_BUS_TYPE_INT64:
2442 case SD_BUS_TYPE_UINT64: {
2445 x = va_arg(ap, uint64_t);
2446 r = sd_bus_message_append_basic(m, *t, &x);
2450 case SD_BUS_TYPE_DOUBLE: {
2453 x = va_arg(ap, double);
2454 r = sd_bus_message_append_basic(m, *t, &x);
2458 case SD_BUS_TYPE_STRING:
2459 case SD_BUS_TYPE_OBJECT_PATH:
2460 case SD_BUS_TYPE_SIGNATURE: {
2463 x = va_arg(ap, const char*);
2464 r = sd_bus_message_append_basic(m, *t, x);
2468 case SD_BUS_TYPE_ARRAY: {
2471 r = signature_element_length(t + 1, &k);
2477 memcpy(s, t + 1, k);
2480 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2485 if (n_array == (unsigned) -1) {
2490 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2496 n_array = va_arg(ap, unsigned);
2501 case SD_BUS_TYPE_VARIANT: {
2504 s = va_arg(ap, const char*);
2508 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2512 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2517 n_struct = strlen(s);
2518 n_array = (unsigned) -1;
2523 case SD_BUS_TYPE_STRUCT_BEGIN:
2524 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2527 r = signature_element_length(t, &k);
2534 memcpy(s, t + 1, k - 2);
2537 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2542 if (n_array == (unsigned) -1) {
2547 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2553 n_array = (unsigned) -1;
2569 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2573 assert_return(m, -EINVAL);
2574 assert_return(types, -EINVAL);
2575 assert_return(!m->sealed, -EPERM);
2576 assert_return(!m->poisoned, -ESTALE);
2578 va_start(ap, types);
2579 r = bus_message_append_ap(m, types, ap);
2585 #if 0 /// UNNEEDED by elogind
2586 _public_ int sd_bus_message_append_array_space(
2596 assert_return(m, -EINVAL);
2597 assert_return(!m->sealed, -EPERM);
2598 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2599 assert_return(ptr || size == 0, -EINVAL);
2600 assert_return(!m->poisoned, -ESTALE);
2602 /* alignment and size of the trivial types (except bool) is
2603 * identical for gvariant and dbus1 marshalling */
2604 align = bus_type_get_alignment(type);
2605 sz = bus_type_get_size(type);
2607 assert_se(align > 0);
2613 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2617 a = message_extend_body(m, align, size, false, false);
2621 r = sd_bus_message_close_container(m);
2629 _public_ int sd_bus_message_append_array(
2637 assert_return(m, -EINVAL);
2638 assert_return(!m->sealed, -EPERM);
2639 assert_return(bus_type_is_trivial(type), -EINVAL);
2640 assert_return(ptr || size == 0, -EINVAL);
2641 assert_return(!m->poisoned, -ESTALE);
2643 r = sd_bus_message_append_array_space(m, type, size, &p);
2648 memcpy(p, ptr, size);
2653 _public_ int sd_bus_message_append_array_iovec(
2656 const struct iovec *iov,
2664 assert_return(m, -EINVAL);
2665 assert_return(!m->sealed, -EPERM);
2666 assert_return(bus_type_is_trivial(type), -EINVAL);
2667 assert_return(iov || n == 0, -EINVAL);
2668 assert_return(!m->poisoned, -ESTALE);
2670 size = IOVEC_TOTAL_SIZE(iov, n);
2672 r = sd_bus_message_append_array_space(m, type, size, &p);
2676 for (i = 0; i < n; i++) {
2678 if (iov[i].iov_base)
2679 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2681 memzero(p, iov[i].iov_len);
2683 p = (uint8_t*) p + iov[i].iov_len;
2689 _public_ int sd_bus_message_append_array_memfd(
2696 _cleanup_close_ int copy_fd = -1;
2697 struct bus_body_part *part;
2703 assert_return(m, -EINVAL);
2704 assert_return(memfd >= 0, -EBADF);
2705 assert_return(bus_type_is_trivial(type), -EINVAL);
2706 assert_return(size > 0, -EINVAL);
2707 assert_return(!m->sealed, -EPERM);
2708 assert_return(!m->poisoned, -ESTALE);
2710 r = memfd_set_sealed(memfd);
2714 copy_fd = dup(memfd);
2718 r = memfd_get_size(memfd, &real_size);
2722 if (offset == 0 && size == (uint64_t) -1)
2724 else if (offset + size > real_size)
2727 align = bus_type_get_alignment(type);
2728 sz = bus_type_get_size(type);
2730 assert_se(align > 0);
2733 if (offset % align != 0)
2739 if (size > (uint64_t) (uint32_t) -1)
2742 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2746 a = message_extend_body(m, align, 0, false, false);
2750 part = message_append_part(m);
2754 part->memfd = copy_fd;
2755 part->memfd_offset = offset;
2756 part->sealed = true;
2760 m->body_size += size;
2761 message_extend_containers(m, size);
2763 return sd_bus_message_close_container(m);
2766 _public_ int sd_bus_message_append_string_memfd(
2772 _cleanup_close_ int copy_fd = -1;
2773 struct bus_body_part *part;
2774 struct bus_container *c;
2779 assert_return(m, -EINVAL);
2780 assert_return(memfd >= 0, -EBADF);
2781 assert_return(size > 0, -EINVAL);
2782 assert_return(!m->sealed, -EPERM);
2783 assert_return(!m->poisoned, -ESTALE);
2785 r = memfd_set_sealed(memfd);
2789 copy_fd = dup(memfd);
2793 r = memfd_get_size(memfd, &real_size);
2797 if (offset == 0 && size == (uint64_t) -1)
2799 else if (offset + size > real_size)
2802 /* We require this to be NUL terminated */
2806 if (size > (uint64_t) (uint32_t) -1)
2809 c = message_get_container(m);
2810 if (c->signature && c->signature[c->index]) {
2811 /* Container signature is already set */
2813 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2818 /* Maybe we can append to the signature? But only if this is the top-level container */
2819 if (c->enclosing != 0)
2822 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2829 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2830 a = message_extend_body(m, 4, 4, false, false);
2834 *(uint32_t*) a = size - 1;
2837 part = message_append_part(m);
2841 part->memfd = copy_fd;
2842 part->memfd_offset = offset;
2843 part->sealed = true;
2847 m->body_size += size;
2848 message_extend_containers(m, size);
2850 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2851 r = message_add_offset(m, m->body_size);
2858 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2865 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2869 assert_return(m, -EINVAL);
2870 assert_return(!m->sealed, -EPERM);
2871 assert_return(!m->poisoned, -ESTALE);
2873 r = sd_bus_message_open_container(m, 'a', "s");
2877 STRV_FOREACH(i, l) {
2878 r = sd_bus_message_append_basic(m, 's', *i);
2883 return sd_bus_message_close_container(m);
2886 static int bus_message_close_header(sd_bus_message *m) {
2890 /* The actual user data is finished now, we just complete the
2891 variant and struct now (at least on gvariant). Remember
2892 this position, so that during parsing we know where to to
2893 put the outer container end. */
2894 m->user_body_size = m->body_size;
2896 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2897 const char *signature;
2901 /* Add offset table to end of fields array */
2902 if (m->n_header_offsets >= 1) {
2906 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2908 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2909 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2913 for (i = 0; i < m->n_header_offsets; i++)
2914 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2917 /* Add gvariant NUL byte plus signature to the end of
2918 * the body, followed by the final offset pointing to
2919 * the end of the fields array */
2921 signature = strempty(m->root_container.signature);
2922 l = strlen(signature);
2924 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2925 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2930 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2931 memcpy((uint8_t*) d + 2, signature, l);
2932 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2934 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2937 m->footer_accessible = 1 + l + 2 + sz;
2939 m->header->dbus1.fields_size = m->fields_size;
2940 m->header->dbus1.body_size = m->body_size;
2946 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2947 struct bus_body_part *part;
2957 if (m->n_containers > 0)
2963 if (cookie > 0xffffffffULL &&
2964 !BUS_MESSAGE_IS_GVARIANT(m))
2967 /* In vtables the return signature of method calls is listed,
2968 * let's check if they match if this is a response */
2969 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2970 m->enforced_reply_signature &&
2971 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2974 /* If gvariant marshalling is used we need to close the body structure */
2975 r = bus_message_close_struct(m, &m->root_container, false);
2979 /* If there's a non-trivial signature set, then add it in
2980 * here, but only on dbus1 */
2981 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2982 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2988 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2993 r = bus_message_close_header(m);
2997 if (BUS_MESSAGE_IS_GVARIANT(m))
2998 m->header->dbus2.cookie = cookie;
3000 m->header->dbus1.serial = (uint32_t) cookie;
3002 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
3004 /* Add padding at the end of the fields part, since we know
3005 * the body needs to start at an 8 byte alignment. We made
3006 * sure we allocated enough space for this, so all we need to
3007 * do here is to zero it out. */
3008 a = ALIGN8(m->fields_size) - m->fields_size;
3010 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
3012 /* If this is something we can send as memfd, then let's seal
3013 the memfd now. Note that we can send memfds as payload only
3014 for directed messages, and not for broadcasts. */
3015 if (m->destination && m->bus->use_memfd) {
3016 MESSAGE_FOREACH_PART(part, i, m)
3017 if (part->memfd >= 0 &&
3019 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3020 part != m->body_end) { /* The last part may never be sent as memfd */
3023 /* Try to seal it if that makes
3024 * sense. First, unmap our own map to
3025 * make sure we don't keep it busy. */
3026 bus_body_part_unmap(part);
3028 /* Then, sync up real memfd size */
3030 r = memfd_set_size(part->memfd, sz);
3034 /* Finally, try to seal */
3035 if (memfd_set_sealed(part->memfd) >= 0)
3036 part->sealed = true;
3040 m->root_container.end = m->user_body_size;
3041 m->root_container.index = 0;
3042 m->root_container.offset_index = 0;
3043 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3050 int bus_body_part_map(struct bus_body_part *part) {
3059 if (part->size <= 0)
3062 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3063 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3064 static const uint8_t zeroes[7] = { };
3065 part->data = (void*) zeroes;
3069 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3070 psz = PAGE_ALIGN(part->size + shift);
3072 if (part->memfd >= 0)
3073 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3074 else if (part->is_zero)
3075 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3079 if (p == MAP_FAILED)
3083 part->mmap_begin = p;
3084 part->data = (uint8_t*) p + shift;
3085 part->munmap_this = true;
3090 void bus_body_part_unmap(struct bus_body_part *part) {
3094 if (part->memfd < 0)
3097 if (!part->mmap_begin)
3100 if (!part->munmap_this)
3103 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3105 part->mmap_begin = NULL;
3108 part->munmap_this = false;
3113 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3114 size_t k, start, end;
3119 start = ALIGN_TO((size_t) *rindex, align);
3120 end = start + nbytes;
3125 /* Verify that padding is 0 */
3126 for (k = *rindex; k < start; k++)
3127 if (((const uint8_t*) p)[k] != 0)
3131 *r = (uint8_t*) p + start;
3138 static bool message_end_of_signature(sd_bus_message *m) {
3139 struct bus_container *c;
3143 c = message_get_container(m);
3144 return !c->signature || c->signature[c->index] == 0;
3147 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3148 struct bus_container *c;
3152 c = message_get_container(m);
3153 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3156 if (BUS_MESSAGE_IS_GVARIANT(m))
3157 return index >= c->end;
3159 assert(c->array_size);
3160 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3164 #if 0 /// UNNEEDED by elogind
3165 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3166 assert_return(m, -EINVAL);
3167 assert_return(m->sealed, -EPERM);
3169 if (complete && m->n_containers > 0)
3172 if (message_end_of_signature(m))
3175 if (message_end_of_array(m, m->rindex))
3182 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3183 struct bus_body_part *part;
3189 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3190 part = m->cached_rindex_part;
3191 begin = m->cached_rindex_part_begin;
3201 if (index + sz <= begin + part->size) {
3203 r = bus_body_part_map(part);
3208 *p = (uint8_t*) part->data + index - begin;
3210 m->cached_rindex_part = part;
3211 m->cached_rindex_part_begin = begin;
3216 begin += part->size;
3223 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3230 if (!BUS_MESSAGE_IS_GVARIANT(m))
3233 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3236 sz = bus_gvariant_get_size(c->signature);
3240 if (c->offset_index+1 >= c->n_offsets)
3243 /* Variable-size array */
3245 alignment = bus_gvariant_get_alignment(c->signature);
3246 assert(alignment > 0);
3248 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3249 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3252 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3255 /* Fixed-size array */
3256 *rindex = c->begin + (c->offset_index+1) * sz;
3262 } else if (c->enclosing == 0 ||
3263 c->enclosing == SD_BUS_TYPE_STRUCT ||
3264 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3269 if (c->offset_index+1 >= c->n_offsets)
3272 r = signature_element_length(c->signature + c->index, &n);
3276 r = signature_element_length(c->signature + c->index + n, &j);
3281 memcpy(t, c->signature + c->index + n, j);
3284 alignment = bus_gvariant_get_alignment(t);
3287 assert(alignment > 0);
3289 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3290 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3294 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3297 assert_not_reached("Unknown container type");
3302 /* Reached the end */
3309 static int message_peek_body(
3316 size_t k, start, end, padding;
3317 struct bus_body_part *part;
3324 start = ALIGN_TO((size_t) *rindex, align);
3325 padding = start - *rindex;
3326 end = start + nbytes;
3328 if (end > m->user_body_size)
3331 part = find_part(m, *rindex, padding, (void**) &q);
3336 /* Verify padding */
3337 for (k = 0; k < padding; k++)
3342 part = find_part(m, start, nbytes, (void**) &q);
3343 if (!part || (nbytes > 0 && !q))
3354 static bool validate_nul(const char *s, size_t l) {
3356 /* Check for NUL chars in the string */
3357 if (memchr(s, 0, l))
3360 /* Check for NUL termination */
3367 static bool validate_string(const char *s, size_t l) {
3369 if (!validate_nul(s, l))
3372 /* Check if valid UTF8 */
3373 if (!utf8_is_valid(s))
3379 static bool validate_signature(const char *s, size_t l) {
3381 if (!validate_nul(s, l))
3384 /* Check if valid signature */
3385 if (!signature_is_valid(s, true))
3391 static bool validate_object_path(const char *s, size_t l) {
3393 if (!validate_nul(s, l))
3396 if (!object_path_is_valid(s))
3402 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3403 struct bus_container *c;
3408 assert_return(m, -EINVAL);
3409 assert_return(m->sealed, -EPERM);
3410 assert_return(bus_type_is_basic(type), -EINVAL);
3412 if (message_end_of_signature(m))
3415 if (message_end_of_array(m, m->rindex))
3418 c = message_get_container(m);
3419 if (c->signature[c->index] != type)
3424 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3426 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3429 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3433 if (type == SD_BUS_TYPE_STRING)
3434 ok = validate_string(q, c->item_size-1);
3435 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3436 ok = validate_object_path(q, c->item_size-1);
3438 ok = validate_signature(q, c->item_size-1);
3444 *(const char**) p = q;
3448 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3450 if ((size_t) sz != c->item_size)
3453 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3456 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3462 case SD_BUS_TYPE_BYTE:
3464 *(uint8_t*) p = *(uint8_t*) q;
3467 case SD_BUS_TYPE_BOOLEAN:
3469 *(int*) p = !!*(uint8_t*) q;
3472 case SD_BUS_TYPE_INT16:
3473 case SD_BUS_TYPE_UINT16:
3475 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3478 case SD_BUS_TYPE_INT32:
3479 case SD_BUS_TYPE_UINT32:
3481 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3484 case SD_BUS_TYPE_INT64:
3485 case SD_BUS_TYPE_UINT64:
3486 case SD_BUS_TYPE_DOUBLE:
3488 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3491 case SD_BUS_TYPE_UNIX_FD: {
3494 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3499 *(int*) p = m->fds[j];
3505 assert_not_reached("unexpected type");
3509 r = container_next_item(m, c, &rindex);
3514 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3518 r = message_peek_body(m, &rindex, 4, 4, &q);
3522 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3523 r = message_peek_body(m, &rindex, 1, l+1, &q);
3527 if (type == SD_BUS_TYPE_OBJECT_PATH)
3528 ok = validate_object_path(q, l);
3530 ok = validate_string(q, l);
3535 *(const char**) p = q;
3537 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3540 r = message_peek_body(m, &rindex, 1, 1, &q);
3545 r = message_peek_body(m, &rindex, 1, l+1, &q);
3549 if (!validate_signature(q, l))
3553 *(const char**) p = q;
3558 align = bus_type_get_alignment(type);
3561 sz = bus_type_get_size(type);
3564 r = message_peek_body(m, &rindex, align, sz, &q);
3570 case SD_BUS_TYPE_BYTE:
3572 *(uint8_t*) p = *(uint8_t*) q;
3575 case SD_BUS_TYPE_BOOLEAN:
3577 *(int*) p = !!*(uint32_t*) q;
3580 case SD_BUS_TYPE_INT16:
3581 case SD_BUS_TYPE_UINT16:
3583 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3586 case SD_BUS_TYPE_INT32:
3587 case SD_BUS_TYPE_UINT32:
3589 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3592 case SD_BUS_TYPE_INT64:
3593 case SD_BUS_TYPE_UINT64:
3594 case SD_BUS_TYPE_DOUBLE:
3596 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3599 case SD_BUS_TYPE_UNIX_FD: {
3602 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3607 *(int*) p = m->fds[j];
3612 assert_not_reached("Unknown basic type...");
3619 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3625 static int bus_message_enter_array(
3627 struct bus_container *c,
3628 const char *contents,
3629 uint32_t **array_size,
3632 size_t *n_offsets) {
3646 if (!signature_is_single(contents, true))
3649 if (!c->signature || c->signature[c->index] == 0)
3652 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3655 if (!startswith(c->signature + c->index + 1, contents))
3660 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3663 r = message_peek_body(m, &rindex, 4, 4, &q);
3667 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3670 alignment = bus_type_get_alignment(contents[0]);
3674 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3678 *array_size = (uint32_t*) q;
3680 } else if (c->item_size <= 0) {
3682 /* gvariant: empty array */
3687 } else if (bus_gvariant_is_fixed_size(contents)) {
3689 /* gvariant: fixed length array */
3690 *item_size = bus_gvariant_get_size(contents);
3695 size_t where, p = 0, framing, sz;
3698 /* gvariant: variable length array */
3699 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3701 where = rindex + c->item_size - sz;
3702 r = message_peek_body(m, &where, 1, sz, &q);
3706 framing = bus_gvariant_read_word_le(q, sz);
3707 if (framing > c->item_size - sz)
3709 if ((c->item_size - framing) % sz != 0)
3712 *n_offsets = (c->item_size - framing) / sz;
3714 where = rindex + framing;
3715 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3719 *offsets = new(size_t, *n_offsets);
3723 for (i = 0; i < *n_offsets; i++) {
3726 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3727 if (x > c->item_size - sz)
3732 (*offsets)[i] = rindex + x;
3736 *item_size = (*offsets)[0] - rindex;
3741 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3742 c->index += 1 + strlen(contents);
3747 static int bus_message_enter_variant(
3749 struct bus_container *c,
3750 const char *contents,
3751 size_t *item_size) {
3763 if (!signature_is_single(contents, false))
3766 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3769 if (!c->signature || c->signature[c->index] == 0)
3772 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3777 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3780 k = strlen(contents);
3781 if (1+k > c->item_size)
3784 where = rindex + c->item_size - (1+k);
3785 r = message_peek_body(m, &where, 1, 1+k, &q);
3789 if (*(char*) q != 0)
3792 if (memcmp((uint8_t*) q+1, contents, k))
3795 *item_size = c->item_size - (1+k);
3798 r = message_peek_body(m, &rindex, 1, 1, &q);
3803 r = message_peek_body(m, &rindex, 1, l+1, &q);
3807 if (!validate_signature(q, l))
3810 if (!streq(q, contents))
3816 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3822 static int build_struct_offsets(
3824 const char *signature,
3828 size_t *n_offsets) {
3830 unsigned n_variable = 0, n_total = 0, v;
3831 size_t previous = 0, where;
3842 if (isempty(signature)) {
3843 /* Unary type is encoded as *fixed* 1 byte padding */
3844 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3848 if (*(uint8_t *) q != 0)
3857 sz = bus_gvariant_determine_word_size(size, 0);
3861 /* First, loop over signature and count variable elements and
3862 * elements in general. We use this to know how large the
3863 * offset array is at the end of the structure. Note that
3864 * GVariant only stores offsets for all variable size elements
3865 * that are not the last item. */
3871 r = signature_element_length(p, &n);
3880 r = bus_gvariant_is_fixed_size(t);
3885 if (r == 0 && p[n] != 0) /* except the last item */
3892 if (size < n_variable * sz)
3895 where = m->rindex + size - (n_variable * sz);
3896 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3902 *offsets = new(size_t, n_total);
3908 /* Second, loop again and build an offset table */
3914 r = signature_element_length(p, &n);
3923 k = bus_gvariant_get_size(t);
3931 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3934 if (m->rindex + x < previous)
3937 /* The last item's end
3938 * is determined from
3941 x = size - (n_variable * sz);
3943 offset = m->rindex + x;
3949 align = bus_gvariant_get_alignment(t);
3952 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3956 previous = (*offsets)[(*n_offsets)++] = offset;
3961 assert(*n_offsets == n_total);
3963 *item_size = (*offsets)[0] - m->rindex;
3967 static int enter_struct_or_dict_entry(
3969 struct bus_container *c,
3970 const char *contents,
3973 size_t *n_offsets) {
3984 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3987 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3992 /* gvariant with contents */
3993 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3998 static int bus_message_enter_struct(
4000 struct bus_container *c,
4001 const char *contents,
4004 size_t *n_offsets) {
4016 if (!signature_is_valid(contents, false))
4019 if (!c->signature || c->signature[c->index] == 0)
4022 l = strlen(contents);
4024 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4025 !startswith(c->signature + c->index + 1, contents) ||
4026 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4029 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4033 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4034 c->index += 1 + l + 1;
4039 static int bus_message_enter_dict_entry(
4041 struct bus_container *c,
4042 const char *contents,
4045 size_t *n_offsets) {
4054 if (!signature_is_pair(contents))
4057 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4060 if (!c->signature || c->signature[c->index] == 0)
4063 l = strlen(contents);
4065 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4066 !startswith(c->signature + c->index + 1, contents) ||
4067 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4070 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4074 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4075 c->index += 1 + l + 1;
4080 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4082 const char *contents) {
4083 struct bus_container *c, *w;
4084 uint32_t *array_size = NULL;
4087 size_t *offsets = NULL;
4088 size_t n_offsets = 0, item_size = 0;
4091 assert_return(m, -EINVAL);
4092 assert_return(m->sealed, -EPERM);
4093 assert_return(type != 0 || !contents, -EINVAL);
4095 if (type == 0 || !contents) {
4099 /* Allow entering into anonymous containers */
4100 r = sd_bus_message_peek_type(m, &tt, &cc);
4104 if (type != 0 && type != tt)
4107 if (contents && !streq(contents, cc))
4115 * We enforce a global limit on container depth, that is much
4116 * higher than the 32 structs and 32 arrays the specification
4117 * mandates. This is simpler to implement for us, and we need
4118 * this only to ensure our container array doesn't grow
4119 * without bounds. We are happy to return any data from a
4120 * message as long as the data itself is valid, even if the
4121 * overall message might be not.
4123 * Note that the message signature is validated when
4124 * parsing the headers, and that validation does check the
4127 * Note that the specification defines no limits on the depth
4128 * of stacked variants, but we do.
4130 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4133 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4136 if (message_end_of_signature(m))
4139 if (message_end_of_array(m, m->rindex))
4142 c = message_get_container(m);
4144 signature = strdup(contents);
4148 c->saved_index = c->index;
4151 if (type == SD_BUS_TYPE_ARRAY)
4152 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4153 else if (type == SD_BUS_TYPE_VARIANT)
4154 r = bus_message_enter_variant(m, c, contents, &item_size);
4155 else if (type == SD_BUS_TYPE_STRUCT)
4156 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4157 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4158 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4168 /* OK, let's fill it in */
4169 w = m->containers + m->n_containers++;
4170 w->enclosing = type;
4171 w->signature = signature;
4172 w->peeked_signature = NULL;
4176 w->begin = m->rindex;
4178 /* Unary type has fixed size of 1, but virtual size of 0 */
4179 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4180 type == SD_BUS_TYPE_STRUCT &&
4182 w->end = m->rindex + 0;
4184 w->end = m->rindex + c->item_size;
4186 w->array_size = array_size;
4187 w->item_size = item_size;
4188 w->offsets = offsets;
4189 w->n_offsets = n_offsets;
4190 w->offset_index = 0;
4195 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4196 struct bus_container *c;
4200 assert_return(m, -EINVAL);
4201 assert_return(m->sealed, -EPERM);
4202 assert_return(m->n_containers > 0, -ENXIO);
4204 c = message_get_container(m);
4206 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4207 if (c->signature && c->signature[c->index] != 0)
4211 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4212 if (m->rindex < c->end)
4215 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4218 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4219 if (c->begin + l != m->rindex)
4224 free(c->peeked_signature);
4228 c = message_get_container(m);
4231 c->index = c->saved_index;
4232 r = container_next_item(m, c, &m->rindex);
4240 static void message_quit_container(sd_bus_message *m) {
4241 struct bus_container *c;
4245 assert(m->n_containers > 0);
4247 c = message_get_container(m);
4250 assert(m->rindex >= c->before);
4251 m->rindex = c->before;
4253 /* Free container */
4258 /* Correct index of new top-level container */
4259 c = message_get_container(m);
4260 c->index = c->saved_index;
4263 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4264 struct bus_container *c;
4267 assert_return(m, -EINVAL);
4268 assert_return(m->sealed, -EPERM);
4270 if (message_end_of_signature(m))
4273 if (message_end_of_array(m, m->rindex))
4276 c = message_get_container(m);
4278 if (bus_type_is_basic(c->signature[c->index])) {
4282 *type = c->signature[c->index];
4286 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4292 r = signature_element_length(c->signature+c->index+1, &l);
4298 sig = strndup(c->signature + c->index + 1, l);
4302 free(c->peeked_signature);
4303 *contents = c->peeked_signature = sig;
4307 *type = SD_BUS_TYPE_ARRAY;
4312 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4313 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4319 r = signature_element_length(c->signature+c->index, &l);
4324 sig = strndup(c->signature + c->index + 1, l - 2);
4328 free(c->peeked_signature);
4329 *contents = c->peeked_signature = sig;
4333 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4338 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4342 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4345 if (c->item_size < 2)
4348 /* Look for the NUL delimiter that
4349 separates the payload from the
4350 signature. Since the body might be
4351 in a different part that then the
4352 signature we map byte by byte. */
4354 for (k = 2; k <= c->item_size; k++) {
4357 where = m->rindex + c->item_size - k;
4358 r = message_peek_body(m, &where, 1, k, &q);
4362 if (*(char*) q == 0)
4366 if (k > c->item_size)
4369 free(c->peeked_signature);
4370 c->peeked_signature = strndup((char*) q + 1, k - 1);
4371 if (!c->peeked_signature)
4374 if (!signature_is_valid(c->peeked_signature, true))
4377 *contents = c->peeked_signature;
4382 r = message_peek_body(m, &rindex, 1, 1, &q);
4387 r = message_peek_body(m, &rindex, 1, l+1, &q);
4391 if (!validate_signature(q, l))
4399 *type = SD_BUS_TYPE_VARIANT;
4414 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4415 struct bus_container *c;
4417 assert_return(m, -EINVAL);
4418 assert_return(m->sealed, -EPERM);
4421 message_reset_containers(m);
4424 c = message_get_container(m);
4426 c = message_get_container(m);
4428 c->offset_index = 0;
4430 m->rindex = c->begin;
4433 c->offset_index = 0;
4434 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4436 return !isempty(c->signature);
4439 static int message_read_ap(
4444 unsigned n_array, n_struct;
4445 TypeStack stack[BUS_CONTAINER_DEPTH];
4446 unsigned stack_ptr = 0;
4447 unsigned n_loop = 0;
4455 /* Ideally, we'd just call ourselves recursively on every
4456 * complex type. However, the state of a va_list that is
4457 * passed to a function is undefined after that function
4458 * returns. This means we need to docode the va_list linearly
4459 * in a single stackframe. We hence implement our own
4460 * home-grown stack in an array. */
4462 n_array = (unsigned) -1; /* length of current array entries */
4463 n_struct = strlen(types); /* length of current struct contents signature */
4470 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4471 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4477 r = sd_bus_message_exit_container(m);
4485 if (n_array != (unsigned) -1)
4494 case SD_BUS_TYPE_BYTE:
4495 case SD_BUS_TYPE_BOOLEAN:
4496 case SD_BUS_TYPE_INT16:
4497 case SD_BUS_TYPE_UINT16:
4498 case SD_BUS_TYPE_INT32:
4499 case SD_BUS_TYPE_UINT32:
4500 case SD_BUS_TYPE_INT64:
4501 case SD_BUS_TYPE_UINT64:
4502 case SD_BUS_TYPE_DOUBLE:
4503 case SD_BUS_TYPE_STRING:
4504 case SD_BUS_TYPE_OBJECT_PATH:
4505 case SD_BUS_TYPE_SIGNATURE:
4506 case SD_BUS_TYPE_UNIX_FD: {
4509 p = va_arg(ap, void*);
4510 r = sd_bus_message_read_basic(m, *t, p);
4523 case SD_BUS_TYPE_ARRAY: {
4526 r = signature_element_length(t + 1, &k);
4532 memcpy(s, t + 1, k);
4535 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4546 if (n_array == (unsigned) -1) {
4551 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4557 n_array = va_arg(ap, unsigned);
4562 case SD_BUS_TYPE_VARIANT: {
4565 s = va_arg(ap, const char *);
4569 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4579 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4584 n_struct = strlen(s);
4585 n_array = (unsigned) -1;
4590 case SD_BUS_TYPE_STRUCT_BEGIN:
4591 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4594 r = signature_element_length(t, &k);
4600 memcpy(s, t + 1, k - 2);
4603 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4613 if (n_array == (unsigned) -1) {
4618 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4624 n_array = (unsigned) -1;
4637 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4641 assert_return(m, -EINVAL);
4642 assert_return(m->sealed, -EPERM);
4643 assert_return(types, -EINVAL);
4645 va_start(ap, types);
4646 r = message_read_ap(m, types, ap);
4652 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4655 assert_return(m, -EINVAL);
4656 assert_return(m->sealed, -EPERM);
4658 /* If types is NULL, read exactly one element */
4660 struct bus_container *c;
4663 if (message_end_of_signature(m))
4666 if (message_end_of_array(m, m->rindex))
4669 c = message_get_container(m);
4671 r = signature_element_length(c->signature + c->index, &l);
4675 types = strndupa(c->signature + c->index, l);
4680 case 0: /* Nothing to drop */
4683 case SD_BUS_TYPE_BYTE:
4684 case SD_BUS_TYPE_BOOLEAN:
4685 case SD_BUS_TYPE_INT16:
4686 case SD_BUS_TYPE_UINT16:
4687 case SD_BUS_TYPE_INT32:
4688 case SD_BUS_TYPE_UINT32:
4689 case SD_BUS_TYPE_INT64:
4690 case SD_BUS_TYPE_UINT64:
4691 case SD_BUS_TYPE_DOUBLE:
4692 case SD_BUS_TYPE_STRING:
4693 case SD_BUS_TYPE_OBJECT_PATH:
4694 case SD_BUS_TYPE_SIGNATURE:
4695 case SD_BUS_TYPE_UNIX_FD:
4697 r = sd_bus_message_read_basic(m, *types, NULL);
4701 r = sd_bus_message_skip(m, types + 1);
4707 case SD_BUS_TYPE_ARRAY: {
4710 r = signature_element_length(types + 1, &k);
4716 memcpy(s, types+1, k);
4719 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4724 r = sd_bus_message_skip(m, s);
4731 r = sd_bus_message_exit_container(m);
4736 r = sd_bus_message_skip(m, types + 1 + k);
4743 case SD_BUS_TYPE_VARIANT: {
4744 const char *contents;
4747 r = sd_bus_message_peek_type(m, &x, &contents);
4751 if (x != SD_BUS_TYPE_VARIANT)
4754 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4758 r = sd_bus_message_skip(m, contents);
4763 r = sd_bus_message_exit_container(m);
4767 r = sd_bus_message_skip(m, types + 1);
4774 case SD_BUS_TYPE_STRUCT_BEGIN:
4775 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4778 r = signature_element_length(types, &k);
4784 memcpy(s, types+1, k-2);
4787 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4791 r = sd_bus_message_skip(m, s);
4795 r = sd_bus_message_exit_container(m);
4800 r = sd_bus_message_skip(m, types + k);
4812 _public_ int sd_bus_message_read_array(
4818 struct bus_container *c;
4824 assert_return(m, -EINVAL);
4825 assert_return(m->sealed, -EPERM);
4826 assert_return(bus_type_is_trivial(type), -EINVAL);
4827 assert_return(ptr, -EINVAL);
4828 assert_return(size, -EINVAL);
4829 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4831 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4835 c = message_get_container(m);
4837 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4838 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4842 sz = c->end - c->begin;
4844 align = bus_type_get_alignment(type);
4848 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4852 /* Zero length array, let's return some aligned
4853 * pointer that is not NULL */
4854 p = (uint8_t*) NULL + align;
4856 r = message_peek_body(m, &m->rindex, align, sz, &p);
4861 r = sd_bus_message_exit_container(m);
4865 *ptr = (const void*) p;
4871 message_quit_container(m);
4875 static int message_peek_fields(
4886 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4889 static int message_peek_field_uint32(
4901 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4904 /* identical for gvariant and dbus1 */
4906 r = message_peek_fields(m, ri, 4, 4, &q);
4911 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4916 static int message_peek_field_uint64(
4928 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4931 /* identical for gvariant and dbus1 */
4933 r = message_peek_fields(m, ri, 8, 8, &q);
4938 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4943 static int message_peek_field_string(
4945 bool (*validate)(const char *p),
4957 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4962 r = message_peek_fields(m, ri, 1, item_size, &q);
4968 r = message_peek_field_uint32(m, ri, 4, &l);
4972 r = message_peek_fields(m, ri, 1, l+1, &q);
4978 if (!validate_nul(q, l))
4984 if (!validate_string(q, l))
4994 static int message_peek_field_signature(
5007 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5012 r = message_peek_fields(m, ri, 1, item_size, &q);
5018 r = message_peek_fields(m, ri, 1, 1, &q);
5023 r = message_peek_fields(m, ri, 1, l+1, &q);
5028 if (!validate_signature(q, l))
5037 static int message_skip_fields(
5040 uint32_t array_size,
5041 const char **signature) {
5043 size_t original_index;
5049 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5051 original_index = *ri;
5057 if (array_size != (uint32_t) -1 &&
5058 array_size <= *ri - original_index)
5065 if (t == SD_BUS_TYPE_STRING) {
5067 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5073 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5075 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5081 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5083 r = message_peek_field_signature(m, ri, 0, NULL);
5089 } else if (bus_type_is_basic(t)) {
5092 align = bus_type_get_alignment(t);
5093 k = bus_type_get_size(t);
5094 assert(align > 0 && k > 0);
5096 r = message_peek_fields(m, ri, align, k, NULL);
5102 } else if (t == SD_BUS_TYPE_ARRAY) {
5104 r = signature_element_length(*signature+1, &l);
5114 strncpy(sig, *signature + 1, l-1);
5117 alignment = bus_type_get_alignment(sig[0]);
5121 r = message_peek_field_uint32(m, ri, 0, &nas);
5124 if (nas > BUS_ARRAY_MAX_SIZE)
5127 r = message_peek_fields(m, ri, alignment, 0, NULL);
5131 r = message_skip_fields(m, ri, nas, (const char**) &s);
5136 (*signature) += 1 + l;
5138 } else if (t == SD_BUS_TYPE_VARIANT) {
5141 r = message_peek_field_signature(m, ri, 0, &s);
5145 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5151 } else if (t == SD_BUS_TYPE_STRUCT ||
5152 t == SD_BUS_TYPE_DICT_ENTRY) {
5154 r = signature_element_length(*signature, &l);
5161 strncpy(sig, *signature + 1, l-1);
5164 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5175 int bus_message_parse_fields(sd_bus_message *m) {
5178 uint32_t unix_fds = 0;
5179 bool unix_fds_set = false;
5180 void *offsets = NULL;
5181 unsigned n_offsets = 0;
5187 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5190 /* Read the signature from the end of the body variant first */
5191 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5192 if (m->footer_accessible < 1 + sz)
5195 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5197 if (p < (char*) m->footer)
5204 /* We found the beginning of the signature
5205 * string, yay! We require the body to be a
5206 * structure, so verify it and then strip the
5207 * opening/closing brackets. */
5209 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5211 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5212 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5215 c = strndup(p + 1 + 1, l - 2);
5219 free(m->root_container.signature);
5220 m->root_container.signature = c;
5227 /* Calculate the actual user body size, by removing
5228 * the trailing variant signature and struct offset
5230 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5232 /* Pull out the offset table for the fields array */
5233 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5238 ri = m->fields_size - sz;
5239 r = message_peek_fields(m, &ri, 1, sz, &q);
5243 framing = bus_gvariant_read_word_le(q, sz);
5244 if (framing >= m->fields_size - sz)
5246 if ((m->fields_size - framing) % sz != 0)
5250 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5254 n_offsets = (m->fields_size - framing) / sz;
5257 m->user_body_size = m->body_size;
5260 while (ri < m->fields_size) {
5261 _cleanup_free_ char *sig = NULL;
5262 const char *signature;
5263 uint64_t field_type;
5264 size_t item_size = (size_t) -1;
5266 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5275 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5277 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5281 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5285 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5292 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5297 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5302 where = ri = ALIGN_TO(ri, 8);
5303 item_size = end - ri;
5304 r = message_peek_fields(m, &where, 1, item_size, &q);
5308 b = memrchr(q, 0, item_size);
5312 sig = strndup(b+1, item_size - (b+1-(char*) q));
5317 item_size = b - (char*) q;
5319 r = message_peek_field_signature(m, &ri, 0, &signature);
5324 switch (field_type) {
5326 case _BUS_MESSAGE_HEADER_INVALID:
5329 case BUS_MESSAGE_HEADER_PATH:
5334 if (!streq(signature, "o"))
5337 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5340 case BUS_MESSAGE_HEADER_INTERFACE:
5345 if (!streq(signature, "s"))
5348 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5351 case BUS_MESSAGE_HEADER_MEMBER:
5356 if (!streq(signature, "s"))
5359 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5362 case BUS_MESSAGE_HEADER_ERROR_NAME:
5367 if (!streq(signature, "s"))
5370 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5372 m->error._need_free = -1;
5376 case BUS_MESSAGE_HEADER_DESTINATION:
5381 if (!streq(signature, "s"))
5384 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5387 case BUS_MESSAGE_HEADER_SENDER:
5392 if (!streq(signature, "s"))
5395 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5397 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5398 m->creds.unique_name = (char*) m->sender;
5399 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5405 case BUS_MESSAGE_HEADER_SIGNATURE: {
5409 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5412 if (m->root_container.signature)
5415 if (!streq(signature, "g"))
5418 r = message_peek_field_signature(m, &ri, item_size, &s);
5426 free(m->root_container.signature);
5427 m->root_container.signature = c;
5431 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5433 if (m->reply_cookie != 0)
5436 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5437 /* 64bit on dbus2 */
5439 if (!streq(signature, "t"))
5442 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5446 /* 32bit on dbus1 */
5449 if (!streq(signature, "u"))
5452 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5456 m->reply_cookie = serial;
5459 if (m->reply_cookie == 0)
5464 case BUS_MESSAGE_HEADER_UNIX_FDS:
5468 if (!streq(signature, "u"))
5471 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5475 unix_fds_set = true;
5479 if (!BUS_MESSAGE_IS_GVARIANT(m))
5480 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5489 if (m->n_fds != unix_fds)
5492 switch (m->header->type) {
5494 case SD_BUS_MESSAGE_SIGNAL:
5495 if (!m->path || !m->interface || !m->member)
5498 if (m->reply_cookie != 0)
5503 case SD_BUS_MESSAGE_METHOD_CALL:
5505 if (!m->path || !m->member)
5508 if (m->reply_cookie != 0)
5513 case SD_BUS_MESSAGE_METHOD_RETURN:
5515 if (m->reply_cookie == 0)
5519 case SD_BUS_MESSAGE_METHOD_ERROR:
5521 if (m->reply_cookie == 0 || !m->error.name)
5526 /* Refuse non-local messages that claim they are local */
5527 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5529 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5531 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5534 m->root_container.end = m->user_body_size;
5536 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5537 r = build_struct_offsets(
5539 m->root_container.signature,
5541 &m->root_container.item_size,
5542 &m->root_container.offsets,
5543 &m->root_container.n_offsets);
5548 /* Try to read the error message, but if we can't it's a non-issue */
5549 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5550 (void) sd_bus_message_read(m, "s", &m->error.message);
5555 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5556 assert_return(m, -EINVAL);
5557 assert_return(destination, -EINVAL);
5558 assert_return(!m->sealed, -EPERM);
5559 assert_return(!m->destination, -EEXIST);
5561 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5564 #if 0 /// UNNEEDED by elogind
5565 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5569 struct bus_body_part *part;
5575 total = BUS_MESSAGE_SIZE(m);
5581 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5582 MESSAGE_FOREACH_PART(part, i, m)
5583 e = mempcpy(e, part->data, part->size);
5585 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5594 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5601 r = sd_bus_message_enter_container(m, 'a', "s");
5605 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5606 r = strv_extend(l, s);
5613 r = sd_bus_message_exit_container(m);
5620 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5624 assert_return(m, -EINVAL);
5625 assert_return(m->sealed, -EPERM);
5626 assert_return(l, -EINVAL);
5628 r = bus_message_read_strv_extend(m, &strv);
5638 static int bus_message_get_arg_skip(
5642 const char **_contents) {
5647 r = sd_bus_message_rewind(m, true);
5652 const char *contents;
5655 r = sd_bus_message_peek_type(m, &type, &contents);
5661 /* Don't match against arguments after the first one we don't understand */
5662 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5663 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5668 *_contents = contents;
5674 r = sd_bus_message_skip(m, NULL);
5681 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5688 r = bus_message_get_arg_skip(m, i, &type, NULL);
5692 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5695 return sd_bus_message_read_basic(m, type, str);
5698 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5699 const char *contents;
5706 r = bus_message_get_arg_skip(m, i, &type, &contents);
5710 if (type != SD_BUS_TYPE_ARRAY)
5712 if (!STR_IN_SET(contents, "s", "o", "g"))
5715 return sd_bus_message_read_strv(m, strv);
5718 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5719 assert_return(m, EINVAL);
5721 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5724 return sd_bus_error_get_errno(&m->error);
5727 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5728 struct bus_container *c;
5730 assert_return(m, NULL);
5732 c = complete ? &m->root_container : message_get_container(m);
5733 return strempty(c->signature);
5736 #if 0 /// UNNEEDED by elogind
5737 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5738 assert_return(m, -EINVAL);
5740 return isempty(m->root_container.signature);
5743 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5744 assert_return(m, -EINVAL);
5746 return streq(strempty(m->root_container.signature), strempty(signature));
5750 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5751 bool done_something = false;
5754 assert_return(m, -EINVAL);
5755 assert_return(source, -EINVAL);
5756 assert_return(!m->sealed, -EPERM);
5757 assert_return(source->sealed, -EPERM);
5760 const char *contents;
5775 r = sd_bus_message_peek_type(source, &type, &contents);
5781 done_something = true;
5783 if (bus_type_is_container(type) > 0) {
5785 r = sd_bus_message_enter_container(source, type, contents);
5789 r = sd_bus_message_open_container(m, type, contents);
5793 r = sd_bus_message_copy(m, source, true);
5797 r = sd_bus_message_close_container(m);
5801 r = sd_bus_message_exit_container(source);
5808 r = sd_bus_message_read_basic(source, type, &basic);
5814 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5815 type == SD_BUS_TYPE_SIGNATURE ||
5816 type == SD_BUS_TYPE_STRING)
5817 r = sd_bus_message_append_basic(m, type, basic.string);
5819 r = sd_bus_message_append_basic(m, type, &basic);
5826 return done_something;
5829 #if 0 /// UNNEEDED by elogind
5830 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5835 assert_return(m, -EINVAL);
5836 assert_return(m->sealed, -EPERM);
5837 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5838 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5839 assert_return(type || contents, -EINVAL);
5840 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5842 r = sd_bus_message_peek_type(m, &t, &c);
5846 if (type != 0 && type != t)
5849 if (contents && !streq_ptr(contents, c))
5856 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5857 assert_return(m, NULL);
5862 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5863 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5871 switch ((*m)->header->type) {
5873 case SD_BUS_MESSAGE_SIGNAL:
5874 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5880 case SD_BUS_MESSAGE_METHOD_CALL:
5881 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5887 case SD_BUS_MESSAGE_METHOD_RETURN:
5888 case SD_BUS_MESSAGE_METHOD_ERROR:
5890 n = message_new(bus, (*m)->header->type);
5894 n->reply_cookie = (*m)->reply_cookie;
5896 r = message_append_reply_cookie(n, n->reply_cookie);
5900 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5901 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5905 n->error._need_free = -1;
5914 if ((*m)->destination && !n->destination) {
5915 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5920 if ((*m)->sender && !n->sender) {
5921 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5926 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5928 r = sd_bus_message_copy(n, *m, true);
5932 timeout = (*m)->timeout;
5933 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5934 timeout = BUS_DEFAULT_TIMEOUT;
5936 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5940 sd_bus_message_unref(*m);
5947 #if 0 /// UNNEEDED by elogind
5948 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5952 assert_return(!m->sealed, -EPERM);
5953 assert_return(!m->sender, -EPERM);
5955 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5958 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5959 assert_return(m, -EINVAL);
5960 assert_return(priority, -EINVAL);
5962 *priority = m->priority;
5966 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5967 assert_return(m, -EINVAL);
5968 assert_return(!m->sealed, -EPERM);
5970 m->priority = priority;