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) {
443 _cleanup_free_ sd_bus_message *m = NULL;
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 (!IN_SET(h->version, 1, 2))
465 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
468 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
471 /* Note that we are happy with unknown flags in the flags header! */
473 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
476 label_sz = strlen(label);
487 m->header_accessible = header_accessible;
489 m->footer_accessible = footer_accessible;
491 if (BUS_MESSAGE_IS_GVARIANT(m)) {
494 if (h->dbus2.cookie == 0)
497 /* dbus2 derives the sizes from the message size and
498 the offset table at the end, since it is formatted as
499 gvariant "yyyyuta{tv}v". Since the message itself is a
500 structure with precisely to variable sized entries,
501 there's only one offset in the table, which marks the
502 end of the fields array. */
504 ws = bus_gvariant_determine_word_size(message_size, 0);
505 if (footer_accessible < ws)
508 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
509 if (ALIGN8(m->fields_size) > message_size - ws)
511 if (m->fields_size < sizeof(struct bus_header))
514 m->fields_size -= sizeof(struct bus_header);
515 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
517 if (h->dbus1.serial == 0)
520 /* dbus1 has the sizes in the header */
521 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
522 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
524 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
532 m->creds.pid = ucred->pid;
533 m->creds.euid = ucred->uid;
534 m->creds.egid = ucred->gid;
536 /* Due to namespace translations some data might be
537 * missing from this ucred record. */
538 if (m->creds.pid > 0)
539 m->creds.mask |= SD_BUS_CREDS_PID;
541 if (m->creds.euid != UID_INVALID)
542 m->creds.mask |= SD_BUS_CREDS_EUID;
544 if (m->creds.egid != GID_INVALID)
545 m->creds.mask |= SD_BUS_CREDS_EGID;
549 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
550 memcpy(m->creds.label, label, label_sz + 1);
552 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
555 m->bus = sd_bus_ref(bus);
562 int bus_message_from_malloc(
568 const struct ucred *ucred,
570 sd_bus_message **ret) {
576 r = bus_message_from_header(
578 buffer, length, /* in this case the initial bytes and the final bytes are the same */
587 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
590 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
592 m->body.sealed = true;
597 m->iovec = m->iovec_fixed;
598 m->iovec[0].iov_base = buffer;
599 m->iovec[0].iov_len = length;
601 r = bus_message_parse_fields(m);
605 /* We take possession of the memory and fds now */
606 m->free_header = true;
617 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
622 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
627 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
628 m->header->endian = BUS_NATIVE_ENDIAN;
629 m->header->type = type;
630 m->header->version = bus ? bus->message_version : 1;
631 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
632 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
633 m->bus = sd_bus_ref(bus);
635 if (bus->allow_interactive_authorization)
636 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
641 _public_ int sd_bus_message_new_signal(
645 const char *interface,
646 const char *member) {
651 assert_return(bus, -ENOTCONN);
652 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
653 assert_return(object_path_is_valid(path), -EINVAL);
654 assert_return(interface_name_is_valid(interface), -EINVAL);
655 assert_return(member_name_is_valid(member), -EINVAL);
656 assert_return(m, -EINVAL);
658 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
662 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
664 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
667 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
670 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
678 sd_bus_message_unref(t);
682 _public_ int sd_bus_message_new_method_call(
685 const char *destination,
687 const char *interface,
688 const char *member) {
693 assert_return(bus, -ENOTCONN);
694 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
695 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
696 assert_return(object_path_is_valid(path), -EINVAL);
697 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
698 assert_return(member_name_is_valid(member), -EINVAL);
699 assert_return(m, -EINVAL);
701 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
705 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
708 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
713 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
719 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
732 static int message_new_reply(
733 sd_bus_message *call,
735 sd_bus_message **m) {
740 assert_return(call, -EINVAL);
741 assert_return(call->sealed, -EPERM);
742 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
743 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
744 assert_return(m, -EINVAL);
746 t = message_new(call->bus, type);
750 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
751 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
752 if (t->reply_cookie == 0)
755 r = message_append_reply_cookie(t, t->reply_cookie);
760 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
765 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
766 t->enforced_reply_signature = call->enforced_reply_signature;
776 _public_ int sd_bus_message_new_method_return(
777 sd_bus_message *call,
778 sd_bus_message **m) {
780 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
783 _public_ int sd_bus_message_new_method_error(
784 sd_bus_message *call,
786 const sd_bus_error *e) {
791 assert_return(sd_bus_error_is_set(e), -EINVAL);
792 assert_return(m, -EINVAL);
794 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
798 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
803 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
808 t->error._need_free = -1;
818 _public_ int sd_bus_message_new_method_errorf(
819 sd_bus_message *call,
825 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
828 assert_return(name, -EINVAL);
829 assert_return(m, -EINVAL);
831 va_start(ap, format);
832 bus_error_setfv(&error, name, format, ap);
835 return sd_bus_message_new_method_error(call, m, &error);
838 _public_ int sd_bus_message_new_method_errno(
839 sd_bus_message *call,
842 const sd_bus_error *p) {
844 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
846 if (sd_bus_error_is_set(p))
847 return sd_bus_message_new_method_error(call, m, p);
849 sd_bus_error_set_errno(&berror, error);
851 return sd_bus_message_new_method_error(call, m, &berror);
854 _public_ int sd_bus_message_new_method_errnof(
855 sd_bus_message *call,
861 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
864 va_start(ap, format);
865 sd_bus_error_set_errnofv(&berror, error, format, ap);
868 return sd_bus_message_new_method_error(call, m, &berror);
871 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
875 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
876 m->creds.well_known_names_local = true;
877 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
880 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
884 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
885 m->creds.well_known_names_driver = true;
886 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
889 int bus_message_new_synthetic_error(
892 const sd_bus_error *e,
893 sd_bus_message **m) {
899 assert(sd_bus_error_is_set(e));
902 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
906 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
907 t->reply_cookie = cookie;
909 r = message_append_reply_cookie(t, t->reply_cookie);
913 if (bus && bus->unique_name) {
914 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
919 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
924 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
929 t->error._need_free = -1;
931 bus_message_set_sender_driver(bus, t);
941 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
942 assert_return(m, NULL);
944 assert(m->n_ref > 0);
950 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
955 assert(m->n_ref > 0);
965 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
966 assert_return(m, -EINVAL);
967 assert_return(type, -EINVAL);
969 *type = m->header->type;
973 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
976 assert_return(m, -EINVAL);
977 assert_return(cookie, -EINVAL);
979 c = BUS_MESSAGE_COOKIE(m);
983 *cookie = BUS_MESSAGE_COOKIE(m);
987 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
988 assert_return(m, -EINVAL);
989 assert_return(cookie, -EINVAL);
991 if (m->reply_cookie == 0)
994 *cookie = m->reply_cookie;
998 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
999 assert_return(m, -EINVAL);
1001 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
1002 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
1005 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
1006 assert_return(m, -EINVAL);
1008 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
1011 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
1012 assert_return(m, -EINVAL);
1014 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
1015 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
1018 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1019 assert_return(m, NULL);
1024 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1025 assert_return(m, NULL);
1027 return m->interface;
1030 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1031 assert_return(m, NULL);
1036 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1037 assert_return(m, NULL);
1039 return m->destination;
1042 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1043 assert_return(m, NULL);
1048 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1049 assert_return(m, NULL);
1050 assert_return(sd_bus_error_is_set(&m->error), NULL);
1055 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1056 assert_return(m, -EINVAL);
1057 assert_return(usec, -EINVAL);
1059 if (m->monotonic <= 0)
1062 *usec = m->monotonic;
1066 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1067 assert_return(m, -EINVAL);
1068 assert_return(usec, -EINVAL);
1070 if (m->realtime <= 0)
1073 *usec = m->realtime;
1077 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1078 assert_return(m, -EINVAL);
1079 assert_return(seqnum, -EINVAL);
1084 *seqnum = m->seqnum;
1088 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1089 assert_return(m, NULL);
1091 if (m->creds.mask == 0)
1097 _public_ int sd_bus_message_is_signal(
1099 const char *interface,
1100 const char *member) {
1102 assert_return(m, -EINVAL);
1104 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
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_call(
1118 const char *interface,
1119 const char *member) {
1121 assert_return(m, -EINVAL);
1123 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1126 if (interface && (!m->interface || !streq(m->interface, interface)))
1129 if (member && (!m->member || !streq(m->member, member)))
1135 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1136 assert_return(m, -EINVAL);
1138 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1141 if (name && (!m->error.name || !streq(m->error.name, name)))
1147 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1148 assert_return(m, -EINVAL);
1149 assert_return(!m->sealed, -EPERM);
1150 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1153 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1155 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1160 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1161 assert_return(m, -EINVAL);
1162 assert_return(!m->sealed, -EPERM);
1165 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1167 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1172 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1173 assert_return(m, -EINVAL);
1174 assert_return(!m->sealed, -EPERM);
1177 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1179 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1184 static struct bus_container *message_get_container(sd_bus_message *m) {
1187 if (m->n_containers == 0)
1188 return &m->root_container;
1190 assert(m->containers);
1191 return m->containers + m->n_containers - 1;
1194 struct bus_body_part *message_append_part(sd_bus_message *m) {
1195 struct bus_body_part *part;
1202 if (m->n_body_parts <= 0) {
1206 assert(m->body_end);
1208 part = new0(struct bus_body_part, 1);
1214 m->body_end->next = part;
1224 static void part_zero(struct bus_body_part *part, size_t sz) {
1229 /* All other fields can be left in their defaults */
1230 assert(!part->data);
1231 assert(part->memfd < 0);
1234 part->is_zero = true;
1235 part->sealed = true;
1238 static int part_make_space(
1239 struct sd_bus_message *m,
1240 struct bus_body_part *part,
1249 assert(!part->sealed);
1254 if (!part->data && part->memfd < 0) {
1255 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1256 part->mmap_begin = part->data;
1259 if (part->memfd >= 0) {
1261 if (part->allocated == 0 || sz > part->allocated) {
1262 uint64_t new_allocated;
1264 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1265 r = memfd_set_size(part->memfd, new_allocated);
1271 part->allocated = new_allocated;
1274 if (!part->data || sz > part->mapped) {
1277 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1278 if (part->mapped <= 0)
1279 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1281 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1283 if (n == MAP_FAILED) {
1288 part->mmap_begin = part->data = n;
1290 part->memfd_offset = 0;
1293 part->munmap_this = true;
1295 if (part->allocated == 0 || sz > part->allocated) {
1296 size_t new_allocated;
1298 new_allocated = sz > 0 ? 2 * sz : 64;
1299 n = realloc(part->data, new_allocated);
1306 part->allocated = new_allocated;
1307 part->free_this = true;
1312 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1318 static int message_add_offset(sd_bus_message *m, size_t offset) {
1319 struct bus_container *c;
1322 assert(BUS_MESSAGE_IS_GVARIANT(m));
1324 /* Add offset to current container, unless this is the first
1325 * item in it, which will have the 0 offset, which we can
1327 c = message_get_container(m);
1329 if (!c->need_offsets)
1332 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1335 c->offsets[c->n_offsets++] = offset;
1339 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1340 struct bus_container *c;
1347 /* Update counters */
1348 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1351 *c->array_size += expand;
1355 static void *message_extend_body(
1360 bool force_inline) {
1362 size_t start_body, end_body, padding, added;
1373 start_body = ALIGN_TO((size_t) m->body_size, align);
1374 end_body = start_body + sz;
1376 padding = start_body - m->body_size;
1377 added = padding + sz;
1379 /* Check for 32bit overflows */
1380 if (end_body > (size_t) ((uint32_t) -1) ||
1381 end_body < start_body) {
1387 struct bus_body_part *part = NULL;
1391 m->n_body_parts <= 0 ||
1392 m->body_end->sealed ||
1393 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1394 (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 */
1398 part = message_append_part(m);
1402 part_zero(part, padding);
1405 part = message_append_part(m);
1409 r = part_make_space(m, part, sz, &p);
1413 struct bus_container *c;
1415 size_t os, start_part, end_part;
1421 start_part = ALIGN_TO(part->size, align);
1422 end_part = start_part + sz;
1424 r = part_make_space(m, part, end_part, &p);
1429 memzero(p, padding);
1430 p = (uint8_t*) p + padding;
1433 /* Readjust pointers */
1434 for (c = m->containers; c < m->containers + m->n_containers; c++)
1435 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1437 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1440 /* Return something that is not NULL and is aligned */
1441 p = (uint8_t *) NULL + align;
1443 m->body_size = end_body;
1444 message_extend_containers(m, added);
1447 r = message_add_offset(m, end_body);
1457 static int message_push_fd(sd_bus_message *m, int fd) {
1468 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1472 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1480 m->fds[m->n_fds] = copy;
1486 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1487 _cleanup_close_ int fd = -1;
1488 struct bus_container *c;
1492 assert_return(m, -EINVAL);
1493 assert_return(!m->sealed, -EPERM);
1494 assert_return(bus_type_is_basic(type), -EINVAL);
1495 assert_return(!m->poisoned, -ESTALE);
1497 c = message_get_container(m);
1499 if (c->signature && c->signature[c->index]) {
1500 /* Container signature is already set */
1502 if (c->signature[c->index] != type)
1507 /* Maybe we can append to the signature? But only if this is the top-level container */
1508 if (c->enclosing != 0)
1511 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1518 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1524 case SD_BUS_TYPE_SIGNATURE:
1525 case SD_BUS_TYPE_STRING:
1528 /* Fall through... */
1529 case SD_BUS_TYPE_OBJECT_PATH:
1537 case SD_BUS_TYPE_BOOLEAN:
1539 u8 = p && *(int*) p;
1545 case SD_BUS_TYPE_UNIX_FD:
1550 fd = message_push_fd(m, *(int*) p);
1561 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1562 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1569 a = message_extend_body(m, align, sz, true, false);
1576 *stored = (const uint8_t*) a;
1583 case SD_BUS_TYPE_STRING:
1584 /* To make things easy we'll serialize a NULL string
1585 * into the empty string */
1588 /* Fall through... */
1589 case SD_BUS_TYPE_OBJECT_PATH:
1595 sz = 4 + strlen(p) + 1;
1598 case SD_BUS_TYPE_SIGNATURE:
1603 sz = 1 + strlen(p) + 1;
1606 case SD_BUS_TYPE_BOOLEAN:
1608 u32 = p && *(int*) p;
1614 case SD_BUS_TYPE_UNIX_FD:
1619 fd = message_push_fd(m, *(int*) p);
1630 align = bus_type_get_alignment(type);
1631 sz = bus_type_get_size(type);
1638 a = message_extend_body(m, align, sz, false, false);
1642 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1643 *(uint32_t*) a = sz - 5;
1644 memcpy((uint8_t*) a + 4, p, sz - 4);
1647 *stored = (const uint8_t*) a + 4;
1649 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1650 *(uint8_t*) a = sz - 2;
1651 memcpy((uint8_t*) a + 1, p, sz - 1);
1654 *stored = (const uint8_t*) a + 1;
1663 if (type == SD_BUS_TYPE_UNIX_FD)
1666 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1673 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1674 return message_append_basic(m, type, p, NULL);
1677 _public_ int sd_bus_message_append_string_space(
1682 struct bus_container *c;
1685 assert_return(m, -EINVAL);
1686 assert_return(s, -EINVAL);
1687 assert_return(!m->sealed, -EPERM);
1688 assert_return(!m->poisoned, -ESTALE);
1690 c = message_get_container(m);
1692 if (c->signature && c->signature[c->index]) {
1693 /* Container signature is already set */
1695 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1700 /* Maybe we can append to the signature? But only if this is the top-level container */
1701 if (c->enclosing != 0)
1704 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1711 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1712 a = message_extend_body(m, 1, size + 1, true, false);
1718 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1722 *(uint32_t*) a = size;
1728 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1734 _public_ int sd_bus_message_append_string_iovec(
1736 const struct iovec *iov,
1744 assert_return(m, -EINVAL);
1745 assert_return(!m->sealed, -EPERM);
1746 assert_return(iov || n == 0, -EINVAL);
1747 assert_return(!m->poisoned, -ESTALE);
1749 size = IOVEC_TOTAL_SIZE(iov, n);
1751 r = sd_bus_message_append_string_space(m, size, &p);
1755 for (i = 0; i < n; i++) {
1757 if (iov[i].iov_base)
1758 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1760 memset(p, ' ', iov[i].iov_len);
1762 p += iov[i].iov_len;
1768 static int bus_message_open_array(
1770 struct bus_container *c,
1771 const char *contents,
1772 uint32_t **array_size,
1774 bool *need_offsets) {
1784 assert(need_offsets);
1786 if (!signature_is_single(contents, true))
1789 if (c->signature && c->signature[c->index]) {
1791 /* Verify the existing signature */
1793 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1796 if (!startswith(c->signature + c->index + 1, contents))
1799 nindex = c->index + 1 + strlen(contents);
1803 if (c->enclosing != 0)
1806 /* Extend the existing signature */
1808 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1814 nindex = e - c->signature;
1817 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1818 alignment = bus_gvariant_get_alignment(contents);
1822 /* Add alignment padding and add to offset list */
1823 if (!message_extend_body(m, alignment, 0, false, false))
1826 r = bus_gvariant_is_fixed_size(contents);
1830 *begin = m->body_size;
1831 *need_offsets = r == 0;
1835 struct bus_body_part *o;
1837 alignment = bus_type_get_alignment(contents[0]);
1841 a = message_extend_body(m, 4, 4, false, false);
1846 op = m->body_end->data;
1847 os = m->body_end->size;
1849 /* Add alignment between size and first element */
1850 if (!message_extend_body(m, alignment, 0, false, false))
1853 /* location of array size might have changed so let's readjust a */
1854 if (o == m->body_end)
1855 a = adjust_pointer(a, op, os, m->body_end->data);
1861 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1867 static int bus_message_open_variant(
1869 struct bus_container *c,
1870 const char *contents) {
1876 if (!signature_is_single(contents, false))
1879 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1882 if (c->signature && c->signature[c->index]) {
1884 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1890 if (c->enclosing != 0)
1893 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1900 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1901 /* Variants are always aligned to 8 */
1903 if (!message_extend_body(m, 8, 0, false, false))
1910 l = strlen(contents);
1911 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1916 memcpy((uint8_t*) a + 1, contents, l + 1);
1919 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1925 static int bus_message_open_struct(
1927 struct bus_container *c,
1928 const char *contents,
1930 bool *need_offsets) {
1939 assert(need_offsets);
1941 if (!signature_is_valid(contents, false))
1944 if (c->signature && c->signature[c->index]) {
1947 l = strlen(contents);
1949 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1950 !startswith(c->signature + c->index + 1, contents) ||
1951 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1954 nindex = c->index + 1 + l + 1;
1958 if (c->enclosing != 0)
1961 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1967 nindex = e - c->signature;
1970 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1973 alignment = bus_gvariant_get_alignment(contents);
1977 if (!message_extend_body(m, alignment, 0, false, false))
1980 r = bus_gvariant_is_fixed_size(contents);
1984 *begin = m->body_size;
1985 *need_offsets = r == 0;
1987 /* Align contents to 8 byte boundary */
1988 if (!message_extend_body(m, 8, 0, false, false))
1992 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1998 static int bus_message_open_dict_entry(
2000 struct bus_container *c,
2001 const char *contents,
2003 bool *need_offsets) {
2011 assert(need_offsets);
2013 if (!signature_is_pair(contents))
2016 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2019 if (c->signature && c->signature[c->index]) {
2022 l = strlen(contents);
2024 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2025 !startswith(c->signature + c->index + 1, contents) ||
2026 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2031 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2034 alignment = bus_gvariant_get_alignment(contents);
2038 if (!message_extend_body(m, alignment, 0, false, false))
2041 r = bus_gvariant_is_fixed_size(contents);
2045 *begin = m->body_size;
2046 *need_offsets = r == 0;
2048 /* Align contents to 8 byte boundary */
2049 if (!message_extend_body(m, 8, 0, false, false))
2056 _public_ int sd_bus_message_open_container(
2059 const char *contents) {
2061 struct bus_container *c, *w;
2062 uint32_t *array_size = NULL;
2064 size_t before, begin = 0;
2065 bool need_offsets = false;
2068 assert_return(m, -EINVAL);
2069 assert_return(!m->sealed, -EPERM);
2070 assert_return(contents, -EINVAL);
2071 assert_return(!m->poisoned, -ESTALE);
2073 /* Make sure we have space for one more container */
2074 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2079 c = message_get_container(m);
2081 signature = strdup(contents);
2087 /* Save old index in the parent container, in case we have to
2088 * abort this container */
2089 c->saved_index = c->index;
2090 before = m->body_size;
2092 if (type == SD_BUS_TYPE_ARRAY)
2093 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2094 else if (type == SD_BUS_TYPE_VARIANT)
2095 r = bus_message_open_variant(m, c, contents);
2096 else if (type == SD_BUS_TYPE_STRUCT)
2097 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2098 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2099 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2108 /* OK, let's fill it in */
2109 w = m->containers + m->n_containers++;
2110 w->enclosing = type;
2111 w->signature = signature;
2113 w->array_size = array_size;
2116 w->n_offsets = w->offsets_allocated = 0;
2118 w->need_offsets = need_offsets;
2123 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2128 if (!BUS_MESSAGE_IS_GVARIANT(m))
2131 if (c->need_offsets) {
2132 size_t payload, sz, i;
2135 /* Variable-width arrays */
2137 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2138 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2140 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2144 for (i = 0; i < c->n_offsets; i++)
2145 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2149 /* Fixed-width or empty arrays */
2151 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2159 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2165 assert(c->signature);
2167 if (!BUS_MESSAGE_IS_GVARIANT(m))
2170 l = strlen(c->signature);
2172 a = message_extend_body(m, 1, 1 + l, true, false);
2177 memcpy(a+1, c->signature, l);
2182 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2183 size_t n_variable = 0;
2192 if (!BUS_MESSAGE_IS_GVARIANT(m))
2195 p = strempty(c->signature);
2199 r = signature_element_length(p, &n);
2208 r = bus_gvariant_is_fixed_size(t);
2213 assert(!c->need_offsets || i <= c->n_offsets);
2215 /* We need to add an offset for each item that has a
2216 * variable size and that is not the last one in the
2218 if (r == 0 && p[n] != 0)
2225 assert(!c->need_offsets || i == c->n_offsets);
2226 assert(c->need_offsets || n_variable == 0);
2228 if (n_variable <= 0) {
2229 a = message_extend_body(m, 1, 0, add_offset, false);
2236 assert(c->offsets[c->n_offsets-1] == m->body_size);
2238 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2240 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2244 p = strempty(c->signature);
2245 for (i = 0, j = 0; i < c->n_offsets; i++) {
2249 r = signature_element_length(p, &n);
2260 r = bus_gvariant_is_fixed_size(t);
2263 if (r > 0 || p[0] == 0)
2267 k = n_variable - 1 - j;
2269 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2278 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2279 struct bus_container *c;
2282 assert_return(m, -EINVAL);
2283 assert_return(!m->sealed, -EPERM);
2284 assert_return(m->n_containers > 0, -EINVAL);
2285 assert_return(!m->poisoned, -ESTALE);
2287 c = message_get_container(m);
2289 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2290 if (c->signature && c->signature[c->index] != 0)
2295 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2296 r = bus_message_close_array(m, c);
2297 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2298 r = bus_message_close_variant(m, c);
2299 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2300 r = bus_message_close_struct(m, c, true);
2302 assert_not_reached("Unknown container type");
2316 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2323 stack[*i].types = types;
2324 stack[*i].n_struct = n_struct;
2325 stack[*i].n_array = n_array;
2331 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2342 *types = stack[*i].types;
2343 *n_struct = stack[*i].n_struct;
2344 *n_array = stack[*i].n_array;
2349 int bus_message_append_ap(
2354 unsigned n_array, n_struct;
2355 TypeStack stack[BUS_CONTAINER_DEPTH];
2356 unsigned stack_ptr = 0;
2364 n_array = (unsigned) -1;
2365 n_struct = strlen(types);
2370 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2371 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2377 r = sd_bus_message_close_container(m);
2385 if (n_array != (unsigned) -1)
2394 case SD_BUS_TYPE_BYTE: {
2397 x = (uint8_t) va_arg(ap, int);
2398 r = sd_bus_message_append_basic(m, *t, &x);
2402 case SD_BUS_TYPE_BOOLEAN:
2403 case SD_BUS_TYPE_INT32:
2404 case SD_BUS_TYPE_UINT32:
2405 case SD_BUS_TYPE_UNIX_FD: {
2408 /* We assume a boolean is the same as int32_t */
2409 assert_cc(sizeof(int32_t) == sizeof(int));
2411 x = va_arg(ap, uint32_t);
2412 r = sd_bus_message_append_basic(m, *t, &x);
2416 case SD_BUS_TYPE_INT16:
2417 case SD_BUS_TYPE_UINT16: {
2420 x = (uint16_t) va_arg(ap, int);
2421 r = sd_bus_message_append_basic(m, *t, &x);
2425 case SD_BUS_TYPE_INT64:
2426 case SD_BUS_TYPE_UINT64: {
2429 x = va_arg(ap, uint64_t);
2430 r = sd_bus_message_append_basic(m, *t, &x);
2434 case SD_BUS_TYPE_DOUBLE: {
2437 x = va_arg(ap, double);
2438 r = sd_bus_message_append_basic(m, *t, &x);
2442 case SD_BUS_TYPE_STRING:
2443 case SD_BUS_TYPE_OBJECT_PATH:
2444 case SD_BUS_TYPE_SIGNATURE: {
2447 x = va_arg(ap, const char*);
2448 r = sd_bus_message_append_basic(m, *t, x);
2452 case SD_BUS_TYPE_ARRAY: {
2455 r = signature_element_length(t + 1, &k);
2461 memcpy(s, t + 1, k);
2464 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2469 if (n_array == (unsigned) -1) {
2474 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2480 n_array = va_arg(ap, unsigned);
2485 case SD_BUS_TYPE_VARIANT: {
2488 s = va_arg(ap, const char*);
2492 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2496 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2501 n_struct = strlen(s);
2502 n_array = (unsigned) -1;
2507 case SD_BUS_TYPE_STRUCT_BEGIN:
2508 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2511 r = signature_element_length(t, &k);
2518 memcpy(s, t + 1, k - 2);
2521 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2526 if (n_array == (unsigned) -1) {
2531 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2537 n_array = (unsigned) -1;
2553 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2557 assert_return(m, -EINVAL);
2558 assert_return(types, -EINVAL);
2559 assert_return(!m->sealed, -EPERM);
2560 assert_return(!m->poisoned, -ESTALE);
2562 va_start(ap, types);
2563 r = bus_message_append_ap(m, types, ap);
2569 _public_ int sd_bus_message_append_array_space(
2579 assert_return(m, -EINVAL);
2580 assert_return(!m->sealed, -EPERM);
2581 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2582 assert_return(ptr || size == 0, -EINVAL);
2583 assert_return(!m->poisoned, -ESTALE);
2585 /* alignment and size of the trivial types (except bool) is
2586 * identical for gvariant and dbus1 marshalling */
2587 align = bus_type_get_alignment(type);
2588 sz = bus_type_get_size(type);
2590 assert_se(align > 0);
2596 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2600 a = message_extend_body(m, align, size, false, false);
2604 r = sd_bus_message_close_container(m);
2612 _public_ int sd_bus_message_append_array(
2620 assert_return(m, -EINVAL);
2621 assert_return(!m->sealed, -EPERM);
2622 assert_return(bus_type_is_trivial(type), -EINVAL);
2623 assert_return(ptr || size == 0, -EINVAL);
2624 assert_return(!m->poisoned, -ESTALE);
2626 r = sd_bus_message_append_array_space(m, type, size, &p);
2631 memcpy(p, ptr, size);
2636 _public_ int sd_bus_message_append_array_iovec(
2639 const struct iovec *iov,
2647 assert_return(m, -EINVAL);
2648 assert_return(!m->sealed, -EPERM);
2649 assert_return(bus_type_is_trivial(type), -EINVAL);
2650 assert_return(iov || n == 0, -EINVAL);
2651 assert_return(!m->poisoned, -ESTALE);
2653 size = IOVEC_TOTAL_SIZE(iov, n);
2655 r = sd_bus_message_append_array_space(m, type, size, &p);
2659 for (i = 0; i < n; i++) {
2661 if (iov[i].iov_base)
2662 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2664 memzero(p, iov[i].iov_len);
2666 p = (uint8_t*) p + iov[i].iov_len;
2672 _public_ int sd_bus_message_append_array_memfd(
2679 _cleanup_close_ int copy_fd = -1;
2680 struct bus_body_part *part;
2686 assert_return(m, -EINVAL);
2687 assert_return(memfd >= 0, -EINVAL);
2688 assert_return(bus_type_is_trivial(type), -EINVAL);
2689 assert_return(size > 0, -EINVAL);
2690 assert_return(!m->sealed, -EPERM);
2691 assert_return(!m->poisoned, -ESTALE);
2693 r = memfd_set_sealed(memfd);
2697 copy_fd = dup(memfd);
2701 r = memfd_get_size(memfd, &real_size);
2705 if (offset == 0 && size == (uint64_t) -1)
2707 else if (offset + size > real_size)
2710 align = bus_type_get_alignment(type);
2711 sz = bus_type_get_size(type);
2713 assert_se(align > 0);
2716 if (offset % align != 0)
2722 if (size > (uint64_t) (uint32_t) -1)
2725 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2729 a = message_extend_body(m, align, 0, false, false);
2733 part = message_append_part(m);
2737 part->memfd = copy_fd;
2738 part->memfd_offset = offset;
2739 part->sealed = true;
2743 m->body_size += size;
2744 message_extend_containers(m, size);
2746 return sd_bus_message_close_container(m);
2749 _public_ int sd_bus_message_append_string_memfd(
2755 _cleanup_close_ int copy_fd = -1;
2756 struct bus_body_part *part;
2757 struct bus_container *c;
2762 assert_return(m, -EINVAL);
2763 assert_return(memfd >= 0, -EINVAL);
2764 assert_return(size > 0, -EINVAL);
2765 assert_return(!m->sealed, -EPERM);
2766 assert_return(!m->poisoned, -ESTALE);
2768 r = memfd_set_sealed(memfd);
2772 copy_fd = dup(memfd);
2776 r = memfd_get_size(memfd, &real_size);
2780 if (offset == 0 && size == (uint64_t) -1)
2782 else if (offset + size > real_size)
2785 /* We require this to be NUL terminated */
2789 if (size > (uint64_t) (uint32_t) -1)
2792 c = message_get_container(m);
2793 if (c->signature && c->signature[c->index]) {
2794 /* Container signature is already set */
2796 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2801 /* Maybe we can append to the signature? But only if this is the top-level container */
2802 if (c->enclosing != 0)
2805 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2812 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2813 a = message_extend_body(m, 4, 4, false, false);
2817 *(uint32_t*) a = size - 1;
2820 part = message_append_part(m);
2824 part->memfd = copy_fd;
2825 part->memfd_offset = offset;
2826 part->sealed = true;
2830 m->body_size += size;
2831 message_extend_containers(m, size);
2833 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2834 r = message_add_offset(m, m->body_size);
2841 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2847 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2851 assert_return(m, -EINVAL);
2852 assert_return(!m->sealed, -EPERM);
2853 assert_return(!m->poisoned, -ESTALE);
2855 r = sd_bus_message_open_container(m, 'a', "s");
2859 STRV_FOREACH(i, l) {
2860 r = sd_bus_message_append_basic(m, 's', *i);
2865 return sd_bus_message_close_container(m);
2868 static int bus_message_close_header(sd_bus_message *m) {
2872 /* The actual user data is finished now, we just complete the
2873 variant and struct now (at least on gvariant). Remember
2874 this position, so that during parsing we know where to to
2875 put the outer container end. */
2876 m->user_body_size = m->body_size;
2878 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2879 const char *signature;
2883 /* Add offset table to end of fields array */
2884 if (m->n_header_offsets >= 1) {
2888 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2890 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2891 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2895 for (i = 0; i < m->n_header_offsets; i++)
2896 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2899 /* Add gvariant NUL byte plus signature to the end of
2900 * the body, followed by the final offset pointing to
2901 * the end of the fields array */
2903 signature = strempty(m->root_container.signature);
2904 l = strlen(signature);
2906 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l, 1);
2907 d = message_extend_body(m, 1, 1 + l + sz, false, true);
2912 memcpy((uint8_t*) d + 1, signature, l);
2914 bus_gvariant_write_word_le((uint8_t*) d + 1 + l, sz, sizeof(struct bus_header) + m->fields_size);
2917 m->footer_accessible = 1 + l + sz;
2919 m->header->dbus1.fields_size = m->fields_size;
2920 m->header->dbus1.body_size = m->body_size;
2926 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2927 struct bus_body_part *part;
2937 if (m->n_containers > 0)
2943 if (cookie > 0xffffffffULL &&
2944 !BUS_MESSAGE_IS_GVARIANT(m))
2947 /* In vtables the return signature of method calls is listed,
2948 * let's check if they match if this is a response */
2949 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2950 m->enforced_reply_signature &&
2951 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2954 /* If gvariant marshalling is used we need to close the body structure */
2955 r = bus_message_close_struct(m, &m->root_container, false);
2959 /* If there's a non-trivial signature set, then add it in
2960 * here, but only on dbus1 */
2961 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2962 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2968 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2973 r = bus_message_close_header(m);
2977 if (BUS_MESSAGE_IS_GVARIANT(m))
2978 m->header->dbus2.cookie = cookie;
2980 m->header->dbus1.serial = (uint32_t) cookie;
2982 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2984 /* Add padding at the end of the fields part, since we know
2985 * the body needs to start at an 8 byte alignment. We made
2986 * sure we allocated enough space for this, so all we need to
2987 * do here is to zero it out. */
2988 a = ALIGN8(m->fields_size) - m->fields_size;
2990 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2992 /* If this is something we can send as memfd, then let's seal
2993 the memfd now. Note that we can send memfds as payload only
2994 for directed messages, and not for broadcasts. */
2995 if (m->destination && m->bus->use_memfd) {
2996 MESSAGE_FOREACH_PART(part, i, m)
2997 if (part->memfd >= 0 &&
2999 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3000 part != m->body_end) { /* The last part may never be sent as memfd */
3003 /* Try to seal it if that makes
3004 * sense. First, unmap our own map to
3005 * make sure we don't keep it busy. */
3006 bus_body_part_unmap(part);
3008 /* Then, sync up real memfd size */
3010 r = memfd_set_size(part->memfd, sz);
3014 /* Finally, try to seal */
3015 if (memfd_set_sealed(part->memfd) >= 0)
3016 part->sealed = true;
3020 m->root_container.end = m->user_body_size;
3021 m->root_container.index = 0;
3022 m->root_container.offset_index = 0;
3023 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3030 int bus_body_part_map(struct bus_body_part *part) {
3039 if (part->size <= 0)
3042 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3043 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3044 static const uint8_t zeroes[7] = { };
3045 part->data = (void*) zeroes;
3049 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3050 psz = PAGE_ALIGN(part->size + shift);
3052 if (part->memfd >= 0)
3053 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3054 else if (part->is_zero)
3055 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3059 if (p == MAP_FAILED)
3063 part->mmap_begin = p;
3064 part->data = (uint8_t*) p + shift;
3065 part->munmap_this = true;
3070 void bus_body_part_unmap(struct bus_body_part *part) {
3074 if (part->memfd < 0)
3077 if (!part->mmap_begin)
3080 if (!part->munmap_this)
3083 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3085 part->mmap_begin = NULL;
3088 part->munmap_this = false;
3093 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3094 size_t k, start, end;
3099 start = ALIGN_TO((size_t) *rindex, align);
3100 end = start + nbytes;
3105 /* Verify that padding is 0 */
3106 for (k = *rindex; k < start; k++)
3107 if (((const uint8_t*) p)[k] != 0)
3111 *r = (uint8_t*) p + start;
3118 static bool message_end_of_signature(sd_bus_message *m) {
3119 struct bus_container *c;
3123 c = message_get_container(m);
3124 return !c->signature || c->signature[c->index] == 0;
3127 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3128 struct bus_container *c;
3132 c = message_get_container(m);
3133 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3136 if (BUS_MESSAGE_IS_GVARIANT(m))
3137 return index >= c->end;
3139 assert(c->array_size);
3140 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3144 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3145 assert_return(m, -EINVAL);
3146 assert_return(m->sealed, -EPERM);
3148 if (complete && m->n_containers > 0)
3151 if (message_end_of_signature(m))
3154 if (message_end_of_array(m, m->rindex))
3160 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3161 struct bus_body_part *part;
3167 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3168 part = m->cached_rindex_part;
3169 begin = m->cached_rindex_part_begin;
3179 if (index + sz <= begin + part->size) {
3181 r = bus_body_part_map(part);
3186 *p = (uint8_t*) part->data + index - begin;
3188 m->cached_rindex_part = part;
3189 m->cached_rindex_part_begin = begin;
3194 begin += part->size;
3201 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3208 if (!BUS_MESSAGE_IS_GVARIANT(m))
3211 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3214 sz = bus_gvariant_get_size(c->signature);
3218 if (c->offset_index+1 >= c->n_offsets)
3221 /* Variable-size array */
3223 alignment = bus_gvariant_get_alignment(c->signature);
3224 assert(alignment > 0);
3226 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3227 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3230 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3233 /* Fixed-size array */
3234 *rindex = c->begin + (c->offset_index+1) * sz;
3240 } else if (c->enclosing == 0 ||
3241 c->enclosing == SD_BUS_TYPE_STRUCT ||
3242 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3247 if (c->offset_index+1 >= c->n_offsets)
3250 r = signature_element_length(c->signature + c->index, &n);
3254 r = signature_element_length(c->signature + c->index + n, &j);
3259 memcpy(t, c->signature + c->index + n, j);
3262 alignment = bus_gvariant_get_alignment(t);
3265 assert(alignment > 0);
3267 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3268 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3272 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3275 assert_not_reached("Unknown container type");
3280 /* Reached the end */
3287 static int message_peek_body(
3294 size_t k, start, end, padding;
3295 struct bus_body_part *part;
3302 start = ALIGN_TO((size_t) *rindex, align);
3303 padding = start - *rindex;
3304 end = start + nbytes;
3306 if (end > m->user_body_size)
3309 part = find_part(m, *rindex, padding, (void**) &q);
3314 /* Verify padding */
3315 for (k = 0; k < padding; k++)
3320 part = find_part(m, start, nbytes, (void**) &q);
3321 if (!part || (nbytes > 0 && !q))
3332 static bool validate_nul(const char *s, size_t l) {
3334 /* Check for NUL chars in the string */
3335 if (memchr(s, 0, l))
3338 /* Check for NUL termination */
3345 static bool validate_string(const char *s, size_t l) {
3347 if (!validate_nul(s, l))
3350 /* Check if valid UTF8 */
3351 if (!utf8_is_valid(s))
3357 static bool validate_signature(const char *s, size_t l) {
3359 if (!validate_nul(s, l))
3362 /* Check if valid signature */
3363 if (!signature_is_valid(s, true))
3369 static bool validate_object_path(const char *s, size_t l) {
3371 if (!validate_nul(s, l))
3374 if (!object_path_is_valid(s))
3380 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3381 struct bus_container *c;
3386 assert_return(m, -EINVAL);
3387 assert_return(m->sealed, -EPERM);
3388 assert_return(bus_type_is_basic(type), -EINVAL);
3390 if (message_end_of_signature(m))
3393 if (message_end_of_array(m, m->rindex))
3396 c = message_get_container(m);
3397 if (c->signature[c->index] != type)
3402 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3404 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3407 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3411 if (type == SD_BUS_TYPE_STRING)
3412 ok = validate_string(q, c->item_size-1);
3413 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3414 ok = validate_object_path(q, c->item_size-1);
3416 ok = validate_signature(q, c->item_size-1);
3422 *(const char**) p = q;
3426 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3428 if ((size_t) sz != c->item_size)
3431 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3434 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3440 case SD_BUS_TYPE_BYTE:
3442 *(uint8_t*) p = *(uint8_t*) q;
3445 case SD_BUS_TYPE_BOOLEAN:
3447 *(int*) p = !!*(uint8_t*) q;
3450 case SD_BUS_TYPE_INT16:
3451 case SD_BUS_TYPE_UINT16:
3453 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3456 case SD_BUS_TYPE_INT32:
3457 case SD_BUS_TYPE_UINT32:
3459 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3462 case SD_BUS_TYPE_INT64:
3463 case SD_BUS_TYPE_UINT64:
3464 case SD_BUS_TYPE_DOUBLE:
3466 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3469 case SD_BUS_TYPE_UNIX_FD: {
3472 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3477 *(int*) p = m->fds[j];
3483 assert_not_reached("unexpected type");
3487 r = container_next_item(m, c, &rindex);
3494 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3498 r = message_peek_body(m, &rindex, 4, 4, &q);
3502 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3503 r = message_peek_body(m, &rindex, 1, l+1, &q);
3507 if (type == SD_BUS_TYPE_OBJECT_PATH)
3508 ok = validate_object_path(q, l);
3510 ok = validate_string(q, l);
3515 *(const char**) p = q;
3517 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3520 r = message_peek_body(m, &rindex, 1, 1, &q);
3525 r = message_peek_body(m, &rindex, 1, l+1, &q);
3529 if (!validate_signature(q, l))
3533 *(const char**) p = q;
3538 align = bus_type_get_alignment(type);
3541 sz = bus_type_get_size(type);
3544 r = message_peek_body(m, &rindex, align, sz, &q);
3550 case SD_BUS_TYPE_BYTE:
3552 *(uint8_t*) p = *(uint8_t*) q;
3555 case SD_BUS_TYPE_BOOLEAN:
3557 *(int*) p = !!*(uint32_t*) q;
3560 case SD_BUS_TYPE_INT16:
3561 case SD_BUS_TYPE_UINT16:
3563 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3566 case SD_BUS_TYPE_INT32:
3567 case SD_BUS_TYPE_UINT32:
3569 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3572 case SD_BUS_TYPE_INT64:
3573 case SD_BUS_TYPE_UINT64:
3574 case SD_BUS_TYPE_DOUBLE:
3576 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3579 case SD_BUS_TYPE_UNIX_FD: {
3582 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3587 *(int*) p = m->fds[j];
3592 assert_not_reached("Unknown basic type...");
3599 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3605 static int bus_message_enter_array(
3607 struct bus_container *c,
3608 const char *contents,
3609 uint32_t **array_size,
3612 size_t *n_offsets) {
3626 if (!signature_is_single(contents, true))
3629 if (!c->signature || c->signature[c->index] == 0)
3632 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3635 if (!startswith(c->signature + c->index + 1, contents))
3640 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3643 r = message_peek_body(m, &rindex, 4, 4, &q);
3647 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3650 alignment = bus_type_get_alignment(contents[0]);
3654 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3658 *array_size = (uint32_t*) q;
3660 } else if (c->item_size <= 0) {
3662 /* gvariant: empty array */
3667 } else if (bus_gvariant_is_fixed_size(contents)) {
3669 /* gvariant: fixed length array */
3670 *item_size = bus_gvariant_get_size(contents);
3675 size_t where, p = 0, framing, sz;
3678 /* gvariant: variable length array */
3679 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3681 where = rindex + c->item_size - sz;
3682 r = message_peek_body(m, &where, 1, sz, &q);
3686 framing = bus_gvariant_read_word_le(q, sz);
3687 if (framing > c->item_size - sz)
3689 if ((c->item_size - framing) % sz != 0)
3692 *n_offsets = (c->item_size - framing) / sz;
3694 where = rindex + framing;
3695 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3699 *offsets = new(size_t, *n_offsets);
3703 for (i = 0; i < *n_offsets; i++) {
3706 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3707 if (x > c->item_size - sz)
3712 (*offsets)[i] = rindex + x;
3716 *item_size = (*offsets)[0] - rindex;
3721 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3722 c->index += 1 + strlen(contents);
3727 static int bus_message_enter_variant(
3729 struct bus_container *c,
3730 const char *contents,
3731 size_t *item_size) {
3743 if (!signature_is_single(contents, false))
3746 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3749 if (!c->signature || c->signature[c->index] == 0)
3752 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3757 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3760 k = strlen(contents);
3761 if (1+k > c->item_size)
3764 where = rindex + c->item_size - (1+k);
3765 r = message_peek_body(m, &where, 1, 1+k, &q);
3769 if (*(char*) q != 0)
3772 if (memcmp((uint8_t*) q+1, contents, k))
3775 *item_size = c->item_size - (1+k);
3778 r = message_peek_body(m, &rindex, 1, 1, &q);
3783 r = message_peek_body(m, &rindex, 1, l+1, &q);
3787 if (!validate_signature(q, l))
3790 if (!streq(q, contents))
3796 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3802 static int build_struct_offsets(
3804 const char *signature,
3808 size_t *n_offsets) {
3810 unsigned n_variable = 0, n_total = 0, v;
3811 size_t previous = 0, where;
3822 if (isempty(signature)) {
3829 sz = bus_gvariant_determine_word_size(size, 0);
3833 /* First, loop over signature and count variable elements and
3834 * elements in general. We use this to know how large the
3835 * offset array is at the end of the structure. Note that
3836 * GVariant only stores offsets for all variable size elements
3837 * that are not the last item. */
3843 r = signature_element_length(p, &n);
3852 r = bus_gvariant_is_fixed_size(t);
3857 if (r == 0 && p[n] != 0) /* except the last item */
3864 if (size < n_variable * sz)
3867 where = m->rindex + size - (n_variable * sz);
3868 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3874 *offsets = new(size_t, n_total);
3880 /* Second, loop again and build an offset table */
3886 r = signature_element_length(p, &n);
3895 k = bus_gvariant_get_size(t);
3903 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3906 if (m->rindex + x < previous)
3909 /* The last item's end
3910 * is determined from
3913 x = size - (n_variable * sz);
3915 offset = m->rindex + x;
3921 align = bus_gvariant_get_alignment(t);
3924 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3928 previous = (*offsets)[(*n_offsets)++] = offset;
3933 assert(*n_offsets == n_total);
3935 *item_size = (*offsets)[0] - m->rindex;
3939 static int enter_struct_or_dict_entry(
3941 struct bus_container *c,
3942 const char *contents,
3945 size_t *n_offsets) {
3956 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3959 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3963 } else if (c->item_size <= 0) {
3965 /* gvariant empty struct */
3970 /* gvariant with contents */
3971 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3976 static int bus_message_enter_struct(
3978 struct bus_container *c,
3979 const char *contents,
3982 size_t *n_offsets) {
3994 if (!signature_is_valid(contents, false))
3997 if (!c->signature || c->signature[c->index] == 0)
4000 l = strlen(contents);
4002 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4003 !startswith(c->signature + c->index + 1, contents) ||
4004 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4007 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4011 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4012 c->index += 1 + l + 1;
4017 static int bus_message_enter_dict_entry(
4019 struct bus_container *c,
4020 const char *contents,
4023 size_t *n_offsets) {
4032 if (!signature_is_pair(contents))
4035 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4038 if (!c->signature || c->signature[c->index] == 0)
4041 l = strlen(contents);
4043 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4044 !startswith(c->signature + c->index + 1, contents) ||
4045 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4048 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4052 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4053 c->index += 1 + l + 1;
4058 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4060 const char *contents) {
4061 struct bus_container *c, *w;
4062 uint32_t *array_size = NULL;
4065 size_t *offsets = NULL;
4066 size_t n_offsets = 0, item_size = 0;
4069 assert_return(m, -EINVAL);
4070 assert_return(m->sealed, -EPERM);
4071 assert_return(type != 0 || !contents, -EINVAL);
4073 if (type == 0 || !contents) {
4077 /* Allow entering into anonymous containers */
4078 r = sd_bus_message_peek_type(m, &tt, &cc);
4082 if (type != 0 && type != tt)
4085 if (contents && !streq(contents, cc))
4093 * We enforce a global limit on container depth, that is much
4094 * higher than the 32 structs and 32 arrays the specification
4095 * mandates. This is simpler to implement for us, and we need
4096 * this only to ensure our container array doesn't grow
4097 * without bounds. We are happy to return any data from a
4098 * message as long as the data itself is valid, even if the
4099 * overall message might be not.
4101 * Note that the message signature is validated when
4102 * parsing the headers, and that validation does check the
4105 * Note that the specification defines no limits on the depth
4106 * of stacked variants, but we do.
4108 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4111 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4114 if (message_end_of_signature(m))
4117 if (message_end_of_array(m, m->rindex))
4120 c = message_get_container(m);
4122 signature = strdup(contents);
4126 c->saved_index = c->index;
4129 if (type == SD_BUS_TYPE_ARRAY)
4130 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4131 else if (type == SD_BUS_TYPE_VARIANT)
4132 r = bus_message_enter_variant(m, c, contents, &item_size);
4133 else if (type == SD_BUS_TYPE_STRUCT)
4134 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4135 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4136 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4146 /* OK, let's fill it in */
4147 w = m->containers + m->n_containers++;
4148 w->enclosing = type;
4149 w->signature = signature;
4150 w->peeked_signature = NULL;
4154 w->begin = m->rindex;
4155 w->end = m->rindex + c->item_size;
4157 w->array_size = array_size;
4158 w->item_size = item_size;
4159 w->offsets = offsets;
4160 w->n_offsets = n_offsets;
4161 w->offset_index = 0;
4166 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4167 struct bus_container *c;
4171 assert_return(m, -EINVAL);
4172 assert_return(m->sealed, -EPERM);
4173 assert_return(m->n_containers > 0, -ENXIO);
4175 c = message_get_container(m);
4177 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4178 if (c->signature && c->signature[c->index] != 0)
4182 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4183 if (m->rindex < c->end)
4186 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4189 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4190 if (c->begin + l != m->rindex)
4195 free(c->peeked_signature);
4199 c = message_get_container(m);
4202 c->index = c->saved_index;
4203 r = container_next_item(m, c, &m->rindex);
4211 static void message_quit_container(sd_bus_message *m) {
4212 struct bus_container *c;
4216 assert(m->n_containers > 0);
4218 c = message_get_container(m);
4221 assert(m->rindex >= c->before);
4222 m->rindex = c->before;
4224 /* Free container */
4229 /* Correct index of new top-level container */
4230 c = message_get_container(m);
4231 c->index = c->saved_index;
4234 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4235 struct bus_container *c;
4238 assert_return(m, -EINVAL);
4239 assert_return(m->sealed, -EPERM);
4241 if (message_end_of_signature(m))
4244 if (message_end_of_array(m, m->rindex))
4247 c = message_get_container(m);
4249 if (bus_type_is_basic(c->signature[c->index])) {
4253 *type = c->signature[c->index];
4257 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4263 r = signature_element_length(c->signature+c->index+1, &l);
4269 sig = strndup(c->signature + c->index + 1, l);
4273 free(c->peeked_signature);
4274 *contents = c->peeked_signature = sig;
4278 *type = SD_BUS_TYPE_ARRAY;
4283 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4284 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4290 r = signature_element_length(c->signature+c->index, &l);
4295 sig = strndup(c->signature + c->index + 1, l - 2);
4299 free(c->peeked_signature);
4300 *contents = c->peeked_signature = sig;
4304 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4309 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4313 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4316 if (c->item_size < 2)
4319 /* Look for the NUL delimiter that
4320 separates the payload from the
4321 signature. Since the body might be
4322 in a different part that then the
4323 signature we map byte by byte. */
4325 for (k = 2; k <= c->item_size; k++) {
4328 where = m->rindex + c->item_size - k;
4329 r = message_peek_body(m, &where, 1, k, &q);
4333 if (*(char*) q == 0)
4337 if (k > c->item_size)
4340 free(c->peeked_signature);
4341 c->peeked_signature = strndup((char*) q + 1, k - 1);
4342 if (!c->peeked_signature)
4345 if (!signature_is_valid(c->peeked_signature, true))
4348 *contents = c->peeked_signature;
4353 r = message_peek_body(m, &rindex, 1, 1, &q);
4358 r = message_peek_body(m, &rindex, 1, l+1, &q);
4362 if (!validate_signature(q, l))
4370 *type = SD_BUS_TYPE_VARIANT;
4385 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4386 struct bus_container *c;
4388 assert_return(m, -EINVAL);
4389 assert_return(m->sealed, -EPERM);
4392 message_reset_containers(m);
4395 c = message_get_container(m);
4397 c = message_get_container(m);
4399 c->offset_index = 0;
4401 m->rindex = c->begin;
4404 c->offset_index = 0;
4405 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4407 return !isempty(c->signature);
4410 static int message_read_ap(
4415 unsigned n_array, n_struct;
4416 TypeStack stack[BUS_CONTAINER_DEPTH];
4417 unsigned stack_ptr = 0;
4418 unsigned n_loop = 0;
4426 /* Ideally, we'd just call ourselves recursively on every
4427 * complex type. However, the state of a va_list that is
4428 * passed to a function is undefined after that function
4429 * returns. This means we need to docode the va_list linearly
4430 * in a single stackframe. We hence implement our own
4431 * home-grown stack in an array. */
4433 n_array = (unsigned) -1; /* length of current array entries */
4434 n_struct = strlen(types); /* length of current struct contents signature */
4441 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4442 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4448 r = sd_bus_message_exit_container(m);
4456 if (n_array != (unsigned) -1)
4465 case SD_BUS_TYPE_BYTE:
4466 case SD_BUS_TYPE_BOOLEAN:
4467 case SD_BUS_TYPE_INT16:
4468 case SD_BUS_TYPE_UINT16:
4469 case SD_BUS_TYPE_INT32:
4470 case SD_BUS_TYPE_UINT32:
4471 case SD_BUS_TYPE_INT64:
4472 case SD_BUS_TYPE_UINT64:
4473 case SD_BUS_TYPE_DOUBLE:
4474 case SD_BUS_TYPE_STRING:
4475 case SD_BUS_TYPE_OBJECT_PATH:
4476 case SD_BUS_TYPE_SIGNATURE:
4477 case SD_BUS_TYPE_UNIX_FD: {
4480 p = va_arg(ap, void*);
4481 r = sd_bus_message_read_basic(m, *t, p);
4494 case SD_BUS_TYPE_ARRAY: {
4497 r = signature_element_length(t + 1, &k);
4503 memcpy(s, t + 1, k);
4506 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4517 if (n_array == (unsigned) -1) {
4522 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4528 n_array = va_arg(ap, unsigned);
4533 case SD_BUS_TYPE_VARIANT: {
4536 s = va_arg(ap, const char *);
4540 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4550 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4555 n_struct = strlen(s);
4556 n_array = (unsigned) -1;
4561 case SD_BUS_TYPE_STRUCT_BEGIN:
4562 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4565 r = signature_element_length(t, &k);
4571 memcpy(s, t + 1, k - 2);
4574 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4584 if (n_array == (unsigned) -1) {
4589 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4595 n_array = (unsigned) -1;
4608 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4612 assert_return(m, -EINVAL);
4613 assert_return(m->sealed, -EPERM);
4614 assert_return(types, -EINVAL);
4616 va_start(ap, types);
4617 r = message_read_ap(m, types, ap);
4623 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4626 assert_return(m, -EINVAL);
4627 assert_return(m->sealed, -EPERM);
4629 /* If types is NULL, read exactly one element */
4631 struct bus_container *c;
4634 if (message_end_of_signature(m))
4637 if (message_end_of_array(m, m->rindex))
4640 c = message_get_container(m);
4642 r = signature_element_length(c->signature + c->index, &l);
4646 types = strndupa(c->signature + c->index, l);
4651 case 0: /* Nothing to drop */
4654 case SD_BUS_TYPE_BYTE:
4655 case SD_BUS_TYPE_BOOLEAN:
4656 case SD_BUS_TYPE_INT16:
4657 case SD_BUS_TYPE_UINT16:
4658 case SD_BUS_TYPE_INT32:
4659 case SD_BUS_TYPE_UINT32:
4660 case SD_BUS_TYPE_INT64:
4661 case SD_BUS_TYPE_UINT64:
4662 case SD_BUS_TYPE_DOUBLE:
4663 case SD_BUS_TYPE_STRING:
4664 case SD_BUS_TYPE_OBJECT_PATH:
4665 case SD_BUS_TYPE_SIGNATURE:
4666 case SD_BUS_TYPE_UNIX_FD:
4668 r = sd_bus_message_read_basic(m, *types, NULL);
4672 r = sd_bus_message_skip(m, types + 1);
4678 case SD_BUS_TYPE_ARRAY: {
4681 r = signature_element_length(types + 1, &k);
4687 memcpy(s, types+1, k);
4690 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4695 r = sd_bus_message_skip(m, s);
4702 r = sd_bus_message_exit_container(m);
4707 r = sd_bus_message_skip(m, types + 1 + k);
4714 case SD_BUS_TYPE_VARIANT: {
4715 const char *contents;
4718 r = sd_bus_message_peek_type(m, &x, &contents);
4722 if (x != SD_BUS_TYPE_VARIANT)
4725 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4729 r = sd_bus_message_skip(m, contents);
4734 r = sd_bus_message_exit_container(m);
4738 r = sd_bus_message_skip(m, types + 1);
4745 case SD_BUS_TYPE_STRUCT_BEGIN:
4746 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4749 r = signature_element_length(types, &k);
4755 memcpy(s, types+1, k-2);
4758 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4762 r = sd_bus_message_skip(m, s);
4767 r = sd_bus_message_exit_container(m);
4772 r = sd_bus_message_skip(m, types + k);
4784 _public_ int sd_bus_message_read_array(
4790 struct bus_container *c;
4796 assert_return(m, -EINVAL);
4797 assert_return(m->sealed, -EPERM);
4798 assert_return(bus_type_is_trivial(type), -EINVAL);
4799 assert_return(ptr, -EINVAL);
4800 assert_return(size, -EINVAL);
4801 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4803 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4807 c = message_get_container(m);
4809 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4810 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4814 sz = c->end - c->begin;
4816 align = bus_type_get_alignment(type);
4820 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4824 /* Zero length array, let's return some aligned
4825 * pointer that is not NULL */
4826 p = (uint8_t*) NULL + align;
4828 r = message_peek_body(m, &m->rindex, align, sz, &p);
4833 r = sd_bus_message_exit_container(m);
4837 *ptr = (const void*) p;
4843 message_quit_container(m);
4847 static int message_peek_fields(
4858 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4861 static int message_peek_field_uint32(
4873 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4876 /* identical for gvariant and dbus1 */
4878 r = message_peek_fields(m, ri, 4, 4, &q);
4883 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4888 static int message_peek_field_uint64(
4900 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4903 /* identical for gvariant and dbus1 */
4905 r = message_peek_fields(m, ri, 8, 8, &q);
4910 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4915 static int message_peek_field_string(
4917 bool (*validate)(const char *p),
4929 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4934 r = message_peek_fields(m, ri, 1, item_size, &q);
4940 r = message_peek_field_uint32(m, ri, 4, &l);
4944 r = message_peek_fields(m, ri, 1, l+1, &q);
4950 if (!validate_nul(q, l))
4956 if (!validate_string(q, l))
4966 static int message_peek_field_signature(
4979 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4984 r = message_peek_fields(m, ri, 1, item_size, &q);
4990 r = message_peek_fields(m, ri, 1, 1, &q);
4995 r = message_peek_fields(m, ri, 1, l+1, &q);
5000 if (!validate_signature(q, l))
5009 static int message_skip_fields(
5012 uint32_t array_size,
5013 const char **signature) {
5015 size_t original_index;
5021 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5023 original_index = *ri;
5029 if (array_size != (uint32_t) -1 &&
5030 array_size <= *ri - original_index)
5037 if (t == SD_BUS_TYPE_STRING) {
5039 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5045 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5047 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5053 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5055 r = message_peek_field_signature(m, ri, 0, NULL);
5061 } else if (bus_type_is_basic(t)) {
5064 align = bus_type_get_alignment(t);
5065 k = bus_type_get_size(t);
5066 assert(align > 0 && k > 0);
5068 r = message_peek_fields(m, ri, align, k, NULL);
5074 } else if (t == SD_BUS_TYPE_ARRAY) {
5076 r = signature_element_length(*signature+1, &l);
5086 strncpy(sig, *signature + 1, l-1);
5089 alignment = bus_type_get_alignment(sig[0]);
5093 r = message_peek_field_uint32(m, ri, 0, &nas);
5096 if (nas > BUS_ARRAY_MAX_SIZE)
5099 r = message_peek_fields(m, ri, alignment, 0, NULL);
5103 r = message_skip_fields(m, ri, nas, (const char**) &s);
5108 (*signature) += 1 + l;
5110 } else if (t == SD_BUS_TYPE_VARIANT) {
5113 r = message_peek_field_signature(m, ri, 0, &s);
5117 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5123 } else if (t == SD_BUS_TYPE_STRUCT ||
5124 t == SD_BUS_TYPE_DICT_ENTRY) {
5126 r = signature_element_length(*signature, &l);
5133 strncpy(sig, *signature + 1, l-1);
5136 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5147 int bus_message_parse_fields(sd_bus_message *m) {
5150 uint32_t unix_fds = 0;
5151 bool unix_fds_set = false;
5152 void *offsets = NULL;
5153 unsigned n_offsets = 0;
5159 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5162 /* Read the signature from the end of the body variant first */
5163 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5164 if (m->footer_accessible < 1 + sz)
5167 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5169 if (p < (char*) m->footer)
5175 /* We found the beginning of the signature string, yay! */
5177 c = strndup(p + 1, ((char*) m->footer + m->footer_accessible) - p - (1 + sz));
5181 free(m->root_container.signature);
5182 m->root_container.signature = c;
5189 /* Calculate the actual user body size, by removing
5190 * the trailing variant signature and struct offset
5192 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5194 /* Pull out the offset table for the fields array */
5195 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5200 ri = m->fields_size - sz;
5201 r = message_peek_fields(m, &ri, 1, sz, &q);
5205 framing = bus_gvariant_read_word_le(q, sz);
5206 if (framing >= m->fields_size - sz)
5208 if ((m->fields_size - framing) % sz != 0)
5212 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5216 n_offsets = (m->fields_size - framing) / sz;
5219 m->user_body_size = m->body_size;
5222 while (ri < m->fields_size) {
5223 _cleanup_free_ char *sig = NULL;
5224 const char *signature;
5225 uint64_t field_type;
5226 size_t item_size = (size_t) -1;
5228 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5237 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5239 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5243 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5247 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5254 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5259 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5264 where = ri = ALIGN_TO(ri, 8);
5265 item_size = end - ri;
5266 r = message_peek_fields(m, &where, 1, item_size, &q);
5270 b = memrchr(q, 0, item_size);
5274 sig = strndup(b+1, item_size - (b+1-(char*) q));
5279 item_size = b - (char*) q;
5281 r = message_peek_field_signature(m, &ri, 0, &signature);
5286 switch (field_type) {
5288 case _BUS_MESSAGE_HEADER_INVALID:
5291 case BUS_MESSAGE_HEADER_PATH:
5296 if (!streq(signature, "o"))
5299 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5302 case BUS_MESSAGE_HEADER_INTERFACE:
5307 if (!streq(signature, "s"))
5310 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5313 case BUS_MESSAGE_HEADER_MEMBER:
5318 if (!streq(signature, "s"))
5321 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5324 case BUS_MESSAGE_HEADER_ERROR_NAME:
5329 if (!streq(signature, "s"))
5332 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5334 m->error._need_free = -1;
5338 case BUS_MESSAGE_HEADER_DESTINATION:
5343 if (!streq(signature, "s"))
5346 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5349 case BUS_MESSAGE_HEADER_SENDER:
5354 if (!streq(signature, "s"))
5357 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5359 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5360 m->creds.unique_name = (char*) m->sender;
5361 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5367 case BUS_MESSAGE_HEADER_SIGNATURE: {
5371 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5374 if (m->root_container.signature)
5377 if (!streq(signature, "g"))
5380 r = message_peek_field_signature(m, &ri, item_size, &s);
5388 free(m->root_container.signature);
5389 m->root_container.signature = c;
5393 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5395 if (m->reply_cookie != 0)
5398 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5399 /* 64bit on dbus2 */
5401 if (!streq(signature, "t"))
5404 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5408 /* 32bit on dbus1 */
5411 if (!streq(signature, "u"))
5414 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5418 m->reply_cookie = serial;
5421 if (m->reply_cookie == 0)
5426 case BUS_MESSAGE_HEADER_UNIX_FDS:
5430 if (!streq(signature, "u"))
5433 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5437 unix_fds_set = true;
5441 if (!BUS_MESSAGE_IS_GVARIANT(m))
5442 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5451 if (m->n_fds != unix_fds)
5454 switch (m->header->type) {
5456 case SD_BUS_MESSAGE_SIGNAL:
5457 if (!m->path || !m->interface || !m->member)
5460 if (m->reply_cookie != 0)
5465 case SD_BUS_MESSAGE_METHOD_CALL:
5467 if (!m->path || !m->member)
5470 if (m->reply_cookie != 0)
5475 case SD_BUS_MESSAGE_METHOD_RETURN:
5477 if (m->reply_cookie == 0)
5481 case SD_BUS_MESSAGE_METHOD_ERROR:
5483 if (m->reply_cookie == 0 || !m->error.name)
5488 /* Refuse non-local messages that claim they are local */
5489 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5491 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5493 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5496 m->root_container.end = m->user_body_size;
5498 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5499 r = build_struct_offsets(
5501 m->root_container.signature,
5503 &m->root_container.item_size,
5504 &m->root_container.offsets,
5505 &m->root_container.n_offsets);
5510 /* Try to read the error message, but if we can't it's a non-issue */
5511 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5512 sd_bus_message_read(m, "s", &m->error.message);
5517 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5518 assert_return(m, -EINVAL);
5519 assert_return(destination, -EINVAL);
5520 assert_return(!m->sealed, -EPERM);
5521 assert_return(!m->destination, -EEXIST);
5523 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5526 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5530 struct bus_body_part *part;
5536 total = BUS_MESSAGE_SIZE(m);
5542 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5543 MESSAGE_FOREACH_PART(part, i, m)
5544 e = mempcpy(e, part->data, part->size);
5546 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5554 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5560 r = sd_bus_message_enter_container(m, 'a', "s");
5567 r = sd_bus_message_read_basic(m, 's', &s);
5573 r = strv_extend(l, s);
5578 r = sd_bus_message_exit_container(m);
5585 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5589 assert_return(m, -EINVAL);
5590 assert_return(m->sealed, -EPERM);
5591 assert_return(l, -EINVAL);
5593 r = bus_message_read_strv_extend(m, &strv);
5603 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5604 const char *contents;
5613 r = sd_bus_message_rewind(m, true);
5618 r = sd_bus_message_peek_type(m, &type, &contents);
5624 /* Don't match against arguments after the first one we don't understand */
5625 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5626 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5632 r = sd_bus_message_skip(m, NULL);
5637 if (type == SD_BUS_TYPE_ARRAY) {
5639 r = sd_bus_message_read_strv(m, strv);
5646 r = sd_bus_message_read_basic(m, type, str);
5656 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5657 assert_return(m, EINVAL);
5659 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5662 return sd_bus_error_get_errno(&m->error);
5665 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5666 struct bus_container *c;
5668 assert_return(m, NULL);
5670 c = complete ? &m->root_container : message_get_container(m);
5671 return strempty(c->signature);
5674 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5675 assert_return(m, -EINVAL);
5677 return isempty(m->root_container.signature);
5680 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5681 assert_return(m, -EINVAL);
5683 return streq(strempty(m->root_container.signature), strempty(signature));
5686 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5687 bool done_something = false;
5690 assert_return(m, -EINVAL);
5691 assert_return(source, -EINVAL);
5692 assert_return(!m->sealed, -EPERM);
5693 assert_return(source->sealed, -EPERM);
5696 const char *contents;
5711 r = sd_bus_message_peek_type(source, &type, &contents);
5717 done_something = true;
5719 if (bus_type_is_container(type) > 0) {
5721 r = sd_bus_message_enter_container(source, type, contents);
5725 r = sd_bus_message_open_container(m, type, contents);
5729 r = sd_bus_message_copy(m, source, true);
5733 r = sd_bus_message_close_container(m);
5737 r = sd_bus_message_exit_container(source);
5744 r = sd_bus_message_read_basic(source, type, &basic);
5750 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5751 type == SD_BUS_TYPE_SIGNATURE ||
5752 type == SD_BUS_TYPE_STRING)
5753 r = sd_bus_message_append_basic(m, type, basic.string);
5755 r = sd_bus_message_append_basic(m, type, &basic);
5762 return done_something;
5765 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5770 assert_return(m, -EINVAL);
5771 assert_return(m->sealed, -EPERM);
5772 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5773 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5774 assert_return(type || contents, -EINVAL);
5775 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5777 r = sd_bus_message_peek_type(m, &t, &c);
5781 if (type != 0 && type != t)
5784 if (contents && !streq_ptr(contents, c))
5790 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5791 assert_return(m, NULL);
5796 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5797 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5805 switch ((*m)->header->type) {
5807 case SD_BUS_MESSAGE_SIGNAL:
5808 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5814 case SD_BUS_MESSAGE_METHOD_CALL:
5815 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5821 case SD_BUS_MESSAGE_METHOD_RETURN:
5822 case SD_BUS_MESSAGE_METHOD_ERROR:
5824 n = message_new(bus, (*m)->header->type);
5828 n->reply_cookie = (*m)->reply_cookie;
5830 r = message_append_reply_cookie(n, n->reply_cookie);
5834 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5835 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5839 n->error._need_free = -1;
5848 if ((*m)->destination && !n->destination) {
5849 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5854 if ((*m)->sender && !n->sender) {
5855 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5860 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5862 r = sd_bus_message_copy(n, *m, true);
5866 timeout = (*m)->timeout;
5867 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5868 timeout = BUS_DEFAULT_TIMEOUT;
5870 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5874 sd_bus_message_unref(*m);
5881 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5885 assert_return(!m->sealed, -EPERM);
5886 assert_return(!m->sender, -EPERM);
5888 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5891 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5892 assert_return(m, -EINVAL);
5893 assert_return(priority, -EINVAL);
5895 *priority = m->priority;
5899 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5900 assert_return(m, -EINVAL);
5901 assert_return(!m->sealed, -EPERM);
5903 m->priority = priority;