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 size_t n_variable = 0;
2173 if (!BUS_MESSAGE_IS_GVARIANT(m))
2176 p = strempty(c->signature);
2180 r = signature_element_length(p, &n);
2189 r = bus_gvariant_is_fixed_size(t);
2194 assert(!c->need_offsets || i <= c->n_offsets);
2196 /* We need to add an offset for each item that has a
2197 * variable size and that is not the last one in the
2199 if (r == 0 && p[n] != 0)
2206 assert(!c->need_offsets || i == c->n_offsets);
2207 assert(c->need_offsets || n_variable == 0);
2209 if (n_variable <= 0) {
2210 a = message_extend_body(m, 1, 0, add_offset, false);
2217 assert(c->offsets[c->n_offsets-1] == m->body_size);
2219 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2221 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2225 p = strempty(c->signature);
2226 for (i = 0, j = 0; i < c->n_offsets; i++) {
2230 r = signature_element_length(p, &n);
2241 r = bus_gvariant_is_fixed_size(t);
2244 if (r > 0 || p[0] == 0)
2248 k = n_variable - 1 - j;
2250 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2259 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2260 struct bus_container *c;
2263 assert_return(m, -EINVAL);
2264 assert_return(!m->sealed, -EPERM);
2265 assert_return(m->n_containers > 0, -EINVAL);
2266 assert_return(!m->poisoned, -ESTALE);
2268 c = message_get_container(m);
2270 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2271 if (c->signature && c->signature[c->index] != 0)
2276 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2277 r = bus_message_close_array(m, c);
2278 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2279 r = bus_message_close_variant(m, c);
2280 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2281 r = bus_message_close_struct(m, c, true);
2283 assert_not_reached("Unknown container type");
2297 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2304 stack[*i].types = types;
2305 stack[*i].n_struct = n_struct;
2306 stack[*i].n_array = n_array;
2312 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2323 *types = stack[*i].types;
2324 *n_struct = stack[*i].n_struct;
2325 *n_array = stack[*i].n_array;
2330 int bus_message_append_ap(
2335 unsigned n_array, n_struct;
2336 TypeStack stack[BUS_CONTAINER_DEPTH];
2337 unsigned stack_ptr = 0;
2345 n_array = (unsigned) -1;
2346 n_struct = strlen(types);
2351 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2352 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2358 r = sd_bus_message_close_container(m);
2366 if (n_array != (unsigned) -1)
2375 case SD_BUS_TYPE_BYTE: {
2378 x = (uint8_t) va_arg(ap, int);
2379 r = sd_bus_message_append_basic(m, *t, &x);
2383 case SD_BUS_TYPE_BOOLEAN:
2384 case SD_BUS_TYPE_INT32:
2385 case SD_BUS_TYPE_UINT32:
2386 case SD_BUS_TYPE_UNIX_FD: {
2389 /* We assume a boolean is the same as int32_t */
2390 assert_cc(sizeof(int32_t) == sizeof(int));
2392 x = va_arg(ap, uint32_t);
2393 r = sd_bus_message_append_basic(m, *t, &x);
2397 case SD_BUS_TYPE_INT16:
2398 case SD_BUS_TYPE_UINT16: {
2401 x = (uint16_t) va_arg(ap, int);
2402 r = sd_bus_message_append_basic(m, *t, &x);
2406 case SD_BUS_TYPE_INT64:
2407 case SD_BUS_TYPE_UINT64: {
2410 x = va_arg(ap, uint64_t);
2411 r = sd_bus_message_append_basic(m, *t, &x);
2415 case SD_BUS_TYPE_DOUBLE: {
2418 x = va_arg(ap, double);
2419 r = sd_bus_message_append_basic(m, *t, &x);
2423 case SD_BUS_TYPE_STRING:
2424 case SD_BUS_TYPE_OBJECT_PATH:
2425 case SD_BUS_TYPE_SIGNATURE: {
2428 x = va_arg(ap, const char*);
2429 r = sd_bus_message_append_basic(m, *t, x);
2433 case SD_BUS_TYPE_ARRAY: {
2436 r = signature_element_length(t + 1, &k);
2442 memcpy(s, t + 1, k);
2445 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2450 if (n_array == (unsigned) -1) {
2455 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2461 n_array = va_arg(ap, unsigned);
2466 case SD_BUS_TYPE_VARIANT: {
2469 s = va_arg(ap, const char*);
2473 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2477 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2482 n_struct = strlen(s);
2483 n_array = (unsigned) -1;
2488 case SD_BUS_TYPE_STRUCT_BEGIN:
2489 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2492 r = signature_element_length(t, &k);
2499 memcpy(s, t + 1, k - 2);
2502 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2507 if (n_array == (unsigned) -1) {
2512 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2518 n_array = (unsigned) -1;
2534 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2538 assert_return(m, -EINVAL);
2539 assert_return(types, -EINVAL);
2540 assert_return(!m->sealed, -EPERM);
2541 assert_return(!m->poisoned, -ESTALE);
2543 va_start(ap, types);
2544 r = bus_message_append_ap(m, types, ap);
2550 _public_ int sd_bus_message_append_array_space(
2560 assert_return(m, -EINVAL);
2561 assert_return(!m->sealed, -EPERM);
2562 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2563 assert_return(ptr || size == 0, -EINVAL);
2564 assert_return(!m->poisoned, -ESTALE);
2566 /* alignment and size of the trivial types (except bool) is
2567 * identical for gvariant and dbus1 marshalling */
2568 align = bus_type_get_alignment(type);
2569 sz = bus_type_get_size(type);
2571 assert_se(align > 0);
2577 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2581 a = message_extend_body(m, align, size, false, false);
2585 r = sd_bus_message_close_container(m);
2593 _public_ int sd_bus_message_append_array(
2601 assert_return(m, -EINVAL);
2602 assert_return(!m->sealed, -EPERM);
2603 assert_return(bus_type_is_trivial(type), -EINVAL);
2604 assert_return(ptr || size == 0, -EINVAL);
2605 assert_return(!m->poisoned, -ESTALE);
2607 r = sd_bus_message_append_array_space(m, type, size, &p);
2612 memcpy(p, ptr, size);
2617 _public_ int sd_bus_message_append_array_iovec(
2620 const struct iovec *iov,
2628 assert_return(m, -EINVAL);
2629 assert_return(!m->sealed, -EPERM);
2630 assert_return(bus_type_is_trivial(type), -EINVAL);
2631 assert_return(iov || n == 0, -EINVAL);
2632 assert_return(!m->poisoned, -ESTALE);
2634 size = IOVEC_TOTAL_SIZE(iov, n);
2636 r = sd_bus_message_append_array_space(m, type, size, &p);
2640 for (i = 0; i < n; i++) {
2642 if (iov[i].iov_base)
2643 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2645 memzero(p, iov[i].iov_len);
2647 p = (uint8_t*) p + iov[i].iov_len;
2653 _public_ int sd_bus_message_append_array_memfd(
2660 _cleanup_close_ int copy_fd = -1;
2661 struct bus_body_part *part;
2667 assert_return(m, -EINVAL);
2668 assert_return(memfd >= 0, -EINVAL);
2669 assert_return(bus_type_is_trivial(type), -EINVAL);
2670 assert_return(size > 0, -EINVAL);
2671 assert_return(!m->sealed, -EPERM);
2672 assert_return(!m->poisoned, -ESTALE);
2674 r = memfd_set_sealed(memfd);
2678 copy_fd = dup(memfd);
2682 r = memfd_get_size(memfd, &real_size);
2686 if (offset == 0 && size == (uint64_t) -1)
2688 else if (offset + size > real_size)
2691 align = bus_type_get_alignment(type);
2692 sz = bus_type_get_size(type);
2694 assert_se(align > 0);
2697 if (offset % align != 0)
2703 if (size > (uint64_t) (uint32_t) -1)
2706 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2710 a = message_extend_body(m, align, 0, false, false);
2714 part = message_append_part(m);
2718 part->memfd = copy_fd;
2719 part->memfd_offset = offset;
2720 part->sealed = true;
2724 m->body_size += size;
2725 message_extend_containers(m, size);
2727 return sd_bus_message_close_container(m);
2730 _public_ int sd_bus_message_append_string_memfd(
2736 _cleanup_close_ int copy_fd = -1;
2737 struct bus_body_part *part;
2738 struct bus_container *c;
2743 assert_return(m, -EINVAL);
2744 assert_return(memfd >= 0, -EINVAL);
2745 assert_return(size > 0, -EINVAL);
2746 assert_return(!m->sealed, -EPERM);
2747 assert_return(!m->poisoned, -ESTALE);
2749 r = memfd_set_sealed(memfd);
2753 copy_fd = dup(memfd);
2757 r = memfd_get_size(memfd, &real_size);
2761 if (offset == 0 && size == (uint64_t) -1)
2763 else if (offset + size > real_size)
2766 /* We require this to be NUL terminated */
2770 if (size > (uint64_t) (uint32_t) -1)
2773 c = message_get_container(m);
2774 if (c->signature && c->signature[c->index]) {
2775 /* Container signature is already set */
2777 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2782 /* Maybe we can append to the signature? But only if this is the top-level container */
2783 if (c->enclosing != 0)
2786 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2793 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2794 a = message_extend_body(m, 4, 4, false, false);
2798 *(uint32_t*) a = size - 1;
2801 part = message_append_part(m);
2805 part->memfd = copy_fd;
2806 part->memfd_offset = offset;
2807 part->sealed = true;
2811 m->body_size += size;
2812 message_extend_containers(m, size);
2814 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2815 r = message_add_offset(m, m->body_size);
2822 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2828 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2832 assert_return(m, -EINVAL);
2833 assert_return(!m->sealed, -EPERM);
2834 assert_return(!m->poisoned, -ESTALE);
2836 r = sd_bus_message_open_container(m, 'a', "s");
2840 STRV_FOREACH(i, l) {
2841 r = sd_bus_message_append_basic(m, 's', *i);
2846 return sd_bus_message_close_container(m);
2849 static int bus_message_close_header(sd_bus_message *m) {
2853 /* The actual user data is finished now, we just complete the
2854 variant and struct now (at least on gvariant). Remember
2855 this position, so that during parsing we know where to to
2856 put the outer container end. */
2857 m->user_body_size = m->body_size;
2859 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2860 const char *signature;
2864 /* Add offset table to end of fields array */
2865 if (m->n_header_offsets >= 1) {
2869 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2871 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2872 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2876 for (i = 0; i < m->n_header_offsets; i++)
2877 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2880 /* Add gvariant NUL byte plus signature to the end of
2881 * the body, followed by the final offset pointing to
2882 * the end of the fields array */
2884 signature = strempty(m->root_container.signature);
2885 l = strlen(signature);
2887 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l, 1);
2888 d = message_extend_body(m, 1, 1 + l + sz, false, true);
2893 memcpy((uint8_t*) d + 1, signature, l);
2895 bus_gvariant_write_word_le((uint8_t*) d + 1 + l, sz, sizeof(struct bus_header) + m->fields_size);
2898 m->footer_accessible = 1 + l + sz;
2900 m->header->dbus1.fields_size = m->fields_size;
2901 m->header->dbus1.body_size = m->body_size;
2907 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2908 struct bus_body_part *part;
2918 if (m->n_containers > 0)
2924 if (cookie > 0xffffffffULL &&
2925 !BUS_MESSAGE_IS_GVARIANT(m))
2928 /* In vtables the return signature of method calls is listed,
2929 * let's check if they match if this is a response */
2930 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2931 m->enforced_reply_signature &&
2932 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2935 /* If gvariant marshalling is used we need to close the body structure */
2936 r = bus_message_close_struct(m, &m->root_container, false);
2940 /* If there's a non-trivial signature set, then add it in
2941 * here, but only on dbus1 */
2942 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2943 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2949 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2954 r = bus_message_close_header(m);
2958 if (BUS_MESSAGE_IS_GVARIANT(m))
2959 m->header->dbus2.cookie = cookie;
2961 m->header->dbus1.serial = (uint32_t) cookie;
2963 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2965 /* Add padding at the end of the fields part, since we know
2966 * the body needs to start at an 8 byte alignment. We made
2967 * sure we allocated enough space for this, so all we need to
2968 * do here is to zero it out. */
2969 a = ALIGN8(m->fields_size) - m->fields_size;
2971 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2973 /* If this is something we can send as memfd, then let's seal
2974 the memfd now. Note that we can send memfds as payload only
2975 for directed messages, and not for broadcasts. */
2976 if (m->destination && m->bus->use_memfd) {
2977 MESSAGE_FOREACH_PART(part, i, m)
2978 if (part->memfd >= 0 &&
2980 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2981 part != m->body_end) { /* The last part may never be sent as memfd */
2984 /* Try to seal it if that makes
2985 * sense. First, unmap our own map to
2986 * make sure we don't keep it busy. */
2987 bus_body_part_unmap(part);
2989 /* Then, sync up real memfd size */
2991 r = memfd_set_size(part->memfd, sz);
2995 /* Finally, try to seal */
2996 if (memfd_set_sealed(part->memfd) >= 0)
2997 part->sealed = true;
3001 m->root_container.end = m->user_body_size;
3002 m->root_container.index = 0;
3003 m->root_container.offset_index = 0;
3004 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3011 int bus_body_part_map(struct bus_body_part *part) {
3020 if (part->size <= 0)
3023 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3024 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3025 static const uint8_t zeroes[7] = { };
3026 part->data = (void*) zeroes;
3030 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3031 psz = PAGE_ALIGN(part->size + shift);
3033 if (part->memfd >= 0)
3034 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3035 else if (part->is_zero)
3036 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3040 if (p == MAP_FAILED)
3044 part->mmap_begin = p;
3045 part->data = (uint8_t*) p + shift;
3046 part->munmap_this = true;
3051 void bus_body_part_unmap(struct bus_body_part *part) {
3055 if (part->memfd < 0)
3058 if (!part->mmap_begin)
3061 if (!part->munmap_this)
3064 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3066 part->mmap_begin = NULL;
3069 part->munmap_this = false;
3074 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3075 size_t k, start, end;
3080 start = ALIGN_TO((size_t) *rindex, align);
3081 end = start + nbytes;
3086 /* Verify that padding is 0 */
3087 for (k = *rindex; k < start; k++)
3088 if (((const uint8_t*) p)[k] != 0)
3092 *r = (uint8_t*) p + start;
3099 static bool message_end_of_signature(sd_bus_message *m) {
3100 struct bus_container *c;
3104 c = message_get_container(m);
3105 return !c->signature || c->signature[c->index] == 0;
3108 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3109 struct bus_container *c;
3113 c = message_get_container(m);
3114 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3117 if (BUS_MESSAGE_IS_GVARIANT(m))
3118 return index >= c->end;
3120 assert(c->array_size);
3121 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3125 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3126 assert_return(m, -EINVAL);
3127 assert_return(m->sealed, -EPERM);
3129 if (complete && m->n_containers > 0)
3132 if (message_end_of_signature(m))
3135 if (message_end_of_array(m, m->rindex))
3141 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3142 struct bus_body_part *part;
3148 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3149 part = m->cached_rindex_part;
3150 begin = m->cached_rindex_part_begin;
3160 if (index + sz <= begin + part->size) {
3162 r = bus_body_part_map(part);
3167 *p = (uint8_t*) part->data + index - begin;
3169 m->cached_rindex_part = part;
3170 m->cached_rindex_part_begin = begin;
3175 begin += part->size;
3182 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3189 if (!BUS_MESSAGE_IS_GVARIANT(m))
3192 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3195 sz = bus_gvariant_get_size(c->signature);
3199 if (c->offset_index+1 >= c->n_offsets)
3202 /* Variable-size array */
3204 alignment = bus_gvariant_get_alignment(c->signature);
3205 assert(alignment > 0);
3207 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3208 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3211 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3214 /* Fixed-size array */
3215 *rindex = c->begin + (c->offset_index+1) * sz;
3221 } else if (c->enclosing == 0 ||
3222 c->enclosing == SD_BUS_TYPE_STRUCT ||
3223 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3228 if (c->offset_index+1 >= c->n_offsets)
3231 r = signature_element_length(c->signature + c->index, &n);
3235 r = signature_element_length(c->signature + c->index + n, &j);
3240 memcpy(t, c->signature + c->index + n, j);
3243 alignment = bus_gvariant_get_alignment(t);
3246 assert(alignment > 0);
3248 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3249 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3253 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3256 assert_not_reached("Unknown container type");
3261 /* Reached the end */
3268 static int message_peek_body(
3275 size_t k, start, end, padding;
3276 struct bus_body_part *part;
3283 start = ALIGN_TO((size_t) *rindex, align);
3284 padding = start - *rindex;
3285 end = start + nbytes;
3287 if (end > m->user_body_size)
3290 part = find_part(m, *rindex, padding, (void**) &q);
3295 /* Verify padding */
3296 for (k = 0; k < padding; k++)
3301 part = find_part(m, start, nbytes, (void**) &q);
3302 if (!part || (nbytes > 0 && !q))
3313 static bool validate_nul(const char *s, size_t l) {
3315 /* Check for NUL chars in the string */
3316 if (memchr(s, 0, l))
3319 /* Check for NUL termination */
3326 static bool validate_string(const char *s, size_t l) {
3328 if (!validate_nul(s, l))
3331 /* Check if valid UTF8 */
3332 if (!utf8_is_valid(s))
3338 static bool validate_signature(const char *s, size_t l) {
3340 if (!validate_nul(s, l))
3343 /* Check if valid signature */
3344 if (!signature_is_valid(s, true))
3350 static bool validate_object_path(const char *s, size_t l) {
3352 if (!validate_nul(s, l))
3355 if (!object_path_is_valid(s))
3361 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3362 struct bus_container *c;
3367 assert_return(m, -EINVAL);
3368 assert_return(m->sealed, -EPERM);
3369 assert_return(bus_type_is_basic(type), -EINVAL);
3371 if (message_end_of_signature(m))
3374 if (message_end_of_array(m, m->rindex))
3377 c = message_get_container(m);
3378 if (c->signature[c->index] != type)
3383 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3385 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3388 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3392 if (type == SD_BUS_TYPE_STRING)
3393 ok = validate_string(q, c->item_size-1);
3394 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3395 ok = validate_object_path(q, c->item_size-1);
3397 ok = validate_signature(q, c->item_size-1);
3403 *(const char**) p = q;
3407 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3409 if ((size_t) sz != c->item_size)
3412 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3415 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3421 case SD_BUS_TYPE_BYTE:
3423 *(uint8_t*) p = *(uint8_t*) q;
3426 case SD_BUS_TYPE_BOOLEAN:
3428 *(int*) p = !!*(uint8_t*) q;
3431 case SD_BUS_TYPE_INT16:
3432 case SD_BUS_TYPE_UINT16:
3434 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3437 case SD_BUS_TYPE_INT32:
3438 case SD_BUS_TYPE_UINT32:
3440 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3443 case SD_BUS_TYPE_INT64:
3444 case SD_BUS_TYPE_UINT64:
3445 case SD_BUS_TYPE_DOUBLE:
3447 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3450 case SD_BUS_TYPE_UNIX_FD: {
3453 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3458 *(int*) p = m->fds[j];
3464 assert_not_reached("unexpected type");
3468 r = container_next_item(m, c, &rindex);
3473 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3477 r = message_peek_body(m, &rindex, 4, 4, &q);
3481 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3482 r = message_peek_body(m, &rindex, 1, l+1, &q);
3486 if (type == SD_BUS_TYPE_OBJECT_PATH)
3487 ok = validate_object_path(q, l);
3489 ok = validate_string(q, l);
3494 *(const char**) p = q;
3496 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3499 r = message_peek_body(m, &rindex, 1, 1, &q);
3504 r = message_peek_body(m, &rindex, 1, l+1, &q);
3508 if (!validate_signature(q, l))
3512 *(const char**) p = q;
3517 align = bus_type_get_alignment(type);
3520 sz = bus_type_get_size(type);
3523 r = message_peek_body(m, &rindex, align, sz, &q);
3529 case SD_BUS_TYPE_BYTE:
3531 *(uint8_t*) p = *(uint8_t*) q;
3534 case SD_BUS_TYPE_BOOLEAN:
3536 *(int*) p = !!*(uint32_t*) q;
3539 case SD_BUS_TYPE_INT16:
3540 case SD_BUS_TYPE_UINT16:
3542 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3545 case SD_BUS_TYPE_INT32:
3546 case SD_BUS_TYPE_UINT32:
3548 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3551 case SD_BUS_TYPE_INT64:
3552 case SD_BUS_TYPE_UINT64:
3553 case SD_BUS_TYPE_DOUBLE:
3555 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3558 case SD_BUS_TYPE_UNIX_FD: {
3561 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3566 *(int*) p = m->fds[j];
3571 assert_not_reached("Unknown basic type...");
3578 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3584 static int bus_message_enter_array(
3586 struct bus_container *c,
3587 const char *contents,
3588 uint32_t **array_size,
3591 size_t *n_offsets) {
3605 if (!signature_is_single(contents, true))
3608 if (!c->signature || c->signature[c->index] == 0)
3611 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3614 if (!startswith(c->signature + c->index + 1, contents))
3619 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3622 r = message_peek_body(m, &rindex, 4, 4, &q);
3626 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3629 alignment = bus_type_get_alignment(contents[0]);
3633 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3637 *array_size = (uint32_t*) q;
3639 } else if (c->item_size <= 0) {
3641 /* gvariant: empty array */
3646 } else if (bus_gvariant_is_fixed_size(contents)) {
3648 /* gvariant: fixed length array */
3649 *item_size = bus_gvariant_get_size(contents);
3654 size_t where, p = 0, framing, sz;
3657 /* gvariant: variable length array */
3658 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3660 where = rindex + c->item_size - sz;
3661 r = message_peek_body(m, &where, 1, sz, &q);
3665 framing = bus_gvariant_read_word_le(q, sz);
3666 if (framing > c->item_size - sz)
3668 if ((c->item_size - framing) % sz != 0)
3671 *n_offsets = (c->item_size - framing) / sz;
3673 where = rindex + framing;
3674 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3678 *offsets = new(size_t, *n_offsets);
3682 for (i = 0; i < *n_offsets; i++) {
3685 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3686 if (x > c->item_size - sz)
3691 (*offsets)[i] = rindex + x;
3695 *item_size = (*offsets)[0] - rindex;
3700 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3701 c->index += 1 + strlen(contents);
3706 static int bus_message_enter_variant(
3708 struct bus_container *c,
3709 const char *contents,
3710 size_t *item_size) {
3722 if (!signature_is_single(contents, false))
3725 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3728 if (!c->signature || c->signature[c->index] == 0)
3731 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3736 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3739 k = strlen(contents);
3740 if (1+k > c->item_size)
3743 where = rindex + c->item_size - (1+k);
3744 r = message_peek_body(m, &where, 1, 1+k, &q);
3748 if (*(char*) q != 0)
3751 if (memcmp((uint8_t*) q+1, contents, k))
3754 *item_size = c->item_size - (1+k);
3757 r = message_peek_body(m, &rindex, 1, 1, &q);
3762 r = message_peek_body(m, &rindex, 1, l+1, &q);
3766 if (!validate_signature(q, l))
3769 if (!streq(q, contents))
3775 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3781 static int build_struct_offsets(
3783 const char *signature,
3787 size_t *n_offsets) {
3789 unsigned n_variable = 0, n_total = 0, v;
3790 size_t previous = 0, where;
3801 if (isempty(signature)) {
3808 sz = bus_gvariant_determine_word_size(size, 0);
3812 /* First, loop over signature and count variable elements and
3813 * elements in general. We use this to know how large the
3814 * offset array is at the end of the structure. Note that
3815 * GVariant only stores offsets for all variable size elements
3816 * that are not the last item. */
3822 r = signature_element_length(p, &n);
3831 r = bus_gvariant_is_fixed_size(t);
3836 if (r == 0 && p[n] != 0) /* except the last item */
3843 if (size < n_variable * sz)
3846 where = m->rindex + size - (n_variable * sz);
3847 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3853 *offsets = new(size_t, n_total);
3859 /* Second, loop again and build an offset table */
3865 r = signature_element_length(p, &n);
3874 k = bus_gvariant_get_size(t);
3882 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3885 if (m->rindex + x < previous)
3888 /* The last item's end
3889 * is determined from
3892 x = size - (n_variable * sz);
3894 offset = m->rindex + x;
3900 align = bus_gvariant_get_alignment(t);
3903 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3907 previous = (*offsets)[(*n_offsets)++] = offset;
3912 assert(*n_offsets == n_total);
3914 *item_size = (*offsets)[0] - m->rindex;
3918 static int enter_struct_or_dict_entry(
3920 struct bus_container *c,
3921 const char *contents,
3924 size_t *n_offsets) {
3935 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3938 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3942 } else if (c->item_size <= 0) {
3944 /* gvariant empty struct */
3949 /* gvariant with contents */
3950 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3955 static int bus_message_enter_struct(
3957 struct bus_container *c,
3958 const char *contents,
3961 size_t *n_offsets) {
3973 if (!signature_is_valid(contents, false))
3976 if (!c->signature || c->signature[c->index] == 0)
3979 l = strlen(contents);
3981 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3982 !startswith(c->signature + c->index + 1, contents) ||
3983 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3986 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3990 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3991 c->index += 1 + l + 1;
3996 static int bus_message_enter_dict_entry(
3998 struct bus_container *c,
3999 const char *contents,
4002 size_t *n_offsets) {
4011 if (!signature_is_pair(contents))
4014 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4017 if (!c->signature || c->signature[c->index] == 0)
4020 l = strlen(contents);
4022 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4023 !startswith(c->signature + c->index + 1, contents) ||
4024 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4027 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4031 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4032 c->index += 1 + l + 1;
4037 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4039 const char *contents) {
4040 struct bus_container *c, *w;
4041 uint32_t *array_size = NULL;
4044 size_t *offsets = NULL;
4045 size_t n_offsets = 0, item_size = 0;
4048 assert_return(m, -EINVAL);
4049 assert_return(m->sealed, -EPERM);
4050 assert_return(type != 0 || !contents, -EINVAL);
4052 if (type == 0 || !contents) {
4056 /* Allow entering into anonymous containers */
4057 r = sd_bus_message_peek_type(m, &tt, &cc);
4061 if (type != 0 && type != tt)
4064 if (contents && !streq(contents, cc))
4072 * We enforce a global limit on container depth, that is much
4073 * higher than the 32 structs and 32 arrays the specification
4074 * mandates. This is simpler to implement for us, and we need
4075 * this only to ensure our container array doesn't grow
4076 * without bounds. We are happy to return any data from a
4077 * message as long as the data itself is valid, even if the
4078 * overall message might be not.
4080 * Note that the message signature is validated when
4081 * parsing the headers, and that validation does check the
4084 * Note that the specification defines no limits on the depth
4085 * of stacked variants, but we do.
4087 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4090 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4093 if (message_end_of_signature(m))
4096 if (message_end_of_array(m, m->rindex))
4099 c = message_get_container(m);
4101 signature = strdup(contents);
4105 c->saved_index = c->index;
4108 if (type == SD_BUS_TYPE_ARRAY)
4109 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4110 else if (type == SD_BUS_TYPE_VARIANT)
4111 r = bus_message_enter_variant(m, c, contents, &item_size);
4112 else if (type == SD_BUS_TYPE_STRUCT)
4113 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4114 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4115 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4125 /* OK, let's fill it in */
4126 w = m->containers + m->n_containers++;
4127 w->enclosing = type;
4128 w->signature = signature;
4129 w->peeked_signature = NULL;
4133 w->begin = m->rindex;
4134 w->end = m->rindex + c->item_size;
4136 w->array_size = array_size;
4137 w->item_size = item_size;
4138 w->offsets = offsets;
4139 w->n_offsets = n_offsets;
4140 w->offset_index = 0;
4145 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4146 struct bus_container *c;
4150 assert_return(m, -EINVAL);
4151 assert_return(m->sealed, -EPERM);
4152 assert_return(m->n_containers > 0, -ENXIO);
4154 c = message_get_container(m);
4156 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4157 if (c->signature && c->signature[c->index] != 0)
4161 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4162 if (m->rindex < c->end)
4165 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4168 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4169 if (c->begin + l != m->rindex)
4174 free(c->peeked_signature);
4178 c = message_get_container(m);
4181 c->index = c->saved_index;
4182 r = container_next_item(m, c, &m->rindex);
4190 static void message_quit_container(sd_bus_message *m) {
4191 struct bus_container *c;
4195 assert(m->n_containers > 0);
4197 c = message_get_container(m);
4200 assert(m->rindex >= c->before);
4201 m->rindex = c->before;
4203 /* Free container */
4208 /* Correct index of new top-level container */
4209 c = message_get_container(m);
4210 c->index = c->saved_index;
4213 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4214 struct bus_container *c;
4217 assert_return(m, -EINVAL);
4218 assert_return(m->sealed, -EPERM);
4220 if (message_end_of_signature(m))
4223 if (message_end_of_array(m, m->rindex))
4226 c = message_get_container(m);
4228 if (bus_type_is_basic(c->signature[c->index])) {
4232 *type = c->signature[c->index];
4236 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4242 r = signature_element_length(c->signature+c->index+1, &l);
4248 sig = strndup(c->signature + c->index + 1, l);
4252 free(c->peeked_signature);
4253 *contents = c->peeked_signature = sig;
4257 *type = SD_BUS_TYPE_ARRAY;
4262 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4263 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4269 r = signature_element_length(c->signature+c->index, &l);
4274 sig = strndup(c->signature + c->index + 1, l - 2);
4278 free(c->peeked_signature);
4279 *contents = c->peeked_signature = sig;
4283 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4288 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4292 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4295 if (c->item_size < 2)
4298 /* Look for the NUL delimiter that
4299 separates the payload from the
4300 signature. Since the body might be
4301 in a different part that then the
4302 signature we map byte by byte. */
4304 for (k = 2; k <= c->item_size; k++) {
4307 where = m->rindex + c->item_size - k;
4308 r = message_peek_body(m, &where, 1, k, &q);
4312 if (*(char*) q == 0)
4316 if (k > c->item_size)
4319 free(c->peeked_signature);
4320 c->peeked_signature = strndup((char*) q + 1, k - 1);
4321 if (!c->peeked_signature)
4324 if (!signature_is_valid(c->peeked_signature, true))
4327 *contents = c->peeked_signature;
4332 r = message_peek_body(m, &rindex, 1, 1, &q);
4337 r = message_peek_body(m, &rindex, 1, l+1, &q);
4341 if (!validate_signature(q, l))
4349 *type = SD_BUS_TYPE_VARIANT;
4364 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4365 struct bus_container *c;
4367 assert_return(m, -EINVAL);
4368 assert_return(m->sealed, -EPERM);
4371 message_reset_containers(m);
4374 c = message_get_container(m);
4376 c = message_get_container(m);
4378 c->offset_index = 0;
4380 m->rindex = c->begin;
4383 c->offset_index = 0;
4384 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4386 return !isempty(c->signature);
4389 static int message_read_ap(
4394 unsigned n_array, n_struct;
4395 TypeStack stack[BUS_CONTAINER_DEPTH];
4396 unsigned stack_ptr = 0;
4397 unsigned n_loop = 0;
4405 /* Ideally, we'd just call ourselves recursively on every
4406 * complex type. However, the state of a va_list that is
4407 * passed to a function is undefined after that function
4408 * returns. This means we need to docode the va_list linearly
4409 * in a single stackframe. We hence implement our own
4410 * home-grown stack in an array. */
4412 n_array = (unsigned) -1; /* length of current array entries */
4413 n_struct = strlen(types); /* length of current struct contents signature */
4420 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4421 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4427 r = sd_bus_message_exit_container(m);
4435 if (n_array != (unsigned) -1)
4444 case SD_BUS_TYPE_BYTE:
4445 case SD_BUS_TYPE_BOOLEAN:
4446 case SD_BUS_TYPE_INT16:
4447 case SD_BUS_TYPE_UINT16:
4448 case SD_BUS_TYPE_INT32:
4449 case SD_BUS_TYPE_UINT32:
4450 case SD_BUS_TYPE_INT64:
4451 case SD_BUS_TYPE_UINT64:
4452 case SD_BUS_TYPE_DOUBLE:
4453 case SD_BUS_TYPE_STRING:
4454 case SD_BUS_TYPE_OBJECT_PATH:
4455 case SD_BUS_TYPE_SIGNATURE:
4456 case SD_BUS_TYPE_UNIX_FD: {
4459 p = va_arg(ap, void*);
4460 r = sd_bus_message_read_basic(m, *t, p);
4473 case SD_BUS_TYPE_ARRAY: {
4476 r = signature_element_length(t + 1, &k);
4482 memcpy(s, t + 1, k);
4485 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4496 if (n_array == (unsigned) -1) {
4501 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4507 n_array = va_arg(ap, unsigned);
4512 case SD_BUS_TYPE_VARIANT: {
4515 s = va_arg(ap, const char *);
4519 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4529 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4534 n_struct = strlen(s);
4535 n_array = (unsigned) -1;
4540 case SD_BUS_TYPE_STRUCT_BEGIN:
4541 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4544 r = signature_element_length(t, &k);
4550 memcpy(s, t + 1, k - 2);
4553 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4563 if (n_array == (unsigned) -1) {
4568 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4574 n_array = (unsigned) -1;
4587 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4591 assert_return(m, -EINVAL);
4592 assert_return(m->sealed, -EPERM);
4593 assert_return(types, -EINVAL);
4595 va_start(ap, types);
4596 r = message_read_ap(m, types, ap);
4602 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4605 assert_return(m, -EINVAL);
4606 assert_return(m->sealed, -EPERM);
4608 /* If types is NULL, read exactly one element */
4610 struct bus_container *c;
4613 if (message_end_of_signature(m))
4616 if (message_end_of_array(m, m->rindex))
4619 c = message_get_container(m);
4621 r = signature_element_length(c->signature + c->index, &l);
4625 types = strndupa(c->signature + c->index, l);
4630 case 0: /* Nothing to drop */
4633 case SD_BUS_TYPE_BYTE:
4634 case SD_BUS_TYPE_BOOLEAN:
4635 case SD_BUS_TYPE_INT16:
4636 case SD_BUS_TYPE_UINT16:
4637 case SD_BUS_TYPE_INT32:
4638 case SD_BUS_TYPE_UINT32:
4639 case SD_BUS_TYPE_INT64:
4640 case SD_BUS_TYPE_UINT64:
4641 case SD_BUS_TYPE_DOUBLE:
4642 case SD_BUS_TYPE_STRING:
4643 case SD_BUS_TYPE_OBJECT_PATH:
4644 case SD_BUS_TYPE_SIGNATURE:
4645 case SD_BUS_TYPE_UNIX_FD:
4647 r = sd_bus_message_read_basic(m, *types, NULL);
4651 r = sd_bus_message_skip(m, types + 1);
4657 case SD_BUS_TYPE_ARRAY: {
4660 r = signature_element_length(types + 1, &k);
4666 memcpy(s, types+1, k);
4669 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4674 r = sd_bus_message_skip(m, s);
4681 r = sd_bus_message_exit_container(m);
4686 r = sd_bus_message_skip(m, types + 1 + k);
4693 case SD_BUS_TYPE_VARIANT: {
4694 const char *contents;
4697 r = sd_bus_message_peek_type(m, &x, &contents);
4701 if (x != SD_BUS_TYPE_VARIANT)
4704 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4708 r = sd_bus_message_skip(m, contents);
4713 r = sd_bus_message_exit_container(m);
4717 r = sd_bus_message_skip(m, types + 1);
4724 case SD_BUS_TYPE_STRUCT_BEGIN:
4725 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4728 r = signature_element_length(types, &k);
4734 memcpy(s, types+1, k-2);
4737 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4741 r = sd_bus_message_skip(m, s);
4746 r = sd_bus_message_exit_container(m);
4751 r = sd_bus_message_skip(m, types + k);
4763 _public_ int sd_bus_message_read_array(
4769 struct bus_container *c;
4775 assert_return(m, -EINVAL);
4776 assert_return(m->sealed, -EPERM);
4777 assert_return(bus_type_is_trivial(type), -EINVAL);
4778 assert_return(ptr, -EINVAL);
4779 assert_return(size, -EINVAL);
4780 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4782 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4786 c = message_get_container(m);
4788 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4789 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4793 sz = c->end - c->begin;
4795 align = bus_type_get_alignment(type);
4799 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4803 /* Zero length array, let's return some aligned
4804 * pointer that is not NULL */
4805 p = (uint8_t*) NULL + align;
4807 r = message_peek_body(m, &m->rindex, align, sz, &p);
4812 r = sd_bus_message_exit_container(m);
4816 *ptr = (const void*) p;
4822 message_quit_container(m);
4826 static int message_peek_fields(
4837 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4840 static int message_peek_field_uint32(
4852 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4855 /* identical for gvariant and dbus1 */
4857 r = message_peek_fields(m, ri, 4, 4, &q);
4862 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4867 static int message_peek_field_uint64(
4879 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4882 /* identical for gvariant and dbus1 */
4884 r = message_peek_fields(m, ri, 8, 8, &q);
4889 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4894 static int message_peek_field_string(
4896 bool (*validate)(const char *p),
4908 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4913 r = message_peek_fields(m, ri, 1, item_size, &q);
4919 r = message_peek_field_uint32(m, ri, 4, &l);
4923 r = message_peek_fields(m, ri, 1, l+1, &q);
4929 if (!validate_nul(q, l))
4935 if (!validate_string(q, l))
4945 static int message_peek_field_signature(
4958 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4963 r = message_peek_fields(m, ri, 1, item_size, &q);
4969 r = message_peek_fields(m, ri, 1, 1, &q);
4974 r = message_peek_fields(m, ri, 1, l+1, &q);
4979 if (!validate_signature(q, l))
4988 static int message_skip_fields(
4991 uint32_t array_size,
4992 const char **signature) {
4994 size_t original_index;
5000 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5002 original_index = *ri;
5008 if (array_size != (uint32_t) -1 &&
5009 array_size <= *ri - original_index)
5016 if (t == SD_BUS_TYPE_STRING) {
5018 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5024 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5026 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5032 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5034 r = message_peek_field_signature(m, ri, 0, NULL);
5040 } else if (bus_type_is_basic(t)) {
5043 align = bus_type_get_alignment(t);
5044 k = bus_type_get_size(t);
5045 assert(align > 0 && k > 0);
5047 r = message_peek_fields(m, ri, align, k, NULL);
5053 } else if (t == SD_BUS_TYPE_ARRAY) {
5055 r = signature_element_length(*signature+1, &l);
5065 strncpy(sig, *signature + 1, l-1);
5068 alignment = bus_type_get_alignment(sig[0]);
5072 r = message_peek_field_uint32(m, ri, 0, &nas);
5075 if (nas > BUS_ARRAY_MAX_SIZE)
5078 r = message_peek_fields(m, ri, alignment, 0, NULL);
5082 r = message_skip_fields(m, ri, nas, (const char**) &s);
5087 (*signature) += 1 + l;
5089 } else if (t == SD_BUS_TYPE_VARIANT) {
5092 r = message_peek_field_signature(m, ri, 0, &s);
5096 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5102 } else if (t == SD_BUS_TYPE_STRUCT ||
5103 t == SD_BUS_TYPE_DICT_ENTRY) {
5105 r = signature_element_length(*signature, &l);
5112 strncpy(sig, *signature + 1, l-1);
5115 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5126 int bus_message_parse_fields(sd_bus_message *m) {
5129 uint32_t unix_fds = 0;
5130 bool unix_fds_set = false;
5131 void *offsets = NULL;
5132 unsigned n_offsets = 0;
5138 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5141 /* Read the signature from the end of the body variant first */
5142 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5143 if (m->footer_accessible < 1 + sz)
5146 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5148 if (p < (char*) m->footer)
5154 /* We found the beginning of the signature string, yay! */
5156 c = strndup(p + 1, ((char*) m->footer + m->footer_accessible) - p - (1 + sz));
5160 free(m->root_container.signature);
5161 m->root_container.signature = c;
5168 /* Calculate the actual user body size, by removing
5169 * the trailing variant signature and struct offset
5171 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5173 /* Pull out the offset table for the fields array */
5174 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5179 ri = m->fields_size - sz;
5180 r = message_peek_fields(m, &ri, 1, sz, &q);
5184 framing = bus_gvariant_read_word_le(q, sz);
5185 if (framing >= m->fields_size - sz)
5187 if ((m->fields_size - framing) % sz != 0)
5191 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5195 n_offsets = (m->fields_size - framing) / sz;
5198 m->user_body_size = m->body_size;
5201 while (ri < m->fields_size) {
5202 _cleanup_free_ char *sig = NULL;
5203 const char *signature;
5204 uint64_t field_type;
5205 size_t item_size = (size_t) -1;
5207 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5216 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5218 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5222 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5226 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5233 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5238 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5243 where = ri = ALIGN_TO(ri, 8);
5244 item_size = end - ri;
5245 r = message_peek_fields(m, &where, 1, item_size, &q);
5249 b = memrchr(q, 0, item_size);
5253 sig = strndup(b+1, item_size - (b+1-(char*) q));
5258 item_size = b - (char*) q;
5260 r = message_peek_field_signature(m, &ri, 0, &signature);
5265 switch (field_type) {
5267 case _BUS_MESSAGE_HEADER_INVALID:
5270 case BUS_MESSAGE_HEADER_PATH:
5275 if (!streq(signature, "o"))
5278 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5281 case BUS_MESSAGE_HEADER_INTERFACE:
5286 if (!streq(signature, "s"))
5289 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5292 case BUS_MESSAGE_HEADER_MEMBER:
5297 if (!streq(signature, "s"))
5300 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5303 case BUS_MESSAGE_HEADER_ERROR_NAME:
5308 if (!streq(signature, "s"))
5311 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5313 m->error._need_free = -1;
5317 case BUS_MESSAGE_HEADER_DESTINATION:
5322 if (!streq(signature, "s"))
5325 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5328 case BUS_MESSAGE_HEADER_SENDER:
5333 if (!streq(signature, "s"))
5336 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5338 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5339 m->creds.unique_name = (char*) m->sender;
5340 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5346 case BUS_MESSAGE_HEADER_SIGNATURE: {
5350 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5353 if (m->root_container.signature)
5356 if (!streq(signature, "g"))
5359 r = message_peek_field_signature(m, &ri, item_size, &s);
5367 free(m->root_container.signature);
5368 m->root_container.signature = c;
5372 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5374 if (m->reply_cookie != 0)
5377 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5378 /* 64bit on dbus2 */
5380 if (!streq(signature, "t"))
5383 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5387 /* 32bit on dbus1 */
5390 if (!streq(signature, "u"))
5393 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5397 m->reply_cookie = serial;
5400 if (m->reply_cookie == 0)
5405 case BUS_MESSAGE_HEADER_UNIX_FDS:
5409 if (!streq(signature, "u"))
5412 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5416 unix_fds_set = true;
5420 if (!BUS_MESSAGE_IS_GVARIANT(m))
5421 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5430 if (m->n_fds != unix_fds)
5433 switch (m->header->type) {
5435 case SD_BUS_MESSAGE_SIGNAL:
5436 if (!m->path || !m->interface || !m->member)
5439 if (m->reply_cookie != 0)
5444 case SD_BUS_MESSAGE_METHOD_CALL:
5446 if (!m->path || !m->member)
5449 if (m->reply_cookie != 0)
5454 case SD_BUS_MESSAGE_METHOD_RETURN:
5456 if (m->reply_cookie == 0)
5460 case SD_BUS_MESSAGE_METHOD_ERROR:
5462 if (m->reply_cookie == 0 || !m->error.name)
5467 /* Refuse non-local messages that claim they are local */
5468 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5470 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5472 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5475 m->root_container.end = m->user_body_size;
5477 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5478 r = build_struct_offsets(
5480 m->root_container.signature,
5482 &m->root_container.item_size,
5483 &m->root_container.offsets,
5484 &m->root_container.n_offsets);
5489 /* Try to read the error message, but if we can't it's a non-issue */
5490 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5491 (void) sd_bus_message_read(m, "s", &m->error.message);
5496 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5497 assert_return(m, -EINVAL);
5498 assert_return(destination, -EINVAL);
5499 assert_return(!m->sealed, -EPERM);
5500 assert_return(!m->destination, -EEXIST);
5502 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5505 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5509 struct bus_body_part *part;
5515 total = BUS_MESSAGE_SIZE(m);
5521 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5522 MESSAGE_FOREACH_PART(part, i, m)
5523 e = mempcpy(e, part->data, part->size);
5525 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5533 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5540 r = sd_bus_message_enter_container(m, 'a', "s");
5544 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5545 r = strv_extend(l, s);
5552 r = sd_bus_message_exit_container(m);
5559 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5563 assert_return(m, -EINVAL);
5564 assert_return(m->sealed, -EPERM);
5565 assert_return(l, -EINVAL);
5567 r = bus_message_read_strv_extend(m, &strv);
5577 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5578 const char *contents;
5587 r = sd_bus_message_rewind(m, true);
5592 r = sd_bus_message_peek_type(m, &type, &contents);
5598 /* Don't match against arguments after the first one we don't understand */
5599 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5600 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5606 r = sd_bus_message_skip(m, NULL);
5611 if (type == SD_BUS_TYPE_ARRAY) {
5613 r = sd_bus_message_read_strv(m, strv);
5620 r = sd_bus_message_read_basic(m, type, str);
5630 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5631 assert_return(m, EINVAL);
5633 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5636 return sd_bus_error_get_errno(&m->error);
5639 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5640 struct bus_container *c;
5642 assert_return(m, NULL);
5644 c = complete ? &m->root_container : message_get_container(m);
5645 return strempty(c->signature);
5648 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5649 assert_return(m, -EINVAL);
5651 return isempty(m->root_container.signature);
5654 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5655 assert_return(m, -EINVAL);
5657 return streq(strempty(m->root_container.signature), strempty(signature));
5660 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5661 bool done_something = false;
5664 assert_return(m, -EINVAL);
5665 assert_return(source, -EINVAL);
5666 assert_return(!m->sealed, -EPERM);
5667 assert_return(source->sealed, -EPERM);
5670 const char *contents;
5685 r = sd_bus_message_peek_type(source, &type, &contents);
5691 done_something = true;
5693 if (bus_type_is_container(type) > 0) {
5695 r = sd_bus_message_enter_container(source, type, contents);
5699 r = sd_bus_message_open_container(m, type, contents);
5703 r = sd_bus_message_copy(m, source, true);
5707 r = sd_bus_message_close_container(m);
5711 r = sd_bus_message_exit_container(source);
5718 r = sd_bus_message_read_basic(source, type, &basic);
5724 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5725 type == SD_BUS_TYPE_SIGNATURE ||
5726 type == SD_BUS_TYPE_STRING)
5727 r = sd_bus_message_append_basic(m, type, basic.string);
5729 r = sd_bus_message_append_basic(m, type, &basic);
5736 return done_something;
5739 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5744 assert_return(m, -EINVAL);
5745 assert_return(m->sealed, -EPERM);
5746 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5747 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5748 assert_return(type || contents, -EINVAL);
5749 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5751 r = sd_bus_message_peek_type(m, &t, &c);
5755 if (type != 0 && type != t)
5758 if (contents && !streq_ptr(contents, c))
5764 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5765 assert_return(m, NULL);
5770 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5771 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5779 switch ((*m)->header->type) {
5781 case SD_BUS_MESSAGE_SIGNAL:
5782 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5788 case SD_BUS_MESSAGE_METHOD_CALL:
5789 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5795 case SD_BUS_MESSAGE_METHOD_RETURN:
5796 case SD_BUS_MESSAGE_METHOD_ERROR:
5798 n = message_new(bus, (*m)->header->type);
5802 n->reply_cookie = (*m)->reply_cookie;
5804 r = message_append_reply_cookie(n, n->reply_cookie);
5808 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5809 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5813 n->error._need_free = -1;
5822 if ((*m)->destination && !n->destination) {
5823 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5828 if ((*m)->sender && !n->sender) {
5829 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5834 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5836 r = sd_bus_message_copy(n, *m, true);
5840 timeout = (*m)->timeout;
5841 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5842 timeout = BUS_DEFAULT_TIMEOUT;
5844 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5848 sd_bus_message_unref(*m);
5855 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5859 assert_return(!m->sealed, -EPERM);
5860 assert_return(!m->sender, -EPERM);
5862 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5865 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5866 assert_return(m, -EINVAL);
5867 assert_return(priority, -EINVAL);
5869 *priority = m->priority;
5873 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5874 assert_return(m, -EINVAL);
5875 assert_return(!m->sealed, -EPERM);
5877 m->priority = priority;