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 (isempty(c->signature)) {
2213 /* The unary type is encoded as fixed 1 byte padding */
2214 a = message_extend_body(m, 1, 1, add_offset, false);
2219 } else if (n_variable <= 0) {
2222 /* Structures with fixed-size members only have to be
2223 * fixed-size themselves. But gvariant requires all fixed-size
2224 * elements to be sized a multiple of their alignment. Hence,
2225 * we must *always* add final padding after the last member so
2226 * the overall size of the structure is properly aligned. */
2228 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2230 assert(alignment > 0);
2232 a = message_extend_body(m, alignment, 0, add_offset, false);
2239 assert(c->offsets[c->n_offsets-1] == m->body_size);
2241 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2243 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2247 p = strempty(c->signature);
2248 for (i = 0, j = 0; i < c->n_offsets; i++) {
2252 r = signature_element_length(p, &n);
2263 r = bus_gvariant_is_fixed_size(t);
2266 if (r > 0 || p[0] == 0)
2270 k = n_variable - 1 - j;
2272 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2281 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2282 struct bus_container *c;
2285 assert_return(m, -EINVAL);
2286 assert_return(!m->sealed, -EPERM);
2287 assert_return(m->n_containers > 0, -EINVAL);
2288 assert_return(!m->poisoned, -ESTALE);
2290 c = message_get_container(m);
2292 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2293 if (c->signature && c->signature[c->index] != 0)
2298 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2299 r = bus_message_close_array(m, c);
2300 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2301 r = bus_message_close_variant(m, c);
2302 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2303 r = bus_message_close_struct(m, c, true);
2305 assert_not_reached("Unknown container type");
2319 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2326 stack[*i].types = types;
2327 stack[*i].n_struct = n_struct;
2328 stack[*i].n_array = n_array;
2334 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2345 *types = stack[*i].types;
2346 *n_struct = stack[*i].n_struct;
2347 *n_array = stack[*i].n_array;
2352 int bus_message_append_ap(
2357 unsigned n_array, n_struct;
2358 TypeStack stack[BUS_CONTAINER_DEPTH];
2359 unsigned stack_ptr = 0;
2367 n_array = (unsigned) -1;
2368 n_struct = strlen(types);
2373 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2374 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2380 r = sd_bus_message_close_container(m);
2388 if (n_array != (unsigned) -1)
2397 case SD_BUS_TYPE_BYTE: {
2400 x = (uint8_t) va_arg(ap, int);
2401 r = sd_bus_message_append_basic(m, *t, &x);
2405 case SD_BUS_TYPE_BOOLEAN:
2406 case SD_BUS_TYPE_INT32:
2407 case SD_BUS_TYPE_UINT32:
2408 case SD_BUS_TYPE_UNIX_FD: {
2411 /* We assume a boolean is the same as int32_t */
2412 assert_cc(sizeof(int32_t) == sizeof(int));
2414 x = va_arg(ap, uint32_t);
2415 r = sd_bus_message_append_basic(m, *t, &x);
2419 case SD_BUS_TYPE_INT16:
2420 case SD_BUS_TYPE_UINT16: {
2423 x = (uint16_t) va_arg(ap, int);
2424 r = sd_bus_message_append_basic(m, *t, &x);
2428 case SD_BUS_TYPE_INT64:
2429 case SD_BUS_TYPE_UINT64: {
2432 x = va_arg(ap, uint64_t);
2433 r = sd_bus_message_append_basic(m, *t, &x);
2437 case SD_BUS_TYPE_DOUBLE: {
2440 x = va_arg(ap, double);
2441 r = sd_bus_message_append_basic(m, *t, &x);
2445 case SD_BUS_TYPE_STRING:
2446 case SD_BUS_TYPE_OBJECT_PATH:
2447 case SD_BUS_TYPE_SIGNATURE: {
2450 x = va_arg(ap, const char*);
2451 r = sd_bus_message_append_basic(m, *t, x);
2455 case SD_BUS_TYPE_ARRAY: {
2458 r = signature_element_length(t + 1, &k);
2464 memcpy(s, t + 1, k);
2467 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2472 if (n_array == (unsigned) -1) {
2477 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2483 n_array = va_arg(ap, unsigned);
2488 case SD_BUS_TYPE_VARIANT: {
2491 s = va_arg(ap, const char*);
2495 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2499 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2504 n_struct = strlen(s);
2505 n_array = (unsigned) -1;
2510 case SD_BUS_TYPE_STRUCT_BEGIN:
2511 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2514 r = signature_element_length(t, &k);
2521 memcpy(s, t + 1, k - 2);
2524 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2529 if (n_array == (unsigned) -1) {
2534 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2540 n_array = (unsigned) -1;
2556 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2560 assert_return(m, -EINVAL);
2561 assert_return(types, -EINVAL);
2562 assert_return(!m->sealed, -EPERM);
2563 assert_return(!m->poisoned, -ESTALE);
2565 va_start(ap, types);
2566 r = bus_message_append_ap(m, types, ap);
2572 _public_ int sd_bus_message_append_array_space(
2582 assert_return(m, -EINVAL);
2583 assert_return(!m->sealed, -EPERM);
2584 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2585 assert_return(ptr || size == 0, -EINVAL);
2586 assert_return(!m->poisoned, -ESTALE);
2588 /* alignment and size of the trivial types (except bool) is
2589 * identical for gvariant and dbus1 marshalling */
2590 align = bus_type_get_alignment(type);
2591 sz = bus_type_get_size(type);
2593 assert_se(align > 0);
2599 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2603 a = message_extend_body(m, align, size, false, false);
2607 r = sd_bus_message_close_container(m);
2615 _public_ int sd_bus_message_append_array(
2623 assert_return(m, -EINVAL);
2624 assert_return(!m->sealed, -EPERM);
2625 assert_return(bus_type_is_trivial(type), -EINVAL);
2626 assert_return(ptr || size == 0, -EINVAL);
2627 assert_return(!m->poisoned, -ESTALE);
2629 r = sd_bus_message_append_array_space(m, type, size, &p);
2634 memcpy(p, ptr, size);
2639 _public_ int sd_bus_message_append_array_iovec(
2642 const struct iovec *iov,
2650 assert_return(m, -EINVAL);
2651 assert_return(!m->sealed, -EPERM);
2652 assert_return(bus_type_is_trivial(type), -EINVAL);
2653 assert_return(iov || n == 0, -EINVAL);
2654 assert_return(!m->poisoned, -ESTALE);
2656 size = IOVEC_TOTAL_SIZE(iov, n);
2658 r = sd_bus_message_append_array_space(m, type, size, &p);
2662 for (i = 0; i < n; i++) {
2664 if (iov[i].iov_base)
2665 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2667 memzero(p, iov[i].iov_len);
2669 p = (uint8_t*) p + iov[i].iov_len;
2675 _public_ int sd_bus_message_append_array_memfd(
2682 _cleanup_close_ int copy_fd = -1;
2683 struct bus_body_part *part;
2689 assert_return(m, -EINVAL);
2690 assert_return(memfd >= 0, -EINVAL);
2691 assert_return(bus_type_is_trivial(type), -EINVAL);
2692 assert_return(size > 0, -EINVAL);
2693 assert_return(!m->sealed, -EPERM);
2694 assert_return(!m->poisoned, -ESTALE);
2696 r = memfd_set_sealed(memfd);
2700 copy_fd = dup(memfd);
2704 r = memfd_get_size(memfd, &real_size);
2708 if (offset == 0 && size == (uint64_t) -1)
2710 else if (offset + size > real_size)
2713 align = bus_type_get_alignment(type);
2714 sz = bus_type_get_size(type);
2716 assert_se(align > 0);
2719 if (offset % align != 0)
2725 if (size > (uint64_t) (uint32_t) -1)
2728 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2732 a = message_extend_body(m, align, 0, false, false);
2736 part = message_append_part(m);
2740 part->memfd = copy_fd;
2741 part->memfd_offset = offset;
2742 part->sealed = true;
2746 m->body_size += size;
2747 message_extend_containers(m, size);
2749 return sd_bus_message_close_container(m);
2752 _public_ int sd_bus_message_append_string_memfd(
2758 _cleanup_close_ int copy_fd = -1;
2759 struct bus_body_part *part;
2760 struct bus_container *c;
2765 assert_return(m, -EINVAL);
2766 assert_return(memfd >= 0, -EINVAL);
2767 assert_return(size > 0, -EINVAL);
2768 assert_return(!m->sealed, -EPERM);
2769 assert_return(!m->poisoned, -ESTALE);
2771 r = memfd_set_sealed(memfd);
2775 copy_fd = dup(memfd);
2779 r = memfd_get_size(memfd, &real_size);
2783 if (offset == 0 && size == (uint64_t) -1)
2785 else if (offset + size > real_size)
2788 /* We require this to be NUL terminated */
2792 if (size > (uint64_t) (uint32_t) -1)
2795 c = message_get_container(m);
2796 if (c->signature && c->signature[c->index]) {
2797 /* Container signature is already set */
2799 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2804 /* Maybe we can append to the signature? But only if this is the top-level container */
2805 if (c->enclosing != 0)
2808 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2815 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2816 a = message_extend_body(m, 4, 4, false, false);
2820 *(uint32_t*) a = size - 1;
2823 part = message_append_part(m);
2827 part->memfd = copy_fd;
2828 part->memfd_offset = offset;
2829 part->sealed = true;
2833 m->body_size += size;
2834 message_extend_containers(m, size);
2836 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2837 r = message_add_offset(m, m->body_size);
2844 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2850 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2854 assert_return(m, -EINVAL);
2855 assert_return(!m->sealed, -EPERM);
2856 assert_return(!m->poisoned, -ESTALE);
2858 r = sd_bus_message_open_container(m, 'a', "s");
2862 STRV_FOREACH(i, l) {
2863 r = sd_bus_message_append_basic(m, 's', *i);
2868 return sd_bus_message_close_container(m);
2871 static int bus_message_close_header(sd_bus_message *m) {
2875 /* The actual user data is finished now, we just complete the
2876 variant and struct now (at least on gvariant). Remember
2877 this position, so that during parsing we know where to to
2878 put the outer container end. */
2879 m->user_body_size = m->body_size;
2881 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2882 const char *signature;
2886 /* Add offset table to end of fields array */
2887 if (m->n_header_offsets >= 1) {
2891 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2893 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2894 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2898 for (i = 0; i < m->n_header_offsets; i++)
2899 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2902 /* Add gvariant NUL byte plus signature to the end of
2903 * the body, followed by the final offset pointing to
2904 * the end of the fields array */
2906 signature = strempty(m->root_container.signature);
2907 l = strlen(signature);
2909 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2910 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2915 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2916 memcpy((uint8_t*) d + 2, signature, l);
2917 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2919 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2922 m->footer_accessible = 1 + l + 2 + sz;
2924 m->header->dbus1.fields_size = m->fields_size;
2925 m->header->dbus1.body_size = m->body_size;
2931 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2932 struct bus_body_part *part;
2942 if (m->n_containers > 0)
2948 if (cookie > 0xffffffffULL &&
2949 !BUS_MESSAGE_IS_GVARIANT(m))
2952 /* In vtables the return signature of method calls is listed,
2953 * let's check if they match if this is a response */
2954 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2955 m->enforced_reply_signature &&
2956 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2959 /* If gvariant marshalling is used we need to close the body structure */
2960 r = bus_message_close_struct(m, &m->root_container, false);
2964 /* If there's a non-trivial signature set, then add it in
2965 * here, but only on dbus1 */
2966 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2967 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2973 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2978 r = bus_message_close_header(m);
2982 if (BUS_MESSAGE_IS_GVARIANT(m))
2983 m->header->dbus2.cookie = cookie;
2985 m->header->dbus1.serial = (uint32_t) cookie;
2987 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2989 /* Add padding at the end of the fields part, since we know
2990 * the body needs to start at an 8 byte alignment. We made
2991 * sure we allocated enough space for this, so all we need to
2992 * do here is to zero it out. */
2993 a = ALIGN8(m->fields_size) - m->fields_size;
2995 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2997 /* If this is something we can send as memfd, then let's seal
2998 the memfd now. Note that we can send memfds as payload only
2999 for directed messages, and not for broadcasts. */
3000 if (m->destination && m->bus->use_memfd) {
3001 MESSAGE_FOREACH_PART(part, i, m)
3002 if (part->memfd >= 0 &&
3004 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3005 part != m->body_end) { /* The last part may never be sent as memfd */
3008 /* Try to seal it if that makes
3009 * sense. First, unmap our own map to
3010 * make sure we don't keep it busy. */
3011 bus_body_part_unmap(part);
3013 /* Then, sync up real memfd size */
3015 r = memfd_set_size(part->memfd, sz);
3019 /* Finally, try to seal */
3020 if (memfd_set_sealed(part->memfd) >= 0)
3021 part->sealed = true;
3025 m->root_container.end = m->user_body_size;
3026 m->root_container.index = 0;
3027 m->root_container.offset_index = 0;
3028 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3035 int bus_body_part_map(struct bus_body_part *part) {
3044 if (part->size <= 0)
3047 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3048 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3049 static const uint8_t zeroes[7] = { };
3050 part->data = (void*) zeroes;
3054 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3055 psz = PAGE_ALIGN(part->size + shift);
3057 if (part->memfd >= 0)
3058 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3059 else if (part->is_zero)
3060 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3064 if (p == MAP_FAILED)
3068 part->mmap_begin = p;
3069 part->data = (uint8_t*) p + shift;
3070 part->munmap_this = true;
3075 void bus_body_part_unmap(struct bus_body_part *part) {
3079 if (part->memfd < 0)
3082 if (!part->mmap_begin)
3085 if (!part->munmap_this)
3088 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3090 part->mmap_begin = NULL;
3093 part->munmap_this = false;
3098 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3099 size_t k, start, end;
3104 start = ALIGN_TO((size_t) *rindex, align);
3105 end = start + nbytes;
3110 /* Verify that padding is 0 */
3111 for (k = *rindex; k < start; k++)
3112 if (((const uint8_t*) p)[k] != 0)
3116 *r = (uint8_t*) p + start;
3123 static bool message_end_of_signature(sd_bus_message *m) {
3124 struct bus_container *c;
3128 c = message_get_container(m);
3129 return !c->signature || c->signature[c->index] == 0;
3132 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3133 struct bus_container *c;
3137 c = message_get_container(m);
3138 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3141 if (BUS_MESSAGE_IS_GVARIANT(m))
3142 return index >= c->end;
3144 assert(c->array_size);
3145 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3149 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3150 assert_return(m, -EINVAL);
3151 assert_return(m->sealed, -EPERM);
3153 if (complete && m->n_containers > 0)
3156 if (message_end_of_signature(m))
3159 if (message_end_of_array(m, m->rindex))
3165 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3166 struct bus_body_part *part;
3172 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3173 part = m->cached_rindex_part;
3174 begin = m->cached_rindex_part_begin;
3184 if (index + sz <= begin + part->size) {
3186 r = bus_body_part_map(part);
3191 *p = (uint8_t*) part->data + index - begin;
3193 m->cached_rindex_part = part;
3194 m->cached_rindex_part_begin = begin;
3199 begin += part->size;
3206 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3213 if (!BUS_MESSAGE_IS_GVARIANT(m))
3216 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3219 sz = bus_gvariant_get_size(c->signature);
3223 if (c->offset_index+1 >= c->n_offsets)
3226 /* Variable-size array */
3228 alignment = bus_gvariant_get_alignment(c->signature);
3229 assert(alignment > 0);
3231 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3232 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3235 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3238 /* Fixed-size array */
3239 *rindex = c->begin + (c->offset_index+1) * sz;
3245 } else if (c->enclosing == 0 ||
3246 c->enclosing == SD_BUS_TYPE_STRUCT ||
3247 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3252 if (c->offset_index+1 >= c->n_offsets)
3255 r = signature_element_length(c->signature + c->index, &n);
3259 r = signature_element_length(c->signature + c->index + n, &j);
3264 memcpy(t, c->signature + c->index + n, j);
3267 alignment = bus_gvariant_get_alignment(t);
3270 assert(alignment > 0);
3272 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3273 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3277 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3280 assert_not_reached("Unknown container type");
3285 /* Reached the end */
3292 static int message_peek_body(
3299 size_t k, start, end, padding;
3300 struct bus_body_part *part;
3307 start = ALIGN_TO((size_t) *rindex, align);
3308 padding = start - *rindex;
3309 end = start + nbytes;
3311 if (end > m->user_body_size)
3314 part = find_part(m, *rindex, padding, (void**) &q);
3319 /* Verify padding */
3320 for (k = 0; k < padding; k++)
3325 part = find_part(m, start, nbytes, (void**) &q);
3326 if (!part || (nbytes > 0 && !q))
3337 static bool validate_nul(const char *s, size_t l) {
3339 /* Check for NUL chars in the string */
3340 if (memchr(s, 0, l))
3343 /* Check for NUL termination */
3350 static bool validate_string(const char *s, size_t l) {
3352 if (!validate_nul(s, l))
3355 /* Check if valid UTF8 */
3356 if (!utf8_is_valid(s))
3362 static bool validate_signature(const char *s, size_t l) {
3364 if (!validate_nul(s, l))
3367 /* Check if valid signature */
3368 if (!signature_is_valid(s, true))
3374 static bool validate_object_path(const char *s, size_t l) {
3376 if (!validate_nul(s, l))
3379 if (!object_path_is_valid(s))
3385 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3386 struct bus_container *c;
3391 assert_return(m, -EINVAL);
3392 assert_return(m->sealed, -EPERM);
3393 assert_return(bus_type_is_basic(type), -EINVAL);
3395 if (message_end_of_signature(m))
3398 if (message_end_of_array(m, m->rindex))
3401 c = message_get_container(m);
3402 if (c->signature[c->index] != type)
3407 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3409 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3412 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3416 if (type == SD_BUS_TYPE_STRING)
3417 ok = validate_string(q, c->item_size-1);
3418 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3419 ok = validate_object_path(q, c->item_size-1);
3421 ok = validate_signature(q, c->item_size-1);
3427 *(const char**) p = q;
3431 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3433 if ((size_t) sz != c->item_size)
3436 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3439 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3445 case SD_BUS_TYPE_BYTE:
3447 *(uint8_t*) p = *(uint8_t*) q;
3450 case SD_BUS_TYPE_BOOLEAN:
3452 *(int*) p = !!*(uint8_t*) q;
3455 case SD_BUS_TYPE_INT16:
3456 case SD_BUS_TYPE_UINT16:
3458 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3461 case SD_BUS_TYPE_INT32:
3462 case SD_BUS_TYPE_UINT32:
3464 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3467 case SD_BUS_TYPE_INT64:
3468 case SD_BUS_TYPE_UINT64:
3469 case SD_BUS_TYPE_DOUBLE:
3471 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3474 case SD_BUS_TYPE_UNIX_FD: {
3477 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3482 *(int*) p = m->fds[j];
3488 assert_not_reached("unexpected type");
3492 r = container_next_item(m, c, &rindex);
3497 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3501 r = message_peek_body(m, &rindex, 4, 4, &q);
3505 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3506 r = message_peek_body(m, &rindex, 1, l+1, &q);
3510 if (type == SD_BUS_TYPE_OBJECT_PATH)
3511 ok = validate_object_path(q, l);
3513 ok = validate_string(q, l);
3518 *(const char**) p = q;
3520 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3523 r = message_peek_body(m, &rindex, 1, 1, &q);
3528 r = message_peek_body(m, &rindex, 1, l+1, &q);
3532 if (!validate_signature(q, l))
3536 *(const char**) p = q;
3541 align = bus_type_get_alignment(type);
3544 sz = bus_type_get_size(type);
3547 r = message_peek_body(m, &rindex, align, sz, &q);
3553 case SD_BUS_TYPE_BYTE:
3555 *(uint8_t*) p = *(uint8_t*) q;
3558 case SD_BUS_TYPE_BOOLEAN:
3560 *(int*) p = !!*(uint32_t*) q;
3563 case SD_BUS_TYPE_INT16:
3564 case SD_BUS_TYPE_UINT16:
3566 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3569 case SD_BUS_TYPE_INT32:
3570 case SD_BUS_TYPE_UINT32:
3572 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3575 case SD_BUS_TYPE_INT64:
3576 case SD_BUS_TYPE_UINT64:
3577 case SD_BUS_TYPE_DOUBLE:
3579 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3582 case SD_BUS_TYPE_UNIX_FD: {
3585 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3590 *(int*) p = m->fds[j];
3595 assert_not_reached("Unknown basic type...");
3602 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3608 static int bus_message_enter_array(
3610 struct bus_container *c,
3611 const char *contents,
3612 uint32_t **array_size,
3615 size_t *n_offsets) {
3629 if (!signature_is_single(contents, true))
3632 if (!c->signature || c->signature[c->index] == 0)
3635 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3638 if (!startswith(c->signature + c->index + 1, contents))
3643 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3646 r = message_peek_body(m, &rindex, 4, 4, &q);
3650 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3653 alignment = bus_type_get_alignment(contents[0]);
3657 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3661 *array_size = (uint32_t*) q;
3663 } else if (c->item_size <= 0) {
3665 /* gvariant: empty array */
3670 } else if (bus_gvariant_is_fixed_size(contents)) {
3672 /* gvariant: fixed length array */
3673 *item_size = bus_gvariant_get_size(contents);
3678 size_t where, p = 0, framing, sz;
3681 /* gvariant: variable length array */
3682 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3684 where = rindex + c->item_size - sz;
3685 r = message_peek_body(m, &where, 1, sz, &q);
3689 framing = bus_gvariant_read_word_le(q, sz);
3690 if (framing > c->item_size - sz)
3692 if ((c->item_size - framing) % sz != 0)
3695 *n_offsets = (c->item_size - framing) / sz;
3697 where = rindex + framing;
3698 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3702 *offsets = new(size_t, *n_offsets);
3706 for (i = 0; i < *n_offsets; i++) {
3709 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3710 if (x > c->item_size - sz)
3715 (*offsets)[i] = rindex + x;
3719 *item_size = (*offsets)[0] - rindex;
3724 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3725 c->index += 1 + strlen(contents);
3730 static int bus_message_enter_variant(
3732 struct bus_container *c,
3733 const char *contents,
3734 size_t *item_size) {
3746 if (!signature_is_single(contents, false))
3749 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3752 if (!c->signature || c->signature[c->index] == 0)
3755 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3760 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3763 k = strlen(contents);
3764 if (1+k > c->item_size)
3767 where = rindex + c->item_size - (1+k);
3768 r = message_peek_body(m, &where, 1, 1+k, &q);
3772 if (*(char*) q != 0)
3775 if (memcmp((uint8_t*) q+1, contents, k))
3778 *item_size = c->item_size - (1+k);
3781 r = message_peek_body(m, &rindex, 1, 1, &q);
3786 r = message_peek_body(m, &rindex, 1, l+1, &q);
3790 if (!validate_signature(q, l))
3793 if (!streq(q, contents))
3799 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3805 static int build_struct_offsets(
3807 const char *signature,
3811 size_t *n_offsets) {
3813 unsigned n_variable = 0, n_total = 0, v;
3814 size_t previous = 0, where;
3825 if (isempty(signature)) {
3826 /* Unary type is encoded as *fixed* 1 byte padding */
3827 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3831 if (*(uint8_t *) q != 0)
3840 sz = bus_gvariant_determine_word_size(size, 0);
3844 /* First, loop over signature and count variable elements and
3845 * elements in general. We use this to know how large the
3846 * offset array is at the end of the structure. Note that
3847 * GVariant only stores offsets for all variable size elements
3848 * that are not the last item. */
3854 r = signature_element_length(p, &n);
3863 r = bus_gvariant_is_fixed_size(t);
3868 if (r == 0 && p[n] != 0) /* except the last item */
3875 if (size < n_variable * sz)
3878 where = m->rindex + size - (n_variable * sz);
3879 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3885 *offsets = new(size_t, n_total);
3891 /* Second, loop again and build an offset table */
3897 r = signature_element_length(p, &n);
3906 k = bus_gvariant_get_size(t);
3914 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3917 if (m->rindex + x < previous)
3920 /* The last item's end
3921 * is determined from
3924 x = size - (n_variable * sz);
3926 offset = m->rindex + x;
3932 align = bus_gvariant_get_alignment(t);
3935 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3939 previous = (*offsets)[(*n_offsets)++] = offset;
3944 assert(*n_offsets == n_total);
3946 *item_size = (*offsets)[0] - m->rindex;
3950 static int enter_struct_or_dict_entry(
3952 struct bus_container *c,
3953 const char *contents,
3956 size_t *n_offsets) {
3967 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3970 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3975 /* gvariant with contents */
3976 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3981 static int bus_message_enter_struct(
3983 struct bus_container *c,
3984 const char *contents,
3987 size_t *n_offsets) {
3999 if (!signature_is_valid(contents, false))
4002 if (!c->signature || c->signature[c->index] == 0)
4005 l = strlen(contents);
4007 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4008 !startswith(c->signature + c->index + 1, contents) ||
4009 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4012 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4016 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4017 c->index += 1 + l + 1;
4022 static int bus_message_enter_dict_entry(
4024 struct bus_container *c,
4025 const char *contents,
4028 size_t *n_offsets) {
4037 if (!signature_is_pair(contents))
4040 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4043 if (!c->signature || c->signature[c->index] == 0)
4046 l = strlen(contents);
4048 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4049 !startswith(c->signature + c->index + 1, contents) ||
4050 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4053 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4057 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4058 c->index += 1 + l + 1;
4063 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4065 const char *contents) {
4066 struct bus_container *c, *w;
4067 uint32_t *array_size = NULL;
4070 size_t *offsets = NULL;
4071 size_t n_offsets = 0, item_size = 0;
4074 assert_return(m, -EINVAL);
4075 assert_return(m->sealed, -EPERM);
4076 assert_return(type != 0 || !contents, -EINVAL);
4078 if (type == 0 || !contents) {
4082 /* Allow entering into anonymous containers */
4083 r = sd_bus_message_peek_type(m, &tt, &cc);
4087 if (type != 0 && type != tt)
4090 if (contents && !streq(contents, cc))
4098 * We enforce a global limit on container depth, that is much
4099 * higher than the 32 structs and 32 arrays the specification
4100 * mandates. This is simpler to implement for us, and we need
4101 * this only to ensure our container array doesn't grow
4102 * without bounds. We are happy to return any data from a
4103 * message as long as the data itself is valid, even if the
4104 * overall message might be not.
4106 * Note that the message signature is validated when
4107 * parsing the headers, and that validation does check the
4110 * Note that the specification defines no limits on the depth
4111 * of stacked variants, but we do.
4113 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4116 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4119 if (message_end_of_signature(m))
4122 if (message_end_of_array(m, m->rindex))
4125 c = message_get_container(m);
4127 signature = strdup(contents);
4131 c->saved_index = c->index;
4134 if (type == SD_BUS_TYPE_ARRAY)
4135 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4136 else if (type == SD_BUS_TYPE_VARIANT)
4137 r = bus_message_enter_variant(m, c, contents, &item_size);
4138 else if (type == SD_BUS_TYPE_STRUCT)
4139 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4140 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4141 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4151 /* OK, let's fill it in */
4152 w = m->containers + m->n_containers++;
4153 w->enclosing = type;
4154 w->signature = signature;
4155 w->peeked_signature = NULL;
4159 w->begin = m->rindex;
4161 /* Unary type has fixed size of 1, but virtual size of 0 */
4162 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4163 type == SD_BUS_TYPE_STRUCT &&
4165 w->end = m->rindex + 0;
4167 w->end = m->rindex + c->item_size;
4169 w->array_size = array_size;
4170 w->item_size = item_size;
4171 w->offsets = offsets;
4172 w->n_offsets = n_offsets;
4173 w->offset_index = 0;
4178 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4179 struct bus_container *c;
4183 assert_return(m, -EINVAL);
4184 assert_return(m->sealed, -EPERM);
4185 assert_return(m->n_containers > 0, -ENXIO);
4187 c = message_get_container(m);
4189 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4190 if (c->signature && c->signature[c->index] != 0)
4194 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4195 if (m->rindex < c->end)
4198 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4201 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4202 if (c->begin + l != m->rindex)
4207 free(c->peeked_signature);
4211 c = message_get_container(m);
4214 c->index = c->saved_index;
4215 r = container_next_item(m, c, &m->rindex);
4223 static void message_quit_container(sd_bus_message *m) {
4224 struct bus_container *c;
4228 assert(m->n_containers > 0);
4230 c = message_get_container(m);
4233 assert(m->rindex >= c->before);
4234 m->rindex = c->before;
4236 /* Free container */
4241 /* Correct index of new top-level container */
4242 c = message_get_container(m);
4243 c->index = c->saved_index;
4246 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4247 struct bus_container *c;
4250 assert_return(m, -EINVAL);
4251 assert_return(m->sealed, -EPERM);
4253 if (message_end_of_signature(m))
4256 if (message_end_of_array(m, m->rindex))
4259 c = message_get_container(m);
4261 if (bus_type_is_basic(c->signature[c->index])) {
4265 *type = c->signature[c->index];
4269 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4275 r = signature_element_length(c->signature+c->index+1, &l);
4281 sig = strndup(c->signature + c->index + 1, l);
4285 free(c->peeked_signature);
4286 *contents = c->peeked_signature = sig;
4290 *type = SD_BUS_TYPE_ARRAY;
4295 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4296 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4302 r = signature_element_length(c->signature+c->index, &l);
4307 sig = strndup(c->signature + c->index + 1, l - 2);
4311 free(c->peeked_signature);
4312 *contents = c->peeked_signature = sig;
4316 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4321 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4325 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4328 if (c->item_size < 2)
4331 /* Look for the NUL delimiter that
4332 separates the payload from the
4333 signature. Since the body might be
4334 in a different part that then the
4335 signature we map byte by byte. */
4337 for (k = 2; k <= c->item_size; k++) {
4340 where = m->rindex + c->item_size - k;
4341 r = message_peek_body(m, &where, 1, k, &q);
4345 if (*(char*) q == 0)
4349 if (k > c->item_size)
4352 free(c->peeked_signature);
4353 c->peeked_signature = strndup((char*) q + 1, k - 1);
4354 if (!c->peeked_signature)
4357 if (!signature_is_valid(c->peeked_signature, true))
4360 *contents = c->peeked_signature;
4365 r = message_peek_body(m, &rindex, 1, 1, &q);
4370 r = message_peek_body(m, &rindex, 1, l+1, &q);
4374 if (!validate_signature(q, l))
4382 *type = SD_BUS_TYPE_VARIANT;
4397 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4398 struct bus_container *c;
4400 assert_return(m, -EINVAL);
4401 assert_return(m->sealed, -EPERM);
4404 message_reset_containers(m);
4407 c = message_get_container(m);
4409 c = message_get_container(m);
4411 c->offset_index = 0;
4413 m->rindex = c->begin;
4416 c->offset_index = 0;
4417 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4419 return !isempty(c->signature);
4422 static int message_read_ap(
4427 unsigned n_array, n_struct;
4428 TypeStack stack[BUS_CONTAINER_DEPTH];
4429 unsigned stack_ptr = 0;
4430 unsigned n_loop = 0;
4438 /* Ideally, we'd just call ourselves recursively on every
4439 * complex type. However, the state of a va_list that is
4440 * passed to a function is undefined after that function
4441 * returns. This means we need to docode the va_list linearly
4442 * in a single stackframe. We hence implement our own
4443 * home-grown stack in an array. */
4445 n_array = (unsigned) -1; /* length of current array entries */
4446 n_struct = strlen(types); /* length of current struct contents signature */
4453 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4454 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4460 r = sd_bus_message_exit_container(m);
4468 if (n_array != (unsigned) -1)
4477 case SD_BUS_TYPE_BYTE:
4478 case SD_BUS_TYPE_BOOLEAN:
4479 case SD_BUS_TYPE_INT16:
4480 case SD_BUS_TYPE_UINT16:
4481 case SD_BUS_TYPE_INT32:
4482 case SD_BUS_TYPE_UINT32:
4483 case SD_BUS_TYPE_INT64:
4484 case SD_BUS_TYPE_UINT64:
4485 case SD_BUS_TYPE_DOUBLE:
4486 case SD_BUS_TYPE_STRING:
4487 case SD_BUS_TYPE_OBJECT_PATH:
4488 case SD_BUS_TYPE_SIGNATURE:
4489 case SD_BUS_TYPE_UNIX_FD: {
4492 p = va_arg(ap, void*);
4493 r = sd_bus_message_read_basic(m, *t, p);
4506 case SD_BUS_TYPE_ARRAY: {
4509 r = signature_element_length(t + 1, &k);
4515 memcpy(s, t + 1, k);
4518 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4529 if (n_array == (unsigned) -1) {
4534 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4540 n_array = va_arg(ap, unsigned);
4545 case SD_BUS_TYPE_VARIANT: {
4548 s = va_arg(ap, const char *);
4552 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4562 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4567 n_struct = strlen(s);
4568 n_array = (unsigned) -1;
4573 case SD_BUS_TYPE_STRUCT_BEGIN:
4574 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4577 r = signature_element_length(t, &k);
4583 memcpy(s, t + 1, k - 2);
4586 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4596 if (n_array == (unsigned) -1) {
4601 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4607 n_array = (unsigned) -1;
4620 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4624 assert_return(m, -EINVAL);
4625 assert_return(m->sealed, -EPERM);
4626 assert_return(types, -EINVAL);
4628 va_start(ap, types);
4629 r = message_read_ap(m, types, ap);
4635 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4638 assert_return(m, -EINVAL);
4639 assert_return(m->sealed, -EPERM);
4641 /* If types is NULL, read exactly one element */
4643 struct bus_container *c;
4646 if (message_end_of_signature(m))
4649 if (message_end_of_array(m, m->rindex))
4652 c = message_get_container(m);
4654 r = signature_element_length(c->signature + c->index, &l);
4658 types = strndupa(c->signature + c->index, l);
4663 case 0: /* Nothing to drop */
4666 case SD_BUS_TYPE_BYTE:
4667 case SD_BUS_TYPE_BOOLEAN:
4668 case SD_BUS_TYPE_INT16:
4669 case SD_BUS_TYPE_UINT16:
4670 case SD_BUS_TYPE_INT32:
4671 case SD_BUS_TYPE_UINT32:
4672 case SD_BUS_TYPE_INT64:
4673 case SD_BUS_TYPE_UINT64:
4674 case SD_BUS_TYPE_DOUBLE:
4675 case SD_BUS_TYPE_STRING:
4676 case SD_BUS_TYPE_OBJECT_PATH:
4677 case SD_BUS_TYPE_SIGNATURE:
4678 case SD_BUS_TYPE_UNIX_FD:
4680 r = sd_bus_message_read_basic(m, *types, NULL);
4684 r = sd_bus_message_skip(m, types + 1);
4690 case SD_BUS_TYPE_ARRAY: {
4693 r = signature_element_length(types + 1, &k);
4699 memcpy(s, types+1, k);
4702 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4707 r = sd_bus_message_skip(m, s);
4714 r = sd_bus_message_exit_container(m);
4719 r = sd_bus_message_skip(m, types + 1 + k);
4726 case SD_BUS_TYPE_VARIANT: {
4727 const char *contents;
4730 r = sd_bus_message_peek_type(m, &x, &contents);
4734 if (x != SD_BUS_TYPE_VARIANT)
4737 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4741 r = sd_bus_message_skip(m, contents);
4746 r = sd_bus_message_exit_container(m);
4750 r = sd_bus_message_skip(m, types + 1);
4757 case SD_BUS_TYPE_STRUCT_BEGIN:
4758 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4761 r = signature_element_length(types, &k);
4767 memcpy(s, types+1, k-2);
4770 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4774 r = sd_bus_message_skip(m, s);
4778 r = sd_bus_message_exit_container(m);
4783 r = sd_bus_message_skip(m, types + k);
4795 _public_ int sd_bus_message_read_array(
4801 struct bus_container *c;
4807 assert_return(m, -EINVAL);
4808 assert_return(m->sealed, -EPERM);
4809 assert_return(bus_type_is_trivial(type), -EINVAL);
4810 assert_return(ptr, -EINVAL);
4811 assert_return(size, -EINVAL);
4812 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4814 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4818 c = message_get_container(m);
4820 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4821 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4825 sz = c->end - c->begin;
4827 align = bus_type_get_alignment(type);
4831 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4835 /* Zero length array, let's return some aligned
4836 * pointer that is not NULL */
4837 p = (uint8_t*) NULL + align;
4839 r = message_peek_body(m, &m->rindex, align, sz, &p);
4844 r = sd_bus_message_exit_container(m);
4848 *ptr = (const void*) p;
4854 message_quit_container(m);
4858 static int message_peek_fields(
4869 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4872 static int message_peek_field_uint32(
4884 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4887 /* identical for gvariant and dbus1 */
4889 r = message_peek_fields(m, ri, 4, 4, &q);
4894 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4899 static int message_peek_field_uint64(
4911 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4914 /* identical for gvariant and dbus1 */
4916 r = message_peek_fields(m, ri, 8, 8, &q);
4921 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4926 static int message_peek_field_string(
4928 bool (*validate)(const char *p),
4940 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4945 r = message_peek_fields(m, ri, 1, item_size, &q);
4951 r = message_peek_field_uint32(m, ri, 4, &l);
4955 r = message_peek_fields(m, ri, 1, l+1, &q);
4961 if (!validate_nul(q, l))
4967 if (!validate_string(q, l))
4977 static int message_peek_field_signature(
4990 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4995 r = message_peek_fields(m, ri, 1, item_size, &q);
5001 r = message_peek_fields(m, ri, 1, 1, &q);
5006 r = message_peek_fields(m, ri, 1, l+1, &q);
5011 if (!validate_signature(q, l))
5020 static int message_skip_fields(
5023 uint32_t array_size,
5024 const char **signature) {
5026 size_t original_index;
5032 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5034 original_index = *ri;
5040 if (array_size != (uint32_t) -1 &&
5041 array_size <= *ri - original_index)
5048 if (t == SD_BUS_TYPE_STRING) {
5050 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5056 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5058 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5064 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5066 r = message_peek_field_signature(m, ri, 0, NULL);
5072 } else if (bus_type_is_basic(t)) {
5075 align = bus_type_get_alignment(t);
5076 k = bus_type_get_size(t);
5077 assert(align > 0 && k > 0);
5079 r = message_peek_fields(m, ri, align, k, NULL);
5085 } else if (t == SD_BUS_TYPE_ARRAY) {
5087 r = signature_element_length(*signature+1, &l);
5097 strncpy(sig, *signature + 1, l-1);
5100 alignment = bus_type_get_alignment(sig[0]);
5104 r = message_peek_field_uint32(m, ri, 0, &nas);
5107 if (nas > BUS_ARRAY_MAX_SIZE)
5110 r = message_peek_fields(m, ri, alignment, 0, NULL);
5114 r = message_skip_fields(m, ri, nas, (const char**) &s);
5119 (*signature) += 1 + l;
5121 } else if (t == SD_BUS_TYPE_VARIANT) {
5124 r = message_peek_field_signature(m, ri, 0, &s);
5128 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5134 } else if (t == SD_BUS_TYPE_STRUCT ||
5135 t == SD_BUS_TYPE_DICT_ENTRY) {
5137 r = signature_element_length(*signature, &l);
5144 strncpy(sig, *signature + 1, l-1);
5147 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5158 int bus_message_parse_fields(sd_bus_message *m) {
5161 uint32_t unix_fds = 0;
5162 bool unix_fds_set = false;
5163 void *offsets = NULL;
5164 unsigned n_offsets = 0;
5170 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5173 /* Read the signature from the end of the body variant first */
5174 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5175 if (m->footer_accessible < 1 + sz)
5178 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5180 if (p < (char*) m->footer)
5187 /* We found the beginning of the signature
5188 * string, yay! We require the body to be a
5189 * structure, so verify it and then strip the
5190 * opening/closing brackets. */
5192 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5194 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5195 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5198 c = strndup(p + 1 + 1, l - 2);
5202 free(m->root_container.signature);
5203 m->root_container.signature = c;
5210 /* Calculate the actual user body size, by removing
5211 * the trailing variant signature and struct offset
5213 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5215 /* Pull out the offset table for the fields array */
5216 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5221 ri = m->fields_size - sz;
5222 r = message_peek_fields(m, &ri, 1, sz, &q);
5226 framing = bus_gvariant_read_word_le(q, sz);
5227 if (framing >= m->fields_size - sz)
5229 if ((m->fields_size - framing) % sz != 0)
5233 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5237 n_offsets = (m->fields_size - framing) / sz;
5240 m->user_body_size = m->body_size;
5243 while (ri < m->fields_size) {
5244 _cleanup_free_ char *sig = NULL;
5245 const char *signature;
5246 uint64_t field_type;
5247 size_t item_size = (size_t) -1;
5249 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5258 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5260 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5264 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5268 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5275 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5280 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5285 where = ri = ALIGN_TO(ri, 8);
5286 item_size = end - ri;
5287 r = message_peek_fields(m, &where, 1, item_size, &q);
5291 b = memrchr(q, 0, item_size);
5295 sig = strndup(b+1, item_size - (b+1-(char*) q));
5300 item_size = b - (char*) q;
5302 r = message_peek_field_signature(m, &ri, 0, &signature);
5307 switch (field_type) {
5309 case _BUS_MESSAGE_HEADER_INVALID:
5312 case BUS_MESSAGE_HEADER_PATH:
5317 if (!streq(signature, "o"))
5320 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5323 case BUS_MESSAGE_HEADER_INTERFACE:
5328 if (!streq(signature, "s"))
5331 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5334 case BUS_MESSAGE_HEADER_MEMBER:
5339 if (!streq(signature, "s"))
5342 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5345 case BUS_MESSAGE_HEADER_ERROR_NAME:
5350 if (!streq(signature, "s"))
5353 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5355 m->error._need_free = -1;
5359 case BUS_MESSAGE_HEADER_DESTINATION:
5364 if (!streq(signature, "s"))
5367 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5370 case BUS_MESSAGE_HEADER_SENDER:
5375 if (!streq(signature, "s"))
5378 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5380 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5381 m->creds.unique_name = (char*) m->sender;
5382 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5388 case BUS_MESSAGE_HEADER_SIGNATURE: {
5392 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5395 if (m->root_container.signature)
5398 if (!streq(signature, "g"))
5401 r = message_peek_field_signature(m, &ri, item_size, &s);
5409 free(m->root_container.signature);
5410 m->root_container.signature = c;
5414 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5416 if (m->reply_cookie != 0)
5419 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5420 /* 64bit on dbus2 */
5422 if (!streq(signature, "t"))
5425 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5429 /* 32bit on dbus1 */
5432 if (!streq(signature, "u"))
5435 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5439 m->reply_cookie = serial;
5442 if (m->reply_cookie == 0)
5447 case BUS_MESSAGE_HEADER_UNIX_FDS:
5451 if (!streq(signature, "u"))
5454 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5458 unix_fds_set = true;
5462 if (!BUS_MESSAGE_IS_GVARIANT(m))
5463 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5472 if (m->n_fds != unix_fds)
5475 switch (m->header->type) {
5477 case SD_BUS_MESSAGE_SIGNAL:
5478 if (!m->path || !m->interface || !m->member)
5481 if (m->reply_cookie != 0)
5486 case SD_BUS_MESSAGE_METHOD_CALL:
5488 if (!m->path || !m->member)
5491 if (m->reply_cookie != 0)
5496 case SD_BUS_MESSAGE_METHOD_RETURN:
5498 if (m->reply_cookie == 0)
5502 case SD_BUS_MESSAGE_METHOD_ERROR:
5504 if (m->reply_cookie == 0 || !m->error.name)
5509 /* Refuse non-local messages that claim they are local */
5510 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5512 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5514 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5517 m->root_container.end = m->user_body_size;
5519 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5520 r = build_struct_offsets(
5522 m->root_container.signature,
5524 &m->root_container.item_size,
5525 &m->root_container.offsets,
5526 &m->root_container.n_offsets);
5531 /* Try to read the error message, but if we can't it's a non-issue */
5532 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5533 (void) sd_bus_message_read(m, "s", &m->error.message);
5538 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5539 assert_return(m, -EINVAL);
5540 assert_return(destination, -EINVAL);
5541 assert_return(!m->sealed, -EPERM);
5542 assert_return(!m->destination, -EEXIST);
5544 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5547 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5551 struct bus_body_part *part;
5557 total = BUS_MESSAGE_SIZE(m);
5563 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5564 MESSAGE_FOREACH_PART(part, i, m)
5565 e = mempcpy(e, part->data, part->size);
5567 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5575 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5582 r = sd_bus_message_enter_container(m, 'a', "s");
5586 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5587 r = strv_extend(l, s);
5594 r = sd_bus_message_exit_container(m);
5601 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5605 assert_return(m, -EINVAL);
5606 assert_return(m->sealed, -EPERM);
5607 assert_return(l, -EINVAL);
5609 r = bus_message_read_strv_extend(m, &strv);
5619 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5620 const char *contents;
5629 r = sd_bus_message_rewind(m, true);
5634 r = sd_bus_message_peek_type(m, &type, &contents);
5640 /* Don't match against arguments after the first one we don't understand */
5641 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5642 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5648 r = sd_bus_message_skip(m, NULL);
5653 if (type == SD_BUS_TYPE_ARRAY) {
5655 r = sd_bus_message_read_strv(m, strv);
5662 r = sd_bus_message_read_basic(m, type, str);
5672 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5673 assert_return(m, EINVAL);
5675 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5678 return sd_bus_error_get_errno(&m->error);
5681 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5682 struct bus_container *c;
5684 assert_return(m, NULL);
5686 c = complete ? &m->root_container : message_get_container(m);
5687 return strempty(c->signature);
5690 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5691 assert_return(m, -EINVAL);
5693 return isempty(m->root_container.signature);
5696 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5697 assert_return(m, -EINVAL);
5699 return streq(strempty(m->root_container.signature), strempty(signature));
5702 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5703 bool done_something = false;
5706 assert_return(m, -EINVAL);
5707 assert_return(source, -EINVAL);
5708 assert_return(!m->sealed, -EPERM);
5709 assert_return(source->sealed, -EPERM);
5712 const char *contents;
5727 r = sd_bus_message_peek_type(source, &type, &contents);
5733 done_something = true;
5735 if (bus_type_is_container(type) > 0) {
5737 r = sd_bus_message_enter_container(source, type, contents);
5741 r = sd_bus_message_open_container(m, type, contents);
5745 r = sd_bus_message_copy(m, source, true);
5749 r = sd_bus_message_close_container(m);
5753 r = sd_bus_message_exit_container(source);
5760 r = sd_bus_message_read_basic(source, type, &basic);
5766 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5767 type == SD_BUS_TYPE_SIGNATURE ||
5768 type == SD_BUS_TYPE_STRING)
5769 r = sd_bus_message_append_basic(m, type, basic.string);
5771 r = sd_bus_message_append_basic(m, type, &basic);
5778 return done_something;
5781 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5786 assert_return(m, -EINVAL);
5787 assert_return(m->sealed, -EPERM);
5788 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5789 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5790 assert_return(type || contents, -EINVAL);
5791 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5793 r = sd_bus_message_peek_type(m, &t, &c);
5797 if (type != 0 && type != t)
5800 if (contents && !streq_ptr(contents, c))
5806 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5807 assert_return(m, NULL);
5812 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5813 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5821 switch ((*m)->header->type) {
5823 case SD_BUS_MESSAGE_SIGNAL:
5824 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5830 case SD_BUS_MESSAGE_METHOD_CALL:
5831 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5837 case SD_BUS_MESSAGE_METHOD_RETURN:
5838 case SD_BUS_MESSAGE_METHOD_ERROR:
5840 n = message_new(bus, (*m)->header->type);
5844 n->reply_cookie = (*m)->reply_cookie;
5846 r = message_append_reply_cookie(n, n->reply_cookie);
5850 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5851 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5855 n->error._need_free = -1;
5864 if ((*m)->destination && !n->destination) {
5865 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5870 if ((*m)->sender && !n->sender) {
5871 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5876 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5878 r = sd_bus_message_copy(n, *m, true);
5882 timeout = (*m)->timeout;
5883 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5884 timeout = BUS_DEFAULT_TIMEOUT;
5886 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5890 sd_bus_message_unref(*m);
5897 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5901 assert_return(!m->sealed, -EPERM);
5902 assert_return(!m->sender, -EPERM);
5904 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5907 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5908 assert_return(m, -EINVAL);
5909 assert_return(priority, -EINVAL);
5911 *priority = m->priority;
5915 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5916 assert_return(m, -EINVAL);
5917 assert_return(!m->sealed, -EPERM);
5919 m->priority = priority;