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_(sd_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_(sd_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_(sd_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) {
928 assert(m->n_ref > 0);
934 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
939 assert(m->n_ref > 0);
949 #if 0 /// UNNEEDED by elogind
950 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
951 assert_return(m, -EINVAL);
952 assert_return(type, -EINVAL);
954 *type = m->header->type;
958 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
961 assert_return(m, -EINVAL);
962 assert_return(cookie, -EINVAL);
964 c = BUS_MESSAGE_COOKIE(m);
968 *cookie = BUS_MESSAGE_COOKIE(m);
972 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
973 assert_return(m, -EINVAL);
974 assert_return(cookie, -EINVAL);
976 if (m->reply_cookie == 0)
979 *cookie = m->reply_cookie;
983 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
984 assert_return(m, -EINVAL);
986 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
987 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
990 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
991 assert_return(m, -EINVAL);
993 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
997 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
998 assert_return(m, -EINVAL);
1000 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
1001 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
1004 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1005 assert_return(m, NULL);
1010 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1011 assert_return(m, NULL);
1013 return m->interface;
1016 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1017 assert_return(m, NULL);
1022 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1023 assert_return(m, NULL);
1025 return m->destination;
1028 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1029 assert_return(m, NULL);
1034 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1035 assert_return(m, NULL);
1037 if (!sd_bus_error_is_set(&m->error))
1043 #if 0 /// UNNEEDED by elogind
1044 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1045 assert_return(m, -EINVAL);
1046 assert_return(usec, -EINVAL);
1048 if (m->monotonic <= 0)
1051 *usec = m->monotonic;
1055 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1056 assert_return(m, -EINVAL);
1057 assert_return(usec, -EINVAL);
1059 if (m->realtime <= 0)
1062 *usec = m->realtime;
1066 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1067 assert_return(m, -EINVAL);
1068 assert_return(seqnum, -EINVAL);
1073 *seqnum = m->seqnum;
1078 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1079 assert_return(m, NULL);
1081 if (m->creds.mask == 0)
1087 #if 0 /// UNNEEDED by elogind
1088 _public_ int sd_bus_message_is_signal(
1090 const char *interface,
1091 const char *member) {
1093 assert_return(m, -EINVAL);
1095 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1098 if (interface && (!m->interface || !streq(m->interface, interface)))
1101 if (member && (!m->member || !streq(m->member, member)))
1108 _public_ int sd_bus_message_is_method_call(
1110 const char *interface,
1111 const char *member) {
1113 assert_return(m, -EINVAL);
1115 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1118 if (interface && (!m->interface || !streq(m->interface, interface)))
1121 if (member && (!m->member || !streq(m->member, member)))
1127 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1128 assert_return(m, -EINVAL);
1130 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1133 if (name && (!m->error.name || !streq(m->error.name, name)))
1139 #if 0 /// UNNEEDED by elogind
1140 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1141 assert_return(m, -EINVAL);
1142 assert_return(!m->sealed, -EPERM);
1143 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1146 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1148 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1153 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1154 assert_return(m, -EINVAL);
1155 assert_return(!m->sealed, -EPERM);
1158 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1160 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1165 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1166 assert_return(m, -EINVAL);
1167 assert_return(!m->sealed, -EPERM);
1170 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1172 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1178 static struct bus_container *message_get_container(sd_bus_message *m) {
1181 if (m->n_containers == 0)
1182 return &m->root_container;
1184 assert(m->containers);
1185 return m->containers + m->n_containers - 1;
1188 struct bus_body_part *message_append_part(sd_bus_message *m) {
1189 struct bus_body_part *part;
1196 if (m->n_body_parts <= 0) {
1200 assert(m->body_end);
1202 part = new0(struct bus_body_part, 1);
1208 m->body_end->next = part;
1218 static void part_zero(struct bus_body_part *part, size_t sz) {
1223 /* All other fields can be left in their defaults */
1224 assert(!part->data);
1225 assert(part->memfd < 0);
1228 part->is_zero = true;
1229 part->sealed = true;
1232 static int part_make_space(
1233 struct sd_bus_message *m,
1234 struct bus_body_part *part,
1243 assert(!part->sealed);
1248 if (!part->data && part->memfd < 0) {
1249 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1250 part->mmap_begin = part->data;
1253 if (part->memfd >= 0) {
1255 if (part->allocated == 0 || sz > part->allocated) {
1256 uint64_t new_allocated;
1258 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1259 r = memfd_set_size(part->memfd, new_allocated);
1265 part->allocated = new_allocated;
1268 if (!part->data || sz > part->mapped) {
1271 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1272 if (part->mapped <= 0)
1273 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1275 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1277 if (n == MAP_FAILED) {
1282 part->mmap_begin = part->data = n;
1284 part->memfd_offset = 0;
1287 part->munmap_this = true;
1289 if (part->allocated == 0 || sz > part->allocated) {
1290 size_t new_allocated;
1292 new_allocated = sz > 0 ? 2 * sz : 64;
1293 n = realloc(part->data, new_allocated);
1300 part->allocated = new_allocated;
1301 part->free_this = true;
1306 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1312 static int message_add_offset(sd_bus_message *m, size_t offset) {
1313 struct bus_container *c;
1316 assert(BUS_MESSAGE_IS_GVARIANT(m));
1318 /* Add offset to current container, unless this is the first
1319 * item in it, which will have the 0 offset, which we can
1321 c = message_get_container(m);
1323 if (!c->need_offsets)
1326 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1329 c->offsets[c->n_offsets++] = offset;
1333 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1334 struct bus_container *c;
1341 /* Update counters */
1342 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1345 *c->array_size += expand;
1349 static void *message_extend_body(
1354 bool force_inline) {
1356 size_t start_body, end_body, padding, added;
1367 start_body = ALIGN_TO((size_t) m->body_size, align);
1368 end_body = start_body + sz;
1370 padding = start_body - m->body_size;
1371 added = padding + sz;
1373 /* Check for 32bit overflows */
1374 if (end_body > (size_t) ((uint32_t) -1) ||
1375 end_body < start_body) {
1381 struct bus_body_part *part = NULL;
1385 m->n_body_parts <= 0 ||
1386 m->body_end->sealed ||
1387 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1388 (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 */
1392 part = message_append_part(m);
1396 part_zero(part, padding);
1399 part = message_append_part(m);
1403 r = part_make_space(m, part, sz, &p);
1407 struct bus_container *c;
1409 size_t os, start_part, end_part;
1415 start_part = ALIGN_TO(part->size, align);
1416 end_part = start_part + sz;
1418 r = part_make_space(m, part, end_part, &p);
1423 memzero(p, padding);
1424 p = (uint8_t*) p + padding;
1427 /* Readjust pointers */
1428 for (c = m->containers; c < m->containers + m->n_containers; c++)
1429 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1431 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1434 /* Return something that is not NULL and is aligned */
1435 p = (uint8_t *) NULL + align;
1437 m->body_size = end_body;
1438 message_extend_containers(m, added);
1441 r = message_add_offset(m, end_body);
1451 static int message_push_fd(sd_bus_message *m, int fd) {
1462 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1466 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1474 m->fds[m->n_fds] = copy;
1480 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1481 _cleanup_close_ int fd = -1;
1482 struct bus_container *c;
1486 assert_return(m, -EINVAL);
1487 assert_return(!m->sealed, -EPERM);
1488 assert_return(bus_type_is_basic(type), -EINVAL);
1489 assert_return(!m->poisoned, -ESTALE);
1491 c = message_get_container(m);
1493 if (c->signature && c->signature[c->index]) {
1494 /* Container signature is already set */
1496 if (c->signature[c->index] != type)
1501 /* Maybe we can append to the signature? But only if this is the top-level container */
1502 if (c->enclosing != 0)
1505 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1512 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1518 case SD_BUS_TYPE_SIGNATURE:
1519 case SD_BUS_TYPE_STRING:
1522 /* Fall through... */
1523 case SD_BUS_TYPE_OBJECT_PATH:
1531 case SD_BUS_TYPE_BOOLEAN:
1533 u8 = p && *(int*) p;
1539 case SD_BUS_TYPE_UNIX_FD:
1544 fd = message_push_fd(m, *(int*) p);
1555 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1556 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1563 a = message_extend_body(m, align, sz, true, false);
1570 *stored = (const uint8_t*) a;
1577 case SD_BUS_TYPE_STRING:
1578 /* To make things easy we'll serialize a NULL string
1579 * into the empty string */
1582 /* Fall through... */
1583 case SD_BUS_TYPE_OBJECT_PATH:
1589 sz = 4 + strlen(p) + 1;
1592 case SD_BUS_TYPE_SIGNATURE:
1597 sz = 1 + strlen(p) + 1;
1600 case SD_BUS_TYPE_BOOLEAN:
1602 u32 = p && *(int*) p;
1608 case SD_BUS_TYPE_UNIX_FD:
1613 fd = message_push_fd(m, *(int*) p);
1624 align = bus_type_get_alignment(type);
1625 sz = bus_type_get_size(type);
1632 a = message_extend_body(m, align, sz, false, false);
1636 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1637 *(uint32_t*) a = sz - 5;
1638 memcpy((uint8_t*) a + 4, p, sz - 4);
1641 *stored = (const uint8_t*) a + 4;
1643 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1644 *(uint8_t*) a = sz - 2;
1645 memcpy((uint8_t*) a + 1, p, sz - 1);
1648 *stored = (const uint8_t*) a + 1;
1657 if (type == SD_BUS_TYPE_UNIX_FD)
1660 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1667 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1668 return message_append_basic(m, type, p, NULL);
1671 #if 0 /// UNNEEDED by elogind
1672 _public_ int sd_bus_message_append_string_space(
1677 struct bus_container *c;
1680 assert_return(m, -EINVAL);
1681 assert_return(s, -EINVAL);
1682 assert_return(!m->sealed, -EPERM);
1683 assert_return(!m->poisoned, -ESTALE);
1685 c = message_get_container(m);
1687 if (c->signature && c->signature[c->index]) {
1688 /* Container signature is already set */
1690 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1695 /* Maybe we can append to the signature? But only if this is the top-level container */
1696 if (c->enclosing != 0)
1699 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1706 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1707 a = message_extend_body(m, 1, size + 1, true, false);
1713 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1717 *(uint32_t*) a = size;
1723 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1729 _public_ int sd_bus_message_append_string_iovec(
1731 const struct iovec *iov,
1739 assert_return(m, -EINVAL);
1740 assert_return(!m->sealed, -EPERM);
1741 assert_return(iov || n == 0, -EINVAL);
1742 assert_return(!m->poisoned, -ESTALE);
1744 size = IOVEC_TOTAL_SIZE(iov, n);
1746 r = sd_bus_message_append_string_space(m, size, &p);
1750 for (i = 0; i < n; i++) {
1752 if (iov[i].iov_base)
1753 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1755 memset(p, ' ', iov[i].iov_len);
1757 p += iov[i].iov_len;
1764 static int bus_message_open_array(
1766 struct bus_container *c,
1767 const char *contents,
1768 uint32_t **array_size,
1770 bool *need_offsets) {
1780 assert(need_offsets);
1782 if (!signature_is_single(contents, true))
1785 if (c->signature && c->signature[c->index]) {
1787 /* Verify the existing signature */
1789 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1792 if (!startswith(c->signature + c->index + 1, contents))
1795 nindex = c->index + 1 + strlen(contents);
1799 if (c->enclosing != 0)
1802 /* Extend the existing signature */
1804 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1810 nindex = e - c->signature;
1813 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1814 alignment = bus_gvariant_get_alignment(contents);
1818 /* Add alignment padding and add to offset list */
1819 if (!message_extend_body(m, alignment, 0, false, false))
1822 r = bus_gvariant_is_fixed_size(contents);
1826 *begin = m->body_size;
1827 *need_offsets = r == 0;
1831 struct bus_body_part *o;
1833 alignment = bus_type_get_alignment(contents[0]);
1837 a = message_extend_body(m, 4, 4, false, false);
1842 op = m->body_end->data;
1843 os = m->body_end->size;
1845 /* Add alignment between size and first element */
1846 if (!message_extend_body(m, alignment, 0, false, false))
1849 /* location of array size might have changed so let's readjust a */
1850 if (o == m->body_end)
1851 a = adjust_pointer(a, op, os, m->body_end->data);
1857 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1863 static int bus_message_open_variant(
1865 struct bus_container *c,
1866 const char *contents) {
1872 if (!signature_is_single(contents, false))
1875 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1878 if (c->signature && c->signature[c->index]) {
1880 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1886 if (c->enclosing != 0)
1889 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1896 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1897 /* Variants are always aligned to 8 */
1899 if (!message_extend_body(m, 8, 0, false, false))
1906 l = strlen(contents);
1907 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1912 memcpy((uint8_t*) a + 1, contents, l + 1);
1915 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1921 static int bus_message_open_struct(
1923 struct bus_container *c,
1924 const char *contents,
1926 bool *need_offsets) {
1935 assert(need_offsets);
1937 if (!signature_is_valid(contents, false))
1940 if (c->signature && c->signature[c->index]) {
1943 l = strlen(contents);
1945 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1946 !startswith(c->signature + c->index + 1, contents) ||
1947 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1950 nindex = c->index + 1 + l + 1;
1954 if (c->enclosing != 0)
1957 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1963 nindex = e - c->signature;
1966 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1969 alignment = bus_gvariant_get_alignment(contents);
1973 if (!message_extend_body(m, alignment, 0, false, false))
1976 r = bus_gvariant_is_fixed_size(contents);
1980 *begin = m->body_size;
1981 *need_offsets = r == 0;
1983 /* Align contents to 8 byte boundary */
1984 if (!message_extend_body(m, 8, 0, false, false))
1988 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1994 static int bus_message_open_dict_entry(
1996 struct bus_container *c,
1997 const char *contents,
1999 bool *need_offsets) {
2007 assert(need_offsets);
2009 if (!signature_is_pair(contents))
2012 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2015 if (c->signature && c->signature[c->index]) {
2018 l = strlen(contents);
2020 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2021 !startswith(c->signature + c->index + 1, contents) ||
2022 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2027 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2030 alignment = bus_gvariant_get_alignment(contents);
2034 if (!message_extend_body(m, alignment, 0, false, false))
2037 r = bus_gvariant_is_fixed_size(contents);
2041 *begin = m->body_size;
2042 *need_offsets = r == 0;
2044 /* Align contents to 8 byte boundary */
2045 if (!message_extend_body(m, 8, 0, false, false))
2052 _public_ int sd_bus_message_open_container(
2055 const char *contents) {
2057 struct bus_container *c, *w;
2058 uint32_t *array_size = NULL;
2060 size_t before, begin = 0;
2061 bool need_offsets = false;
2064 assert_return(m, -EINVAL);
2065 assert_return(!m->sealed, -EPERM);
2066 assert_return(contents, -EINVAL);
2067 assert_return(!m->poisoned, -ESTALE);
2069 /* Make sure we have space for one more container */
2070 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2075 c = message_get_container(m);
2077 signature = strdup(contents);
2083 /* Save old index in the parent container, in case we have to
2084 * abort this container */
2085 c->saved_index = c->index;
2086 before = m->body_size;
2088 if (type == SD_BUS_TYPE_ARRAY)
2089 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2090 else if (type == SD_BUS_TYPE_VARIANT)
2091 r = bus_message_open_variant(m, c, contents);
2092 else if (type == SD_BUS_TYPE_STRUCT)
2093 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2094 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2095 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2104 /* OK, let's fill it in */
2105 w = m->containers + m->n_containers++;
2106 w->enclosing = type;
2107 w->signature = signature;
2109 w->array_size = array_size;
2112 w->n_offsets = w->offsets_allocated = 0;
2114 w->need_offsets = need_offsets;
2119 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2124 if (!BUS_MESSAGE_IS_GVARIANT(m))
2127 if (c->need_offsets) {
2128 size_t payload, sz, i;
2131 /* Variable-width arrays */
2133 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2134 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2136 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2140 for (i = 0; i < c->n_offsets; i++)
2141 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2145 /* Fixed-width or empty arrays */
2147 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2155 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2161 assert(c->signature);
2163 if (!BUS_MESSAGE_IS_GVARIANT(m))
2166 l = strlen(c->signature);
2168 a = message_extend_body(m, 1, 1 + l, true, false);
2173 memcpy(a+1, c->signature, l);
2178 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2179 bool fixed_size = true;
2180 size_t n_variable = 0;
2189 if (!BUS_MESSAGE_IS_GVARIANT(m))
2192 p = strempty(c->signature);
2196 r = signature_element_length(p, &n);
2205 r = bus_gvariant_is_fixed_size(t);
2210 assert(!c->need_offsets || i <= c->n_offsets);
2212 /* We need to add an offset for each item that has a
2213 * variable size and that is not the last one in the
2217 if (r == 0 && p[n] != 0)
2224 assert(!c->need_offsets || i == c->n_offsets);
2225 assert(c->need_offsets || n_variable == 0);
2227 if (isempty(c->signature)) {
2228 /* The unary type is encoded as fixed 1 byte padding */
2229 a = message_extend_body(m, 1, 1, add_offset, false);
2234 } else if (n_variable <= 0) {
2237 /* Structures with fixed-size members only have to be
2238 * fixed-size themselves. But gvariant requires all fixed-size
2239 * elements to be sized a multiple of their alignment. Hence,
2240 * we must *always* add final padding after the last member so
2241 * the overall size of the structure is properly aligned. */
2243 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2245 assert(alignment > 0);
2247 a = message_extend_body(m, alignment, 0, add_offset, false);
2254 assert(c->offsets[c->n_offsets-1] == m->body_size);
2256 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2258 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2262 p = strempty(c->signature);
2263 for (i = 0, j = 0; i < c->n_offsets; i++) {
2267 r = signature_element_length(p, &n);
2278 r = bus_gvariant_is_fixed_size(t);
2281 if (r > 0 || p[0] == 0)
2285 k = n_variable - 1 - j;
2287 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2296 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2297 struct bus_container *c;
2300 assert_return(m, -EINVAL);
2301 assert_return(!m->sealed, -EPERM);
2302 assert_return(m->n_containers > 0, -EINVAL);
2303 assert_return(!m->poisoned, -ESTALE);
2305 c = message_get_container(m);
2307 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2308 if (c->signature && c->signature[c->index] != 0)
2313 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2314 r = bus_message_close_array(m, c);
2315 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2316 r = bus_message_close_variant(m, c);
2317 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2318 r = bus_message_close_struct(m, c, true);
2320 assert_not_reached("Unknown container type");
2334 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2341 stack[*i].types = types;
2342 stack[*i].n_struct = n_struct;
2343 stack[*i].n_array = n_array;
2349 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2360 *types = stack[*i].types;
2361 *n_struct = stack[*i].n_struct;
2362 *n_array = stack[*i].n_array;
2367 int bus_message_append_ap(
2372 unsigned n_array, n_struct;
2373 TypeStack stack[BUS_CONTAINER_DEPTH];
2374 unsigned stack_ptr = 0;
2382 n_array = (unsigned) -1;
2383 n_struct = strlen(types);
2388 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2389 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2395 r = sd_bus_message_close_container(m);
2403 if (n_array != (unsigned) -1)
2412 case SD_BUS_TYPE_BYTE: {
2415 x = (uint8_t) va_arg(ap, int);
2416 r = sd_bus_message_append_basic(m, *t, &x);
2420 case SD_BUS_TYPE_BOOLEAN:
2421 case SD_BUS_TYPE_INT32:
2422 case SD_BUS_TYPE_UINT32:
2423 case SD_BUS_TYPE_UNIX_FD: {
2426 /* We assume a boolean is the same as int32_t */
2427 assert_cc(sizeof(int32_t) == sizeof(int));
2429 x = va_arg(ap, uint32_t);
2430 r = sd_bus_message_append_basic(m, *t, &x);
2434 case SD_BUS_TYPE_INT16:
2435 case SD_BUS_TYPE_UINT16: {
2438 x = (uint16_t) va_arg(ap, int);
2439 r = sd_bus_message_append_basic(m, *t, &x);
2443 case SD_BUS_TYPE_INT64:
2444 case SD_BUS_TYPE_UINT64: {
2447 x = va_arg(ap, uint64_t);
2448 r = sd_bus_message_append_basic(m, *t, &x);
2452 case SD_BUS_TYPE_DOUBLE: {
2455 x = va_arg(ap, double);
2456 r = sd_bus_message_append_basic(m, *t, &x);
2460 case SD_BUS_TYPE_STRING:
2461 case SD_BUS_TYPE_OBJECT_PATH:
2462 case SD_BUS_TYPE_SIGNATURE: {
2465 x = va_arg(ap, const char*);
2466 r = sd_bus_message_append_basic(m, *t, x);
2470 case SD_BUS_TYPE_ARRAY: {
2473 r = signature_element_length(t + 1, &k);
2479 memcpy(s, t + 1, k);
2482 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2487 if (n_array == (unsigned) -1) {
2492 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2498 n_array = va_arg(ap, unsigned);
2503 case SD_BUS_TYPE_VARIANT: {
2506 s = va_arg(ap, const char*);
2510 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2514 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2519 n_struct = strlen(s);
2520 n_array = (unsigned) -1;
2525 case SD_BUS_TYPE_STRUCT_BEGIN:
2526 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2529 r = signature_element_length(t, &k);
2536 memcpy(s, t + 1, k - 2);
2539 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2544 if (n_array == (unsigned) -1) {
2549 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2555 n_array = (unsigned) -1;
2571 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2575 assert_return(m, -EINVAL);
2576 assert_return(types, -EINVAL);
2577 assert_return(!m->sealed, -EPERM);
2578 assert_return(!m->poisoned, -ESTALE);
2580 va_start(ap, types);
2581 r = bus_message_append_ap(m, types, ap);
2587 #if 0 /// UNNEEDED by elogind
2588 _public_ int sd_bus_message_append_array_space(
2598 assert_return(m, -EINVAL);
2599 assert_return(!m->sealed, -EPERM);
2600 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2601 assert_return(ptr || size == 0, -EINVAL);
2602 assert_return(!m->poisoned, -ESTALE);
2604 /* alignment and size of the trivial types (except bool) is
2605 * identical for gvariant and dbus1 marshalling */
2606 align = bus_type_get_alignment(type);
2607 sz = bus_type_get_size(type);
2609 assert_se(align > 0);
2615 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2619 a = message_extend_body(m, align, size, false, false);
2623 r = sd_bus_message_close_container(m);
2631 _public_ int sd_bus_message_append_array(
2639 assert_return(m, -EINVAL);
2640 assert_return(!m->sealed, -EPERM);
2641 assert_return(bus_type_is_trivial(type), -EINVAL);
2642 assert_return(ptr || size == 0, -EINVAL);
2643 assert_return(!m->poisoned, -ESTALE);
2645 r = sd_bus_message_append_array_space(m, type, size, &p);
2650 memcpy(p, ptr, size);
2655 _public_ int sd_bus_message_append_array_iovec(
2658 const struct iovec *iov,
2666 assert_return(m, -EINVAL);
2667 assert_return(!m->sealed, -EPERM);
2668 assert_return(bus_type_is_trivial(type), -EINVAL);
2669 assert_return(iov || n == 0, -EINVAL);
2670 assert_return(!m->poisoned, -ESTALE);
2672 size = IOVEC_TOTAL_SIZE(iov, n);
2674 r = sd_bus_message_append_array_space(m, type, size, &p);
2678 for (i = 0; i < n; i++) {
2680 if (iov[i].iov_base)
2681 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2683 memzero(p, iov[i].iov_len);
2685 p = (uint8_t*) p + iov[i].iov_len;
2691 _public_ int sd_bus_message_append_array_memfd(
2698 _cleanup_close_ int copy_fd = -1;
2699 struct bus_body_part *part;
2705 assert_return(m, -EINVAL);
2706 assert_return(memfd >= 0, -EBADF);
2707 assert_return(bus_type_is_trivial(type), -EINVAL);
2708 assert_return(size > 0, -EINVAL);
2709 assert_return(!m->sealed, -EPERM);
2710 assert_return(!m->poisoned, -ESTALE);
2712 r = memfd_set_sealed(memfd);
2716 copy_fd = dup(memfd);
2720 r = memfd_get_size(memfd, &real_size);
2724 if (offset == 0 && size == (uint64_t) -1)
2726 else if (offset + size > real_size)
2729 align = bus_type_get_alignment(type);
2730 sz = bus_type_get_size(type);
2732 assert_se(align > 0);
2735 if (offset % align != 0)
2741 if (size > (uint64_t) (uint32_t) -1)
2744 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2748 a = message_extend_body(m, align, 0, false, false);
2752 part = message_append_part(m);
2756 part->memfd = copy_fd;
2757 part->memfd_offset = offset;
2758 part->sealed = true;
2762 m->body_size += size;
2763 message_extend_containers(m, size);
2765 return sd_bus_message_close_container(m);
2768 _public_ int sd_bus_message_append_string_memfd(
2774 _cleanup_close_ int copy_fd = -1;
2775 struct bus_body_part *part;
2776 struct bus_container *c;
2781 assert_return(m, -EINVAL);
2782 assert_return(memfd >= 0, -EBADF);
2783 assert_return(size > 0, -EINVAL);
2784 assert_return(!m->sealed, -EPERM);
2785 assert_return(!m->poisoned, -ESTALE);
2787 r = memfd_set_sealed(memfd);
2791 copy_fd = dup(memfd);
2795 r = memfd_get_size(memfd, &real_size);
2799 if (offset == 0 && size == (uint64_t) -1)
2801 else if (offset + size > real_size)
2804 /* We require this to be NUL terminated */
2808 if (size > (uint64_t) (uint32_t) -1)
2811 c = message_get_container(m);
2812 if (c->signature && c->signature[c->index]) {
2813 /* Container signature is already set */
2815 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2820 /* Maybe we can append to the signature? But only if this is the top-level container */
2821 if (c->enclosing != 0)
2824 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2831 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2832 a = message_extend_body(m, 4, 4, false, false);
2836 *(uint32_t*) a = size - 1;
2839 part = message_append_part(m);
2843 part->memfd = copy_fd;
2844 part->memfd_offset = offset;
2845 part->sealed = true;
2849 m->body_size += size;
2850 message_extend_containers(m, size);
2852 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2853 r = message_add_offset(m, m->body_size);
2860 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2867 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2871 assert_return(m, -EINVAL);
2872 assert_return(!m->sealed, -EPERM);
2873 assert_return(!m->poisoned, -ESTALE);
2875 r = sd_bus_message_open_container(m, 'a', "s");
2879 STRV_FOREACH(i, l) {
2880 r = sd_bus_message_append_basic(m, 's', *i);
2885 return sd_bus_message_close_container(m);
2888 static int bus_message_close_header(sd_bus_message *m) {
2892 /* The actual user data is finished now, we just complete the
2893 variant and struct now (at least on gvariant). Remember
2894 this position, so that during parsing we know where to to
2895 put the outer container end. */
2896 m->user_body_size = m->body_size;
2898 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2899 const char *signature;
2903 /* Add offset table to end of fields array */
2904 if (m->n_header_offsets >= 1) {
2908 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2910 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2911 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2915 for (i = 0; i < m->n_header_offsets; i++)
2916 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2919 /* Add gvariant NUL byte plus signature to the end of
2920 * the body, followed by the final offset pointing to
2921 * the end of the fields array */
2923 signature = strempty(m->root_container.signature);
2924 l = strlen(signature);
2926 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2927 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2932 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2933 memcpy((uint8_t*) d + 2, signature, l);
2934 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2936 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2939 m->footer_accessible = 1 + l + 2 + sz;
2941 m->header->dbus1.fields_size = m->fields_size;
2942 m->header->dbus1.body_size = m->body_size;
2948 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2949 struct bus_body_part *part;
2959 if (m->n_containers > 0)
2965 if (cookie > 0xffffffffULL &&
2966 !BUS_MESSAGE_IS_GVARIANT(m))
2969 /* In vtables the return signature of method calls is listed,
2970 * let's check if they match if this is a response */
2971 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2972 m->enforced_reply_signature &&
2973 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2976 /* If gvariant marshalling is used we need to close the body structure */
2977 r = bus_message_close_struct(m, &m->root_container, false);
2981 /* If there's a non-trivial signature set, then add it in
2982 * here, but only on dbus1 */
2983 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2984 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2990 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2995 r = bus_message_close_header(m);
2999 if (BUS_MESSAGE_IS_GVARIANT(m))
3000 m->header->dbus2.cookie = cookie;
3002 m->header->dbus1.serial = (uint32_t) cookie;
3004 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
3006 /* Add padding at the end of the fields part, since we know
3007 * the body needs to start at an 8 byte alignment. We made
3008 * sure we allocated enough space for this, so all we need to
3009 * do here is to zero it out. */
3010 a = ALIGN8(m->fields_size) - m->fields_size;
3012 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
3014 /* If this is something we can send as memfd, then let's seal
3015 the memfd now. Note that we can send memfds as payload only
3016 for directed messages, and not for broadcasts. */
3017 if (m->destination && m->bus->use_memfd) {
3018 MESSAGE_FOREACH_PART(part, i, m)
3019 if (part->memfd >= 0 &&
3021 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3022 part != m->body_end) { /* The last part may never be sent as memfd */
3025 /* Try to seal it if that makes
3026 * sense. First, unmap our own map to
3027 * make sure we don't keep it busy. */
3028 bus_body_part_unmap(part);
3030 /* Then, sync up real memfd size */
3032 r = memfd_set_size(part->memfd, sz);
3036 /* Finally, try to seal */
3037 if (memfd_set_sealed(part->memfd) >= 0)
3038 part->sealed = true;
3042 m->root_container.end = m->user_body_size;
3043 m->root_container.index = 0;
3044 m->root_container.offset_index = 0;
3045 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3052 int bus_body_part_map(struct bus_body_part *part) {
3061 if (part->size <= 0)
3064 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3065 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3066 static const uint8_t zeroes[7] = { };
3067 part->data = (void*) zeroes;
3071 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3072 psz = PAGE_ALIGN(part->size + shift);
3074 if (part->memfd >= 0)
3075 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3076 else if (part->is_zero)
3077 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3081 if (p == MAP_FAILED)
3085 part->mmap_begin = p;
3086 part->data = (uint8_t*) p + shift;
3087 part->munmap_this = true;
3092 void bus_body_part_unmap(struct bus_body_part *part) {
3096 if (part->memfd < 0)
3099 if (!part->mmap_begin)
3102 if (!part->munmap_this)
3105 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3107 part->mmap_begin = NULL;
3110 part->munmap_this = false;
3115 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3116 size_t k, start, end;
3121 start = ALIGN_TO((size_t) *rindex, align);
3122 end = start + nbytes;
3127 /* Verify that padding is 0 */
3128 for (k = *rindex; k < start; k++)
3129 if (((const uint8_t*) p)[k] != 0)
3133 *r = (uint8_t*) p + start;
3140 static bool message_end_of_signature(sd_bus_message *m) {
3141 struct bus_container *c;
3145 c = message_get_container(m);
3146 return !c->signature || c->signature[c->index] == 0;
3149 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3150 struct bus_container *c;
3154 c = message_get_container(m);
3155 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3158 if (BUS_MESSAGE_IS_GVARIANT(m))
3159 return index >= c->end;
3161 assert(c->array_size);
3162 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3166 #if 0 /// UNNEEDED by elogind
3167 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3168 assert_return(m, -EINVAL);
3169 assert_return(m->sealed, -EPERM);
3171 if (complete && m->n_containers > 0)
3174 if (message_end_of_signature(m))
3177 if (message_end_of_array(m, m->rindex))
3184 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3185 struct bus_body_part *part;
3191 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3192 part = m->cached_rindex_part;
3193 begin = m->cached_rindex_part_begin;
3203 if (index + sz <= begin + part->size) {
3205 r = bus_body_part_map(part);
3210 *p = (uint8_t*) part->data + index - begin;
3212 m->cached_rindex_part = part;
3213 m->cached_rindex_part_begin = begin;
3218 begin += part->size;
3225 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3232 if (!BUS_MESSAGE_IS_GVARIANT(m))
3235 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3238 sz = bus_gvariant_get_size(c->signature);
3242 if (c->offset_index+1 >= c->n_offsets)
3245 /* Variable-size array */
3247 alignment = bus_gvariant_get_alignment(c->signature);
3248 assert(alignment > 0);
3250 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3251 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3254 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3257 /* Fixed-size array */
3258 *rindex = c->begin + (c->offset_index+1) * sz;
3264 } else if (c->enclosing == 0 ||
3265 c->enclosing == SD_BUS_TYPE_STRUCT ||
3266 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3271 if (c->offset_index+1 >= c->n_offsets)
3274 r = signature_element_length(c->signature + c->index, &n);
3278 r = signature_element_length(c->signature + c->index + n, &j);
3283 memcpy(t, c->signature + c->index + n, j);
3286 alignment = bus_gvariant_get_alignment(t);
3289 assert(alignment > 0);
3291 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3292 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3296 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3299 assert_not_reached("Unknown container type");
3304 /* Reached the end */
3311 static int message_peek_body(
3318 size_t k, start, end, padding;
3319 struct bus_body_part *part;
3326 start = ALIGN_TO((size_t) *rindex, align);
3327 padding = start - *rindex;
3328 end = start + nbytes;
3330 if (end > m->user_body_size)
3333 part = find_part(m, *rindex, padding, (void**) &q);
3338 /* Verify padding */
3339 for (k = 0; k < padding; k++)
3344 part = find_part(m, start, nbytes, (void**) &q);
3345 if (!part || (nbytes > 0 && !q))
3356 static bool validate_nul(const char *s, size_t l) {
3358 /* Check for NUL chars in the string */
3359 if (memchr(s, 0, l))
3362 /* Check for NUL termination */
3369 static bool validate_string(const char *s, size_t l) {
3371 if (!validate_nul(s, l))
3374 /* Check if valid UTF8 */
3375 if (!utf8_is_valid(s))
3381 static bool validate_signature(const char *s, size_t l) {
3383 if (!validate_nul(s, l))
3386 /* Check if valid signature */
3387 if (!signature_is_valid(s, true))
3393 static bool validate_object_path(const char *s, size_t l) {
3395 if (!validate_nul(s, l))
3398 if (!object_path_is_valid(s))
3404 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3405 struct bus_container *c;
3410 assert_return(m, -EINVAL);
3411 assert_return(m->sealed, -EPERM);
3412 assert_return(bus_type_is_basic(type), -EINVAL);
3414 if (message_end_of_signature(m))
3417 if (message_end_of_array(m, m->rindex))
3420 c = message_get_container(m);
3421 if (c->signature[c->index] != type)
3426 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3428 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3431 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3435 if (type == SD_BUS_TYPE_STRING)
3436 ok = validate_string(q, c->item_size-1);
3437 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3438 ok = validate_object_path(q, c->item_size-1);
3440 ok = validate_signature(q, c->item_size-1);
3446 *(const char**) p = q;
3450 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3452 if ((size_t) sz != c->item_size)
3455 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3458 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3464 case SD_BUS_TYPE_BYTE:
3466 *(uint8_t*) p = *(uint8_t*) q;
3469 case SD_BUS_TYPE_BOOLEAN:
3471 *(int*) p = !!*(uint8_t*) q;
3474 case SD_BUS_TYPE_INT16:
3475 case SD_BUS_TYPE_UINT16:
3477 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3480 case SD_BUS_TYPE_INT32:
3481 case SD_BUS_TYPE_UINT32:
3483 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3486 case SD_BUS_TYPE_INT64:
3487 case SD_BUS_TYPE_UINT64:
3488 case SD_BUS_TYPE_DOUBLE:
3490 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3493 case SD_BUS_TYPE_UNIX_FD: {
3496 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3501 *(int*) p = m->fds[j];
3507 assert_not_reached("unexpected type");
3511 r = container_next_item(m, c, &rindex);
3516 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3520 r = message_peek_body(m, &rindex, 4, 4, &q);
3524 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3525 r = message_peek_body(m, &rindex, 1, l+1, &q);
3529 if (type == SD_BUS_TYPE_OBJECT_PATH)
3530 ok = validate_object_path(q, l);
3532 ok = validate_string(q, l);
3537 *(const char**) p = q;
3539 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3542 r = message_peek_body(m, &rindex, 1, 1, &q);
3547 r = message_peek_body(m, &rindex, 1, l+1, &q);
3551 if (!validate_signature(q, l))
3555 *(const char**) p = q;
3560 align = bus_type_get_alignment(type);
3563 sz = bus_type_get_size(type);
3566 r = message_peek_body(m, &rindex, align, sz, &q);
3572 case SD_BUS_TYPE_BYTE:
3574 *(uint8_t*) p = *(uint8_t*) q;
3577 case SD_BUS_TYPE_BOOLEAN:
3579 *(int*) p = !!*(uint32_t*) q;
3582 case SD_BUS_TYPE_INT16:
3583 case SD_BUS_TYPE_UINT16:
3585 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3588 case SD_BUS_TYPE_INT32:
3589 case SD_BUS_TYPE_UINT32:
3591 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3594 case SD_BUS_TYPE_INT64:
3595 case SD_BUS_TYPE_UINT64:
3596 case SD_BUS_TYPE_DOUBLE:
3598 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3601 case SD_BUS_TYPE_UNIX_FD: {
3604 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3609 *(int*) p = m->fds[j];
3614 assert_not_reached("Unknown basic type...");
3621 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3627 static int bus_message_enter_array(
3629 struct bus_container *c,
3630 const char *contents,
3631 uint32_t **array_size,
3634 size_t *n_offsets) {
3648 if (!signature_is_single(contents, true))
3651 if (!c->signature || c->signature[c->index] == 0)
3654 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3657 if (!startswith(c->signature + c->index + 1, contents))
3662 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3665 r = message_peek_body(m, &rindex, 4, 4, &q);
3669 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3672 alignment = bus_type_get_alignment(contents[0]);
3676 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3680 *array_size = (uint32_t*) q;
3682 } else if (c->item_size <= 0) {
3684 /* gvariant: empty array */
3689 } else if (bus_gvariant_is_fixed_size(contents)) {
3691 /* gvariant: fixed length array */
3692 *item_size = bus_gvariant_get_size(contents);
3697 size_t where, p = 0, framing, sz;
3700 /* gvariant: variable length array */
3701 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3703 where = rindex + c->item_size - sz;
3704 r = message_peek_body(m, &where, 1, sz, &q);
3708 framing = bus_gvariant_read_word_le(q, sz);
3709 if (framing > c->item_size - sz)
3711 if ((c->item_size - framing) % sz != 0)
3714 *n_offsets = (c->item_size - framing) / sz;
3716 where = rindex + framing;
3717 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3721 *offsets = new(size_t, *n_offsets);
3725 for (i = 0; i < *n_offsets; i++) {
3728 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3729 if (x > c->item_size - sz)
3734 (*offsets)[i] = rindex + x;
3738 *item_size = (*offsets)[0] - rindex;
3743 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3744 c->index += 1 + strlen(contents);
3749 static int bus_message_enter_variant(
3751 struct bus_container *c,
3752 const char *contents,
3753 size_t *item_size) {
3765 if (!signature_is_single(contents, false))
3768 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3771 if (!c->signature || c->signature[c->index] == 0)
3774 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3779 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3782 k = strlen(contents);
3783 if (1+k > c->item_size)
3786 where = rindex + c->item_size - (1+k);
3787 r = message_peek_body(m, &where, 1, 1+k, &q);
3791 if (*(char*) q != 0)
3794 if (memcmp((uint8_t*) q+1, contents, k))
3797 *item_size = c->item_size - (1+k);
3800 r = message_peek_body(m, &rindex, 1, 1, &q);
3805 r = message_peek_body(m, &rindex, 1, l+1, &q);
3809 if (!validate_signature(q, l))
3812 if (!streq(q, contents))
3818 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3824 static int build_struct_offsets(
3826 const char *signature,
3830 size_t *n_offsets) {
3832 unsigned n_variable = 0, n_total = 0, v;
3833 size_t previous = 0, where;
3844 if (isempty(signature)) {
3845 /* Unary type is encoded as *fixed* 1 byte padding */
3846 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3850 if (*(uint8_t *) q != 0)
3859 sz = bus_gvariant_determine_word_size(size, 0);
3863 /* First, loop over signature and count variable elements and
3864 * elements in general. We use this to know how large the
3865 * offset array is at the end of the structure. Note that
3866 * GVariant only stores offsets for all variable size elements
3867 * that are not the last item. */
3873 r = signature_element_length(p, &n);
3882 r = bus_gvariant_is_fixed_size(t);
3887 if (r == 0 && p[n] != 0) /* except the last item */
3894 if (size < n_variable * sz)
3897 where = m->rindex + size - (n_variable * sz);
3898 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3904 *offsets = new(size_t, n_total);
3910 /* Second, loop again and build an offset table */
3916 r = signature_element_length(p, &n);
3925 k = bus_gvariant_get_size(t);
3933 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3936 if (m->rindex + x < previous)
3939 /* The last item's end
3940 * is determined from
3943 x = size - (n_variable * sz);
3945 offset = m->rindex + x;
3951 align = bus_gvariant_get_alignment(t);
3954 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3958 previous = (*offsets)[(*n_offsets)++] = offset;
3963 assert(*n_offsets == n_total);
3965 *item_size = (*offsets)[0] - m->rindex;
3969 static int enter_struct_or_dict_entry(
3971 struct bus_container *c,
3972 const char *contents,
3975 size_t *n_offsets) {
3986 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3989 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3994 /* gvariant with contents */
3995 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
4000 static int bus_message_enter_struct(
4002 struct bus_container *c,
4003 const char *contents,
4006 size_t *n_offsets) {
4018 if (!signature_is_valid(contents, false))
4021 if (!c->signature || c->signature[c->index] == 0)
4024 l = strlen(contents);
4026 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4027 !startswith(c->signature + c->index + 1, contents) ||
4028 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4031 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4035 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4036 c->index += 1 + l + 1;
4041 static int bus_message_enter_dict_entry(
4043 struct bus_container *c,
4044 const char *contents,
4047 size_t *n_offsets) {
4056 if (!signature_is_pair(contents))
4059 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4062 if (!c->signature || c->signature[c->index] == 0)
4065 l = strlen(contents);
4067 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4068 !startswith(c->signature + c->index + 1, contents) ||
4069 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4072 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4076 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4077 c->index += 1 + l + 1;
4082 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4084 const char *contents) {
4085 struct bus_container *c, *w;
4086 uint32_t *array_size = NULL;
4089 size_t *offsets = NULL;
4090 size_t n_offsets = 0, item_size = 0;
4093 assert_return(m, -EINVAL);
4094 assert_return(m->sealed, -EPERM);
4095 assert_return(type != 0 || !contents, -EINVAL);
4097 if (type == 0 || !contents) {
4101 /* Allow entering into anonymous containers */
4102 r = sd_bus_message_peek_type(m, &tt, &cc);
4106 if (type != 0 && type != tt)
4109 if (contents && !streq(contents, cc))
4117 * We enforce a global limit on container depth, that is much
4118 * higher than the 32 structs and 32 arrays the specification
4119 * mandates. This is simpler to implement for us, and we need
4120 * this only to ensure our container array doesn't grow
4121 * without bounds. We are happy to return any data from a
4122 * message as long as the data itself is valid, even if the
4123 * overall message might be not.
4125 * Note that the message signature is validated when
4126 * parsing the headers, and that validation does check the
4129 * Note that the specification defines no limits on the depth
4130 * of stacked variants, but we do.
4132 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4135 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4138 if (message_end_of_signature(m))
4141 if (message_end_of_array(m, m->rindex))
4144 c = message_get_container(m);
4146 signature = strdup(contents);
4150 c->saved_index = c->index;
4153 if (type == SD_BUS_TYPE_ARRAY)
4154 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4155 else if (type == SD_BUS_TYPE_VARIANT)
4156 r = bus_message_enter_variant(m, c, contents, &item_size);
4157 else if (type == SD_BUS_TYPE_STRUCT)
4158 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4159 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4160 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4170 /* OK, let's fill it in */
4171 w = m->containers + m->n_containers++;
4172 w->enclosing = type;
4173 w->signature = signature;
4174 w->peeked_signature = NULL;
4178 w->begin = m->rindex;
4180 /* Unary type has fixed size of 1, but virtual size of 0 */
4181 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4182 type == SD_BUS_TYPE_STRUCT &&
4184 w->end = m->rindex + 0;
4186 w->end = m->rindex + c->item_size;
4188 w->array_size = array_size;
4189 w->item_size = item_size;
4190 w->offsets = offsets;
4191 w->n_offsets = n_offsets;
4192 w->offset_index = 0;
4197 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4198 struct bus_container *c;
4202 assert_return(m, -EINVAL);
4203 assert_return(m->sealed, -EPERM);
4204 assert_return(m->n_containers > 0, -ENXIO);
4206 c = message_get_container(m);
4208 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4209 if (c->signature && c->signature[c->index] != 0)
4213 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4214 if (m->rindex < c->end)
4217 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4220 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4221 if (c->begin + l != m->rindex)
4226 free(c->peeked_signature);
4230 c = message_get_container(m);
4233 c->index = c->saved_index;
4234 r = container_next_item(m, c, &m->rindex);
4242 static void message_quit_container(sd_bus_message *m) {
4243 struct bus_container *c;
4247 assert(m->n_containers > 0);
4249 c = message_get_container(m);
4252 assert(m->rindex >= c->before);
4253 m->rindex = c->before;
4255 /* Free container */
4260 /* Correct index of new top-level container */
4261 c = message_get_container(m);
4262 c->index = c->saved_index;
4265 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4266 struct bus_container *c;
4269 assert_return(m, -EINVAL);
4270 assert_return(m->sealed, -EPERM);
4272 if (message_end_of_signature(m))
4275 if (message_end_of_array(m, m->rindex))
4278 c = message_get_container(m);
4280 if (bus_type_is_basic(c->signature[c->index])) {
4284 *type = c->signature[c->index];
4288 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4294 r = signature_element_length(c->signature+c->index+1, &l);
4300 sig = strndup(c->signature + c->index + 1, l);
4304 free(c->peeked_signature);
4305 *contents = c->peeked_signature = sig;
4309 *type = SD_BUS_TYPE_ARRAY;
4314 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4315 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4321 r = signature_element_length(c->signature+c->index, &l);
4326 sig = strndup(c->signature + c->index + 1, l - 2);
4330 free(c->peeked_signature);
4331 *contents = c->peeked_signature = sig;
4335 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4340 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4344 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4347 if (c->item_size < 2)
4350 /* Look for the NUL delimiter that
4351 separates the payload from the
4352 signature. Since the body might be
4353 in a different part that then the
4354 signature we map byte by byte. */
4356 for (k = 2; k <= c->item_size; k++) {
4359 where = m->rindex + c->item_size - k;
4360 r = message_peek_body(m, &where, 1, k, &q);
4364 if (*(char*) q == 0)
4368 if (k > c->item_size)
4371 free(c->peeked_signature);
4372 c->peeked_signature = strndup((char*) q + 1, k - 1);
4373 if (!c->peeked_signature)
4376 if (!signature_is_valid(c->peeked_signature, true))
4379 *contents = c->peeked_signature;
4384 r = message_peek_body(m, &rindex, 1, 1, &q);
4389 r = message_peek_body(m, &rindex, 1, l+1, &q);
4393 if (!validate_signature(q, l))
4401 *type = SD_BUS_TYPE_VARIANT;
4416 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4417 struct bus_container *c;
4419 assert_return(m, -EINVAL);
4420 assert_return(m->sealed, -EPERM);
4423 message_reset_containers(m);
4426 c = message_get_container(m);
4428 c = message_get_container(m);
4430 c->offset_index = 0;
4432 m->rindex = c->begin;
4435 c->offset_index = 0;
4436 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4438 return !isempty(c->signature);
4441 static int message_read_ap(
4446 unsigned n_array, n_struct;
4447 TypeStack stack[BUS_CONTAINER_DEPTH];
4448 unsigned stack_ptr = 0;
4449 unsigned n_loop = 0;
4457 /* Ideally, we'd just call ourselves recursively on every
4458 * complex type. However, the state of a va_list that is
4459 * passed to a function is undefined after that function
4460 * returns. This means we need to docode the va_list linearly
4461 * in a single stackframe. We hence implement our own
4462 * home-grown stack in an array. */
4464 n_array = (unsigned) -1; /* length of current array entries */
4465 n_struct = strlen(types); /* length of current struct contents signature */
4472 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4473 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4479 r = sd_bus_message_exit_container(m);
4487 if (n_array != (unsigned) -1)
4496 case SD_BUS_TYPE_BYTE:
4497 case SD_BUS_TYPE_BOOLEAN:
4498 case SD_BUS_TYPE_INT16:
4499 case SD_BUS_TYPE_UINT16:
4500 case SD_BUS_TYPE_INT32:
4501 case SD_BUS_TYPE_UINT32:
4502 case SD_BUS_TYPE_INT64:
4503 case SD_BUS_TYPE_UINT64:
4504 case SD_BUS_TYPE_DOUBLE:
4505 case SD_BUS_TYPE_STRING:
4506 case SD_BUS_TYPE_OBJECT_PATH:
4507 case SD_BUS_TYPE_SIGNATURE:
4508 case SD_BUS_TYPE_UNIX_FD: {
4511 p = va_arg(ap, void*);
4512 r = sd_bus_message_read_basic(m, *t, p);
4525 case SD_BUS_TYPE_ARRAY: {
4528 r = signature_element_length(t + 1, &k);
4534 memcpy(s, t + 1, k);
4537 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4548 if (n_array == (unsigned) -1) {
4553 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4559 n_array = va_arg(ap, unsigned);
4564 case SD_BUS_TYPE_VARIANT: {
4567 s = va_arg(ap, const char *);
4571 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4581 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4586 n_struct = strlen(s);
4587 n_array = (unsigned) -1;
4592 case SD_BUS_TYPE_STRUCT_BEGIN:
4593 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4596 r = signature_element_length(t, &k);
4602 memcpy(s, t + 1, k - 2);
4605 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4615 if (n_array == (unsigned) -1) {
4620 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4626 n_array = (unsigned) -1;
4639 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4643 assert_return(m, -EINVAL);
4644 assert_return(m->sealed, -EPERM);
4645 assert_return(types, -EINVAL);
4647 va_start(ap, types);
4648 r = message_read_ap(m, types, ap);
4654 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4657 assert_return(m, -EINVAL);
4658 assert_return(m->sealed, -EPERM);
4660 /* If types is NULL, read exactly one element */
4662 struct bus_container *c;
4665 if (message_end_of_signature(m))
4668 if (message_end_of_array(m, m->rindex))
4671 c = message_get_container(m);
4673 r = signature_element_length(c->signature + c->index, &l);
4677 types = strndupa(c->signature + c->index, l);
4682 case 0: /* Nothing to drop */
4685 case SD_BUS_TYPE_BYTE:
4686 case SD_BUS_TYPE_BOOLEAN:
4687 case SD_BUS_TYPE_INT16:
4688 case SD_BUS_TYPE_UINT16:
4689 case SD_BUS_TYPE_INT32:
4690 case SD_BUS_TYPE_UINT32:
4691 case SD_BUS_TYPE_INT64:
4692 case SD_BUS_TYPE_UINT64:
4693 case SD_BUS_TYPE_DOUBLE:
4694 case SD_BUS_TYPE_STRING:
4695 case SD_BUS_TYPE_OBJECT_PATH:
4696 case SD_BUS_TYPE_SIGNATURE:
4697 case SD_BUS_TYPE_UNIX_FD:
4699 r = sd_bus_message_read_basic(m, *types, NULL);
4703 r = sd_bus_message_skip(m, types + 1);
4709 case SD_BUS_TYPE_ARRAY: {
4712 r = signature_element_length(types + 1, &k);
4718 memcpy(s, types+1, k);
4721 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4726 r = sd_bus_message_skip(m, s);
4733 r = sd_bus_message_exit_container(m);
4738 r = sd_bus_message_skip(m, types + 1 + k);
4745 case SD_BUS_TYPE_VARIANT: {
4746 const char *contents;
4749 r = sd_bus_message_peek_type(m, &x, &contents);
4753 if (x != SD_BUS_TYPE_VARIANT)
4756 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4760 r = sd_bus_message_skip(m, contents);
4765 r = sd_bus_message_exit_container(m);
4769 r = sd_bus_message_skip(m, types + 1);
4776 case SD_BUS_TYPE_STRUCT_BEGIN:
4777 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4780 r = signature_element_length(types, &k);
4786 memcpy(s, types+1, k-2);
4789 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4793 r = sd_bus_message_skip(m, s);
4797 r = sd_bus_message_exit_container(m);
4802 r = sd_bus_message_skip(m, types + k);
4814 _public_ int sd_bus_message_read_array(
4820 struct bus_container *c;
4826 assert_return(m, -EINVAL);
4827 assert_return(m->sealed, -EPERM);
4828 assert_return(bus_type_is_trivial(type), -EINVAL);
4829 assert_return(ptr, -EINVAL);
4830 assert_return(size, -EINVAL);
4831 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4833 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4837 c = message_get_container(m);
4839 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4840 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4844 sz = c->end - c->begin;
4846 align = bus_type_get_alignment(type);
4850 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4854 /* Zero length array, let's return some aligned
4855 * pointer that is not NULL */
4856 p = (uint8_t*) NULL + align;
4858 r = message_peek_body(m, &m->rindex, align, sz, &p);
4863 r = sd_bus_message_exit_container(m);
4867 *ptr = (const void*) p;
4873 message_quit_container(m);
4877 static int message_peek_fields(
4888 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4891 static int message_peek_field_uint32(
4903 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4906 /* identical for gvariant and dbus1 */
4908 r = message_peek_fields(m, ri, 4, 4, &q);
4913 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4918 static int message_peek_field_uint64(
4930 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4933 /* identical for gvariant and dbus1 */
4935 r = message_peek_fields(m, ri, 8, 8, &q);
4940 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4945 static int message_peek_field_string(
4947 bool (*validate)(const char *p),
4959 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4964 r = message_peek_fields(m, ri, 1, item_size, &q);
4970 r = message_peek_field_uint32(m, ri, 4, &l);
4974 r = message_peek_fields(m, ri, 1, l+1, &q);
4980 if (!validate_nul(q, l))
4986 if (!validate_string(q, l))
4996 static int message_peek_field_signature(
5009 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5014 r = message_peek_fields(m, ri, 1, item_size, &q);
5020 r = message_peek_fields(m, ri, 1, 1, &q);
5025 r = message_peek_fields(m, ri, 1, l+1, &q);
5030 if (!validate_signature(q, l))
5039 static int message_skip_fields(
5042 uint32_t array_size,
5043 const char **signature) {
5045 size_t original_index;
5051 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5053 original_index = *ri;
5059 if (array_size != (uint32_t) -1 &&
5060 array_size <= *ri - original_index)
5067 if (t == SD_BUS_TYPE_STRING) {
5069 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5075 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5077 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5083 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5085 r = message_peek_field_signature(m, ri, 0, NULL);
5091 } else if (bus_type_is_basic(t)) {
5094 align = bus_type_get_alignment(t);
5095 k = bus_type_get_size(t);
5096 assert(align > 0 && k > 0);
5098 r = message_peek_fields(m, ri, align, k, NULL);
5104 } else if (t == SD_BUS_TYPE_ARRAY) {
5106 r = signature_element_length(*signature+1, &l);
5116 strncpy(sig, *signature + 1, l-1);
5119 alignment = bus_type_get_alignment(sig[0]);
5123 r = message_peek_field_uint32(m, ri, 0, &nas);
5126 if (nas > BUS_ARRAY_MAX_SIZE)
5129 r = message_peek_fields(m, ri, alignment, 0, NULL);
5133 r = message_skip_fields(m, ri, nas, (const char**) &s);
5138 (*signature) += 1 + l;
5140 } else if (t == SD_BUS_TYPE_VARIANT) {
5143 r = message_peek_field_signature(m, ri, 0, &s);
5147 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5153 } else if (t == SD_BUS_TYPE_STRUCT ||
5154 t == SD_BUS_TYPE_DICT_ENTRY) {
5156 r = signature_element_length(*signature, &l);
5163 strncpy(sig, *signature + 1, l-1);
5166 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5177 int bus_message_parse_fields(sd_bus_message *m) {
5180 uint32_t unix_fds = 0;
5181 bool unix_fds_set = false;
5182 void *offsets = NULL;
5183 unsigned n_offsets = 0;
5189 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5192 /* Read the signature from the end of the body variant first */
5193 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5194 if (m->footer_accessible < 1 + sz)
5197 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5199 if (p < (char*) m->footer)
5206 /* We found the beginning of the signature
5207 * string, yay! We require the body to be a
5208 * structure, so verify it and then strip the
5209 * opening/closing brackets. */
5211 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5213 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5214 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5217 c = strndup(p + 1 + 1, l - 2);
5221 free(m->root_container.signature);
5222 m->root_container.signature = c;
5229 /* Calculate the actual user body size, by removing
5230 * the trailing variant signature and struct offset
5232 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5234 /* Pull out the offset table for the fields array */
5235 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5240 ri = m->fields_size - sz;
5241 r = message_peek_fields(m, &ri, 1, sz, &q);
5245 framing = bus_gvariant_read_word_le(q, sz);
5246 if (framing >= m->fields_size - sz)
5248 if ((m->fields_size - framing) % sz != 0)
5252 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5256 n_offsets = (m->fields_size - framing) / sz;
5259 m->user_body_size = m->body_size;
5262 while (ri < m->fields_size) {
5263 _cleanup_free_ char *sig = NULL;
5264 const char *signature;
5265 uint64_t field_type;
5266 size_t item_size = (size_t) -1;
5268 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5277 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5279 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5283 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5287 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5294 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5299 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5304 where = ri = ALIGN_TO(ri, 8);
5305 item_size = end - ri;
5306 r = message_peek_fields(m, &where, 1, item_size, &q);
5310 b = memrchr(q, 0, item_size);
5314 sig = strndup(b+1, item_size - (b+1-(char*) q));
5319 item_size = b - (char*) q;
5321 r = message_peek_field_signature(m, &ri, 0, &signature);
5326 switch (field_type) {
5328 case _BUS_MESSAGE_HEADER_INVALID:
5331 case BUS_MESSAGE_HEADER_PATH:
5336 if (!streq(signature, "o"))
5339 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5342 case BUS_MESSAGE_HEADER_INTERFACE:
5347 if (!streq(signature, "s"))
5350 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5353 case BUS_MESSAGE_HEADER_MEMBER:
5358 if (!streq(signature, "s"))
5361 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5364 case BUS_MESSAGE_HEADER_ERROR_NAME:
5369 if (!streq(signature, "s"))
5372 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5374 m->error._need_free = -1;
5378 case BUS_MESSAGE_HEADER_DESTINATION:
5383 if (!streq(signature, "s"))
5386 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5389 case BUS_MESSAGE_HEADER_SENDER:
5394 if (!streq(signature, "s"))
5397 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5399 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5400 m->creds.unique_name = (char*) m->sender;
5401 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5407 case BUS_MESSAGE_HEADER_SIGNATURE: {
5411 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5414 if (m->root_container.signature)
5417 if (!streq(signature, "g"))
5420 r = message_peek_field_signature(m, &ri, item_size, &s);
5428 free(m->root_container.signature);
5429 m->root_container.signature = c;
5433 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5435 if (m->reply_cookie != 0)
5438 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5439 /* 64bit on dbus2 */
5441 if (!streq(signature, "t"))
5444 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5448 /* 32bit on dbus1 */
5451 if (!streq(signature, "u"))
5454 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5458 m->reply_cookie = serial;
5461 if (m->reply_cookie == 0)
5466 case BUS_MESSAGE_HEADER_UNIX_FDS:
5470 if (!streq(signature, "u"))
5473 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5477 unix_fds_set = true;
5481 if (!BUS_MESSAGE_IS_GVARIANT(m))
5482 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5491 if (m->n_fds != unix_fds)
5494 switch (m->header->type) {
5496 case SD_BUS_MESSAGE_SIGNAL:
5497 if (!m->path || !m->interface || !m->member)
5500 if (m->reply_cookie != 0)
5505 case SD_BUS_MESSAGE_METHOD_CALL:
5507 if (!m->path || !m->member)
5510 if (m->reply_cookie != 0)
5515 case SD_BUS_MESSAGE_METHOD_RETURN:
5517 if (m->reply_cookie == 0)
5521 case SD_BUS_MESSAGE_METHOD_ERROR:
5523 if (m->reply_cookie == 0 || !m->error.name)
5528 /* Refuse non-local messages that claim they are local */
5529 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5531 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5533 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5536 m->root_container.end = m->user_body_size;
5538 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5539 r = build_struct_offsets(
5541 m->root_container.signature,
5543 &m->root_container.item_size,
5544 &m->root_container.offsets,
5545 &m->root_container.n_offsets);
5550 /* Try to read the error message, but if we can't it's a non-issue */
5551 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5552 (void) sd_bus_message_read(m, "s", &m->error.message);
5557 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5558 assert_return(m, -EINVAL);
5559 assert_return(destination, -EINVAL);
5560 assert_return(!m->sealed, -EPERM);
5561 assert_return(!m->destination, -EEXIST);
5563 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5566 #if 0 /// UNNEEDED by elogind
5567 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5571 struct bus_body_part *part;
5577 total = BUS_MESSAGE_SIZE(m);
5583 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5584 MESSAGE_FOREACH_PART(part, i, m)
5585 e = mempcpy(e, part->data, part->size);
5587 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5596 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5603 r = sd_bus_message_enter_container(m, 'a', "s");
5607 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5608 r = strv_extend(l, s);
5615 r = sd_bus_message_exit_container(m);
5622 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5626 assert_return(m, -EINVAL);
5627 assert_return(m->sealed, -EPERM);
5628 assert_return(l, -EINVAL);
5630 r = bus_message_read_strv_extend(m, &strv);
5640 static int bus_message_get_arg_skip(
5644 const char **_contents) {
5649 r = sd_bus_message_rewind(m, true);
5654 const char *contents;
5657 r = sd_bus_message_peek_type(m, &type, &contents);
5663 /* Don't match against arguments after the first one we don't understand */
5664 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5665 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5670 *_contents = contents;
5676 r = sd_bus_message_skip(m, NULL);
5683 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5690 r = bus_message_get_arg_skip(m, i, &type, NULL);
5694 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5697 return sd_bus_message_read_basic(m, type, str);
5700 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5701 const char *contents;
5708 r = bus_message_get_arg_skip(m, i, &type, &contents);
5712 if (type != SD_BUS_TYPE_ARRAY)
5714 if (!STR_IN_SET(contents, "s", "o", "g"))
5717 return sd_bus_message_read_strv(m, strv);
5720 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5721 assert_return(m, EINVAL);
5723 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5726 return sd_bus_error_get_errno(&m->error);
5729 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5730 struct bus_container *c;
5732 assert_return(m, NULL);
5734 c = complete ? &m->root_container : message_get_container(m);
5735 return strempty(c->signature);
5738 #if 0 /// UNNEEDED by elogind
5739 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5740 assert_return(m, -EINVAL);
5742 return isempty(m->root_container.signature);
5745 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5746 assert_return(m, -EINVAL);
5748 return streq(strempty(m->root_container.signature), strempty(signature));
5752 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5753 bool done_something = false;
5756 assert_return(m, -EINVAL);
5757 assert_return(source, -EINVAL);
5758 assert_return(!m->sealed, -EPERM);
5759 assert_return(source->sealed, -EPERM);
5762 const char *contents;
5777 r = sd_bus_message_peek_type(source, &type, &contents);
5783 done_something = true;
5785 if (bus_type_is_container(type) > 0) {
5787 r = sd_bus_message_enter_container(source, type, contents);
5791 r = sd_bus_message_open_container(m, type, contents);
5795 r = sd_bus_message_copy(m, source, true);
5799 r = sd_bus_message_close_container(m);
5803 r = sd_bus_message_exit_container(source);
5810 r = sd_bus_message_read_basic(source, type, &basic);
5816 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5817 type == SD_BUS_TYPE_SIGNATURE ||
5818 type == SD_BUS_TYPE_STRING)
5819 r = sd_bus_message_append_basic(m, type, basic.string);
5821 r = sd_bus_message_append_basic(m, type, &basic);
5828 return done_something;
5831 #if 0 /// UNNEEDED by elogind
5832 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5837 assert_return(m, -EINVAL);
5838 assert_return(m->sealed, -EPERM);
5839 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5840 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5841 assert_return(type || contents, -EINVAL);
5842 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5844 r = sd_bus_message_peek_type(m, &t, &c);
5848 if (type != 0 && type != t)
5851 if (contents && !streq_ptr(contents, c))
5858 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5859 assert_return(m, NULL);
5864 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5865 _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5873 switch ((*m)->header->type) {
5875 case SD_BUS_MESSAGE_SIGNAL:
5876 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5882 case SD_BUS_MESSAGE_METHOD_CALL:
5883 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5889 case SD_BUS_MESSAGE_METHOD_RETURN:
5890 case SD_BUS_MESSAGE_METHOD_ERROR:
5892 n = message_new(bus, (*m)->header->type);
5896 n->reply_cookie = (*m)->reply_cookie;
5898 r = message_append_reply_cookie(n, n->reply_cookie);
5902 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5903 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5907 n->error._need_free = -1;
5916 if ((*m)->destination && !n->destination) {
5917 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5922 if ((*m)->sender && !n->sender) {
5923 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5928 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5930 r = sd_bus_message_copy(n, *m, true);
5934 timeout = (*m)->timeout;
5935 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5936 timeout = BUS_DEFAULT_TIMEOUT;
5938 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5942 sd_bus_message_unref(*m);
5949 #if 0 /// UNNEEDED by elogind
5950 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5954 assert_return(!m->sealed, -EPERM);
5955 assert_return(!m->sender, -EPERM);
5957 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5960 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5961 assert_return(m, -EINVAL);
5962 assert_return(priority, -EINVAL);
5964 *priority = m->priority;
5968 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5969 assert_return(m, -EINVAL);
5970 assert_return(!m->sealed, -EPERM);
5972 m->priority = priority;