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/>.
29 #include "time-util.h"
30 #include "memfd-util.h"
33 #include "bus-message.h"
34 #include "bus-internal.h"
36 #include "bus-signature.h"
37 #include "bus-gvariant.h"
40 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
42 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
47 if (old_base == new_base)
50 if ((uint8_t*) p < (uint8_t*) old_base)
53 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
56 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
59 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
63 if (part->memfd >= 0) {
64 /* If we can reuse the memfd, try that. For that it
65 * can't be sealed yet. */
68 assert(part->memfd_offset == 0);
69 assert(part->data == part->mmap_begin);
70 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
73 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
75 safe_close(part->memfd);
78 } else if (part->munmap_this)
79 munmap(part->mmap_begin, part->mapped);
80 else if (part->free_this)
87 static void message_reset_parts(sd_bus_message *m) {
88 struct bus_body_part *part;
93 while (m->n_body_parts > 0) {
94 struct bus_body_part *next = part->next;
95 message_free_part(m, part);
102 m->cached_rindex_part = NULL;
103 m->cached_rindex_part_begin = 0;
106 static void message_reset_containers(sd_bus_message *m) {
111 for (i = 0; i < m->n_containers; i++) {
112 free(m->containers[i].signature);
113 free(m->containers[i].offsets);
117 m->containers = NULL;
119 m->n_containers = m->containers_allocated = 0;
120 m->root_container.index = 0;
123 static void message_free(sd_bus_message *m) {
129 message_reset_parts(m);
131 if (m->release_kdbus)
132 bus_kernel_cmd_free(m->bus, (uint8_t *) m->kdbus - (uint8_t *) m->bus->kdbus_buffer);
137 sd_bus_unref(m->bus);
140 close_many(m->fds, m->n_fds);
144 if (m->iovec != m->iovec_fixed)
147 if (m->destination_ptr) {
148 free(m->destination_ptr);
149 m->destination_ptr = NULL;
152 message_reset_containers(m);
153 free(m->root_container.signature);
154 free(m->root_container.offsets);
156 free(m->root_container.peeked_signature);
158 bus_creds_done(&m->creds);
162 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
164 size_t old_size, new_size, start;
171 old_size = sizeof(struct bus_header) + m->fields_size;
172 start = ALIGN_TO(old_size, align);
173 new_size = start + sz;
175 if (new_size < start ||
176 new_size > (size_t) ((uint32_t) -1))
179 if (old_size == new_size)
180 return (uint8_t*) m->header + old_size;
182 if (m->free_header) {
183 np = realloc(m->header, ALIGN8(new_size));
187 /* Initially, the header is allocated as part of of
188 * the sd_bus_message itself, let's replace it by
191 np = malloc(ALIGN8(new_size));
195 memcpy(np, m->header, sizeof(struct bus_header));
198 /* Zero out padding */
199 if (start > old_size)
200 memzero((uint8_t*) np + old_size, start - old_size);
204 m->fields_size = new_size - sizeof(struct bus_header);
206 /* Adjust quick access pointers */
207 m->path = adjust_pointer(m->path, op, old_size, m->header);
208 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
209 m->member = adjust_pointer(m->member, op, old_size, m->header);
210 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
211 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
212 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
214 m->free_header = true;
217 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
220 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
223 return (uint8_t*) np + start;
230 static int message_append_field_string(
242 /* dbus1 only allows 8bit header field ids */
246 /* dbus1 doesn't allow strings over 32bit, let's enforce this
247 * globally, to not risk convertability */
249 if (l > (size_t) (uint32_t) -1)
252 /* Signature "(yv)" where the variant contains "s" */
254 if (BUS_MESSAGE_IS_GVARIANT(m)) {
256 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
257 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
261 *((uint64_t*) p) = h;
268 *ret = (char*) p + 8;
271 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
272 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
281 ((uint32_t*) p)[1] = l;
282 memcpy(p + 8, s, l + 1);
285 *ret = (char*) p + 8;
291 static int message_append_field_signature(
302 /* dbus1 only allows 8bit header field ids */
306 /* dbus1 doesn't allow signatures over 8bit, let's enforce
307 * this globally, to not risk convertability */
312 /* Signature "(yv)" where the variant contains "g" */
314 if (BUS_MESSAGE_IS_GVARIANT(m))
315 /* For gvariant the serialization is the same as for normal strings */
316 return message_append_field_string(m, h, 'g', s, ret);
318 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
319 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
325 p[2] = SD_BUS_TYPE_SIGNATURE;
328 memcpy(p + 5, s, l + 1);
331 *ret = (const char*) p + 5;
337 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
342 /* dbus1 only allows 8bit header field ids */
346 if (BUS_MESSAGE_IS_GVARIANT(m)) {
347 /* (field id 64bit + ((value + NUL + signature string 'u') */
349 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
353 *((uint64_t*) p) = h;
354 *((uint32_t*) (p + 8)) = x;
358 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
359 p = message_extend_fields(m, 8, 4 + 4, false);
368 ((uint32_t*) p)[1] = x;
374 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
379 /* dbus1 only allows 8bit header field ids */
383 if (BUS_MESSAGE_IS_GVARIANT(m)) {
384 /* (field id 64bit + ((value + NUL + signature string 't') */
386 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
390 *((uint64_t*) p) = h;
391 *((uint64_t*) (p + 8)) = x;
395 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
396 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
409 ((uint64_t*) p)[1] = x;
415 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
418 if (BUS_MESSAGE_IS_GVARIANT(m))
419 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
421 /* 64bit cookies are not supported on dbus1 */
422 if (cookie > 0xffffffffUL)
425 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
429 int bus_message_from_header(
432 size_t header_accessible,
434 size_t footer_accessible,
440 sd_bus_message **ret) {
442 _cleanup_free_ sd_bus_message *m = NULL;
443 struct bus_header *h;
447 assert(header || header_accessible <= 0);
448 assert(footer || footer_accessible <= 0);
449 assert(fds || n_fds <= 0);
452 if (header_accessible < sizeof(struct bus_header))
455 if (header_accessible > message_size)
457 if (footer_accessible > message_size)
461 if (!IN_SET(h->version, 1, 2))
464 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
467 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
470 /* Note that we are happy with unknown flags in the flags header! */
472 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
475 label_sz = strlen(label);
486 m->header_accessible = header_accessible;
488 m->footer_accessible = footer_accessible;
490 if (BUS_MESSAGE_IS_GVARIANT(m)) {
493 if (h->dbus2.cookie == 0)
496 /* dbus2 derives the sizes from the message size and
497 the offset table at the end, since it is formatted as
498 gvariant "yyyyuta{tv}v". Since the message itself is a
499 structure with precisely to variable sized entries,
500 there's only one offset in the table, which marks the
501 end of the fields array. */
503 ws = bus_gvariant_determine_word_size(message_size, 0);
504 if (footer_accessible < ws)
507 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
508 if (ALIGN8(m->fields_size) > message_size - ws)
510 if (m->fields_size < sizeof(struct bus_header))
513 m->fields_size -= sizeof(struct bus_header);
514 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
516 if (h->dbus1.serial == 0)
519 /* dbus1 has the sizes in the header */
520 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
521 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
523 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
531 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
532 memcpy(m->creds.label, label, label_sz + 1);
534 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
537 m->bus = sd_bus_ref(bus);
544 int bus_message_from_malloc(
551 sd_bus_message **ret) {
557 r = bus_message_from_header(
559 buffer, length, /* in this case the initial bytes and the final bytes are the same */
568 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
571 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
573 m->body.sealed = true;
578 m->iovec = m->iovec_fixed;
579 m->iovec[0].iov_base = buffer;
580 m->iovec[0].iov_len = length;
582 r = bus_message_parse_fields(m);
586 /* We take possession of the memory and fds now */
587 m->free_header = true;
598 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
603 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
608 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
609 m->header->endian = BUS_NATIVE_ENDIAN;
610 m->header->type = type;
611 m->header->version = bus ? bus->message_version : 1;
612 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
613 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
614 m->bus = sd_bus_ref(bus);
616 if (bus->allow_interactive_authorization)
617 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
622 _public_ int sd_bus_message_new_signal(
626 const char *interface,
627 const char *member) {
632 assert_return(bus, -ENOTCONN);
633 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
634 assert_return(object_path_is_valid(path), -EINVAL);
635 assert_return(interface_name_is_valid(interface), -EINVAL);
636 assert_return(member_name_is_valid(member), -EINVAL);
637 assert_return(m, -EINVAL);
639 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
643 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
645 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
648 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
651 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
659 sd_bus_message_unref(t);
663 _public_ int sd_bus_message_new_method_call(
666 const char *destination,
668 const char *interface,
669 const char *member) {
674 assert_return(bus, -ENOTCONN);
675 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
676 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
677 assert_return(object_path_is_valid(path), -EINVAL);
678 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
679 assert_return(member_name_is_valid(member), -EINVAL);
680 assert_return(m, -EINVAL);
682 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
686 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
689 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
694 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
700 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
713 static int message_new_reply(
714 sd_bus_message *call,
716 sd_bus_message **m) {
721 assert_return(call, -EINVAL);
722 assert_return(call->sealed, -EPERM);
723 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
724 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
725 assert_return(m, -EINVAL);
727 t = message_new(call->bus, type);
731 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
732 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
733 if (t->reply_cookie == 0)
736 r = message_append_reply_cookie(t, t->reply_cookie);
741 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
746 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
747 t->enforced_reply_signature = call->enforced_reply_signature;
757 _public_ int sd_bus_message_new_method_return(
758 sd_bus_message *call,
759 sd_bus_message **m) {
761 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
764 _public_ int sd_bus_message_new_method_error(
765 sd_bus_message *call,
767 const sd_bus_error *e) {
772 assert_return(sd_bus_error_is_set(e), -EINVAL);
773 assert_return(m, -EINVAL);
775 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
779 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
784 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
789 t->error._need_free = -1;
799 _public_ int sd_bus_message_new_method_errorf(
800 sd_bus_message *call,
806 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
809 assert_return(name, -EINVAL);
810 assert_return(m, -EINVAL);
812 va_start(ap, format);
813 bus_error_setfv(&error, name, format, ap);
816 return sd_bus_message_new_method_error(call, m, &error);
819 _public_ int sd_bus_message_new_method_errno(
820 sd_bus_message *call,
823 const sd_bus_error *p) {
825 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
827 if (sd_bus_error_is_set(p))
828 return sd_bus_message_new_method_error(call, m, p);
830 sd_bus_error_set_errno(&berror, error);
832 return sd_bus_message_new_method_error(call, m, &berror);
835 _public_ int sd_bus_message_new_method_errnof(
836 sd_bus_message *call,
842 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
845 va_start(ap, format);
846 sd_bus_error_set_errnofv(&berror, error, format, ap);
849 return sd_bus_message_new_method_error(call, m, &berror);
852 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
856 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
857 m->creds.well_known_names_local = true;
858 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
861 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
865 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
866 m->creds.well_known_names_driver = true;
867 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
870 int bus_message_new_synthetic_error(
873 const sd_bus_error *e,
874 sd_bus_message **m) {
880 assert(sd_bus_error_is_set(e));
883 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
887 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
888 t->reply_cookie = cookie;
890 r = message_append_reply_cookie(t, t->reply_cookie);
894 if (bus && bus->unique_name) {
895 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
900 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
905 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
910 t->error._need_free = -1;
912 bus_message_set_sender_driver(bus, t);
922 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
923 assert_return(m, NULL);
925 assert(m->n_ref > 0);
931 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
936 assert(m->n_ref > 0);
946 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
947 assert_return(m, -EINVAL);
948 assert_return(type, -EINVAL);
950 *type = m->header->type;
954 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
957 assert_return(m, -EINVAL);
958 assert_return(cookie, -EINVAL);
960 c = BUS_MESSAGE_COOKIE(m);
964 *cookie = BUS_MESSAGE_COOKIE(m);
968 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
969 assert_return(m, -EINVAL);
970 assert_return(cookie, -EINVAL);
972 if (m->reply_cookie == 0)
975 *cookie = m->reply_cookie;
979 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
980 assert_return(m, -EINVAL);
982 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
983 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
986 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
987 assert_return(m, -EINVAL);
989 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
992 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
993 assert_return(m, -EINVAL);
995 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
996 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
999 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1000 assert_return(m, NULL);
1005 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1006 assert_return(m, NULL);
1008 return m->interface;
1011 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1012 assert_return(m, NULL);
1017 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1018 assert_return(m, NULL);
1020 return m->destination;
1023 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1024 assert_return(m, NULL);
1029 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1030 assert_return(m, NULL);
1031 assert_return(sd_bus_error_is_set(&m->error), NULL);
1036 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1037 assert_return(m, -EINVAL);
1038 assert_return(usec, -EINVAL);
1040 if (m->monotonic <= 0)
1043 *usec = m->monotonic;
1047 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1048 assert_return(m, -EINVAL);
1049 assert_return(usec, -EINVAL);
1051 if (m->realtime <= 0)
1054 *usec = m->realtime;
1058 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1059 assert_return(m, -EINVAL);
1060 assert_return(seqnum, -EINVAL);
1065 *seqnum = m->seqnum;
1069 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1070 assert_return(m, NULL);
1072 if (m->creds.mask == 0)
1078 _public_ int sd_bus_message_is_signal(
1080 const char *interface,
1081 const char *member) {
1083 assert_return(m, -EINVAL);
1085 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1088 if (interface && (!m->interface || !streq(m->interface, interface)))
1091 if (member && (!m->member || !streq(m->member, member)))
1097 _public_ int sd_bus_message_is_method_call(
1099 const char *interface,
1100 const char *member) {
1102 assert_return(m, -EINVAL);
1104 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1107 if (interface && (!m->interface || !streq(m->interface, interface)))
1110 if (member && (!m->member || !streq(m->member, member)))
1116 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1117 assert_return(m, -EINVAL);
1119 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1122 if (name && (!m->error.name || !streq(m->error.name, name)))
1128 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1129 assert_return(m, -EINVAL);
1130 assert_return(!m->sealed, -EPERM);
1131 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1134 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1136 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1141 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1142 assert_return(m, -EINVAL);
1143 assert_return(!m->sealed, -EPERM);
1146 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1148 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1153 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1154 assert_return(m, -EINVAL);
1155 assert_return(!m->sealed, -EPERM);
1158 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1160 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1165 static struct bus_container *message_get_container(sd_bus_message *m) {
1168 if (m->n_containers == 0)
1169 return &m->root_container;
1171 assert(m->containers);
1172 return m->containers + m->n_containers - 1;
1175 struct bus_body_part *message_append_part(sd_bus_message *m) {
1176 struct bus_body_part *part;
1183 if (m->n_body_parts <= 0) {
1187 assert(m->body_end);
1189 part = new0(struct bus_body_part, 1);
1195 m->body_end->next = part;
1205 static void part_zero(struct bus_body_part *part, size_t sz) {
1210 /* All other fields can be left in their defaults */
1211 assert(!part->data);
1212 assert(part->memfd < 0);
1215 part->is_zero = true;
1216 part->sealed = true;
1219 static int part_make_space(
1220 struct sd_bus_message *m,
1221 struct bus_body_part *part,
1230 assert(!part->sealed);
1235 if (!part->data && part->memfd < 0) {
1236 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1237 part->mmap_begin = part->data;
1240 if (part->memfd >= 0) {
1242 if (part->allocated == 0 || sz > part->allocated) {
1243 uint64_t new_allocated;
1245 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1246 r = memfd_set_size(part->memfd, new_allocated);
1252 part->allocated = new_allocated;
1255 if (!part->data || sz > part->mapped) {
1258 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1259 if (part->mapped <= 0)
1260 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1262 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1264 if (n == MAP_FAILED) {
1269 part->mmap_begin = part->data = n;
1271 part->memfd_offset = 0;
1274 part->munmap_this = true;
1276 if (part->allocated == 0 || sz > part->allocated) {
1277 size_t new_allocated;
1279 new_allocated = sz > 0 ? 2 * sz : 64;
1280 n = realloc(part->data, new_allocated);
1287 part->allocated = new_allocated;
1288 part->free_this = true;
1293 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1299 static int message_add_offset(sd_bus_message *m, size_t offset) {
1300 struct bus_container *c;
1303 assert(BUS_MESSAGE_IS_GVARIANT(m));
1305 /* Add offset to current container, unless this is the first
1306 * item in it, which will have the 0 offset, which we can
1308 c = message_get_container(m);
1310 if (!c->need_offsets)
1313 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1316 c->offsets[c->n_offsets++] = offset;
1320 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1321 struct bus_container *c;
1328 /* Update counters */
1329 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1332 *c->array_size += expand;
1336 static void *message_extend_body(
1341 bool force_inline) {
1343 size_t start_body, end_body, padding, added;
1354 start_body = ALIGN_TO((size_t) m->body_size, align);
1355 end_body = start_body + sz;
1357 padding = start_body - m->body_size;
1358 added = padding + sz;
1360 /* Check for 32bit overflows */
1361 if (end_body > (size_t) ((uint32_t) -1) ||
1362 end_body < start_body) {
1368 struct bus_body_part *part = NULL;
1372 m->n_body_parts <= 0 ||
1373 m->body_end->sealed ||
1374 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1375 (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 */
1379 part = message_append_part(m);
1383 part_zero(part, padding);
1386 part = message_append_part(m);
1390 r = part_make_space(m, part, sz, &p);
1394 struct bus_container *c;
1396 size_t os, start_part, end_part;
1402 start_part = ALIGN_TO(part->size, align);
1403 end_part = start_part + sz;
1405 r = part_make_space(m, part, end_part, &p);
1410 memzero(p, padding);
1411 p = (uint8_t*) p + padding;
1414 /* Readjust pointers */
1415 for (c = m->containers; c < m->containers + m->n_containers; c++)
1416 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1418 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1421 /* Return something that is not NULL and is aligned */
1422 p = (uint8_t *) NULL + align;
1424 m->body_size = end_body;
1425 message_extend_containers(m, added);
1428 r = message_add_offset(m, end_body);
1438 static int message_push_fd(sd_bus_message *m, int fd) {
1449 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1453 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1461 m->fds[m->n_fds] = copy;
1467 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1468 _cleanup_close_ int fd = -1;
1469 struct bus_container *c;
1473 assert_return(m, -EINVAL);
1474 assert_return(!m->sealed, -EPERM);
1475 assert_return(bus_type_is_basic(type), -EINVAL);
1476 assert_return(!m->poisoned, -ESTALE);
1478 c = message_get_container(m);
1480 if (c->signature && c->signature[c->index]) {
1481 /* Container signature is already set */
1483 if (c->signature[c->index] != type)
1488 /* Maybe we can append to the signature? But only if this is the top-level container */
1489 if (c->enclosing != 0)
1492 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1499 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1505 case SD_BUS_TYPE_SIGNATURE:
1506 case SD_BUS_TYPE_STRING:
1509 /* Fall through... */
1510 case SD_BUS_TYPE_OBJECT_PATH:
1518 case SD_BUS_TYPE_BOOLEAN:
1520 u8 = p && *(int*) p;
1526 case SD_BUS_TYPE_UNIX_FD:
1531 fd = message_push_fd(m, *(int*) p);
1542 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1543 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1550 a = message_extend_body(m, align, sz, true, false);
1557 *stored = (const uint8_t*) a;
1564 case SD_BUS_TYPE_STRING:
1565 /* To make things easy we'll serialize a NULL string
1566 * into the empty string */
1569 /* Fall through... */
1570 case SD_BUS_TYPE_OBJECT_PATH:
1576 sz = 4 + strlen(p) + 1;
1579 case SD_BUS_TYPE_SIGNATURE:
1584 sz = 1 + strlen(p) + 1;
1587 case SD_BUS_TYPE_BOOLEAN:
1589 u32 = p && *(int*) p;
1595 case SD_BUS_TYPE_UNIX_FD:
1600 fd = message_push_fd(m, *(int*) p);
1611 align = bus_type_get_alignment(type);
1612 sz = bus_type_get_size(type);
1619 a = message_extend_body(m, align, sz, false, false);
1623 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1624 *(uint32_t*) a = sz - 5;
1625 memcpy((uint8_t*) a + 4, p, sz - 4);
1628 *stored = (const uint8_t*) a + 4;
1630 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1631 *(uint8_t*) a = sz - 2;
1632 memcpy((uint8_t*) a + 1, p, sz - 1);
1635 *stored = (const uint8_t*) a + 1;
1644 if (type == SD_BUS_TYPE_UNIX_FD)
1647 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1654 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1655 return message_append_basic(m, type, p, NULL);
1658 _public_ int sd_bus_message_append_string_space(
1663 struct bus_container *c;
1666 assert_return(m, -EINVAL);
1667 assert_return(s, -EINVAL);
1668 assert_return(!m->sealed, -EPERM);
1669 assert_return(!m->poisoned, -ESTALE);
1671 c = message_get_container(m);
1673 if (c->signature && c->signature[c->index]) {
1674 /* Container signature is already set */
1676 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1681 /* Maybe we can append to the signature? But only if this is the top-level container */
1682 if (c->enclosing != 0)
1685 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1692 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1693 a = message_extend_body(m, 1, size + 1, true, false);
1699 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1703 *(uint32_t*) a = size;
1709 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1715 _public_ int sd_bus_message_append_string_iovec(
1717 const struct iovec *iov,
1725 assert_return(m, -EINVAL);
1726 assert_return(!m->sealed, -EPERM);
1727 assert_return(iov || n == 0, -EINVAL);
1728 assert_return(!m->poisoned, -ESTALE);
1730 size = IOVEC_TOTAL_SIZE(iov, n);
1732 r = sd_bus_message_append_string_space(m, size, &p);
1736 for (i = 0; i < n; i++) {
1738 if (iov[i].iov_base)
1739 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1741 memset(p, ' ', iov[i].iov_len);
1743 p += iov[i].iov_len;
1749 static int bus_message_open_array(
1751 struct bus_container *c,
1752 const char *contents,
1753 uint32_t **array_size,
1755 bool *need_offsets) {
1765 assert(need_offsets);
1767 if (!signature_is_single(contents, true))
1770 if (c->signature && c->signature[c->index]) {
1772 /* Verify the existing signature */
1774 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1777 if (!startswith(c->signature + c->index + 1, contents))
1780 nindex = c->index + 1 + strlen(contents);
1784 if (c->enclosing != 0)
1787 /* Extend the existing signature */
1789 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1795 nindex = e - c->signature;
1798 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1799 alignment = bus_gvariant_get_alignment(contents);
1803 /* Add alignment padding and add to offset list */
1804 if (!message_extend_body(m, alignment, 0, false, false))
1807 r = bus_gvariant_is_fixed_size(contents);
1811 *begin = m->body_size;
1812 *need_offsets = r == 0;
1816 struct bus_body_part *o;
1818 alignment = bus_type_get_alignment(contents[0]);
1822 a = message_extend_body(m, 4, 4, false, false);
1827 op = m->body_end->data;
1828 os = m->body_end->size;
1830 /* Add alignment between size and first element */
1831 if (!message_extend_body(m, alignment, 0, false, false))
1834 /* location of array size might have changed so let's readjust a */
1835 if (o == m->body_end)
1836 a = adjust_pointer(a, op, os, m->body_end->data);
1842 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1848 static int bus_message_open_variant(
1850 struct bus_container *c,
1851 const char *contents) {
1857 if (!signature_is_single(contents, false))
1860 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1863 if (c->signature && c->signature[c->index]) {
1865 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1871 if (c->enclosing != 0)
1874 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1881 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1882 /* Variants are always aligned to 8 */
1884 if (!message_extend_body(m, 8, 0, false, false))
1891 l = strlen(contents);
1892 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1897 memcpy((uint8_t*) a + 1, contents, l + 1);
1900 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1906 static int bus_message_open_struct(
1908 struct bus_container *c,
1909 const char *contents,
1911 bool *need_offsets) {
1920 assert(need_offsets);
1922 if (!signature_is_valid(contents, false))
1925 if (c->signature && c->signature[c->index]) {
1928 l = strlen(contents);
1930 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1931 !startswith(c->signature + c->index + 1, contents) ||
1932 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1935 nindex = c->index + 1 + l + 1;
1939 if (c->enclosing != 0)
1942 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1948 nindex = e - c->signature;
1951 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1954 alignment = bus_gvariant_get_alignment(contents);
1958 if (!message_extend_body(m, alignment, 0, false, false))
1961 r = bus_gvariant_is_fixed_size(contents);
1965 *begin = m->body_size;
1966 *need_offsets = r == 0;
1968 /* Align contents to 8 byte boundary */
1969 if (!message_extend_body(m, 8, 0, false, false))
1973 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1979 static int bus_message_open_dict_entry(
1981 struct bus_container *c,
1982 const char *contents,
1984 bool *need_offsets) {
1992 assert(need_offsets);
1994 if (!signature_is_pair(contents))
1997 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2000 if (c->signature && c->signature[c->index]) {
2003 l = strlen(contents);
2005 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2006 !startswith(c->signature + c->index + 1, contents) ||
2007 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2012 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2015 alignment = bus_gvariant_get_alignment(contents);
2019 if (!message_extend_body(m, alignment, 0, false, false))
2022 r = bus_gvariant_is_fixed_size(contents);
2026 *begin = m->body_size;
2027 *need_offsets = r == 0;
2029 /* Align contents to 8 byte boundary */
2030 if (!message_extend_body(m, 8, 0, false, false))
2037 _public_ int sd_bus_message_open_container(
2040 const char *contents) {
2042 struct bus_container *c, *w;
2043 uint32_t *array_size = NULL;
2045 size_t before, begin = 0;
2046 bool need_offsets = false;
2049 assert_return(m, -EINVAL);
2050 assert_return(!m->sealed, -EPERM);
2051 assert_return(contents, -EINVAL);
2052 assert_return(!m->poisoned, -ESTALE);
2054 /* Make sure we have space for one more container */
2055 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2060 c = message_get_container(m);
2062 signature = strdup(contents);
2068 /* Save old index in the parent container, in case we have to
2069 * abort this container */
2070 c->saved_index = c->index;
2071 before = m->body_size;
2073 if (type == SD_BUS_TYPE_ARRAY)
2074 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2075 else if (type == SD_BUS_TYPE_VARIANT)
2076 r = bus_message_open_variant(m, c, contents);
2077 else if (type == SD_BUS_TYPE_STRUCT)
2078 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2079 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2080 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2089 /* OK, let's fill it in */
2090 w = m->containers + m->n_containers++;
2091 w->enclosing = type;
2092 w->signature = signature;
2094 w->array_size = array_size;
2097 w->n_offsets = w->offsets_allocated = 0;
2099 w->need_offsets = need_offsets;
2104 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2109 if (!BUS_MESSAGE_IS_GVARIANT(m))
2112 if (c->need_offsets) {
2113 size_t payload, sz, i;
2116 /* Variable-width arrays */
2118 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2119 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2121 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2125 for (i = 0; i < c->n_offsets; i++)
2126 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2130 /* Fixed-width or empty arrays */
2132 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2140 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2146 assert(c->signature);
2148 if (!BUS_MESSAGE_IS_GVARIANT(m))
2151 l = strlen(c->signature);
2153 a = message_extend_body(m, 1, 1 + l, true, false);
2158 memcpy(a+1, c->signature, l);
2163 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2164 bool fixed_size = true;
2165 size_t n_variable = 0;
2174 if (!BUS_MESSAGE_IS_GVARIANT(m))
2177 p = strempty(c->signature);
2181 r = signature_element_length(p, &n);
2190 r = bus_gvariant_is_fixed_size(t);
2195 assert(!c->need_offsets || i <= c->n_offsets);
2197 /* We need to add an offset for each item that has a
2198 * variable size and that is not the last one in the
2202 if (r == 0 && p[n] != 0)
2209 assert(!c->need_offsets || i == c->n_offsets);
2210 assert(c->need_offsets || n_variable == 0);
2212 if (n_variable <= 0) {
2215 /* Structures with fixed-size members only have to be
2216 * fixed-size themselves. But gvariant requires all fixed-size
2217 * elements to be sized a multiple of their alignment. Hence,
2218 * we must *always* add final padding after the last member so
2219 * the overall size of the structure is properly aligned. */
2221 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2223 assert(alignment > 0);
2225 a = message_extend_body(m, alignment, 0, add_offset, false);
2232 assert(c->offsets[c->n_offsets-1] == m->body_size);
2234 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2236 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2240 p = strempty(c->signature);
2241 for (i = 0, j = 0; i < c->n_offsets; i++) {
2245 r = signature_element_length(p, &n);
2256 r = bus_gvariant_is_fixed_size(t);
2259 if (r > 0 || p[0] == 0)
2263 k = n_variable - 1 - j;
2265 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2274 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2275 struct bus_container *c;
2278 assert_return(m, -EINVAL);
2279 assert_return(!m->sealed, -EPERM);
2280 assert_return(m->n_containers > 0, -EINVAL);
2281 assert_return(!m->poisoned, -ESTALE);
2283 c = message_get_container(m);
2285 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2286 if (c->signature && c->signature[c->index] != 0)
2291 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2292 r = bus_message_close_array(m, c);
2293 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2294 r = bus_message_close_variant(m, c);
2295 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2296 r = bus_message_close_struct(m, c, true);
2298 assert_not_reached("Unknown container type");
2312 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2319 stack[*i].types = types;
2320 stack[*i].n_struct = n_struct;
2321 stack[*i].n_array = n_array;
2327 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2338 *types = stack[*i].types;
2339 *n_struct = stack[*i].n_struct;
2340 *n_array = stack[*i].n_array;
2345 int bus_message_append_ap(
2350 unsigned n_array, n_struct;
2351 TypeStack stack[BUS_CONTAINER_DEPTH];
2352 unsigned stack_ptr = 0;
2360 n_array = (unsigned) -1;
2361 n_struct = strlen(types);
2366 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2367 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2373 r = sd_bus_message_close_container(m);
2381 if (n_array != (unsigned) -1)
2390 case SD_BUS_TYPE_BYTE: {
2393 x = (uint8_t) va_arg(ap, int);
2394 r = sd_bus_message_append_basic(m, *t, &x);
2398 case SD_BUS_TYPE_BOOLEAN:
2399 case SD_BUS_TYPE_INT32:
2400 case SD_BUS_TYPE_UINT32:
2401 case SD_BUS_TYPE_UNIX_FD: {
2404 /* We assume a boolean is the same as int32_t */
2405 assert_cc(sizeof(int32_t) == sizeof(int));
2407 x = va_arg(ap, uint32_t);
2408 r = sd_bus_message_append_basic(m, *t, &x);
2412 case SD_BUS_TYPE_INT16:
2413 case SD_BUS_TYPE_UINT16: {
2416 x = (uint16_t) va_arg(ap, int);
2417 r = sd_bus_message_append_basic(m, *t, &x);
2421 case SD_BUS_TYPE_INT64:
2422 case SD_BUS_TYPE_UINT64: {
2425 x = va_arg(ap, uint64_t);
2426 r = sd_bus_message_append_basic(m, *t, &x);
2430 case SD_BUS_TYPE_DOUBLE: {
2433 x = va_arg(ap, double);
2434 r = sd_bus_message_append_basic(m, *t, &x);
2438 case SD_BUS_TYPE_STRING:
2439 case SD_BUS_TYPE_OBJECT_PATH:
2440 case SD_BUS_TYPE_SIGNATURE: {
2443 x = va_arg(ap, const char*);
2444 r = sd_bus_message_append_basic(m, *t, x);
2448 case SD_BUS_TYPE_ARRAY: {
2451 r = signature_element_length(t + 1, &k);
2457 memcpy(s, t + 1, k);
2460 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2465 if (n_array == (unsigned) -1) {
2470 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2476 n_array = va_arg(ap, unsigned);
2481 case SD_BUS_TYPE_VARIANT: {
2484 s = va_arg(ap, const char*);
2488 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2492 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2497 n_struct = strlen(s);
2498 n_array = (unsigned) -1;
2503 case SD_BUS_TYPE_STRUCT_BEGIN:
2504 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2507 r = signature_element_length(t, &k);
2514 memcpy(s, t + 1, k - 2);
2517 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2522 if (n_array == (unsigned) -1) {
2527 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2533 n_array = (unsigned) -1;
2549 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2553 assert_return(m, -EINVAL);
2554 assert_return(types, -EINVAL);
2555 assert_return(!m->sealed, -EPERM);
2556 assert_return(!m->poisoned, -ESTALE);
2558 va_start(ap, types);
2559 r = bus_message_append_ap(m, types, ap);
2565 _public_ int sd_bus_message_append_array_space(
2575 assert_return(m, -EINVAL);
2576 assert_return(!m->sealed, -EPERM);
2577 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2578 assert_return(ptr || size == 0, -EINVAL);
2579 assert_return(!m->poisoned, -ESTALE);
2581 /* alignment and size of the trivial types (except bool) is
2582 * identical for gvariant and dbus1 marshalling */
2583 align = bus_type_get_alignment(type);
2584 sz = bus_type_get_size(type);
2586 assert_se(align > 0);
2592 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2596 a = message_extend_body(m, align, size, false, false);
2600 r = sd_bus_message_close_container(m);
2608 _public_ int sd_bus_message_append_array(
2616 assert_return(m, -EINVAL);
2617 assert_return(!m->sealed, -EPERM);
2618 assert_return(bus_type_is_trivial(type), -EINVAL);
2619 assert_return(ptr || size == 0, -EINVAL);
2620 assert_return(!m->poisoned, -ESTALE);
2622 r = sd_bus_message_append_array_space(m, type, size, &p);
2627 memcpy(p, ptr, size);
2632 _public_ int sd_bus_message_append_array_iovec(
2635 const struct iovec *iov,
2643 assert_return(m, -EINVAL);
2644 assert_return(!m->sealed, -EPERM);
2645 assert_return(bus_type_is_trivial(type), -EINVAL);
2646 assert_return(iov || n == 0, -EINVAL);
2647 assert_return(!m->poisoned, -ESTALE);
2649 size = IOVEC_TOTAL_SIZE(iov, n);
2651 r = sd_bus_message_append_array_space(m, type, size, &p);
2655 for (i = 0; i < n; i++) {
2657 if (iov[i].iov_base)
2658 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2660 memzero(p, iov[i].iov_len);
2662 p = (uint8_t*) p + iov[i].iov_len;
2668 _public_ int sd_bus_message_append_array_memfd(
2675 _cleanup_close_ int copy_fd = -1;
2676 struct bus_body_part *part;
2682 assert_return(m, -EINVAL);
2683 assert_return(memfd >= 0, -EINVAL);
2684 assert_return(bus_type_is_trivial(type), -EINVAL);
2685 assert_return(size > 0, -EINVAL);
2686 assert_return(!m->sealed, -EPERM);
2687 assert_return(!m->poisoned, -ESTALE);
2689 r = memfd_set_sealed(memfd);
2693 copy_fd = dup(memfd);
2697 r = memfd_get_size(memfd, &real_size);
2701 if (offset == 0 && size == (uint64_t) -1)
2703 else if (offset + size > real_size)
2706 align = bus_type_get_alignment(type);
2707 sz = bus_type_get_size(type);
2709 assert_se(align > 0);
2712 if (offset % align != 0)
2718 if (size > (uint64_t) (uint32_t) -1)
2721 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2725 a = message_extend_body(m, align, 0, false, false);
2729 part = message_append_part(m);
2733 part->memfd = copy_fd;
2734 part->memfd_offset = offset;
2735 part->sealed = true;
2739 m->body_size += size;
2740 message_extend_containers(m, size);
2742 return sd_bus_message_close_container(m);
2745 _public_ int sd_bus_message_append_string_memfd(
2751 _cleanup_close_ int copy_fd = -1;
2752 struct bus_body_part *part;
2753 struct bus_container *c;
2758 assert_return(m, -EINVAL);
2759 assert_return(memfd >= 0, -EINVAL);
2760 assert_return(size > 0, -EINVAL);
2761 assert_return(!m->sealed, -EPERM);
2762 assert_return(!m->poisoned, -ESTALE);
2764 r = memfd_set_sealed(memfd);
2768 copy_fd = dup(memfd);
2772 r = memfd_get_size(memfd, &real_size);
2776 if (offset == 0 && size == (uint64_t) -1)
2778 else if (offset + size > real_size)
2781 /* We require this to be NUL terminated */
2785 if (size > (uint64_t) (uint32_t) -1)
2788 c = message_get_container(m);
2789 if (c->signature && c->signature[c->index]) {
2790 /* Container signature is already set */
2792 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2797 /* Maybe we can append to the signature? But only if this is the top-level container */
2798 if (c->enclosing != 0)
2801 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2808 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2809 a = message_extend_body(m, 4, 4, false, false);
2813 *(uint32_t*) a = size - 1;
2816 part = message_append_part(m);
2820 part->memfd = copy_fd;
2821 part->memfd_offset = offset;
2822 part->sealed = true;
2826 m->body_size += size;
2827 message_extend_containers(m, size);
2829 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2830 r = message_add_offset(m, m->body_size);
2837 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2843 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2847 assert_return(m, -EINVAL);
2848 assert_return(!m->sealed, -EPERM);
2849 assert_return(!m->poisoned, -ESTALE);
2851 r = sd_bus_message_open_container(m, 'a', "s");
2855 STRV_FOREACH(i, l) {
2856 r = sd_bus_message_append_basic(m, 's', *i);
2861 return sd_bus_message_close_container(m);
2864 static int bus_message_close_header(sd_bus_message *m) {
2868 /* The actual user data is finished now, we just complete the
2869 variant and struct now (at least on gvariant). Remember
2870 this position, so that during parsing we know where to to
2871 put the outer container end. */
2872 m->user_body_size = m->body_size;
2874 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2875 const char *signature;
2879 /* Add offset table to end of fields array */
2880 if (m->n_header_offsets >= 1) {
2884 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2886 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2887 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2891 for (i = 0; i < m->n_header_offsets; i++)
2892 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2895 /* Add gvariant NUL byte plus signature to the end of
2896 * the body, followed by the final offset pointing to
2897 * the end of the fields array */
2899 signature = strempty(m->root_container.signature);
2900 l = strlen(signature);
2902 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l, 1);
2903 d = message_extend_body(m, 1, 1 + l + sz, false, true);
2908 memcpy((uint8_t*) d + 1, signature, l);
2910 bus_gvariant_write_word_le((uint8_t*) d + 1 + l, sz, sizeof(struct bus_header) + m->fields_size);
2913 m->footer_accessible = 1 + l + sz;
2915 m->header->dbus1.fields_size = m->fields_size;
2916 m->header->dbus1.body_size = m->body_size;
2922 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2923 struct bus_body_part *part;
2933 if (m->n_containers > 0)
2939 if (cookie > 0xffffffffULL &&
2940 !BUS_MESSAGE_IS_GVARIANT(m))
2943 /* In vtables the return signature of method calls is listed,
2944 * let's check if they match if this is a response */
2945 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2946 m->enforced_reply_signature &&
2947 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2950 /* If gvariant marshalling is used we need to close the body structure */
2951 r = bus_message_close_struct(m, &m->root_container, false);
2955 /* If there's a non-trivial signature set, then add it in
2956 * here, but only on dbus1 */
2957 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2958 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2964 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2969 r = bus_message_close_header(m);
2973 if (BUS_MESSAGE_IS_GVARIANT(m))
2974 m->header->dbus2.cookie = cookie;
2976 m->header->dbus1.serial = (uint32_t) cookie;
2978 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2980 /* Add padding at the end of the fields part, since we know
2981 * the body needs to start at an 8 byte alignment. We made
2982 * sure we allocated enough space for this, so all we need to
2983 * do here is to zero it out. */
2984 a = ALIGN8(m->fields_size) - m->fields_size;
2986 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2988 /* If this is something we can send as memfd, then let's seal
2989 the memfd now. Note that we can send memfds as payload only
2990 for directed messages, and not for broadcasts. */
2991 if (m->destination && m->bus->use_memfd) {
2992 MESSAGE_FOREACH_PART(part, i, m)
2993 if (part->memfd >= 0 &&
2995 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2996 part != m->body_end) { /* The last part may never be sent as memfd */
2999 /* Try to seal it if that makes
3000 * sense. First, unmap our own map to
3001 * make sure we don't keep it busy. */
3002 bus_body_part_unmap(part);
3004 /* Then, sync up real memfd size */
3006 r = memfd_set_size(part->memfd, sz);
3010 /* Finally, try to seal */
3011 if (memfd_set_sealed(part->memfd) >= 0)
3012 part->sealed = true;
3016 m->root_container.end = m->user_body_size;
3017 m->root_container.index = 0;
3018 m->root_container.offset_index = 0;
3019 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3026 int bus_body_part_map(struct bus_body_part *part) {
3035 if (part->size <= 0)
3038 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3039 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3040 static const uint8_t zeroes[7] = { };
3041 part->data = (void*) zeroes;
3045 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3046 psz = PAGE_ALIGN(part->size + shift);
3048 if (part->memfd >= 0)
3049 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3050 else if (part->is_zero)
3051 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3055 if (p == MAP_FAILED)
3059 part->mmap_begin = p;
3060 part->data = (uint8_t*) p + shift;
3061 part->munmap_this = true;
3066 void bus_body_part_unmap(struct bus_body_part *part) {
3070 if (part->memfd < 0)
3073 if (!part->mmap_begin)
3076 if (!part->munmap_this)
3079 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3081 part->mmap_begin = NULL;
3084 part->munmap_this = false;
3089 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3090 size_t k, start, end;
3095 start = ALIGN_TO((size_t) *rindex, align);
3096 end = start + nbytes;
3101 /* Verify that padding is 0 */
3102 for (k = *rindex; k < start; k++)
3103 if (((const uint8_t*) p)[k] != 0)
3107 *r = (uint8_t*) p + start;
3114 static bool message_end_of_signature(sd_bus_message *m) {
3115 struct bus_container *c;
3119 c = message_get_container(m);
3120 return !c->signature || c->signature[c->index] == 0;
3123 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3124 struct bus_container *c;
3128 c = message_get_container(m);
3129 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3132 if (BUS_MESSAGE_IS_GVARIANT(m))
3133 return index >= c->end;
3135 assert(c->array_size);
3136 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3140 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3141 assert_return(m, -EINVAL);
3142 assert_return(m->sealed, -EPERM);
3144 if (complete && m->n_containers > 0)
3147 if (message_end_of_signature(m))
3150 if (message_end_of_array(m, m->rindex))
3156 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3157 struct bus_body_part *part;
3163 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3164 part = m->cached_rindex_part;
3165 begin = m->cached_rindex_part_begin;
3175 if (index + sz <= begin + part->size) {
3177 r = bus_body_part_map(part);
3182 *p = (uint8_t*) part->data + index - begin;
3184 m->cached_rindex_part = part;
3185 m->cached_rindex_part_begin = begin;
3190 begin += part->size;
3197 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3204 if (!BUS_MESSAGE_IS_GVARIANT(m))
3207 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3210 sz = bus_gvariant_get_size(c->signature);
3214 if (c->offset_index+1 >= c->n_offsets)
3217 /* Variable-size array */
3219 alignment = bus_gvariant_get_alignment(c->signature);
3220 assert(alignment > 0);
3222 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3223 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3226 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3229 /* Fixed-size array */
3230 *rindex = c->begin + (c->offset_index+1) * sz;
3236 } else if (c->enclosing == 0 ||
3237 c->enclosing == SD_BUS_TYPE_STRUCT ||
3238 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3243 if (c->offset_index+1 >= c->n_offsets)
3246 r = signature_element_length(c->signature + c->index, &n);
3250 r = signature_element_length(c->signature + c->index + n, &j);
3255 memcpy(t, c->signature + c->index + n, j);
3258 alignment = bus_gvariant_get_alignment(t);
3261 assert(alignment > 0);
3263 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3264 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3268 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3271 assert_not_reached("Unknown container type");
3276 /* Reached the end */
3283 static int message_peek_body(
3290 size_t k, start, end, padding;
3291 struct bus_body_part *part;
3298 start = ALIGN_TO((size_t) *rindex, align);
3299 padding = start - *rindex;
3300 end = start + nbytes;
3302 if (end > m->user_body_size)
3305 part = find_part(m, *rindex, padding, (void**) &q);
3310 /* Verify padding */
3311 for (k = 0; k < padding; k++)
3316 part = find_part(m, start, nbytes, (void**) &q);
3317 if (!part || (nbytes > 0 && !q))
3328 static bool validate_nul(const char *s, size_t l) {
3330 /* Check for NUL chars in the string */
3331 if (memchr(s, 0, l))
3334 /* Check for NUL termination */
3341 static bool validate_string(const char *s, size_t l) {
3343 if (!validate_nul(s, l))
3346 /* Check if valid UTF8 */
3347 if (!utf8_is_valid(s))
3353 static bool validate_signature(const char *s, size_t l) {
3355 if (!validate_nul(s, l))
3358 /* Check if valid signature */
3359 if (!signature_is_valid(s, true))
3365 static bool validate_object_path(const char *s, size_t l) {
3367 if (!validate_nul(s, l))
3370 if (!object_path_is_valid(s))
3376 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3377 struct bus_container *c;
3382 assert_return(m, -EINVAL);
3383 assert_return(m->sealed, -EPERM);
3384 assert_return(bus_type_is_basic(type), -EINVAL);
3386 if (message_end_of_signature(m))
3389 if (message_end_of_array(m, m->rindex))
3392 c = message_get_container(m);
3393 if (c->signature[c->index] != type)
3398 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3400 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3403 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3407 if (type == SD_BUS_TYPE_STRING)
3408 ok = validate_string(q, c->item_size-1);
3409 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3410 ok = validate_object_path(q, c->item_size-1);
3412 ok = validate_signature(q, c->item_size-1);
3418 *(const char**) p = q;
3422 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3424 if ((size_t) sz != c->item_size)
3427 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3430 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3436 case SD_BUS_TYPE_BYTE:
3438 *(uint8_t*) p = *(uint8_t*) q;
3441 case SD_BUS_TYPE_BOOLEAN:
3443 *(int*) p = !!*(uint8_t*) q;
3446 case SD_BUS_TYPE_INT16:
3447 case SD_BUS_TYPE_UINT16:
3449 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3452 case SD_BUS_TYPE_INT32:
3453 case SD_BUS_TYPE_UINT32:
3455 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3458 case SD_BUS_TYPE_INT64:
3459 case SD_BUS_TYPE_UINT64:
3460 case SD_BUS_TYPE_DOUBLE:
3462 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3465 case SD_BUS_TYPE_UNIX_FD: {
3468 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3473 *(int*) p = m->fds[j];
3479 assert_not_reached("unexpected type");
3483 r = container_next_item(m, c, &rindex);
3488 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3492 r = message_peek_body(m, &rindex, 4, 4, &q);
3496 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3497 r = message_peek_body(m, &rindex, 1, l+1, &q);
3501 if (type == SD_BUS_TYPE_OBJECT_PATH)
3502 ok = validate_object_path(q, l);
3504 ok = validate_string(q, l);
3509 *(const char**) p = q;
3511 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3514 r = message_peek_body(m, &rindex, 1, 1, &q);
3519 r = message_peek_body(m, &rindex, 1, l+1, &q);
3523 if (!validate_signature(q, l))
3527 *(const char**) p = q;
3532 align = bus_type_get_alignment(type);
3535 sz = bus_type_get_size(type);
3538 r = message_peek_body(m, &rindex, align, sz, &q);
3544 case SD_BUS_TYPE_BYTE:
3546 *(uint8_t*) p = *(uint8_t*) q;
3549 case SD_BUS_TYPE_BOOLEAN:
3551 *(int*) p = !!*(uint32_t*) q;
3554 case SD_BUS_TYPE_INT16:
3555 case SD_BUS_TYPE_UINT16:
3557 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3560 case SD_BUS_TYPE_INT32:
3561 case SD_BUS_TYPE_UINT32:
3563 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3566 case SD_BUS_TYPE_INT64:
3567 case SD_BUS_TYPE_UINT64:
3568 case SD_BUS_TYPE_DOUBLE:
3570 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3573 case SD_BUS_TYPE_UNIX_FD: {
3576 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3581 *(int*) p = m->fds[j];
3586 assert_not_reached("Unknown basic type...");
3593 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3599 static int bus_message_enter_array(
3601 struct bus_container *c,
3602 const char *contents,
3603 uint32_t **array_size,
3606 size_t *n_offsets) {
3620 if (!signature_is_single(contents, true))
3623 if (!c->signature || c->signature[c->index] == 0)
3626 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3629 if (!startswith(c->signature + c->index + 1, contents))
3634 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3637 r = message_peek_body(m, &rindex, 4, 4, &q);
3641 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3644 alignment = bus_type_get_alignment(contents[0]);
3648 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3652 *array_size = (uint32_t*) q;
3654 } else if (c->item_size <= 0) {
3656 /* gvariant: empty array */
3661 } else if (bus_gvariant_is_fixed_size(contents)) {
3663 /* gvariant: fixed length array */
3664 *item_size = bus_gvariant_get_size(contents);
3669 size_t where, p = 0, framing, sz;
3672 /* gvariant: variable length array */
3673 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3675 where = rindex + c->item_size - sz;
3676 r = message_peek_body(m, &where, 1, sz, &q);
3680 framing = bus_gvariant_read_word_le(q, sz);
3681 if (framing > c->item_size - sz)
3683 if ((c->item_size - framing) % sz != 0)
3686 *n_offsets = (c->item_size - framing) / sz;
3688 where = rindex + framing;
3689 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3693 *offsets = new(size_t, *n_offsets);
3697 for (i = 0; i < *n_offsets; i++) {
3700 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3701 if (x > c->item_size - sz)
3706 (*offsets)[i] = rindex + x;
3710 *item_size = (*offsets)[0] - rindex;
3715 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3716 c->index += 1 + strlen(contents);
3721 static int bus_message_enter_variant(
3723 struct bus_container *c,
3724 const char *contents,
3725 size_t *item_size) {
3737 if (!signature_is_single(contents, false))
3740 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3743 if (!c->signature || c->signature[c->index] == 0)
3746 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3751 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3754 k = strlen(contents);
3755 if (1+k > c->item_size)
3758 where = rindex + c->item_size - (1+k);
3759 r = message_peek_body(m, &where, 1, 1+k, &q);
3763 if (*(char*) q != 0)
3766 if (memcmp((uint8_t*) q+1, contents, k))
3769 *item_size = c->item_size - (1+k);
3772 r = message_peek_body(m, &rindex, 1, 1, &q);
3777 r = message_peek_body(m, &rindex, 1, l+1, &q);
3781 if (!validate_signature(q, l))
3784 if (!streq(q, contents))
3790 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3796 static int build_struct_offsets(
3798 const char *signature,
3802 size_t *n_offsets) {
3804 unsigned n_variable = 0, n_total = 0, v;
3805 size_t previous = 0, where;
3816 if (isempty(signature)) {
3823 sz = bus_gvariant_determine_word_size(size, 0);
3827 /* First, loop over signature and count variable elements and
3828 * elements in general. We use this to know how large the
3829 * offset array is at the end of the structure. Note that
3830 * GVariant only stores offsets for all variable size elements
3831 * that are not the last item. */
3837 r = signature_element_length(p, &n);
3846 r = bus_gvariant_is_fixed_size(t);
3851 if (r == 0 && p[n] != 0) /* except the last item */
3858 if (size < n_variable * sz)
3861 where = m->rindex + size - (n_variable * sz);
3862 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3868 *offsets = new(size_t, n_total);
3874 /* Second, loop again and build an offset table */
3880 r = signature_element_length(p, &n);
3889 k = bus_gvariant_get_size(t);
3897 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3900 if (m->rindex + x < previous)
3903 /* The last item's end
3904 * is determined from
3907 x = size - (n_variable * sz);
3909 offset = m->rindex + x;
3915 align = bus_gvariant_get_alignment(t);
3918 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3922 previous = (*offsets)[(*n_offsets)++] = offset;
3927 assert(*n_offsets == n_total);
3929 *item_size = (*offsets)[0] - m->rindex;
3933 static int enter_struct_or_dict_entry(
3935 struct bus_container *c,
3936 const char *contents,
3939 size_t *n_offsets) {
3950 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3953 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3957 } else if (c->item_size <= 0) {
3959 /* gvariant empty struct */
3964 /* gvariant with contents */
3965 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3970 static int bus_message_enter_struct(
3972 struct bus_container *c,
3973 const char *contents,
3976 size_t *n_offsets) {
3988 if (!signature_is_valid(contents, false))
3991 if (!c->signature || c->signature[c->index] == 0)
3994 l = strlen(contents);
3996 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3997 !startswith(c->signature + c->index + 1, contents) ||
3998 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4001 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4005 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4006 c->index += 1 + l + 1;
4011 static int bus_message_enter_dict_entry(
4013 struct bus_container *c,
4014 const char *contents,
4017 size_t *n_offsets) {
4026 if (!signature_is_pair(contents))
4029 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4032 if (!c->signature || c->signature[c->index] == 0)
4035 l = strlen(contents);
4037 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4038 !startswith(c->signature + c->index + 1, contents) ||
4039 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4042 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4046 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4047 c->index += 1 + l + 1;
4052 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4054 const char *contents) {
4055 struct bus_container *c, *w;
4056 uint32_t *array_size = NULL;
4059 size_t *offsets = NULL;
4060 size_t n_offsets = 0, item_size = 0;
4063 assert_return(m, -EINVAL);
4064 assert_return(m->sealed, -EPERM);
4065 assert_return(type != 0 || !contents, -EINVAL);
4067 if (type == 0 || !contents) {
4071 /* Allow entering into anonymous containers */
4072 r = sd_bus_message_peek_type(m, &tt, &cc);
4076 if (type != 0 && type != tt)
4079 if (contents && !streq(contents, cc))
4087 * We enforce a global limit on container depth, that is much
4088 * higher than the 32 structs and 32 arrays the specification
4089 * mandates. This is simpler to implement for us, and we need
4090 * this only to ensure our container array doesn't grow
4091 * without bounds. We are happy to return any data from a
4092 * message as long as the data itself is valid, even if the
4093 * overall message might be not.
4095 * Note that the message signature is validated when
4096 * parsing the headers, and that validation does check the
4099 * Note that the specification defines no limits on the depth
4100 * of stacked variants, but we do.
4102 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4105 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4108 if (message_end_of_signature(m))
4111 if (message_end_of_array(m, m->rindex))
4114 c = message_get_container(m);
4116 signature = strdup(contents);
4120 c->saved_index = c->index;
4123 if (type == SD_BUS_TYPE_ARRAY)
4124 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4125 else if (type == SD_BUS_TYPE_VARIANT)
4126 r = bus_message_enter_variant(m, c, contents, &item_size);
4127 else if (type == SD_BUS_TYPE_STRUCT)
4128 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4129 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4130 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4140 /* OK, let's fill it in */
4141 w = m->containers + m->n_containers++;
4142 w->enclosing = type;
4143 w->signature = signature;
4144 w->peeked_signature = NULL;
4148 w->begin = m->rindex;
4149 w->end = m->rindex + c->item_size;
4151 w->array_size = array_size;
4152 w->item_size = item_size;
4153 w->offsets = offsets;
4154 w->n_offsets = n_offsets;
4155 w->offset_index = 0;
4160 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4161 struct bus_container *c;
4165 assert_return(m, -EINVAL);
4166 assert_return(m->sealed, -EPERM);
4167 assert_return(m->n_containers > 0, -ENXIO);
4169 c = message_get_container(m);
4171 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4172 if (c->signature && c->signature[c->index] != 0)
4176 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4177 if (m->rindex < c->end)
4180 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4183 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4184 if (c->begin + l != m->rindex)
4189 free(c->peeked_signature);
4193 c = message_get_container(m);
4196 c->index = c->saved_index;
4197 r = container_next_item(m, c, &m->rindex);
4205 static void message_quit_container(sd_bus_message *m) {
4206 struct bus_container *c;
4210 assert(m->n_containers > 0);
4212 c = message_get_container(m);
4215 assert(m->rindex >= c->before);
4216 m->rindex = c->before;
4218 /* Free container */
4223 /* Correct index of new top-level container */
4224 c = message_get_container(m);
4225 c->index = c->saved_index;
4228 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4229 struct bus_container *c;
4232 assert_return(m, -EINVAL);
4233 assert_return(m->sealed, -EPERM);
4235 if (message_end_of_signature(m))
4238 if (message_end_of_array(m, m->rindex))
4241 c = message_get_container(m);
4243 if (bus_type_is_basic(c->signature[c->index])) {
4247 *type = c->signature[c->index];
4251 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4257 r = signature_element_length(c->signature+c->index+1, &l);
4263 sig = strndup(c->signature + c->index + 1, l);
4267 free(c->peeked_signature);
4268 *contents = c->peeked_signature = sig;
4272 *type = SD_BUS_TYPE_ARRAY;
4277 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4278 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4284 r = signature_element_length(c->signature+c->index, &l);
4289 sig = strndup(c->signature + c->index + 1, l - 2);
4293 free(c->peeked_signature);
4294 *contents = c->peeked_signature = sig;
4298 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4303 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4307 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4310 if (c->item_size < 2)
4313 /* Look for the NUL delimiter that
4314 separates the payload from the
4315 signature. Since the body might be
4316 in a different part that then the
4317 signature we map byte by byte. */
4319 for (k = 2; k <= c->item_size; k++) {
4322 where = m->rindex + c->item_size - k;
4323 r = message_peek_body(m, &where, 1, k, &q);
4327 if (*(char*) q == 0)
4331 if (k > c->item_size)
4334 free(c->peeked_signature);
4335 c->peeked_signature = strndup((char*) q + 1, k - 1);
4336 if (!c->peeked_signature)
4339 if (!signature_is_valid(c->peeked_signature, true))
4342 *contents = c->peeked_signature;
4347 r = message_peek_body(m, &rindex, 1, 1, &q);
4352 r = message_peek_body(m, &rindex, 1, l+1, &q);
4356 if (!validate_signature(q, l))
4364 *type = SD_BUS_TYPE_VARIANT;
4379 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4380 struct bus_container *c;
4382 assert_return(m, -EINVAL);
4383 assert_return(m->sealed, -EPERM);
4386 message_reset_containers(m);
4389 c = message_get_container(m);
4391 c = message_get_container(m);
4393 c->offset_index = 0;
4395 m->rindex = c->begin;
4398 c->offset_index = 0;
4399 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4401 return !isempty(c->signature);
4404 static int message_read_ap(
4409 unsigned n_array, n_struct;
4410 TypeStack stack[BUS_CONTAINER_DEPTH];
4411 unsigned stack_ptr = 0;
4412 unsigned n_loop = 0;
4420 /* Ideally, we'd just call ourselves recursively on every
4421 * complex type. However, the state of a va_list that is
4422 * passed to a function is undefined after that function
4423 * returns. This means we need to docode the va_list linearly
4424 * in a single stackframe. We hence implement our own
4425 * home-grown stack in an array. */
4427 n_array = (unsigned) -1; /* length of current array entries */
4428 n_struct = strlen(types); /* length of current struct contents signature */
4435 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4436 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4442 r = sd_bus_message_exit_container(m);
4450 if (n_array != (unsigned) -1)
4459 case SD_BUS_TYPE_BYTE:
4460 case SD_BUS_TYPE_BOOLEAN:
4461 case SD_BUS_TYPE_INT16:
4462 case SD_BUS_TYPE_UINT16:
4463 case SD_BUS_TYPE_INT32:
4464 case SD_BUS_TYPE_UINT32:
4465 case SD_BUS_TYPE_INT64:
4466 case SD_BUS_TYPE_UINT64:
4467 case SD_BUS_TYPE_DOUBLE:
4468 case SD_BUS_TYPE_STRING:
4469 case SD_BUS_TYPE_OBJECT_PATH:
4470 case SD_BUS_TYPE_SIGNATURE:
4471 case SD_BUS_TYPE_UNIX_FD: {
4474 p = va_arg(ap, void*);
4475 r = sd_bus_message_read_basic(m, *t, p);
4488 case SD_BUS_TYPE_ARRAY: {
4491 r = signature_element_length(t + 1, &k);
4497 memcpy(s, t + 1, k);
4500 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4511 if (n_array == (unsigned) -1) {
4516 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4522 n_array = va_arg(ap, unsigned);
4527 case SD_BUS_TYPE_VARIANT: {
4530 s = va_arg(ap, const char *);
4534 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4544 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4549 n_struct = strlen(s);
4550 n_array = (unsigned) -1;
4555 case SD_BUS_TYPE_STRUCT_BEGIN:
4556 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4559 r = signature_element_length(t, &k);
4565 memcpy(s, t + 1, k - 2);
4568 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4578 if (n_array == (unsigned) -1) {
4583 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4589 n_array = (unsigned) -1;
4602 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4606 assert_return(m, -EINVAL);
4607 assert_return(m->sealed, -EPERM);
4608 assert_return(types, -EINVAL);
4610 va_start(ap, types);
4611 r = message_read_ap(m, types, ap);
4617 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4620 assert_return(m, -EINVAL);
4621 assert_return(m->sealed, -EPERM);
4623 /* If types is NULL, read exactly one element */
4625 struct bus_container *c;
4628 if (message_end_of_signature(m))
4631 if (message_end_of_array(m, m->rindex))
4634 c = message_get_container(m);
4636 r = signature_element_length(c->signature + c->index, &l);
4640 types = strndupa(c->signature + c->index, l);
4645 case 0: /* Nothing to drop */
4648 case SD_BUS_TYPE_BYTE:
4649 case SD_BUS_TYPE_BOOLEAN:
4650 case SD_BUS_TYPE_INT16:
4651 case SD_BUS_TYPE_UINT16:
4652 case SD_BUS_TYPE_INT32:
4653 case SD_BUS_TYPE_UINT32:
4654 case SD_BUS_TYPE_INT64:
4655 case SD_BUS_TYPE_UINT64:
4656 case SD_BUS_TYPE_DOUBLE:
4657 case SD_BUS_TYPE_STRING:
4658 case SD_BUS_TYPE_OBJECT_PATH:
4659 case SD_BUS_TYPE_SIGNATURE:
4660 case SD_BUS_TYPE_UNIX_FD:
4662 r = sd_bus_message_read_basic(m, *types, NULL);
4666 r = sd_bus_message_skip(m, types + 1);
4672 case SD_BUS_TYPE_ARRAY: {
4675 r = signature_element_length(types + 1, &k);
4681 memcpy(s, types+1, k);
4684 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4689 r = sd_bus_message_skip(m, s);
4696 r = sd_bus_message_exit_container(m);
4701 r = sd_bus_message_skip(m, types + 1 + k);
4708 case SD_BUS_TYPE_VARIANT: {
4709 const char *contents;
4712 r = sd_bus_message_peek_type(m, &x, &contents);
4716 if (x != SD_BUS_TYPE_VARIANT)
4719 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4723 r = sd_bus_message_skip(m, contents);
4728 r = sd_bus_message_exit_container(m);
4732 r = sd_bus_message_skip(m, types + 1);
4739 case SD_BUS_TYPE_STRUCT_BEGIN:
4740 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4743 r = signature_element_length(types, &k);
4749 memcpy(s, types+1, k-2);
4752 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4756 r = sd_bus_message_skip(m, s);
4761 r = sd_bus_message_exit_container(m);
4766 r = sd_bus_message_skip(m, types + k);
4778 _public_ int sd_bus_message_read_array(
4784 struct bus_container *c;
4790 assert_return(m, -EINVAL);
4791 assert_return(m->sealed, -EPERM);
4792 assert_return(bus_type_is_trivial(type), -EINVAL);
4793 assert_return(ptr, -EINVAL);
4794 assert_return(size, -EINVAL);
4795 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4797 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4801 c = message_get_container(m);
4803 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4804 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4808 sz = c->end - c->begin;
4810 align = bus_type_get_alignment(type);
4814 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4818 /* Zero length array, let's return some aligned
4819 * pointer that is not NULL */
4820 p = (uint8_t*) NULL + align;
4822 r = message_peek_body(m, &m->rindex, align, sz, &p);
4827 r = sd_bus_message_exit_container(m);
4831 *ptr = (const void*) p;
4837 message_quit_container(m);
4841 static int message_peek_fields(
4852 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4855 static int message_peek_field_uint32(
4867 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4870 /* identical for gvariant and dbus1 */
4872 r = message_peek_fields(m, ri, 4, 4, &q);
4877 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4882 static int message_peek_field_uint64(
4894 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4897 /* identical for gvariant and dbus1 */
4899 r = message_peek_fields(m, ri, 8, 8, &q);
4904 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4909 static int message_peek_field_string(
4911 bool (*validate)(const char *p),
4923 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4928 r = message_peek_fields(m, ri, 1, item_size, &q);
4934 r = message_peek_field_uint32(m, ri, 4, &l);
4938 r = message_peek_fields(m, ri, 1, l+1, &q);
4944 if (!validate_nul(q, l))
4950 if (!validate_string(q, l))
4960 static int message_peek_field_signature(
4973 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4978 r = message_peek_fields(m, ri, 1, item_size, &q);
4984 r = message_peek_fields(m, ri, 1, 1, &q);
4989 r = message_peek_fields(m, ri, 1, l+1, &q);
4994 if (!validate_signature(q, l))
5003 static int message_skip_fields(
5006 uint32_t array_size,
5007 const char **signature) {
5009 size_t original_index;
5015 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5017 original_index = *ri;
5023 if (array_size != (uint32_t) -1 &&
5024 array_size <= *ri - original_index)
5031 if (t == SD_BUS_TYPE_STRING) {
5033 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5039 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5041 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5047 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5049 r = message_peek_field_signature(m, ri, 0, NULL);
5055 } else if (bus_type_is_basic(t)) {
5058 align = bus_type_get_alignment(t);
5059 k = bus_type_get_size(t);
5060 assert(align > 0 && k > 0);
5062 r = message_peek_fields(m, ri, align, k, NULL);
5068 } else if (t == SD_BUS_TYPE_ARRAY) {
5070 r = signature_element_length(*signature+1, &l);
5080 strncpy(sig, *signature + 1, l-1);
5083 alignment = bus_type_get_alignment(sig[0]);
5087 r = message_peek_field_uint32(m, ri, 0, &nas);
5090 if (nas > BUS_ARRAY_MAX_SIZE)
5093 r = message_peek_fields(m, ri, alignment, 0, NULL);
5097 r = message_skip_fields(m, ri, nas, (const char**) &s);
5102 (*signature) += 1 + l;
5104 } else if (t == SD_BUS_TYPE_VARIANT) {
5107 r = message_peek_field_signature(m, ri, 0, &s);
5111 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5117 } else if (t == SD_BUS_TYPE_STRUCT ||
5118 t == SD_BUS_TYPE_DICT_ENTRY) {
5120 r = signature_element_length(*signature, &l);
5127 strncpy(sig, *signature + 1, l-1);
5130 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5141 int bus_message_parse_fields(sd_bus_message *m) {
5144 uint32_t unix_fds = 0;
5145 bool unix_fds_set = false;
5146 void *offsets = NULL;
5147 unsigned n_offsets = 0;
5153 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5156 /* Read the signature from the end of the body variant first */
5157 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5158 if (m->footer_accessible < 1 + sz)
5161 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5163 if (p < (char*) m->footer)
5169 /* We found the beginning of the signature string, yay! */
5171 c = strndup(p + 1, ((char*) m->footer + m->footer_accessible) - p - (1 + sz));
5175 free(m->root_container.signature);
5176 m->root_container.signature = c;
5183 /* Calculate the actual user body size, by removing
5184 * the trailing variant signature and struct offset
5186 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5188 /* Pull out the offset table for the fields array */
5189 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5194 ri = m->fields_size - sz;
5195 r = message_peek_fields(m, &ri, 1, sz, &q);
5199 framing = bus_gvariant_read_word_le(q, sz);
5200 if (framing >= m->fields_size - sz)
5202 if ((m->fields_size - framing) % sz != 0)
5206 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5210 n_offsets = (m->fields_size - framing) / sz;
5213 m->user_body_size = m->body_size;
5216 while (ri < m->fields_size) {
5217 _cleanup_free_ char *sig = NULL;
5218 const char *signature;
5219 uint64_t field_type;
5220 size_t item_size = (size_t) -1;
5222 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5231 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5233 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5237 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5241 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5248 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5253 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5258 where = ri = ALIGN_TO(ri, 8);
5259 item_size = end - ri;
5260 r = message_peek_fields(m, &where, 1, item_size, &q);
5264 b = memrchr(q, 0, item_size);
5268 sig = strndup(b+1, item_size - (b+1-(char*) q));
5273 item_size = b - (char*) q;
5275 r = message_peek_field_signature(m, &ri, 0, &signature);
5280 switch (field_type) {
5282 case _BUS_MESSAGE_HEADER_INVALID:
5285 case BUS_MESSAGE_HEADER_PATH:
5290 if (!streq(signature, "o"))
5293 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5296 case BUS_MESSAGE_HEADER_INTERFACE:
5301 if (!streq(signature, "s"))
5304 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5307 case BUS_MESSAGE_HEADER_MEMBER:
5312 if (!streq(signature, "s"))
5315 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5318 case BUS_MESSAGE_HEADER_ERROR_NAME:
5323 if (!streq(signature, "s"))
5326 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5328 m->error._need_free = -1;
5332 case BUS_MESSAGE_HEADER_DESTINATION:
5337 if (!streq(signature, "s"))
5340 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5343 case BUS_MESSAGE_HEADER_SENDER:
5348 if (!streq(signature, "s"))
5351 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5353 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5354 m->creds.unique_name = (char*) m->sender;
5355 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5361 case BUS_MESSAGE_HEADER_SIGNATURE: {
5365 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5368 if (m->root_container.signature)
5371 if (!streq(signature, "g"))
5374 r = message_peek_field_signature(m, &ri, item_size, &s);
5382 free(m->root_container.signature);
5383 m->root_container.signature = c;
5387 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5389 if (m->reply_cookie != 0)
5392 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5393 /* 64bit on dbus2 */
5395 if (!streq(signature, "t"))
5398 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5402 /* 32bit on dbus1 */
5405 if (!streq(signature, "u"))
5408 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5412 m->reply_cookie = serial;
5415 if (m->reply_cookie == 0)
5420 case BUS_MESSAGE_HEADER_UNIX_FDS:
5424 if (!streq(signature, "u"))
5427 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5431 unix_fds_set = true;
5435 if (!BUS_MESSAGE_IS_GVARIANT(m))
5436 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5445 if (m->n_fds != unix_fds)
5448 switch (m->header->type) {
5450 case SD_BUS_MESSAGE_SIGNAL:
5451 if (!m->path || !m->interface || !m->member)
5454 if (m->reply_cookie != 0)
5459 case SD_BUS_MESSAGE_METHOD_CALL:
5461 if (!m->path || !m->member)
5464 if (m->reply_cookie != 0)
5469 case SD_BUS_MESSAGE_METHOD_RETURN:
5471 if (m->reply_cookie == 0)
5475 case SD_BUS_MESSAGE_METHOD_ERROR:
5477 if (m->reply_cookie == 0 || !m->error.name)
5482 /* Refuse non-local messages that claim they are local */
5483 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5485 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5487 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5490 m->root_container.end = m->user_body_size;
5492 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5493 r = build_struct_offsets(
5495 m->root_container.signature,
5497 &m->root_container.item_size,
5498 &m->root_container.offsets,
5499 &m->root_container.n_offsets);
5504 /* Try to read the error message, but if we can't it's a non-issue */
5505 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5506 (void) sd_bus_message_read(m, "s", &m->error.message);
5511 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5512 assert_return(m, -EINVAL);
5513 assert_return(destination, -EINVAL);
5514 assert_return(!m->sealed, -EPERM);
5515 assert_return(!m->destination, -EEXIST);
5517 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5520 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5524 struct bus_body_part *part;
5530 total = BUS_MESSAGE_SIZE(m);
5536 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5537 MESSAGE_FOREACH_PART(part, i, m)
5538 e = mempcpy(e, part->data, part->size);
5540 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5548 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5555 r = sd_bus_message_enter_container(m, 'a', "s");
5559 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5560 r = strv_extend(l, s);
5567 r = sd_bus_message_exit_container(m);
5574 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5578 assert_return(m, -EINVAL);
5579 assert_return(m->sealed, -EPERM);
5580 assert_return(l, -EINVAL);
5582 r = bus_message_read_strv_extend(m, &strv);
5592 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5593 const char *contents;
5602 r = sd_bus_message_rewind(m, true);
5607 r = sd_bus_message_peek_type(m, &type, &contents);
5613 /* Don't match against arguments after the first one we don't understand */
5614 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5615 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5621 r = sd_bus_message_skip(m, NULL);
5626 if (type == SD_BUS_TYPE_ARRAY) {
5628 r = sd_bus_message_read_strv(m, strv);
5635 r = sd_bus_message_read_basic(m, type, str);
5645 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5646 assert_return(m, EINVAL);
5648 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5651 return sd_bus_error_get_errno(&m->error);
5654 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5655 struct bus_container *c;
5657 assert_return(m, NULL);
5659 c = complete ? &m->root_container : message_get_container(m);
5660 return strempty(c->signature);
5663 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5664 assert_return(m, -EINVAL);
5666 return isempty(m->root_container.signature);
5669 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5670 assert_return(m, -EINVAL);
5672 return streq(strempty(m->root_container.signature), strempty(signature));
5675 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5676 bool done_something = false;
5679 assert_return(m, -EINVAL);
5680 assert_return(source, -EINVAL);
5681 assert_return(!m->sealed, -EPERM);
5682 assert_return(source->sealed, -EPERM);
5685 const char *contents;
5700 r = sd_bus_message_peek_type(source, &type, &contents);
5706 done_something = true;
5708 if (bus_type_is_container(type) > 0) {
5710 r = sd_bus_message_enter_container(source, type, contents);
5714 r = sd_bus_message_open_container(m, type, contents);
5718 r = sd_bus_message_copy(m, source, true);
5722 r = sd_bus_message_close_container(m);
5726 r = sd_bus_message_exit_container(source);
5733 r = sd_bus_message_read_basic(source, type, &basic);
5739 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5740 type == SD_BUS_TYPE_SIGNATURE ||
5741 type == SD_BUS_TYPE_STRING)
5742 r = sd_bus_message_append_basic(m, type, basic.string);
5744 r = sd_bus_message_append_basic(m, type, &basic);
5751 return done_something;
5754 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5759 assert_return(m, -EINVAL);
5760 assert_return(m->sealed, -EPERM);
5761 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5762 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5763 assert_return(type || contents, -EINVAL);
5764 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5766 r = sd_bus_message_peek_type(m, &t, &c);
5770 if (type != 0 && type != t)
5773 if (contents && !streq_ptr(contents, c))
5779 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5780 assert_return(m, NULL);
5785 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5786 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5794 switch ((*m)->header->type) {
5796 case SD_BUS_MESSAGE_SIGNAL:
5797 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5803 case SD_BUS_MESSAGE_METHOD_CALL:
5804 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5810 case SD_BUS_MESSAGE_METHOD_RETURN:
5811 case SD_BUS_MESSAGE_METHOD_ERROR:
5813 n = message_new(bus, (*m)->header->type);
5817 n->reply_cookie = (*m)->reply_cookie;
5819 r = message_append_reply_cookie(n, n->reply_cookie);
5823 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5824 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5828 n->error._need_free = -1;
5837 if ((*m)->destination && !n->destination) {
5838 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5843 if ((*m)->sender && !n->sender) {
5844 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5849 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5851 r = sd_bus_message_copy(n, *m, true);
5855 timeout = (*m)->timeout;
5856 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5857 timeout = BUS_DEFAULT_TIMEOUT;
5859 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5863 sd_bus_message_unref(*m);
5870 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5874 assert_return(!m->sealed, -EPERM);
5875 assert_return(!m->sender, -EPERM);
5877 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5880 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5881 assert_return(m, -EINVAL);
5882 assert_return(priority, -EINVAL);
5884 *priority = m->priority;
5888 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5889 assert_return(m, -EINVAL);
5890 assert_return(!m->sealed, -EPERM);
5892 m->priority = priority;