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);
3492 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3496 r = message_peek_body(m, &rindex, 4, 4, &q);
3500 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3501 r = message_peek_body(m, &rindex, 1, l+1, &q);
3505 if (type == SD_BUS_TYPE_OBJECT_PATH)
3506 ok = validate_object_path(q, l);
3508 ok = validate_string(q, l);
3513 *(const char**) p = q;
3515 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3518 r = message_peek_body(m, &rindex, 1, 1, &q);
3523 r = message_peek_body(m, &rindex, 1, l+1, &q);
3527 if (!validate_signature(q, l))
3531 *(const char**) p = q;
3536 align = bus_type_get_alignment(type);
3539 sz = bus_type_get_size(type);
3542 r = message_peek_body(m, &rindex, align, sz, &q);
3548 case SD_BUS_TYPE_BYTE:
3550 *(uint8_t*) p = *(uint8_t*) q;
3553 case SD_BUS_TYPE_BOOLEAN:
3555 *(int*) p = !!*(uint32_t*) q;
3558 case SD_BUS_TYPE_INT16:
3559 case SD_BUS_TYPE_UINT16:
3561 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3564 case SD_BUS_TYPE_INT32:
3565 case SD_BUS_TYPE_UINT32:
3567 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3570 case SD_BUS_TYPE_INT64:
3571 case SD_BUS_TYPE_UINT64:
3572 case SD_BUS_TYPE_DOUBLE:
3574 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3577 case SD_BUS_TYPE_UNIX_FD: {
3580 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3585 *(int*) p = m->fds[j];
3590 assert_not_reached("Unknown basic type...");
3597 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3603 static int bus_message_enter_array(
3605 struct bus_container *c,
3606 const char *contents,
3607 uint32_t **array_size,
3610 size_t *n_offsets) {
3624 if (!signature_is_single(contents, true))
3627 if (!c->signature || c->signature[c->index] == 0)
3630 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3633 if (!startswith(c->signature + c->index + 1, contents))
3638 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3641 r = message_peek_body(m, &rindex, 4, 4, &q);
3645 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3648 alignment = bus_type_get_alignment(contents[0]);
3652 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3656 *array_size = (uint32_t*) q;
3658 } else if (c->item_size <= 0) {
3660 /* gvariant: empty array */
3665 } else if (bus_gvariant_is_fixed_size(contents)) {
3667 /* gvariant: fixed length array */
3668 *item_size = bus_gvariant_get_size(contents);
3673 size_t where, p = 0, framing, sz;
3676 /* gvariant: variable length array */
3677 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3679 where = rindex + c->item_size - sz;
3680 r = message_peek_body(m, &where, 1, sz, &q);
3684 framing = bus_gvariant_read_word_le(q, sz);
3685 if (framing > c->item_size - sz)
3687 if ((c->item_size - framing) % sz != 0)
3690 *n_offsets = (c->item_size - framing) / sz;
3692 where = rindex + framing;
3693 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3697 *offsets = new(size_t, *n_offsets);
3701 for (i = 0; i < *n_offsets; i++) {
3704 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3705 if (x > c->item_size - sz)
3710 (*offsets)[i] = rindex + x;
3714 *item_size = (*offsets)[0] - rindex;
3719 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3720 c->index += 1 + strlen(contents);
3725 static int bus_message_enter_variant(
3727 struct bus_container *c,
3728 const char *contents,
3729 size_t *item_size) {
3741 if (!signature_is_single(contents, false))
3744 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3747 if (!c->signature || c->signature[c->index] == 0)
3750 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3755 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3758 k = strlen(contents);
3759 if (1+k > c->item_size)
3762 where = rindex + c->item_size - (1+k);
3763 r = message_peek_body(m, &where, 1, 1+k, &q);
3767 if (*(char*) q != 0)
3770 if (memcmp((uint8_t*) q+1, contents, k))
3773 *item_size = c->item_size - (1+k);
3776 r = message_peek_body(m, &rindex, 1, 1, &q);
3781 r = message_peek_body(m, &rindex, 1, l+1, &q);
3785 if (!validate_signature(q, l))
3788 if (!streq(q, contents))
3794 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3800 static int build_struct_offsets(
3802 const char *signature,
3806 size_t *n_offsets) {
3808 unsigned n_variable = 0, n_total = 0, v;
3809 size_t previous = 0, where;
3820 if (isempty(signature)) {
3827 sz = bus_gvariant_determine_word_size(size, 0);
3831 /* First, loop over signature and count variable elements and
3832 * elements in general. We use this to know how large the
3833 * offset array is at the end of the structure. Note that
3834 * GVariant only stores offsets for all variable size elements
3835 * that are not the last item. */
3841 r = signature_element_length(p, &n);
3850 r = bus_gvariant_is_fixed_size(t);
3855 if (r == 0 && p[n] != 0) /* except the last item */
3862 if (size < n_variable * sz)
3865 where = m->rindex + size - (n_variable * sz);
3866 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3872 *offsets = new(size_t, n_total);
3878 /* Second, loop again and build an offset table */
3884 r = signature_element_length(p, &n);
3893 k = bus_gvariant_get_size(t);
3901 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3904 if (m->rindex + x < previous)
3907 /* The last item's end
3908 * is determined from
3911 x = size - (n_variable * sz);
3913 offset = m->rindex + x;
3919 align = bus_gvariant_get_alignment(t);
3922 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3926 previous = (*offsets)[(*n_offsets)++] = offset;
3931 assert(*n_offsets == n_total);
3933 *item_size = (*offsets)[0] - m->rindex;
3937 static int enter_struct_or_dict_entry(
3939 struct bus_container *c,
3940 const char *contents,
3943 size_t *n_offsets) {
3954 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3957 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3961 } else if (c->item_size <= 0) {
3963 /* gvariant empty struct */
3968 /* gvariant with contents */
3969 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3974 static int bus_message_enter_struct(
3976 struct bus_container *c,
3977 const char *contents,
3980 size_t *n_offsets) {
3992 if (!signature_is_valid(contents, false))
3995 if (!c->signature || c->signature[c->index] == 0)
3998 l = strlen(contents);
4000 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4001 !startswith(c->signature + c->index + 1, contents) ||
4002 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4005 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4009 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4010 c->index += 1 + l + 1;
4015 static int bus_message_enter_dict_entry(
4017 struct bus_container *c,
4018 const char *contents,
4021 size_t *n_offsets) {
4030 if (!signature_is_pair(contents))
4033 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4036 if (!c->signature || c->signature[c->index] == 0)
4039 l = strlen(contents);
4041 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4042 !startswith(c->signature + c->index + 1, contents) ||
4043 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4046 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4050 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4051 c->index += 1 + l + 1;
4056 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4058 const char *contents) {
4059 struct bus_container *c, *w;
4060 uint32_t *array_size = NULL;
4063 size_t *offsets = NULL;
4064 size_t n_offsets = 0, item_size = 0;
4067 assert_return(m, -EINVAL);
4068 assert_return(m->sealed, -EPERM);
4069 assert_return(type != 0 || !contents, -EINVAL);
4071 if (type == 0 || !contents) {
4075 /* Allow entering into anonymous containers */
4076 r = sd_bus_message_peek_type(m, &tt, &cc);
4080 if (type != 0 && type != tt)
4083 if (contents && !streq(contents, cc))
4091 * We enforce a global limit on container depth, that is much
4092 * higher than the 32 structs and 32 arrays the specification
4093 * mandates. This is simpler to implement for us, and we need
4094 * this only to ensure our container array doesn't grow
4095 * without bounds. We are happy to return any data from a
4096 * message as long as the data itself is valid, even if the
4097 * overall message might be not.
4099 * Note that the message signature is validated when
4100 * parsing the headers, and that validation does check the
4103 * Note that the specification defines no limits on the depth
4104 * of stacked variants, but we do.
4106 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4109 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4112 if (message_end_of_signature(m))
4115 if (message_end_of_array(m, m->rindex))
4118 c = message_get_container(m);
4120 signature = strdup(contents);
4124 c->saved_index = c->index;
4127 if (type == SD_BUS_TYPE_ARRAY)
4128 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4129 else if (type == SD_BUS_TYPE_VARIANT)
4130 r = bus_message_enter_variant(m, c, contents, &item_size);
4131 else if (type == SD_BUS_TYPE_STRUCT)
4132 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4133 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4134 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4144 /* OK, let's fill it in */
4145 w = m->containers + m->n_containers++;
4146 w->enclosing = type;
4147 w->signature = signature;
4148 w->peeked_signature = NULL;
4152 w->begin = m->rindex;
4153 w->end = m->rindex + c->item_size;
4155 w->array_size = array_size;
4156 w->item_size = item_size;
4157 w->offsets = offsets;
4158 w->n_offsets = n_offsets;
4159 w->offset_index = 0;
4164 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4165 struct bus_container *c;
4169 assert_return(m, -EINVAL);
4170 assert_return(m->sealed, -EPERM);
4171 assert_return(m->n_containers > 0, -ENXIO);
4173 c = message_get_container(m);
4175 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4176 if (c->signature && c->signature[c->index] != 0)
4180 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4181 if (m->rindex < c->end)
4184 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4187 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4188 if (c->begin + l != m->rindex)
4193 free(c->peeked_signature);
4197 c = message_get_container(m);
4200 c->index = c->saved_index;
4201 r = container_next_item(m, c, &m->rindex);
4209 static void message_quit_container(sd_bus_message *m) {
4210 struct bus_container *c;
4214 assert(m->n_containers > 0);
4216 c = message_get_container(m);
4219 assert(m->rindex >= c->before);
4220 m->rindex = c->before;
4222 /* Free container */
4227 /* Correct index of new top-level container */
4228 c = message_get_container(m);
4229 c->index = c->saved_index;
4232 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4233 struct bus_container *c;
4236 assert_return(m, -EINVAL);
4237 assert_return(m->sealed, -EPERM);
4239 if (message_end_of_signature(m))
4242 if (message_end_of_array(m, m->rindex))
4245 c = message_get_container(m);
4247 if (bus_type_is_basic(c->signature[c->index])) {
4251 *type = c->signature[c->index];
4255 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4261 r = signature_element_length(c->signature+c->index+1, &l);
4267 sig = strndup(c->signature + c->index + 1, l);
4271 free(c->peeked_signature);
4272 *contents = c->peeked_signature = sig;
4276 *type = SD_BUS_TYPE_ARRAY;
4281 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4282 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4288 r = signature_element_length(c->signature+c->index, &l);
4293 sig = strndup(c->signature + c->index + 1, l - 2);
4297 free(c->peeked_signature);
4298 *contents = c->peeked_signature = sig;
4302 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4307 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4311 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4314 if (c->item_size < 2)
4317 /* Look for the NUL delimiter that
4318 separates the payload from the
4319 signature. Since the body might be
4320 in a different part that then the
4321 signature we map byte by byte. */
4323 for (k = 2; k <= c->item_size; k++) {
4326 where = m->rindex + c->item_size - k;
4327 r = message_peek_body(m, &where, 1, k, &q);
4331 if (*(char*) q == 0)
4335 if (k > c->item_size)
4338 free(c->peeked_signature);
4339 c->peeked_signature = strndup((char*) q + 1, k - 1);
4340 if (!c->peeked_signature)
4343 if (!signature_is_valid(c->peeked_signature, true))
4346 *contents = c->peeked_signature;
4351 r = message_peek_body(m, &rindex, 1, 1, &q);
4356 r = message_peek_body(m, &rindex, 1, l+1, &q);
4360 if (!validate_signature(q, l))
4368 *type = SD_BUS_TYPE_VARIANT;
4383 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4384 struct bus_container *c;
4386 assert_return(m, -EINVAL);
4387 assert_return(m->sealed, -EPERM);
4390 message_reset_containers(m);
4393 c = message_get_container(m);
4395 c = message_get_container(m);
4397 c->offset_index = 0;
4399 m->rindex = c->begin;
4402 c->offset_index = 0;
4403 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4405 return !isempty(c->signature);
4408 static int message_read_ap(
4413 unsigned n_array, n_struct;
4414 TypeStack stack[BUS_CONTAINER_DEPTH];
4415 unsigned stack_ptr = 0;
4416 unsigned n_loop = 0;
4424 /* Ideally, we'd just call ourselves recursively on every
4425 * complex type. However, the state of a va_list that is
4426 * passed to a function is undefined after that function
4427 * returns. This means we need to docode the va_list linearly
4428 * in a single stackframe. We hence implement our own
4429 * home-grown stack in an array. */
4431 n_array = (unsigned) -1; /* length of current array entries */
4432 n_struct = strlen(types); /* length of current struct contents signature */
4439 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4440 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4446 r = sd_bus_message_exit_container(m);
4454 if (n_array != (unsigned) -1)
4463 case SD_BUS_TYPE_BYTE:
4464 case SD_BUS_TYPE_BOOLEAN:
4465 case SD_BUS_TYPE_INT16:
4466 case SD_BUS_TYPE_UINT16:
4467 case SD_BUS_TYPE_INT32:
4468 case SD_BUS_TYPE_UINT32:
4469 case SD_BUS_TYPE_INT64:
4470 case SD_BUS_TYPE_UINT64:
4471 case SD_BUS_TYPE_DOUBLE:
4472 case SD_BUS_TYPE_STRING:
4473 case SD_BUS_TYPE_OBJECT_PATH:
4474 case SD_BUS_TYPE_SIGNATURE:
4475 case SD_BUS_TYPE_UNIX_FD: {
4478 p = va_arg(ap, void*);
4479 r = sd_bus_message_read_basic(m, *t, p);
4492 case SD_BUS_TYPE_ARRAY: {
4495 r = signature_element_length(t + 1, &k);
4501 memcpy(s, t + 1, k);
4504 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4515 if (n_array == (unsigned) -1) {
4520 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4526 n_array = va_arg(ap, unsigned);
4531 case SD_BUS_TYPE_VARIANT: {
4534 s = va_arg(ap, const char *);
4538 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4548 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4553 n_struct = strlen(s);
4554 n_array = (unsigned) -1;
4559 case SD_BUS_TYPE_STRUCT_BEGIN:
4560 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4563 r = signature_element_length(t, &k);
4569 memcpy(s, t + 1, k - 2);
4572 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4582 if (n_array == (unsigned) -1) {
4587 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4593 n_array = (unsigned) -1;
4606 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4610 assert_return(m, -EINVAL);
4611 assert_return(m->sealed, -EPERM);
4612 assert_return(types, -EINVAL);
4614 va_start(ap, types);
4615 r = message_read_ap(m, types, ap);
4621 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4624 assert_return(m, -EINVAL);
4625 assert_return(m->sealed, -EPERM);
4627 /* If types is NULL, read exactly one element */
4629 struct bus_container *c;
4632 if (message_end_of_signature(m))
4635 if (message_end_of_array(m, m->rindex))
4638 c = message_get_container(m);
4640 r = signature_element_length(c->signature + c->index, &l);
4644 types = strndupa(c->signature + c->index, l);
4649 case 0: /* Nothing to drop */
4652 case SD_BUS_TYPE_BYTE:
4653 case SD_BUS_TYPE_BOOLEAN:
4654 case SD_BUS_TYPE_INT16:
4655 case SD_BUS_TYPE_UINT16:
4656 case SD_BUS_TYPE_INT32:
4657 case SD_BUS_TYPE_UINT32:
4658 case SD_BUS_TYPE_INT64:
4659 case SD_BUS_TYPE_UINT64:
4660 case SD_BUS_TYPE_DOUBLE:
4661 case SD_BUS_TYPE_STRING:
4662 case SD_BUS_TYPE_OBJECT_PATH:
4663 case SD_BUS_TYPE_SIGNATURE:
4664 case SD_BUS_TYPE_UNIX_FD:
4666 r = sd_bus_message_read_basic(m, *types, NULL);
4670 r = sd_bus_message_skip(m, types + 1);
4676 case SD_BUS_TYPE_ARRAY: {
4679 r = signature_element_length(types + 1, &k);
4685 memcpy(s, types+1, k);
4688 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4693 r = sd_bus_message_skip(m, s);
4700 r = sd_bus_message_exit_container(m);
4705 r = sd_bus_message_skip(m, types + 1 + k);
4712 case SD_BUS_TYPE_VARIANT: {
4713 const char *contents;
4716 r = sd_bus_message_peek_type(m, &x, &contents);
4720 if (x != SD_BUS_TYPE_VARIANT)
4723 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4727 r = sd_bus_message_skip(m, contents);
4732 r = sd_bus_message_exit_container(m);
4736 r = sd_bus_message_skip(m, types + 1);
4743 case SD_BUS_TYPE_STRUCT_BEGIN:
4744 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4747 r = signature_element_length(types, &k);
4753 memcpy(s, types+1, k-2);
4756 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4760 r = sd_bus_message_skip(m, s);
4765 r = sd_bus_message_exit_container(m);
4770 r = sd_bus_message_skip(m, types + k);
4782 _public_ int sd_bus_message_read_array(
4788 struct bus_container *c;
4794 assert_return(m, -EINVAL);
4795 assert_return(m->sealed, -EPERM);
4796 assert_return(bus_type_is_trivial(type), -EINVAL);
4797 assert_return(ptr, -EINVAL);
4798 assert_return(size, -EINVAL);
4799 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4801 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4805 c = message_get_container(m);
4807 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4808 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4812 sz = c->end - c->begin;
4814 align = bus_type_get_alignment(type);
4818 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4822 /* Zero length array, let's return some aligned
4823 * pointer that is not NULL */
4824 p = (uint8_t*) NULL + align;
4826 r = message_peek_body(m, &m->rindex, align, sz, &p);
4831 r = sd_bus_message_exit_container(m);
4835 *ptr = (const void*) p;
4841 message_quit_container(m);
4845 static int message_peek_fields(
4856 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4859 static int message_peek_field_uint32(
4871 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4874 /* identical for gvariant and dbus1 */
4876 r = message_peek_fields(m, ri, 4, 4, &q);
4881 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4886 static int message_peek_field_uint64(
4898 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4901 /* identical for gvariant and dbus1 */
4903 r = message_peek_fields(m, ri, 8, 8, &q);
4908 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4913 static int message_peek_field_string(
4915 bool (*validate)(const char *p),
4927 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4932 r = message_peek_fields(m, ri, 1, item_size, &q);
4938 r = message_peek_field_uint32(m, ri, 4, &l);
4942 r = message_peek_fields(m, ri, 1, l+1, &q);
4948 if (!validate_nul(q, l))
4954 if (!validate_string(q, l))
4964 static int message_peek_field_signature(
4977 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4982 r = message_peek_fields(m, ri, 1, item_size, &q);
4988 r = message_peek_fields(m, ri, 1, 1, &q);
4993 r = message_peek_fields(m, ri, 1, l+1, &q);
4998 if (!validate_signature(q, l))
5007 static int message_skip_fields(
5010 uint32_t array_size,
5011 const char **signature) {
5013 size_t original_index;
5019 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5021 original_index = *ri;
5027 if (array_size != (uint32_t) -1 &&
5028 array_size <= *ri - original_index)
5035 if (t == SD_BUS_TYPE_STRING) {
5037 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5043 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5045 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5051 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5053 r = message_peek_field_signature(m, ri, 0, NULL);
5059 } else if (bus_type_is_basic(t)) {
5062 align = bus_type_get_alignment(t);
5063 k = bus_type_get_size(t);
5064 assert(align > 0 && k > 0);
5066 r = message_peek_fields(m, ri, align, k, NULL);
5072 } else if (t == SD_BUS_TYPE_ARRAY) {
5074 r = signature_element_length(*signature+1, &l);
5084 strncpy(sig, *signature + 1, l-1);
5087 alignment = bus_type_get_alignment(sig[0]);
5091 r = message_peek_field_uint32(m, ri, 0, &nas);
5094 if (nas > BUS_ARRAY_MAX_SIZE)
5097 r = message_peek_fields(m, ri, alignment, 0, NULL);
5101 r = message_skip_fields(m, ri, nas, (const char**) &s);
5106 (*signature) += 1 + l;
5108 } else if (t == SD_BUS_TYPE_VARIANT) {
5111 r = message_peek_field_signature(m, ri, 0, &s);
5115 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5121 } else if (t == SD_BUS_TYPE_STRUCT ||
5122 t == SD_BUS_TYPE_DICT_ENTRY) {
5124 r = signature_element_length(*signature, &l);
5131 strncpy(sig, *signature + 1, l-1);
5134 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5145 int bus_message_parse_fields(sd_bus_message *m) {
5148 uint32_t unix_fds = 0;
5149 bool unix_fds_set = false;
5150 void *offsets = NULL;
5151 unsigned n_offsets = 0;
5157 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5160 /* Read the signature from the end of the body variant first */
5161 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5162 if (m->footer_accessible < 1 + sz)
5165 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5167 if (p < (char*) m->footer)
5173 /* We found the beginning of the signature string, yay! */
5175 c = strndup(p + 1, ((char*) m->footer + m->footer_accessible) - p - (1 + sz));
5179 free(m->root_container.signature);
5180 m->root_container.signature = c;
5187 /* Calculate the actual user body size, by removing
5188 * the trailing variant signature and struct offset
5190 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5192 /* Pull out the offset table for the fields array */
5193 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5198 ri = m->fields_size - sz;
5199 r = message_peek_fields(m, &ri, 1, sz, &q);
5203 framing = bus_gvariant_read_word_le(q, sz);
5204 if (framing >= m->fields_size - sz)
5206 if ((m->fields_size - framing) % sz != 0)
5210 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5214 n_offsets = (m->fields_size - framing) / sz;
5217 m->user_body_size = m->body_size;
5220 while (ri < m->fields_size) {
5221 _cleanup_free_ char *sig = NULL;
5222 const char *signature;
5223 uint64_t field_type;
5224 size_t item_size = (size_t) -1;
5226 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5235 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5237 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5241 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5245 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5252 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5257 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5262 where = ri = ALIGN_TO(ri, 8);
5263 item_size = end - ri;
5264 r = message_peek_fields(m, &where, 1, item_size, &q);
5268 b = memrchr(q, 0, item_size);
5272 sig = strndup(b+1, item_size - (b+1-(char*) q));
5277 item_size = b - (char*) q;
5279 r = message_peek_field_signature(m, &ri, 0, &signature);
5284 switch (field_type) {
5286 case _BUS_MESSAGE_HEADER_INVALID:
5289 case BUS_MESSAGE_HEADER_PATH:
5294 if (!streq(signature, "o"))
5297 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5300 case BUS_MESSAGE_HEADER_INTERFACE:
5305 if (!streq(signature, "s"))
5308 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5311 case BUS_MESSAGE_HEADER_MEMBER:
5316 if (!streq(signature, "s"))
5319 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5322 case BUS_MESSAGE_HEADER_ERROR_NAME:
5327 if (!streq(signature, "s"))
5330 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5332 m->error._need_free = -1;
5336 case BUS_MESSAGE_HEADER_DESTINATION:
5341 if (!streq(signature, "s"))
5344 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5347 case BUS_MESSAGE_HEADER_SENDER:
5352 if (!streq(signature, "s"))
5355 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5357 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5358 m->creds.unique_name = (char*) m->sender;
5359 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5365 case BUS_MESSAGE_HEADER_SIGNATURE: {
5369 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5372 if (m->root_container.signature)
5375 if (!streq(signature, "g"))
5378 r = message_peek_field_signature(m, &ri, item_size, &s);
5386 free(m->root_container.signature);
5387 m->root_container.signature = c;
5391 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5393 if (m->reply_cookie != 0)
5396 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5397 /* 64bit on dbus2 */
5399 if (!streq(signature, "t"))
5402 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5406 /* 32bit on dbus1 */
5409 if (!streq(signature, "u"))
5412 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5416 m->reply_cookie = serial;
5419 if (m->reply_cookie == 0)
5424 case BUS_MESSAGE_HEADER_UNIX_FDS:
5428 if (!streq(signature, "u"))
5431 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5435 unix_fds_set = true;
5439 if (!BUS_MESSAGE_IS_GVARIANT(m))
5440 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5449 if (m->n_fds != unix_fds)
5452 switch (m->header->type) {
5454 case SD_BUS_MESSAGE_SIGNAL:
5455 if (!m->path || !m->interface || !m->member)
5458 if (m->reply_cookie != 0)
5463 case SD_BUS_MESSAGE_METHOD_CALL:
5465 if (!m->path || !m->member)
5468 if (m->reply_cookie != 0)
5473 case SD_BUS_MESSAGE_METHOD_RETURN:
5475 if (m->reply_cookie == 0)
5479 case SD_BUS_MESSAGE_METHOD_ERROR:
5481 if (m->reply_cookie == 0 || !m->error.name)
5486 /* Refuse non-local messages that claim they are local */
5487 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5489 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5491 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5494 m->root_container.end = m->user_body_size;
5496 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5497 r = build_struct_offsets(
5499 m->root_container.signature,
5501 &m->root_container.item_size,
5502 &m->root_container.offsets,
5503 &m->root_container.n_offsets);
5508 /* Try to read the error message, but if we can't it's a non-issue */
5509 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5510 (void) sd_bus_message_read(m, "s", &m->error.message);
5515 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5516 assert_return(m, -EINVAL);
5517 assert_return(destination, -EINVAL);
5518 assert_return(!m->sealed, -EPERM);
5519 assert_return(!m->destination, -EEXIST);
5521 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5524 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5528 struct bus_body_part *part;
5534 total = BUS_MESSAGE_SIZE(m);
5540 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5541 MESSAGE_FOREACH_PART(part, i, m)
5542 e = mempcpy(e, part->data, part->size);
5544 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5552 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5559 r = sd_bus_message_enter_container(m, 'a', "s");
5563 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5564 r = strv_extend(l, s);
5571 r = sd_bus_message_exit_container(m);
5578 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5582 assert_return(m, -EINVAL);
5583 assert_return(m->sealed, -EPERM);
5584 assert_return(l, -EINVAL);
5586 r = bus_message_read_strv_extend(m, &strv);
5596 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5597 const char *contents;
5606 r = sd_bus_message_rewind(m, true);
5611 r = sd_bus_message_peek_type(m, &type, &contents);
5617 /* Don't match against arguments after the first one we don't understand */
5618 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5619 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5625 r = sd_bus_message_skip(m, NULL);
5630 if (type == SD_BUS_TYPE_ARRAY) {
5632 r = sd_bus_message_read_strv(m, strv);
5639 r = sd_bus_message_read_basic(m, type, str);
5649 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5650 assert_return(m, EINVAL);
5652 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5655 return sd_bus_error_get_errno(&m->error);
5658 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5659 struct bus_container *c;
5661 assert_return(m, NULL);
5663 c = complete ? &m->root_container : message_get_container(m);
5664 return strempty(c->signature);
5667 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5668 assert_return(m, -EINVAL);
5670 return isempty(m->root_container.signature);
5673 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5674 assert_return(m, -EINVAL);
5676 return streq(strempty(m->root_container.signature), strempty(signature));
5679 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5680 bool done_something = false;
5683 assert_return(m, -EINVAL);
5684 assert_return(source, -EINVAL);
5685 assert_return(!m->sealed, -EPERM);
5686 assert_return(source->sealed, -EPERM);
5689 const char *contents;
5704 r = sd_bus_message_peek_type(source, &type, &contents);
5710 done_something = true;
5712 if (bus_type_is_container(type) > 0) {
5714 r = sd_bus_message_enter_container(source, type, contents);
5718 r = sd_bus_message_open_container(m, type, contents);
5722 r = sd_bus_message_copy(m, source, true);
5726 r = sd_bus_message_close_container(m);
5730 r = sd_bus_message_exit_container(source);
5737 r = sd_bus_message_read_basic(source, type, &basic);
5743 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5744 type == SD_BUS_TYPE_SIGNATURE ||
5745 type == SD_BUS_TYPE_STRING)
5746 r = sd_bus_message_append_basic(m, type, basic.string);
5748 r = sd_bus_message_append_basic(m, type, &basic);
5755 return done_something;
5758 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5763 assert_return(m, -EINVAL);
5764 assert_return(m->sealed, -EPERM);
5765 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5766 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5767 assert_return(type || contents, -EINVAL);
5768 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5770 r = sd_bus_message_peek_type(m, &t, &c);
5774 if (type != 0 && type != t)
5777 if (contents && !streq_ptr(contents, c))
5783 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5784 assert_return(m, NULL);
5789 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5790 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5798 switch ((*m)->header->type) {
5800 case SD_BUS_MESSAGE_SIGNAL:
5801 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5807 case SD_BUS_MESSAGE_METHOD_CALL:
5808 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5814 case SD_BUS_MESSAGE_METHOD_RETURN:
5815 case SD_BUS_MESSAGE_METHOD_ERROR:
5817 n = message_new(bus, (*m)->header->type);
5821 n->reply_cookie = (*m)->reply_cookie;
5823 r = message_append_reply_cookie(n, n->reply_cookie);
5827 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5828 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5832 n->error._need_free = -1;
5841 if ((*m)->destination && !n->destination) {
5842 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5847 if ((*m)->sender && !n->sender) {
5848 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5853 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5855 r = sd_bus_message_copy(n, *m, true);
5859 timeout = (*m)->timeout;
5860 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5861 timeout = BUS_DEFAULT_TIMEOUT;
5863 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5867 sd_bus_message_unref(*m);
5874 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5878 assert_return(!m->sealed, -EPERM);
5879 assert_return(!m->sender, -EPERM);
5881 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5884 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5885 assert_return(m, -EINVAL);
5886 assert_return(priority, -EINVAL);
5888 *priority = m->priority;
5892 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5893 assert_return(m, -EINVAL);
5894 assert_return(!m->sealed, -EPERM);
5896 m->priority = priority;