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,
438 const struct ucred *ucred,
441 sd_bus_message **ret) {
444 struct bus_header *h;
448 assert(header || header_accessible <= 0);
449 assert(footer || footer_accessible <= 0);
450 assert(fds || n_fds <= 0);
453 if (header_accessible < sizeof(struct bus_header))
456 if (header_accessible > message_size)
458 if (footer_accessible > message_size)
462 if (h->version != 1 &&
466 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
469 if (h->endian != BUS_LITTLE_ENDIAN &&
470 h->endian != BUS_BIG_ENDIAN)
473 /* Note that we are happy with unknown flags in the flags header! */
475 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
478 label_sz = strlen(label);
489 m->header_accessible = header_accessible;
491 m->footer_accessible = footer_accessible;
493 if (BUS_MESSAGE_IS_GVARIANT(m)) {
496 if (h->dbus2.cookie == 0)
499 /* dbus2 derives the sizes from the message size and
500 the offset table at the end, since it is formatted as
501 gvariant "yyyyuta{tv}v". Since the message itself is a
502 structure with precisely to variable sized entries,
503 there's only one offset in the table, which marks the
504 end of the fields array. */
506 ws = bus_gvariant_determine_word_size(message_size, 0);
507 if (footer_accessible < ws)
510 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
511 if (ALIGN8(m->fields_size) > message_size - ws)
513 if (m->fields_size < sizeof(struct bus_header))
516 m->fields_size -= sizeof(struct bus_header);
517 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
519 if (h->dbus1.serial == 0)
522 /* dbus1 has the sizes in the header */
523 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
524 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
526 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
534 m->creds.pid = ucred->pid;
535 m->creds.euid = ucred->uid;
536 m->creds.egid = ucred->gid;
538 /* Due to namespace translations some data might be
539 * missing from this ucred record. */
540 if (m->creds.pid > 0)
541 m->creds.mask |= SD_BUS_CREDS_PID;
543 if (m->creds.euid != UID_INVALID)
544 m->creds.mask |= SD_BUS_CREDS_EUID;
546 if (m->creds.egid != GID_INVALID)
547 m->creds.mask |= SD_BUS_CREDS_EGID;
551 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
552 memcpy(m->creds.label, label, label_sz + 1);
554 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
557 m->bus = sd_bus_ref(bus);
563 int bus_message_from_malloc(
569 const struct ucred *ucred,
571 sd_bus_message **ret) {
577 r = bus_message_from_header(
579 buffer, length, /* in this case the initial bytes and the final bytes are the same */
588 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
591 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
593 m->body.sealed = true;
598 m->iovec = m->iovec_fixed;
599 m->iovec[0].iov_base = buffer;
600 m->iovec[0].iov_len = length;
602 r = bus_message_parse_fields(m);
606 /* We take possession of the memory and fds now */
607 m->free_header = true;
618 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
623 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
628 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
629 m->header->endian = BUS_NATIVE_ENDIAN;
630 m->header->type = type;
631 m->header->version = bus ? bus->message_version : 1;
632 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
633 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
634 m->bus = sd_bus_ref(bus);
636 if (bus->allow_interactive_authorization)
637 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
642 _public_ int sd_bus_message_new_signal(
646 const char *interface,
647 const char *member) {
652 assert_return(bus, -ENOTCONN);
653 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
654 assert_return(object_path_is_valid(path), -EINVAL);
655 assert_return(interface_name_is_valid(interface), -EINVAL);
656 assert_return(member_name_is_valid(member), -EINVAL);
657 assert_return(m, -EINVAL);
659 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
663 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
665 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
668 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
671 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
679 sd_bus_message_unref(t);
683 _public_ int sd_bus_message_new_method_call(
686 const char *destination,
688 const char *interface,
689 const char *member) {
694 assert_return(bus, -ENOTCONN);
695 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
696 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
697 assert_return(object_path_is_valid(path), -EINVAL);
698 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
699 assert_return(member_name_is_valid(member), -EINVAL);
700 assert_return(m, -EINVAL);
702 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
706 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
709 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
714 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
720 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
733 static int message_new_reply(
734 sd_bus_message *call,
736 sd_bus_message **m) {
741 assert_return(call, -EINVAL);
742 assert_return(call->sealed, -EPERM);
743 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
744 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
745 assert_return(m, -EINVAL);
747 t = message_new(call->bus, type);
751 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
752 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
753 if (t->reply_cookie == 0)
756 r = message_append_reply_cookie(t, t->reply_cookie);
761 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
766 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
767 t->enforced_reply_signature = call->enforced_reply_signature;
777 _public_ int sd_bus_message_new_method_return(
778 sd_bus_message *call,
779 sd_bus_message **m) {
781 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
784 _public_ int sd_bus_message_new_method_error(
785 sd_bus_message *call,
787 const sd_bus_error *e) {
792 assert_return(sd_bus_error_is_set(e), -EINVAL);
793 assert_return(m, -EINVAL);
795 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
799 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
804 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
809 t->error._need_free = -1;
819 _public_ int sd_bus_message_new_method_errorf(
820 sd_bus_message *call,
826 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
829 assert_return(name, -EINVAL);
830 assert_return(m, -EINVAL);
832 va_start(ap, format);
833 bus_error_setfv(&error, name, format, ap);
836 return sd_bus_message_new_method_error(call, m, &error);
839 _public_ int sd_bus_message_new_method_errno(
840 sd_bus_message *call,
843 const sd_bus_error *p) {
845 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
847 if (sd_bus_error_is_set(p))
848 return sd_bus_message_new_method_error(call, m, p);
850 sd_bus_error_set_errno(&berror, error);
852 return sd_bus_message_new_method_error(call, m, &berror);
855 _public_ int sd_bus_message_new_method_errnof(
856 sd_bus_message *call,
862 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
865 va_start(ap, format);
866 sd_bus_error_set_errnofv(&berror, error, format, ap);
869 return sd_bus_message_new_method_error(call, m, &berror);
872 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
876 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
877 m->creds.well_known_names_local = true;
878 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
881 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
885 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
886 m->creds.well_known_names_driver = true;
887 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
890 int bus_message_new_synthetic_error(
893 const sd_bus_error *e,
894 sd_bus_message **m) {
900 assert(sd_bus_error_is_set(e));
903 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
907 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
908 t->reply_cookie = cookie;
910 r = message_append_reply_cookie(t, t->reply_cookie);
914 if (bus && bus->unique_name) {
915 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
920 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
925 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
930 t->error._need_free = -1;
932 bus_message_set_sender_driver(bus, t);
942 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
943 assert_return(m, NULL);
945 assert(m->n_ref > 0);
951 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
956 assert(m->n_ref > 0);
966 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
967 assert_return(m, -EINVAL);
968 assert_return(type, -EINVAL);
970 *type = m->header->type;
974 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
977 assert_return(m, -EINVAL);
978 assert_return(cookie, -EINVAL);
980 c = BUS_MESSAGE_COOKIE(m);
984 *cookie = BUS_MESSAGE_COOKIE(m);
988 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
989 assert_return(m, -EINVAL);
990 assert_return(cookie, -EINVAL);
992 if (m->reply_cookie == 0)
995 *cookie = m->reply_cookie;
999 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
1000 assert_return(m, -EINVAL);
1002 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
1003 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
1006 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
1007 assert_return(m, -EINVAL);
1009 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
1012 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
1013 assert_return(m, -EINVAL);
1015 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
1016 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
1019 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1020 assert_return(m, NULL);
1025 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1026 assert_return(m, NULL);
1028 return m->interface;
1031 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1032 assert_return(m, NULL);
1037 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1038 assert_return(m, NULL);
1040 return m->destination;
1043 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1044 assert_return(m, NULL);
1049 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1050 assert_return(m, NULL);
1051 assert_return(sd_bus_error_is_set(&m->error), NULL);
1056 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1057 assert_return(m, -EINVAL);
1058 assert_return(usec, -EINVAL);
1060 if (m->monotonic <= 0)
1063 *usec = m->monotonic;
1067 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1068 assert_return(m, -EINVAL);
1069 assert_return(usec, -EINVAL);
1071 if (m->realtime <= 0)
1074 *usec = m->realtime;
1078 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1079 assert_return(m, -EINVAL);
1080 assert_return(seqnum, -EINVAL);
1085 *seqnum = m->seqnum;
1089 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1090 assert_return(m, NULL);
1092 if (m->creds.mask == 0)
1098 _public_ int sd_bus_message_is_signal(
1100 const char *interface,
1101 const char *member) {
1103 assert_return(m, -EINVAL);
1105 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1108 if (interface && (!m->interface || !streq(m->interface, interface)))
1111 if (member && (!m->member || !streq(m->member, member)))
1117 _public_ int sd_bus_message_is_method_call(
1119 const char *interface,
1120 const char *member) {
1122 assert_return(m, -EINVAL);
1124 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1127 if (interface && (!m->interface || !streq(m->interface, interface)))
1130 if (member && (!m->member || !streq(m->member, member)))
1136 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1137 assert_return(m, -EINVAL);
1139 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1142 if (name && (!m->error.name || !streq(m->error.name, name)))
1148 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1149 assert_return(m, -EINVAL);
1150 assert_return(!m->sealed, -EPERM);
1151 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1154 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1156 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1161 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1162 assert_return(m, -EINVAL);
1163 assert_return(!m->sealed, -EPERM);
1166 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1168 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1173 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1174 assert_return(m, -EINVAL);
1175 assert_return(!m->sealed, -EPERM);
1178 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1180 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1185 static struct bus_container *message_get_container(sd_bus_message *m) {
1188 if (m->n_containers == 0)
1189 return &m->root_container;
1191 assert(m->containers);
1192 return m->containers + m->n_containers - 1;
1195 struct bus_body_part *message_append_part(sd_bus_message *m) {
1196 struct bus_body_part *part;
1203 if (m->n_body_parts <= 0) {
1207 assert(m->body_end);
1209 part = new0(struct bus_body_part, 1);
1215 m->body_end->next = part;
1225 static void part_zero(struct bus_body_part *part, size_t sz) {
1230 /* All other fields can be left in their defaults */
1231 assert(!part->data);
1232 assert(part->memfd < 0);
1235 part->is_zero = true;
1236 part->sealed = true;
1239 static int part_make_space(
1240 struct sd_bus_message *m,
1241 struct bus_body_part *part,
1250 assert(!part->sealed);
1255 if (!part->data && part->memfd < 0) {
1256 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1257 part->mmap_begin = part->data;
1260 if (part->memfd >= 0) {
1262 if (part->allocated == 0 || sz > part->allocated) {
1263 uint64_t new_allocated;
1265 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1266 r = memfd_set_size(part->memfd, new_allocated);
1272 part->allocated = new_allocated;
1275 if (!part->data || sz > part->mapped) {
1278 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1279 if (part->mapped <= 0)
1280 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1282 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1284 if (n == MAP_FAILED) {
1289 part->mmap_begin = part->data = n;
1291 part->memfd_offset = 0;
1294 part->munmap_this = true;
1296 if (part->allocated == 0 || sz > part->allocated) {
1297 size_t new_allocated;
1299 new_allocated = sz > 0 ? 2 * sz : 64;
1300 n = realloc(part->data, new_allocated);
1307 part->allocated = new_allocated;
1308 part->free_this = true;
1313 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1319 static int message_add_offset(sd_bus_message *m, size_t offset) {
1320 struct bus_container *c;
1323 assert(BUS_MESSAGE_IS_GVARIANT(m));
1325 /* Add offset to current container, unless this is the first
1326 * item in it, which will have the 0 offset, which we can
1328 c = message_get_container(m);
1330 if (!c->need_offsets)
1333 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1336 c->offsets[c->n_offsets++] = offset;
1340 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1341 struct bus_container *c;
1348 /* Update counters */
1349 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1352 *c->array_size += expand;
1356 static void *message_extend_body(
1361 bool force_inline) {
1363 size_t start_body, end_body, padding, added;
1374 start_body = ALIGN_TO((size_t) m->body_size, align);
1375 end_body = start_body + sz;
1377 padding = start_body - m->body_size;
1378 added = padding + sz;
1380 /* Check for 32bit overflows */
1381 if (end_body > (size_t) ((uint32_t) -1) ||
1382 end_body < start_body) {
1388 struct bus_body_part *part = NULL;
1392 m->n_body_parts <= 0 ||
1393 m->body_end->sealed ||
1394 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1395 (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 */
1399 part = message_append_part(m);
1403 part_zero(part, padding);
1406 part = message_append_part(m);
1410 r = part_make_space(m, part, sz, &p);
1414 struct bus_container *c;
1416 size_t os, start_part, end_part;
1422 start_part = ALIGN_TO(part->size, align);
1423 end_part = start_part + sz;
1425 r = part_make_space(m, part, end_part, &p);
1430 memzero(p, padding);
1431 p = (uint8_t*) p + padding;
1434 /* Readjust pointers */
1435 for (c = m->containers; c < m->containers + m->n_containers; c++)
1436 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1438 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1441 /* Return something that is not NULL and is aligned */
1442 p = (uint8_t *) NULL + align;
1444 m->body_size = end_body;
1445 message_extend_containers(m, added);
1448 r = message_add_offset(m, end_body);
1458 static int message_push_fd(sd_bus_message *m, int fd) {
1469 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1473 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1481 m->fds[m->n_fds] = copy;
1487 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1488 _cleanup_close_ int fd = -1;
1489 struct bus_container *c;
1493 assert_return(m, -EINVAL);
1494 assert_return(!m->sealed, -EPERM);
1495 assert_return(bus_type_is_basic(type), -EINVAL);
1496 assert_return(!m->poisoned, -ESTALE);
1498 c = message_get_container(m);
1500 if (c->signature && c->signature[c->index]) {
1501 /* Container signature is already set */
1503 if (c->signature[c->index] != type)
1508 /* Maybe we can append to the signature? But only if this is the top-level container */
1509 if (c->enclosing != 0)
1512 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1519 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1525 case SD_BUS_TYPE_SIGNATURE:
1526 case SD_BUS_TYPE_STRING:
1529 /* Fall through... */
1530 case SD_BUS_TYPE_OBJECT_PATH:
1538 case SD_BUS_TYPE_BOOLEAN:
1540 u8 = p && *(int*) p;
1546 case SD_BUS_TYPE_UNIX_FD:
1551 fd = message_push_fd(m, *(int*) p);
1562 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1563 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1570 a = message_extend_body(m, align, sz, true, false);
1577 *stored = (const uint8_t*) a;
1584 case SD_BUS_TYPE_STRING:
1585 /* To make things easy we'll serialize a NULL string
1586 * into the empty string */
1589 /* Fall through... */
1590 case SD_BUS_TYPE_OBJECT_PATH:
1596 sz = 4 + strlen(p) + 1;
1599 case SD_BUS_TYPE_SIGNATURE:
1604 sz = 1 + strlen(p) + 1;
1607 case SD_BUS_TYPE_BOOLEAN:
1609 u32 = p && *(int*) p;
1615 case SD_BUS_TYPE_UNIX_FD:
1620 fd = message_push_fd(m, *(int*) p);
1631 align = bus_type_get_alignment(type);
1632 sz = bus_type_get_size(type);
1639 a = message_extend_body(m, align, sz, false, false);
1643 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1644 *(uint32_t*) a = sz - 5;
1645 memcpy((uint8_t*) a + 4, p, sz - 4);
1648 *stored = (const uint8_t*) a + 4;
1650 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1651 *(uint8_t*) a = sz - 2;
1652 memcpy((uint8_t*) a + 1, p, sz - 1);
1655 *stored = (const uint8_t*) a + 1;
1664 if (type == SD_BUS_TYPE_UNIX_FD)
1667 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1674 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1675 return message_append_basic(m, type, p, NULL);
1678 _public_ int sd_bus_message_append_string_space(
1683 struct bus_container *c;
1686 assert_return(m, -EINVAL);
1687 assert_return(s, -EINVAL);
1688 assert_return(!m->sealed, -EPERM);
1689 assert_return(!m->poisoned, -ESTALE);
1691 c = message_get_container(m);
1693 if (c->signature && c->signature[c->index]) {
1694 /* Container signature is already set */
1696 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1701 /* Maybe we can append to the signature? But only if this is the top-level container */
1702 if (c->enclosing != 0)
1705 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1712 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1713 a = message_extend_body(m, 1, size + 1, true, false);
1719 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1723 *(uint32_t*) a = size;
1729 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1735 _public_ int sd_bus_message_append_string_iovec(
1737 const struct iovec *iov,
1745 assert_return(m, -EINVAL);
1746 assert_return(!m->sealed, -EPERM);
1747 assert_return(iov || n == 0, -EINVAL);
1748 assert_return(!m->poisoned, -ESTALE);
1750 size = IOVEC_TOTAL_SIZE(iov, n);
1752 r = sd_bus_message_append_string_space(m, size, &p);
1756 for (i = 0; i < n; i++) {
1758 if (iov[i].iov_base)
1759 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1761 memset(p, ' ', iov[i].iov_len);
1763 p += iov[i].iov_len;
1769 static int bus_message_open_array(
1771 struct bus_container *c,
1772 const char *contents,
1773 uint32_t **array_size,
1775 bool *need_offsets) {
1785 assert(need_offsets);
1787 if (!signature_is_single(contents, true))
1790 if (c->signature && c->signature[c->index]) {
1792 /* Verify the existing signature */
1794 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1797 if (!startswith(c->signature + c->index + 1, contents))
1800 nindex = c->index + 1 + strlen(contents);
1804 if (c->enclosing != 0)
1807 /* Extend the existing signature */
1809 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1815 nindex = e - c->signature;
1818 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1819 alignment = bus_gvariant_get_alignment(contents);
1823 /* Add alignment padding and add to offset list */
1824 if (!message_extend_body(m, alignment, 0, false, false))
1827 r = bus_gvariant_is_fixed_size(contents);
1831 *begin = m->body_size;
1832 *need_offsets = r == 0;
1836 struct bus_body_part *o;
1838 alignment = bus_type_get_alignment(contents[0]);
1842 a = message_extend_body(m, 4, 4, false, false);
1847 op = m->body_end->data;
1848 os = m->body_end->size;
1850 /* Add alignment between size and first element */
1851 if (!message_extend_body(m, alignment, 0, false, false))
1854 /* location of array size might have changed so let's readjust a */
1855 if (o == m->body_end)
1856 a = adjust_pointer(a, op, os, m->body_end->data);
1862 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1868 static int bus_message_open_variant(
1870 struct bus_container *c,
1871 const char *contents) {
1877 if (!signature_is_single(contents, false))
1880 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1883 if (c->signature && c->signature[c->index]) {
1885 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1891 if (c->enclosing != 0)
1894 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1901 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1902 /* Variants are always aligned to 8 */
1904 if (!message_extend_body(m, 8, 0, false, false))
1911 l = strlen(contents);
1912 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1917 memcpy((uint8_t*) a + 1, contents, l + 1);
1920 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1926 static int bus_message_open_struct(
1928 struct bus_container *c,
1929 const char *contents,
1931 bool *need_offsets) {
1940 assert(need_offsets);
1942 if (!signature_is_valid(contents, false))
1945 if (c->signature && c->signature[c->index]) {
1948 l = strlen(contents);
1950 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1951 !startswith(c->signature + c->index + 1, contents) ||
1952 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1955 nindex = c->index + 1 + l + 1;
1959 if (c->enclosing != 0)
1962 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1968 nindex = e - c->signature;
1971 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1974 alignment = bus_gvariant_get_alignment(contents);
1978 if (!message_extend_body(m, alignment, 0, false, false))
1981 r = bus_gvariant_is_fixed_size(contents);
1985 *begin = m->body_size;
1986 *need_offsets = r == 0;
1988 /* Align contents to 8 byte boundary */
1989 if (!message_extend_body(m, 8, 0, false, false))
1993 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1999 static int bus_message_open_dict_entry(
2001 struct bus_container *c,
2002 const char *contents,
2004 bool *need_offsets) {
2012 assert(need_offsets);
2014 if (!signature_is_pair(contents))
2017 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2020 if (c->signature && c->signature[c->index]) {
2023 l = strlen(contents);
2025 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2026 !startswith(c->signature + c->index + 1, contents) ||
2027 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2032 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2035 alignment = bus_gvariant_get_alignment(contents);
2039 if (!message_extend_body(m, alignment, 0, false, false))
2042 r = bus_gvariant_is_fixed_size(contents);
2046 *begin = m->body_size;
2047 *need_offsets = r == 0;
2049 /* Align contents to 8 byte boundary */
2050 if (!message_extend_body(m, 8, 0, false, false))
2057 _public_ int sd_bus_message_open_container(
2060 const char *contents) {
2062 struct bus_container *c, *w;
2063 uint32_t *array_size = NULL;
2065 size_t before, begin = 0;
2066 bool need_offsets = false;
2069 assert_return(m, -EINVAL);
2070 assert_return(!m->sealed, -EPERM);
2071 assert_return(contents, -EINVAL);
2072 assert_return(!m->poisoned, -ESTALE);
2074 /* Make sure we have space for one more container */
2075 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2080 c = message_get_container(m);
2082 signature = strdup(contents);
2088 /* Save old index in the parent container, in case we have to
2089 * abort this container */
2090 c->saved_index = c->index;
2091 before = m->body_size;
2093 if (type == SD_BUS_TYPE_ARRAY)
2094 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2095 else if (type == SD_BUS_TYPE_VARIANT)
2096 r = bus_message_open_variant(m, c, contents);
2097 else if (type == SD_BUS_TYPE_STRUCT)
2098 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2099 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2100 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2109 /* OK, let's fill it in */
2110 w = m->containers + m->n_containers++;
2111 w->enclosing = type;
2112 w->signature = signature;
2114 w->array_size = array_size;
2117 w->n_offsets = w->offsets_allocated = 0;
2119 w->need_offsets = need_offsets;
2124 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2129 if (!BUS_MESSAGE_IS_GVARIANT(m))
2132 if (c->need_offsets) {
2133 size_t payload, sz, i;
2136 /* Variable-width arrays */
2138 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2139 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2141 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2145 for (i = 0; i < c->n_offsets; i++)
2146 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2150 /* Fixed-width or empty arrays */
2152 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2160 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2166 assert(c->signature);
2168 if (!BUS_MESSAGE_IS_GVARIANT(m))
2171 l = strlen(c->signature);
2173 a = message_extend_body(m, 1, 1 + l, true, false);
2178 memcpy(a+1, c->signature, l);
2183 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2184 size_t n_variable = 0;
2193 if (!BUS_MESSAGE_IS_GVARIANT(m))
2196 p = strempty(c->signature);
2200 r = signature_element_length(p, &n);
2209 r = bus_gvariant_is_fixed_size(t);
2214 assert(!c->need_offsets || i <= c->n_offsets);
2216 /* We need to add an offset for each item that has a
2217 * variable size and that is not the last one in the
2219 if (r == 0 && p[n] != 0)
2226 assert(!c->need_offsets || i == c->n_offsets);
2227 assert(c->need_offsets || n_variable == 0);
2229 if (n_variable <= 0) {
2230 a = message_extend_body(m, 1, 0, add_offset, false);
2237 assert(c->offsets[c->n_offsets-1] == m->body_size);
2239 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2241 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2245 p = strempty(c->signature);
2246 for (i = 0, j = 0; i < c->n_offsets; i++) {
2250 r = signature_element_length(p, &n);
2261 r = bus_gvariant_is_fixed_size(t);
2264 if (r > 0 || p[0] == 0)
2268 k = n_variable - 1 - j;
2270 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2279 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2280 struct bus_container *c;
2283 assert_return(m, -EINVAL);
2284 assert_return(!m->sealed, -EPERM);
2285 assert_return(m->n_containers > 0, -EINVAL);
2286 assert_return(!m->poisoned, -ESTALE);
2288 c = message_get_container(m);
2290 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2291 if (c->signature && c->signature[c->index] != 0)
2296 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2297 r = bus_message_close_array(m, c);
2298 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2299 r = bus_message_close_variant(m, c);
2300 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2301 r = bus_message_close_struct(m, c, true);
2303 assert_not_reached("Unknown container type");
2317 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2324 stack[*i].types = types;
2325 stack[*i].n_struct = n_struct;
2326 stack[*i].n_array = n_array;
2332 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2343 *types = stack[*i].types;
2344 *n_struct = stack[*i].n_struct;
2345 *n_array = stack[*i].n_array;
2350 int bus_message_append_ap(
2355 unsigned n_array, n_struct;
2356 TypeStack stack[BUS_CONTAINER_DEPTH];
2357 unsigned stack_ptr = 0;
2365 n_array = (unsigned) -1;
2366 n_struct = strlen(types);
2371 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2372 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2378 r = sd_bus_message_close_container(m);
2386 if (n_array != (unsigned) -1)
2395 case SD_BUS_TYPE_BYTE: {
2398 x = (uint8_t) va_arg(ap, int);
2399 r = sd_bus_message_append_basic(m, *t, &x);
2403 case SD_BUS_TYPE_BOOLEAN:
2404 case SD_BUS_TYPE_INT32:
2405 case SD_BUS_TYPE_UINT32:
2406 case SD_BUS_TYPE_UNIX_FD: {
2409 /* We assume a boolean is the same as int32_t */
2410 assert_cc(sizeof(int32_t) == sizeof(int));
2412 x = va_arg(ap, uint32_t);
2413 r = sd_bus_message_append_basic(m, *t, &x);
2417 case SD_BUS_TYPE_INT16:
2418 case SD_BUS_TYPE_UINT16: {
2421 x = (uint16_t) va_arg(ap, int);
2422 r = sd_bus_message_append_basic(m, *t, &x);
2426 case SD_BUS_TYPE_INT64:
2427 case SD_BUS_TYPE_UINT64: {
2430 x = va_arg(ap, uint64_t);
2431 r = sd_bus_message_append_basic(m, *t, &x);
2435 case SD_BUS_TYPE_DOUBLE: {
2438 x = va_arg(ap, double);
2439 r = sd_bus_message_append_basic(m, *t, &x);
2443 case SD_BUS_TYPE_STRING:
2444 case SD_BUS_TYPE_OBJECT_PATH:
2445 case SD_BUS_TYPE_SIGNATURE: {
2448 x = va_arg(ap, const char*);
2449 r = sd_bus_message_append_basic(m, *t, x);
2453 case SD_BUS_TYPE_ARRAY: {
2456 r = signature_element_length(t + 1, &k);
2462 memcpy(s, t + 1, k);
2465 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2470 if (n_array == (unsigned) -1) {
2475 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2481 n_array = va_arg(ap, unsigned);
2486 case SD_BUS_TYPE_VARIANT: {
2489 s = va_arg(ap, const char*);
2493 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2497 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2502 n_struct = strlen(s);
2503 n_array = (unsigned) -1;
2508 case SD_BUS_TYPE_STRUCT_BEGIN:
2509 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2512 r = signature_element_length(t, &k);
2519 memcpy(s, t + 1, k - 2);
2522 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2527 if (n_array == (unsigned) -1) {
2532 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2538 n_array = (unsigned) -1;
2554 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2558 assert_return(m, -EINVAL);
2559 assert_return(types, -EINVAL);
2560 assert_return(!m->sealed, -EPERM);
2561 assert_return(!m->poisoned, -ESTALE);
2563 va_start(ap, types);
2564 r = bus_message_append_ap(m, types, ap);
2570 _public_ int sd_bus_message_append_array_space(
2580 assert_return(m, -EINVAL);
2581 assert_return(!m->sealed, -EPERM);
2582 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2583 assert_return(ptr || size == 0, -EINVAL);
2584 assert_return(!m->poisoned, -ESTALE);
2586 /* alignment and size of the trivial types (except bool) is
2587 * identical for gvariant and dbus1 marshalling */
2588 align = bus_type_get_alignment(type);
2589 sz = bus_type_get_size(type);
2591 assert_se(align > 0);
2597 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2601 a = message_extend_body(m, align, size, false, false);
2605 r = sd_bus_message_close_container(m);
2613 _public_ int sd_bus_message_append_array(
2621 assert_return(m, -EINVAL);
2622 assert_return(!m->sealed, -EPERM);
2623 assert_return(bus_type_is_trivial(type), -EINVAL);
2624 assert_return(ptr || size == 0, -EINVAL);
2625 assert_return(!m->poisoned, -ESTALE);
2627 r = sd_bus_message_append_array_space(m, type, size, &p);
2632 memcpy(p, ptr, size);
2637 _public_ int sd_bus_message_append_array_iovec(
2640 const struct iovec *iov,
2648 assert_return(m, -EINVAL);
2649 assert_return(!m->sealed, -EPERM);
2650 assert_return(bus_type_is_trivial(type), -EINVAL);
2651 assert_return(iov || n == 0, -EINVAL);
2652 assert_return(!m->poisoned, -ESTALE);
2654 size = IOVEC_TOTAL_SIZE(iov, n);
2656 r = sd_bus_message_append_array_space(m, type, size, &p);
2660 for (i = 0; i < n; i++) {
2662 if (iov[i].iov_base)
2663 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2665 memzero(p, iov[i].iov_len);
2667 p = (uint8_t*) p + iov[i].iov_len;
2673 _public_ int sd_bus_message_append_array_memfd(
2680 _cleanup_close_ int copy_fd = -1;
2681 struct bus_body_part *part;
2687 assert_return(m, -EINVAL);
2688 assert_return(memfd >= 0, -EINVAL);
2689 assert_return(bus_type_is_trivial(type), -EINVAL);
2690 assert_return(size > 0, -EINVAL);
2691 assert_return(!m->sealed, -EPERM);
2692 assert_return(!m->poisoned, -ESTALE);
2694 r = memfd_set_sealed(memfd);
2698 copy_fd = dup(memfd);
2702 r = memfd_get_size(memfd, &real_size);
2706 if (offset == 0 && size == (uint64_t) -1)
2708 else if (offset + size > real_size)
2711 align = bus_type_get_alignment(type);
2712 sz = bus_type_get_size(type);
2714 assert_se(align > 0);
2717 if (offset % align != 0)
2723 if (size > (uint64_t) (uint32_t) -1)
2726 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2730 a = message_extend_body(m, align, 0, false, false);
2734 part = message_append_part(m);
2738 part->memfd = copy_fd;
2739 part->memfd_offset = offset;
2740 part->sealed = true;
2744 m->body_size += size;
2745 message_extend_containers(m, size);
2747 return sd_bus_message_close_container(m);
2750 _public_ int sd_bus_message_append_string_memfd(
2756 _cleanup_close_ int copy_fd = -1;
2757 struct bus_body_part *part;
2758 struct bus_container *c;
2763 assert_return(m, -EINVAL);
2764 assert_return(memfd >= 0, -EINVAL);
2765 assert_return(size > 0, -EINVAL);
2766 assert_return(!m->sealed, -EPERM);
2767 assert_return(!m->poisoned, -ESTALE);
2769 r = memfd_set_sealed(memfd);
2773 copy_fd = dup(memfd);
2777 r = memfd_get_size(memfd, &real_size);
2781 if (offset == 0 && size == (uint64_t) -1)
2783 else if (offset + size > real_size)
2786 /* We require this to be NUL terminated */
2790 if (size > (uint64_t) (uint32_t) -1)
2793 c = message_get_container(m);
2794 if (c->signature && c->signature[c->index]) {
2795 /* Container signature is already set */
2797 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2802 /* Maybe we can append to the signature? But only if this is the top-level container */
2803 if (c->enclosing != 0)
2806 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2813 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2814 a = message_extend_body(m, 4, 4, false, false);
2818 *(uint32_t*) a = size - 1;
2821 part = message_append_part(m);
2825 part->memfd = copy_fd;
2826 part->memfd_offset = offset;
2827 part->sealed = true;
2831 m->body_size += size;
2832 message_extend_containers(m, size);
2834 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2835 r = message_add_offset(m, m->body_size);
2842 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2848 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2852 assert_return(m, -EINVAL);
2853 assert_return(!m->sealed, -EPERM);
2854 assert_return(!m->poisoned, -ESTALE);
2856 r = sd_bus_message_open_container(m, 'a', "s");
2860 STRV_FOREACH(i, l) {
2861 r = sd_bus_message_append_basic(m, 's', *i);
2866 return sd_bus_message_close_container(m);
2869 static int bus_message_close_header(sd_bus_message *m) {
2873 /* The actual user data is finished now, we just complete the
2874 variant and struct now (at least on gvariant). Remember
2875 this position, so that during parsing we know where to to
2876 put the outer container end. */
2877 m->user_body_size = m->body_size;
2879 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2880 const char *signature;
2884 /* Add offset table to end of fields array */
2885 if (m->n_header_offsets >= 1) {
2889 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2891 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2892 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2896 for (i = 0; i < m->n_header_offsets; i++)
2897 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2900 /* Add gvariant NUL byte plus signature to the end of
2901 * the body, followed by the final offset pointing to
2902 * the end of the fields array */
2904 signature = strempty(m->root_container.signature);
2905 l = strlen(signature);
2907 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l, 1);
2908 d = message_extend_body(m, 1, 1 + l + sz, false, true);
2913 memcpy((uint8_t*) d + 1, signature, l);
2915 bus_gvariant_write_word_le((uint8_t*) d + 1 + l, sz, sizeof(struct bus_header) + m->fields_size);
2918 m->footer_accessible = 1 + l + sz;
2920 m->header->dbus1.fields_size = m->fields_size;
2921 m->header->dbus1.body_size = m->body_size;
2927 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2928 struct bus_body_part *part;
2938 if (m->n_containers > 0)
2944 if (cookie > 0xffffffffULL &&
2945 !BUS_MESSAGE_IS_GVARIANT(m))
2948 /* In vtables the return signature of method calls is listed,
2949 * let's check if they match if this is a response */
2950 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2951 m->enforced_reply_signature &&
2952 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2955 /* If gvariant marshalling is used we need to close the body structure */
2956 r = bus_message_close_struct(m, &m->root_container, false);
2960 /* If there's a non-trivial signature set, then add it in
2961 * here, but only on dbus1 */
2962 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2963 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2969 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2974 r = bus_message_close_header(m);
2978 if (BUS_MESSAGE_IS_GVARIANT(m))
2979 m->header->dbus2.cookie = cookie;
2981 m->header->dbus1.serial = (uint32_t) cookie;
2983 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2985 /* Add padding at the end of the fields part, since we know
2986 * the body needs to start at an 8 byte alignment. We made
2987 * sure we allocated enough space for this, so all we need to
2988 * do here is to zero it out. */
2989 a = ALIGN8(m->fields_size) - m->fields_size;
2991 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2993 /* If this is something we can send as memfd, then let's seal
2994 the memfd now. Note that we can send memfds as payload only
2995 for directed messages, and not for broadcasts. */
2996 if (m->destination && m->bus->use_memfd) {
2997 MESSAGE_FOREACH_PART(part, i, m)
2998 if (part->memfd >= 0 &&
3000 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3001 part != m->body_end) { /* The last part may never be sent as memfd */
3004 /* Try to seal it if that makes
3005 * sense. First, unmap our own map to
3006 * make sure we don't keep it busy. */
3007 bus_body_part_unmap(part);
3009 /* Then, sync up real memfd size */
3011 r = memfd_set_size(part->memfd, sz);
3015 /* Finally, try to seal */
3016 if (memfd_set_sealed(part->memfd) >= 0)
3017 part->sealed = true;
3021 m->root_container.end = m->user_body_size;
3022 m->root_container.index = 0;
3023 m->root_container.offset_index = 0;
3024 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3031 int bus_body_part_map(struct bus_body_part *part) {
3040 if (part->size <= 0)
3043 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3044 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3045 static const uint8_t zeroes[7] = { };
3046 part->data = (void*) zeroes;
3050 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3051 psz = PAGE_ALIGN(part->size + shift);
3053 if (part->memfd >= 0)
3054 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3055 else if (part->is_zero)
3056 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3060 if (p == MAP_FAILED)
3064 part->mmap_begin = p;
3065 part->data = (uint8_t*) p + shift;
3066 part->munmap_this = true;
3071 void bus_body_part_unmap(struct bus_body_part *part) {
3075 if (part->memfd < 0)
3078 if (!part->mmap_begin)
3081 if (!part->munmap_this)
3084 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3086 part->mmap_begin = NULL;
3089 part->munmap_this = false;
3094 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3095 size_t k, start, end;
3100 start = ALIGN_TO((size_t) *rindex, align);
3101 end = start + nbytes;
3106 /* Verify that padding is 0 */
3107 for (k = *rindex; k < start; k++)
3108 if (((const uint8_t*) p)[k] != 0)
3112 *r = (uint8_t*) p + start;
3119 static bool message_end_of_signature(sd_bus_message *m) {
3120 struct bus_container *c;
3124 c = message_get_container(m);
3125 return !c->signature || c->signature[c->index] == 0;
3128 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3129 struct bus_container *c;
3133 c = message_get_container(m);
3134 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3137 if (BUS_MESSAGE_IS_GVARIANT(m))
3138 return index >= c->end;
3140 assert(c->array_size);
3141 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3145 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3146 assert_return(m, -EINVAL);
3147 assert_return(m->sealed, -EPERM);
3149 if (complete && m->n_containers > 0)
3152 if (message_end_of_signature(m))
3155 if (message_end_of_array(m, m->rindex))
3161 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3162 struct bus_body_part *part;
3168 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3169 part = m->cached_rindex_part;
3170 begin = m->cached_rindex_part_begin;
3180 if (index + sz <= begin + part->size) {
3182 r = bus_body_part_map(part);
3187 *p = (uint8_t*) part->data + index - begin;
3189 m->cached_rindex_part = part;
3190 m->cached_rindex_part_begin = begin;
3195 begin += part->size;
3202 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3209 if (!BUS_MESSAGE_IS_GVARIANT(m))
3212 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3215 sz = bus_gvariant_get_size(c->signature);
3219 if (c->offset_index+1 >= c->n_offsets)
3222 /* Variable-size array */
3224 alignment = bus_gvariant_get_alignment(c->signature);
3225 assert(alignment > 0);
3227 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3228 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3231 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3234 /* Fixed-size array */
3235 *rindex = c->begin + (c->offset_index+1) * sz;
3241 } else if (c->enclosing == 0 ||
3242 c->enclosing == SD_BUS_TYPE_STRUCT ||
3243 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3248 if (c->offset_index+1 >= c->n_offsets)
3251 r = signature_element_length(c->signature + c->index, &n);
3255 r = signature_element_length(c->signature + c->index + n, &j);
3260 memcpy(t, c->signature + c->index + n, j);
3263 alignment = bus_gvariant_get_alignment(t);
3266 assert(alignment > 0);
3268 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3269 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3273 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3276 assert_not_reached("Unknown container type");
3281 /* Reached the end */
3288 static int message_peek_body(
3295 size_t k, start, end, padding;
3296 struct bus_body_part *part;
3303 start = ALIGN_TO((size_t) *rindex, align);
3304 padding = start - *rindex;
3305 end = start + nbytes;
3307 if (end > m->user_body_size)
3310 part = find_part(m, *rindex, padding, (void**) &q);
3315 /* Verify padding */
3316 for (k = 0; k < padding; k++)
3321 part = find_part(m, start, nbytes, (void**) &q);
3322 if (!part || (nbytes > 0 && !q))
3333 static bool validate_nul(const char *s, size_t l) {
3335 /* Check for NUL chars in the string */
3336 if (memchr(s, 0, l))
3339 /* Check for NUL termination */
3346 static bool validate_string(const char *s, size_t l) {
3348 if (!validate_nul(s, l))
3351 /* Check if valid UTF8 */
3352 if (!utf8_is_valid(s))
3358 static bool validate_signature(const char *s, size_t l) {
3360 if (!validate_nul(s, l))
3363 /* Check if valid signature */
3364 if (!signature_is_valid(s, true))
3370 static bool validate_object_path(const char *s, size_t l) {
3372 if (!validate_nul(s, l))
3375 if (!object_path_is_valid(s))
3381 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3382 struct bus_container *c;
3387 assert_return(m, -EINVAL);
3388 assert_return(m->sealed, -EPERM);
3389 assert_return(bus_type_is_basic(type), -EINVAL);
3391 if (message_end_of_signature(m))
3394 if (message_end_of_array(m, m->rindex))
3397 c = message_get_container(m);
3398 if (c->signature[c->index] != type)
3403 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3405 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3408 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3412 if (type == SD_BUS_TYPE_STRING)
3413 ok = validate_string(q, c->item_size-1);
3414 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3415 ok = validate_object_path(q, c->item_size-1);
3417 ok = validate_signature(q, c->item_size-1);
3423 *(const char**) p = q;
3427 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3429 if ((size_t) sz != c->item_size)
3432 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3435 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3441 case SD_BUS_TYPE_BYTE:
3443 *(uint8_t*) p = *(uint8_t*) q;
3446 case SD_BUS_TYPE_BOOLEAN:
3448 *(int*) p = !!*(uint8_t*) q;
3451 case SD_BUS_TYPE_INT16:
3452 case SD_BUS_TYPE_UINT16:
3454 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3457 case SD_BUS_TYPE_INT32:
3458 case SD_BUS_TYPE_UINT32:
3460 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3463 case SD_BUS_TYPE_INT64:
3464 case SD_BUS_TYPE_UINT64:
3465 case SD_BUS_TYPE_DOUBLE:
3467 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3470 case SD_BUS_TYPE_UNIX_FD: {
3473 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3478 *(int*) p = m->fds[j];
3484 assert_not_reached("unexpected type");
3488 r = container_next_item(m, c, &rindex);
3495 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3499 r = message_peek_body(m, &rindex, 4, 4, &q);
3503 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3504 r = message_peek_body(m, &rindex, 1, l+1, &q);
3508 if (type == SD_BUS_TYPE_OBJECT_PATH)
3509 ok = validate_object_path(q, l);
3511 ok = validate_string(q, l);
3516 *(const char**) p = q;
3518 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3521 r = message_peek_body(m, &rindex, 1, 1, &q);
3526 r = message_peek_body(m, &rindex, 1, l+1, &q);
3530 if (!validate_signature(q, l))
3534 *(const char**) p = q;
3539 align = bus_type_get_alignment(type);
3542 sz = bus_type_get_size(type);
3545 r = message_peek_body(m, &rindex, align, sz, &q);
3551 case SD_BUS_TYPE_BYTE:
3553 *(uint8_t*) p = *(uint8_t*) q;
3556 case SD_BUS_TYPE_BOOLEAN:
3558 *(int*) p = !!*(uint32_t*) q;
3561 case SD_BUS_TYPE_INT16:
3562 case SD_BUS_TYPE_UINT16:
3564 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3567 case SD_BUS_TYPE_INT32:
3568 case SD_BUS_TYPE_UINT32:
3570 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3573 case SD_BUS_TYPE_INT64:
3574 case SD_BUS_TYPE_UINT64:
3575 case SD_BUS_TYPE_DOUBLE:
3577 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3580 case SD_BUS_TYPE_UNIX_FD: {
3583 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3588 *(int*) p = m->fds[j];
3593 assert_not_reached("Unknown basic type...");
3600 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3606 static int bus_message_enter_array(
3608 struct bus_container *c,
3609 const char *contents,
3610 uint32_t **array_size,
3613 size_t *n_offsets) {
3627 if (!signature_is_single(contents, true))
3630 if (!c->signature || c->signature[c->index] == 0)
3633 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3636 if (!startswith(c->signature + c->index + 1, contents))
3641 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3644 r = message_peek_body(m, &rindex, 4, 4, &q);
3648 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3651 alignment = bus_type_get_alignment(contents[0]);
3655 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3659 *array_size = (uint32_t*) q;
3661 } else if (c->item_size <= 0) {
3663 /* gvariant: empty array */
3668 } else if (bus_gvariant_is_fixed_size(contents)) {
3670 /* gvariant: fixed length array */
3671 *item_size = bus_gvariant_get_size(contents);
3676 size_t where, p = 0, framing, sz;
3679 /* gvariant: variable length array */
3680 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3682 where = rindex + c->item_size - sz;
3683 r = message_peek_body(m, &where, 1, sz, &q);
3687 framing = bus_gvariant_read_word_le(q, sz);
3688 if (framing > c->item_size - sz)
3690 if ((c->item_size - framing) % sz != 0)
3693 *n_offsets = (c->item_size - framing) / sz;
3695 where = rindex + framing;
3696 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3700 *offsets = new(size_t, *n_offsets);
3704 for (i = 0; i < *n_offsets; i++) {
3707 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3708 if (x > c->item_size - sz)
3713 (*offsets)[i] = rindex + x;
3717 *item_size = (*offsets)[0] - rindex;
3722 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3723 c->index += 1 + strlen(contents);
3728 static int bus_message_enter_variant(
3730 struct bus_container *c,
3731 const char *contents,
3732 size_t *item_size) {
3744 if (!signature_is_single(contents, false))
3747 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3750 if (!c->signature || c->signature[c->index] == 0)
3753 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3758 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3761 k = strlen(contents);
3762 if (1+k > c->item_size)
3765 where = rindex + c->item_size - (1+k);
3766 r = message_peek_body(m, &where, 1, 1+k, &q);
3770 if (*(char*) q != 0)
3773 if (memcmp((uint8_t*) q+1, contents, k))
3776 *item_size = c->item_size - (1+k);
3779 r = message_peek_body(m, &rindex, 1, 1, &q);
3784 r = message_peek_body(m, &rindex, 1, l+1, &q);
3788 if (!validate_signature(q, l))
3791 if (!streq(q, contents))
3797 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3803 static int build_struct_offsets(
3805 const char *signature,
3809 size_t *n_offsets) {
3811 unsigned n_variable = 0, n_total = 0, v;
3812 size_t previous = 0, where;
3823 if (isempty(signature)) {
3830 sz = bus_gvariant_determine_word_size(size, 0);
3834 /* First, loop over signature and count variable elements and
3835 * elements in general. We use this to know how large the
3836 * offset array is at the end of the structure. Note that
3837 * GVariant only stores offsets for all variable size elements
3838 * that are not the last item. */
3844 r = signature_element_length(p, &n);
3853 r = bus_gvariant_is_fixed_size(t);
3858 if (r == 0 && p[n] != 0) /* except the last item */
3865 if (size < n_variable * sz)
3868 where = m->rindex + size - (n_variable * sz);
3869 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3875 *offsets = new(size_t, n_total);
3881 /* Second, loop again and build an offset table */
3887 r = signature_element_length(p, &n);
3896 k = bus_gvariant_get_size(t);
3904 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3907 if (m->rindex + x < previous)
3910 /* The last item's end
3911 * is determined from
3914 x = size - (n_variable * sz);
3916 offset = m->rindex + x;
3922 align = bus_gvariant_get_alignment(t);
3925 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3929 previous = (*offsets)[(*n_offsets)++] = offset;
3934 assert(*n_offsets == n_total);
3936 *item_size = (*offsets)[0] - m->rindex;
3940 static int enter_struct_or_dict_entry(
3942 struct bus_container *c,
3943 const char *contents,
3946 size_t *n_offsets) {
3957 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3960 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3964 } else if (c->item_size <= 0) {
3966 /* gvariant empty struct */
3971 /* gvariant with contents */
3972 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3977 static int bus_message_enter_struct(
3979 struct bus_container *c,
3980 const char *contents,
3983 size_t *n_offsets) {
3995 if (!signature_is_valid(contents, false))
3998 if (!c->signature || c->signature[c->index] == 0)
4001 l = strlen(contents);
4003 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4004 !startswith(c->signature + c->index + 1, contents) ||
4005 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4008 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4012 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4013 c->index += 1 + l + 1;
4018 static int bus_message_enter_dict_entry(
4020 struct bus_container *c,
4021 const char *contents,
4024 size_t *n_offsets) {
4033 if (!signature_is_pair(contents))
4036 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4039 if (!c->signature || c->signature[c->index] == 0)
4042 l = strlen(contents);
4044 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4045 !startswith(c->signature + c->index + 1, contents) ||
4046 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4049 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4053 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4054 c->index += 1 + l + 1;
4059 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4061 const char *contents) {
4062 struct bus_container *c, *w;
4063 uint32_t *array_size = NULL;
4066 size_t *offsets = NULL;
4067 size_t n_offsets = 0, item_size = 0;
4070 assert_return(m, -EINVAL);
4071 assert_return(m->sealed, -EPERM);
4072 assert_return(type != 0 || !contents, -EINVAL);
4074 if (type == 0 || !contents) {
4078 /* Allow entering into anonymous containers */
4079 r = sd_bus_message_peek_type(m, &tt, &cc);
4083 if (type != 0 && type != tt)
4086 if (contents && !streq(contents, cc))
4094 * We enforce a global limit on container depth, that is much
4095 * higher than the 32 structs and 32 arrays the specification
4096 * mandates. This is simpler to implement for us, and we need
4097 * this only to ensure our container array doesn't grow
4098 * without bounds. We are happy to return any data from a
4099 * message as long as the data itself is valid, even if the
4100 * overall message might be not.
4102 * Note that the message signature is validated when
4103 * parsing the headers, and that validation does check the
4106 * Note that the specification defines no limits on the depth
4107 * of stacked variants, but we do.
4109 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4112 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4115 if (message_end_of_signature(m))
4118 if (message_end_of_array(m, m->rindex))
4121 c = message_get_container(m);
4123 signature = strdup(contents);
4127 c->saved_index = c->index;
4130 if (type == SD_BUS_TYPE_ARRAY)
4131 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4132 else if (type == SD_BUS_TYPE_VARIANT)
4133 r = bus_message_enter_variant(m, c, contents, &item_size);
4134 else if (type == SD_BUS_TYPE_STRUCT)
4135 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4136 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4137 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4147 /* OK, let's fill it in */
4148 w = m->containers + m->n_containers++;
4149 w->enclosing = type;
4150 w->signature = signature;
4151 w->peeked_signature = NULL;
4155 w->begin = m->rindex;
4156 w->end = m->rindex + c->item_size;
4158 w->array_size = array_size;
4159 w->item_size = item_size;
4160 w->offsets = offsets;
4161 w->n_offsets = n_offsets;
4162 w->offset_index = 0;
4167 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4168 struct bus_container *c;
4172 assert_return(m, -EINVAL);
4173 assert_return(m->sealed, -EPERM);
4174 assert_return(m->n_containers > 0, -ENXIO);
4176 c = message_get_container(m);
4178 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4179 if (c->signature && c->signature[c->index] != 0)
4183 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4184 if (m->rindex < c->end)
4187 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4190 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4191 if (c->begin + l != m->rindex)
4196 free(c->peeked_signature);
4200 c = message_get_container(m);
4203 c->index = c->saved_index;
4204 r = container_next_item(m, c, &m->rindex);
4212 static void message_quit_container(sd_bus_message *m) {
4213 struct bus_container *c;
4217 assert(m->n_containers > 0);
4219 c = message_get_container(m);
4222 assert(m->rindex >= c->before);
4223 m->rindex = c->before;
4225 /* Free container */
4230 /* Correct index of new top-level container */
4231 c = message_get_container(m);
4232 c->index = c->saved_index;
4235 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4236 struct bus_container *c;
4239 assert_return(m, -EINVAL);
4240 assert_return(m->sealed, -EPERM);
4242 if (message_end_of_signature(m))
4245 if (message_end_of_array(m, m->rindex))
4248 c = message_get_container(m);
4250 if (bus_type_is_basic(c->signature[c->index])) {
4254 *type = c->signature[c->index];
4258 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4264 r = signature_element_length(c->signature+c->index+1, &l);
4270 sig = strndup(c->signature + c->index + 1, l);
4274 free(c->peeked_signature);
4275 *contents = c->peeked_signature = sig;
4279 *type = SD_BUS_TYPE_ARRAY;
4284 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4285 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4291 r = signature_element_length(c->signature+c->index, &l);
4296 sig = strndup(c->signature + c->index + 1, l - 2);
4300 free(c->peeked_signature);
4301 *contents = c->peeked_signature = sig;
4305 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4310 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4314 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4317 if (c->item_size < 2)
4320 /* Look for the NUL delimiter that
4321 separates the payload from the
4322 signature. Since the body might be
4323 in a different part that then the
4324 signature we map byte by byte. */
4326 for (k = 2; k <= c->item_size; k++) {
4329 where = m->rindex + c->item_size - k;
4330 r = message_peek_body(m, &where, 1, k, &q);
4334 if (*(char*) q == 0)
4338 if (k > c->item_size)
4341 free(c->peeked_signature);
4342 c->peeked_signature = strndup((char*) q + 1, k - 1);
4343 if (!c->peeked_signature)
4346 if (!signature_is_valid(c->peeked_signature, true))
4349 *contents = c->peeked_signature;
4354 r = message_peek_body(m, &rindex, 1, 1, &q);
4359 r = message_peek_body(m, &rindex, 1, l+1, &q);
4363 if (!validate_signature(q, l))
4371 *type = SD_BUS_TYPE_VARIANT;
4386 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4387 struct bus_container *c;
4389 assert_return(m, -EINVAL);
4390 assert_return(m->sealed, -EPERM);
4393 message_reset_containers(m);
4396 c = message_get_container(m);
4398 c = message_get_container(m);
4400 c->offset_index = 0;
4402 m->rindex = c->begin;
4405 c->offset_index = 0;
4406 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4408 return !isempty(c->signature);
4411 static int message_read_ap(
4416 unsigned n_array, n_struct;
4417 TypeStack stack[BUS_CONTAINER_DEPTH];
4418 unsigned stack_ptr = 0;
4419 unsigned n_loop = 0;
4427 /* Ideally, we'd just call ourselves recursively on every
4428 * complex type. However, the state of a va_list that is
4429 * passed to a function is undefined after that function
4430 * returns. This means we need to docode the va_list linearly
4431 * in a single stackframe. We hence implement our own
4432 * home-grown stack in an array. */
4434 n_array = (unsigned) -1; /* length of current array entries */
4435 n_struct = strlen(types); /* length of current struct contents signature */
4442 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4443 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4449 r = sd_bus_message_exit_container(m);
4457 if (n_array != (unsigned) -1)
4466 case SD_BUS_TYPE_BYTE:
4467 case SD_BUS_TYPE_BOOLEAN:
4468 case SD_BUS_TYPE_INT16:
4469 case SD_BUS_TYPE_UINT16:
4470 case SD_BUS_TYPE_INT32:
4471 case SD_BUS_TYPE_UINT32:
4472 case SD_BUS_TYPE_INT64:
4473 case SD_BUS_TYPE_UINT64:
4474 case SD_BUS_TYPE_DOUBLE:
4475 case SD_BUS_TYPE_STRING:
4476 case SD_BUS_TYPE_OBJECT_PATH:
4477 case SD_BUS_TYPE_SIGNATURE:
4478 case SD_BUS_TYPE_UNIX_FD: {
4481 p = va_arg(ap, void*);
4482 r = sd_bus_message_read_basic(m, *t, p);
4495 case SD_BUS_TYPE_ARRAY: {
4498 r = signature_element_length(t + 1, &k);
4504 memcpy(s, t + 1, k);
4507 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4518 if (n_array == (unsigned) -1) {
4523 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4529 n_array = va_arg(ap, unsigned);
4534 case SD_BUS_TYPE_VARIANT: {
4537 s = va_arg(ap, const char *);
4541 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4551 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4556 n_struct = strlen(s);
4557 n_array = (unsigned) -1;
4562 case SD_BUS_TYPE_STRUCT_BEGIN:
4563 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4566 r = signature_element_length(t, &k);
4572 memcpy(s, t + 1, k - 2);
4575 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4585 if (n_array == (unsigned) -1) {
4590 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4596 n_array = (unsigned) -1;
4609 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4613 assert_return(m, -EINVAL);
4614 assert_return(m->sealed, -EPERM);
4615 assert_return(types, -EINVAL);
4617 va_start(ap, types);
4618 r = message_read_ap(m, types, ap);
4624 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4627 assert_return(m, -EINVAL);
4628 assert_return(m->sealed, -EPERM);
4630 /* If types is NULL, read exactly one element */
4632 struct bus_container *c;
4635 if (message_end_of_signature(m))
4638 if (message_end_of_array(m, m->rindex))
4641 c = message_get_container(m);
4643 r = signature_element_length(c->signature + c->index, &l);
4647 types = strndupa(c->signature + c->index, l);
4652 case 0: /* Nothing to drop */
4655 case SD_BUS_TYPE_BYTE:
4656 case SD_BUS_TYPE_BOOLEAN:
4657 case SD_BUS_TYPE_INT16:
4658 case SD_BUS_TYPE_UINT16:
4659 case SD_BUS_TYPE_INT32:
4660 case SD_BUS_TYPE_UINT32:
4661 case SD_BUS_TYPE_INT64:
4662 case SD_BUS_TYPE_UINT64:
4663 case SD_BUS_TYPE_DOUBLE:
4664 case SD_BUS_TYPE_STRING:
4665 case SD_BUS_TYPE_OBJECT_PATH:
4666 case SD_BUS_TYPE_SIGNATURE:
4667 case SD_BUS_TYPE_UNIX_FD:
4669 r = sd_bus_message_read_basic(m, *types, NULL);
4673 r = sd_bus_message_skip(m, types + 1);
4679 case SD_BUS_TYPE_ARRAY: {
4682 r = signature_element_length(types + 1, &k);
4688 memcpy(s, types+1, k);
4691 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4696 r = sd_bus_message_skip(m, s);
4703 r = sd_bus_message_exit_container(m);
4708 r = sd_bus_message_skip(m, types + 1 + k);
4715 case SD_BUS_TYPE_VARIANT: {
4716 const char *contents;
4719 r = sd_bus_message_peek_type(m, &x, &contents);
4723 if (x != SD_BUS_TYPE_VARIANT)
4726 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4730 r = sd_bus_message_skip(m, contents);
4735 r = sd_bus_message_exit_container(m);
4739 r = sd_bus_message_skip(m, types + 1);
4746 case SD_BUS_TYPE_STRUCT_BEGIN:
4747 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4750 r = signature_element_length(types, &k);
4756 memcpy(s, types+1, k-2);
4759 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4763 r = sd_bus_message_skip(m, s);
4768 r = sd_bus_message_exit_container(m);
4773 r = sd_bus_message_skip(m, types + k);
4785 _public_ int sd_bus_message_read_array(
4791 struct bus_container *c;
4797 assert_return(m, -EINVAL);
4798 assert_return(m->sealed, -EPERM);
4799 assert_return(bus_type_is_trivial(type), -EINVAL);
4800 assert_return(ptr, -EINVAL);
4801 assert_return(size, -EINVAL);
4802 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4804 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4808 c = message_get_container(m);
4810 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4811 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4815 sz = c->end - c->begin;
4817 align = bus_type_get_alignment(type);
4821 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4825 /* Zero length array, let's return some aligned
4826 * pointer that is not NULL */
4827 p = (uint8_t*) NULL + align;
4829 r = message_peek_body(m, &m->rindex, align, sz, &p);
4834 r = sd_bus_message_exit_container(m);
4838 *ptr = (const void*) p;
4844 message_quit_container(m);
4848 static int message_peek_fields(
4859 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4862 static int message_peek_field_uint32(
4874 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4877 /* identical for gvariant and dbus1 */
4879 r = message_peek_fields(m, ri, 4, 4, &q);
4884 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4889 static int message_peek_field_uint64(
4901 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4904 /* identical for gvariant and dbus1 */
4906 r = message_peek_fields(m, ri, 8, 8, &q);
4911 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4916 static int message_peek_field_string(
4918 bool (*validate)(const char *p),
4930 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4935 r = message_peek_fields(m, ri, 1, item_size, &q);
4941 r = message_peek_field_uint32(m, ri, 4, &l);
4945 r = message_peek_fields(m, ri, 1, l+1, &q);
4951 if (!validate_nul(q, l))
4957 if (!validate_string(q, l))
4967 static int message_peek_field_signature(
4980 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4985 r = message_peek_fields(m, ri, 1, item_size, &q);
4991 r = message_peek_fields(m, ri, 1, 1, &q);
4996 r = message_peek_fields(m, ri, 1, l+1, &q);
5001 if (!validate_signature(q, l))
5010 static int message_skip_fields(
5013 uint32_t array_size,
5014 const char **signature) {
5016 size_t original_index;
5022 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5024 original_index = *ri;
5030 if (array_size != (uint32_t) -1 &&
5031 array_size <= *ri - original_index)
5038 if (t == SD_BUS_TYPE_STRING) {
5040 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5046 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5048 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5054 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5056 r = message_peek_field_signature(m, ri, 0, NULL);
5062 } else if (bus_type_is_basic(t)) {
5065 align = bus_type_get_alignment(t);
5066 k = bus_type_get_size(t);
5067 assert(align > 0 && k > 0);
5069 r = message_peek_fields(m, ri, align, k, NULL);
5075 } else if (t == SD_BUS_TYPE_ARRAY) {
5077 r = signature_element_length(*signature+1, &l);
5087 strncpy(sig, *signature + 1, l-1);
5090 alignment = bus_type_get_alignment(sig[0]);
5094 r = message_peek_field_uint32(m, ri, 0, &nas);
5097 if (nas > BUS_ARRAY_MAX_SIZE)
5100 r = message_peek_fields(m, ri, alignment, 0, NULL);
5104 r = message_skip_fields(m, ri, nas, (const char**) &s);
5109 (*signature) += 1 + l;
5111 } else if (t == SD_BUS_TYPE_VARIANT) {
5114 r = message_peek_field_signature(m, ri, 0, &s);
5118 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5124 } else if (t == SD_BUS_TYPE_STRUCT ||
5125 t == SD_BUS_TYPE_DICT_ENTRY) {
5127 r = signature_element_length(*signature, &l);
5134 strncpy(sig, *signature + 1, l-1);
5137 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5148 int bus_message_parse_fields(sd_bus_message *m) {
5151 uint32_t unix_fds = 0;
5152 bool unix_fds_set = false;
5153 void *offsets = NULL;
5154 unsigned n_offsets = 0;
5160 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5163 /* Read the signature from the end of the body variant first */
5164 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5165 if (m->footer_accessible < 1 + sz)
5168 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5170 if (p < (char*) m->footer)
5176 /* We found the beginning of the signature string, yay! */
5178 c = strndup(p + 1, ((char*) m->footer + m->footer_accessible) - p - (1 + sz));
5182 free(m->root_container.signature);
5183 m->root_container.signature = c;
5190 /* Calculate the actual user body size, by removing
5191 * the trailing variant signature and struct offset
5193 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5195 /* Pull out the offset table for the fields array */
5196 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5201 ri = m->fields_size - sz;
5202 r = message_peek_fields(m, &ri, 1, sz, &q);
5206 framing = bus_gvariant_read_word_le(q, sz);
5207 if (framing >= m->fields_size - sz)
5209 if ((m->fields_size - framing) % sz != 0)
5213 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5217 n_offsets = (m->fields_size - framing) / sz;
5220 m->user_body_size = m->body_size;
5223 while (ri < m->fields_size) {
5224 _cleanup_free_ char *sig = NULL;
5225 const char *signature;
5226 uint64_t field_type;
5227 size_t item_size = (size_t) -1;
5229 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5238 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5240 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5244 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5248 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5255 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5260 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5265 where = ri = ALIGN_TO(ri, 8);
5266 item_size = end - ri;
5267 r = message_peek_fields(m, &where, 1, item_size, &q);
5271 b = memrchr(q, 0, item_size);
5275 sig = strndup(b+1, item_size - (b+1-(char*) q));
5280 item_size = b - (char*) q;
5282 r = message_peek_field_signature(m, &ri, 0, &signature);
5287 switch (field_type) {
5289 case _BUS_MESSAGE_HEADER_INVALID:
5292 case BUS_MESSAGE_HEADER_PATH:
5297 if (!streq(signature, "o"))
5300 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5303 case BUS_MESSAGE_HEADER_INTERFACE:
5308 if (!streq(signature, "s"))
5311 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5314 case BUS_MESSAGE_HEADER_MEMBER:
5319 if (!streq(signature, "s"))
5322 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5325 case BUS_MESSAGE_HEADER_ERROR_NAME:
5330 if (!streq(signature, "s"))
5333 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5335 m->error._need_free = -1;
5339 case BUS_MESSAGE_HEADER_DESTINATION:
5344 if (!streq(signature, "s"))
5347 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5350 case BUS_MESSAGE_HEADER_SENDER:
5355 if (!streq(signature, "s"))
5358 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5360 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5361 m->creds.unique_name = (char*) m->sender;
5362 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5368 case BUS_MESSAGE_HEADER_SIGNATURE: {
5372 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5375 if (m->root_container.signature)
5378 if (!streq(signature, "g"))
5381 r = message_peek_field_signature(m, &ri, item_size, &s);
5389 free(m->root_container.signature);
5390 m->root_container.signature = c;
5394 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5396 if (m->reply_cookie != 0)
5399 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5400 /* 64bit on dbus2 */
5402 if (!streq(signature, "t"))
5405 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5409 /* 32bit on dbus1 */
5412 if (!streq(signature, "u"))
5415 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5419 m->reply_cookie = serial;
5422 if (m->reply_cookie == 0)
5427 case BUS_MESSAGE_HEADER_UNIX_FDS:
5431 if (!streq(signature, "u"))
5434 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5438 unix_fds_set = true;
5442 if (!BUS_MESSAGE_IS_GVARIANT(m))
5443 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5452 if (m->n_fds != unix_fds)
5455 switch (m->header->type) {
5457 case SD_BUS_MESSAGE_SIGNAL:
5458 if (!m->path || !m->interface || !m->member)
5461 if (m->reply_cookie != 0)
5466 case SD_BUS_MESSAGE_METHOD_CALL:
5468 if (!m->path || !m->member)
5471 if (m->reply_cookie != 0)
5476 case SD_BUS_MESSAGE_METHOD_RETURN:
5478 if (m->reply_cookie == 0)
5482 case SD_BUS_MESSAGE_METHOD_ERROR:
5484 if (m->reply_cookie == 0 || !m->error.name)
5489 /* Refuse non-local messages that claim they are local */
5490 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5492 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5494 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5497 m->root_container.end = m->user_body_size;
5499 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5500 r = build_struct_offsets(
5502 m->root_container.signature,
5504 &m->root_container.item_size,
5505 &m->root_container.offsets,
5506 &m->root_container.n_offsets);
5511 /* Try to read the error message, but if we can't it's a non-issue */
5512 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5513 sd_bus_message_read(m, "s", &m->error.message);
5518 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5519 assert_return(m, -EINVAL);
5520 assert_return(destination, -EINVAL);
5521 assert_return(!m->sealed, -EPERM);
5522 assert_return(!m->destination, -EEXIST);
5524 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5527 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5531 struct bus_body_part *part;
5537 total = BUS_MESSAGE_SIZE(m);
5543 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5544 MESSAGE_FOREACH_PART(part, i, m)
5545 e = mempcpy(e, part->data, part->size);
5547 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5555 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5561 r = sd_bus_message_enter_container(m, 'a', "s");
5568 r = sd_bus_message_read_basic(m, 's', &s);
5574 r = strv_extend(l, s);
5579 r = sd_bus_message_exit_container(m);
5586 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5590 assert_return(m, -EINVAL);
5591 assert_return(m->sealed, -EPERM);
5592 assert_return(l, -EINVAL);
5594 r = bus_message_read_strv_extend(m, &strv);
5604 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5605 const char *contents;
5614 r = sd_bus_message_rewind(m, true);
5619 r = sd_bus_message_peek_type(m, &type, &contents);
5625 /* Don't match against arguments after the first one we don't understand */
5626 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5627 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5633 r = sd_bus_message_skip(m, NULL);
5638 if (type == SD_BUS_TYPE_ARRAY) {
5640 r = sd_bus_message_read_strv(m, strv);
5647 r = sd_bus_message_read_basic(m, type, str);
5657 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5658 assert_return(m, EINVAL);
5660 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5663 return sd_bus_error_get_errno(&m->error);
5666 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5667 struct bus_container *c;
5669 assert_return(m, NULL);
5671 c = complete ? &m->root_container : message_get_container(m);
5672 return strempty(c->signature);
5675 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5676 assert_return(m, -EINVAL);
5678 return isempty(m->root_container.signature);
5681 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5682 assert_return(m, -EINVAL);
5684 return streq(strempty(m->root_container.signature), strempty(signature));
5687 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5688 bool done_something = false;
5691 assert_return(m, -EINVAL);
5692 assert_return(source, -EINVAL);
5693 assert_return(!m->sealed, -EPERM);
5694 assert_return(source->sealed, -EPERM);
5697 const char *contents;
5712 r = sd_bus_message_peek_type(source, &type, &contents);
5718 done_something = true;
5720 if (bus_type_is_container(type) > 0) {
5722 r = sd_bus_message_enter_container(source, type, contents);
5726 r = sd_bus_message_open_container(m, type, contents);
5730 r = sd_bus_message_copy(m, source, true);
5734 r = sd_bus_message_close_container(m);
5738 r = sd_bus_message_exit_container(source);
5745 r = sd_bus_message_read_basic(source, type, &basic);
5751 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5752 type == SD_BUS_TYPE_SIGNATURE ||
5753 type == SD_BUS_TYPE_STRING)
5754 r = sd_bus_message_append_basic(m, type, basic.string);
5756 r = sd_bus_message_append_basic(m, type, &basic);
5763 return done_something;
5766 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5771 assert_return(m, -EINVAL);
5772 assert_return(m->sealed, -EPERM);
5773 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5774 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5775 assert_return(type || contents, -EINVAL);
5776 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5778 r = sd_bus_message_peek_type(m, &t, &c);
5782 if (type != 0 && type != t)
5785 if (contents && !streq_ptr(contents, c))
5791 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5792 assert_return(m, NULL);
5797 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5798 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5806 switch ((*m)->header->type) {
5808 case SD_BUS_MESSAGE_SIGNAL:
5809 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5815 case SD_BUS_MESSAGE_METHOD_CALL:
5816 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5822 case SD_BUS_MESSAGE_METHOD_RETURN:
5823 case SD_BUS_MESSAGE_METHOD_ERROR:
5825 n = message_new(bus, (*m)->header->type);
5829 n->reply_cookie = (*m)->reply_cookie;
5831 r = message_append_reply_cookie(n, n->reply_cookie);
5835 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5836 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5840 n->error._need_free = -1;
5849 if ((*m)->destination && !n->destination) {
5850 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5855 if ((*m)->sender && !n->sender) {
5856 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5861 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5863 r = sd_bus_message_copy(n, *m, true);
5867 timeout = (*m)->timeout;
5868 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5869 timeout = BUS_DEFAULT_TIMEOUT;
5871 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5875 sd_bus_message_unref(*m);
5882 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5886 assert_return(!m->sealed, -EPERM);
5887 assert_return(!m->sender, -EPERM);
5889 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5892 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5893 assert_return(m, -EINVAL);
5894 assert_return(priority, -EINVAL);
5896 *priority = m->priority;
5900 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5901 assert_return(m, -EINVAL);
5902 assert_return(!m->sealed, -EPERM);
5904 m->priority = priority;