1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include "time-util.h"
30 #include "memfd-util.h"
33 #include "bus-message.h"
34 #include "bus-internal.h"
36 #include "bus-signature.h"
37 #include "bus-gvariant.h"
40 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
42 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
47 if (old_base == new_base)
50 if ((uint8_t*) p < (uint8_t*) old_base)
53 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
56 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
59 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
63 if (part->memfd >= 0) {
64 /* If we can reuse the memfd, try that. For that it
65 * can't be sealed yet. */
68 assert(part->memfd_offset == 0);
69 assert(part->data == part->mmap_begin);
70 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
73 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
75 safe_close(part->memfd);
78 } else if (part->munmap_this)
79 munmap(part->mmap_begin, part->mapped);
80 else if (part->free_this)
87 static void message_reset_parts(sd_bus_message *m) {
88 struct bus_body_part *part;
93 while (m->n_body_parts > 0) {
94 struct bus_body_part *next = part->next;
95 message_free_part(m, part);
102 m->cached_rindex_part = NULL;
103 m->cached_rindex_part_begin = 0;
106 static void message_reset_containers(sd_bus_message *m) {
111 for (i = 0; i < m->n_containers; i++) {
112 free(m->containers[i].signature);
113 free(m->containers[i].offsets);
117 m->containers = NULL;
119 m->n_containers = m->containers_allocated = 0;
120 m->root_container.index = 0;
123 static void message_free(sd_bus_message *m) {
129 message_reset_parts(m);
131 if (m->release_kdbus)
132 bus_kernel_cmd_free(m->bus, (uint8_t *) m->kdbus - (uint8_t *) m->bus->kdbus_buffer);
137 sd_bus_unref(m->bus);
140 close_many(m->fds, m->n_fds);
144 if (m->iovec != m->iovec_fixed)
147 if (m->destination_ptr) {
148 free(m->destination_ptr);
149 m->destination_ptr = NULL;
152 message_reset_containers(m);
153 free(m->root_container.signature);
154 free(m->root_container.offsets);
156 free(m->root_container.peeked_signature);
158 bus_creds_done(&m->creds);
162 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
164 size_t old_size, new_size, start;
171 old_size = sizeof(struct bus_header) + m->fields_size;
172 start = ALIGN_TO(old_size, align);
173 new_size = start + sz;
175 if (new_size < start ||
176 new_size > (size_t) ((uint32_t) -1))
179 if (old_size == new_size)
180 return (uint8_t*) m->header + old_size;
182 if (m->free_header) {
183 np = realloc(m->header, ALIGN8(new_size));
187 /* Initially, the header is allocated as part of of
188 * the sd_bus_message itself, let's replace it by
191 np = malloc(ALIGN8(new_size));
195 memcpy(np, m->header, sizeof(struct bus_header));
198 /* Zero out padding */
199 if (start > old_size)
200 memzero((uint8_t*) np + old_size, start - old_size);
204 m->fields_size = new_size - sizeof(struct bus_header);
206 /* Adjust quick access pointers */
207 m->path = adjust_pointer(m->path, op, old_size, m->header);
208 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
209 m->member = adjust_pointer(m->member, op, old_size, m->header);
210 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
211 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
212 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
214 m->free_header = true;
217 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
220 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
223 return (uint8_t*) np + start;
230 static int message_append_field_string(
242 /* dbus1 only allows 8bit header field ids */
246 /* dbus1 doesn't allow strings over 32bit, let's enforce this
247 * globally, to not risk convertability */
249 if (l > (size_t) (uint32_t) -1)
252 /* Signature "(yv)" where the variant contains "s" */
254 if (BUS_MESSAGE_IS_GVARIANT(m)) {
256 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
257 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
261 *((uint64_t*) p) = h;
268 *ret = (char*) p + 8;
271 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
272 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
281 ((uint32_t*) p)[1] = l;
282 memcpy(p + 8, s, l + 1);
285 *ret = (char*) p + 8;
291 static int message_append_field_signature(
302 /* dbus1 only allows 8bit header field ids */
306 /* dbus1 doesn't allow signatures over 8bit, let's enforce
307 * this globally, to not risk convertability */
312 /* Signature "(yv)" where the variant contains "g" */
314 if (BUS_MESSAGE_IS_GVARIANT(m))
315 /* For gvariant the serialization is the same as for normal strings */
316 return message_append_field_string(m, h, 'g', s, ret);
318 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
319 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
325 p[2] = SD_BUS_TYPE_SIGNATURE;
328 memcpy(p + 5, s, l + 1);
331 *ret = (const char*) p + 5;
337 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
342 /* dbus1 only allows 8bit header field ids */
346 if (BUS_MESSAGE_IS_GVARIANT(m)) {
347 /* (field id 64bit + ((value + NUL + signature string 'u') */
349 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
353 *((uint64_t*) p) = h;
354 *((uint32_t*) (p + 8)) = x;
358 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
359 p = message_extend_fields(m, 8, 4 + 4, false);
368 ((uint32_t*) p)[1] = x;
374 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
379 /* dbus1 only allows 8bit header field ids */
383 if (BUS_MESSAGE_IS_GVARIANT(m)) {
384 /* (field id 64bit + ((value + NUL + signature string 't') */
386 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
390 *((uint64_t*) p) = h;
391 *((uint64_t*) (p + 8)) = x;
395 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
396 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
409 ((uint64_t*) p)[1] = x;
415 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
418 if (BUS_MESSAGE_IS_GVARIANT(m))
419 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
421 /* 64bit cookies are not supported on dbus1 */
422 if (cookie > 0xffffffffUL)
425 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
429 int bus_message_from_header(
432 size_t header_accessible,
434 size_t footer_accessible,
440 sd_bus_message **ret) {
442 _cleanup_free_ sd_bus_message *m = NULL;
443 struct bus_header *h;
447 assert(header || header_accessible <= 0);
448 assert(footer || footer_accessible <= 0);
449 assert(fds || n_fds <= 0);
452 if (header_accessible < sizeof(struct bus_header))
455 if (header_accessible > message_size)
457 if (footer_accessible > message_size)
461 if (!IN_SET(h->version, 1, 2))
464 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
467 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
470 /* Note that we are happy with unknown flags in the flags header! */
472 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
475 label_sz = strlen(label);
486 m->header_accessible = header_accessible;
488 m->footer_accessible = footer_accessible;
490 if (BUS_MESSAGE_IS_GVARIANT(m)) {
493 if (h->dbus2.cookie == 0)
496 /* dbus2 derives the sizes from the message size and
497 the offset table at the end, since it is formatted as
498 gvariant "yyyyuta{tv}v". Since the message itself is a
499 structure with precisely to variable sized entries,
500 there's only one offset in the table, which marks the
501 end of the fields array. */
503 ws = bus_gvariant_determine_word_size(message_size, 0);
504 if (footer_accessible < ws)
507 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
508 if (ALIGN8(m->fields_size) > message_size - ws)
510 if (m->fields_size < sizeof(struct bus_header))
513 m->fields_size -= sizeof(struct bus_header);
514 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
516 if (h->dbus1.serial == 0)
519 /* dbus1 has the sizes in the header */
520 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
521 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
523 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
531 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
532 memcpy(m->creds.label, label, label_sz + 1);
534 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
537 m->bus = sd_bus_ref(bus);
544 int bus_message_from_malloc(
551 sd_bus_message **ret) {
557 r = bus_message_from_header(
559 buffer, length, /* in this case the initial bytes and the final bytes are the same */
568 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
571 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
573 m->body.sealed = true;
578 m->iovec = m->iovec_fixed;
579 m->iovec[0].iov_base = buffer;
580 m->iovec[0].iov_len = length;
582 r = bus_message_parse_fields(m);
586 /* We take possession of the memory and fds now */
587 m->free_header = true;
598 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
603 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
608 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
609 m->header->endian = BUS_NATIVE_ENDIAN;
610 m->header->type = type;
611 m->header->version = bus->message_version;
612 m->allow_fds = bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
613 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
614 m->bus = sd_bus_ref(bus);
616 if (bus->allow_interactive_authorization)
617 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
622 _public_ int sd_bus_message_new_signal(
626 const char *interface,
627 const char *member) {
632 assert_return(bus, -ENOTCONN);
633 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
634 assert_return(object_path_is_valid(path), -EINVAL);
635 assert_return(interface_name_is_valid(interface), -EINVAL);
636 assert_return(member_name_is_valid(member), -EINVAL);
637 assert_return(m, -EINVAL);
639 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
643 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
645 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
648 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
651 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
659 sd_bus_message_unref(t);
663 _public_ int sd_bus_message_new_method_call(
666 const char *destination,
668 const char *interface,
669 const char *member) {
674 assert_return(bus, -ENOTCONN);
675 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
676 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
677 assert_return(object_path_is_valid(path), -EINVAL);
678 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
679 assert_return(member_name_is_valid(member), -EINVAL);
680 assert_return(m, -EINVAL);
682 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
686 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
689 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
694 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
700 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
713 static int message_new_reply(
714 sd_bus_message *call,
716 sd_bus_message **m) {
721 assert_return(call, -EINVAL);
722 assert_return(call->sealed, -EPERM);
723 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
724 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
725 assert_return(m, -EINVAL);
727 t = message_new(call->bus, type);
731 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
732 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
733 if (t->reply_cookie == 0)
736 r = message_append_reply_cookie(t, t->reply_cookie);
741 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
746 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
747 t->enforced_reply_signature = call->enforced_reply_signature;
757 _public_ int sd_bus_message_new_method_return(
758 sd_bus_message *call,
759 sd_bus_message **m) {
761 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
764 _public_ int sd_bus_message_new_method_error(
765 sd_bus_message *call,
767 const sd_bus_error *e) {
772 assert_return(sd_bus_error_is_set(e), -EINVAL);
773 assert_return(m, -EINVAL);
775 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
779 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
784 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
789 t->error._need_free = -1;
799 _public_ int sd_bus_message_new_method_errorf(
800 sd_bus_message *call,
806 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
809 assert_return(name, -EINVAL);
810 assert_return(m, -EINVAL);
812 va_start(ap, format);
813 bus_error_setfv(&error, name, format, ap);
816 return sd_bus_message_new_method_error(call, m, &error);
819 _public_ int sd_bus_message_new_method_errno(
820 sd_bus_message *call,
823 const sd_bus_error *p) {
825 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
827 if (sd_bus_error_is_set(p))
828 return sd_bus_message_new_method_error(call, m, p);
830 sd_bus_error_set_errno(&berror, error);
832 return sd_bus_message_new_method_error(call, m, &berror);
835 /// UNNEEDED by elogind
837 _public_ int sd_bus_message_new_method_errnof(
838 sd_bus_message *call,
844 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
847 va_start(ap, format);
848 sd_bus_error_set_errnofv(&berror, error, format, ap);
851 return sd_bus_message_new_method_error(call, m, &berror);
855 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
859 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
860 m->creds.well_known_names_local = true;
861 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
864 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
868 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
869 m->creds.well_known_names_driver = true;
870 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
873 int bus_message_new_synthetic_error(
876 const sd_bus_error *e,
877 sd_bus_message **m) {
883 assert(sd_bus_error_is_set(e));
886 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
890 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
891 t->reply_cookie = cookie;
893 r = message_append_reply_cookie(t, t->reply_cookie);
897 if (bus && bus->unique_name) {
898 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
903 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
908 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
913 t->error._need_free = -1;
915 bus_message_set_sender_driver(bus, t);
925 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
926 assert_return(m, NULL);
928 assert(m->n_ref > 0);
934 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
939 assert(m->n_ref > 0);
949 /// UNNEEDED by elogind
951 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
952 assert_return(m, -EINVAL);
953 assert_return(type, -EINVAL);
955 *type = m->header->type;
959 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
962 assert_return(m, -EINVAL);
963 assert_return(cookie, -EINVAL);
965 c = BUS_MESSAGE_COOKIE(m);
969 *cookie = BUS_MESSAGE_COOKIE(m);
973 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
974 assert_return(m, -EINVAL);
975 assert_return(cookie, -EINVAL);
977 if (m->reply_cookie == 0)
980 *cookie = m->reply_cookie;
984 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
985 assert_return(m, -EINVAL);
987 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
988 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
991 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
992 assert_return(m, -EINVAL);
994 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
998 _public_ int sd_bus_message_get_allow_interactive_authorization(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_ALLOW_INTERACTIVE_AUTHORIZATION);
1005 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1006 assert_return(m, NULL);
1011 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1012 assert_return(m, NULL);
1014 return m->interface;
1017 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1018 assert_return(m, NULL);
1023 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1024 assert_return(m, NULL);
1026 return m->destination;
1029 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1030 assert_return(m, NULL);
1035 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1036 assert_return(m, NULL);
1037 assert_return(sd_bus_error_is_set(&m->error), NULL);
1042 /// UNNEEDED by elogind
1044 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1045 assert_return(m, -EINVAL);
1046 assert_return(usec, -EINVAL);
1048 if (m->monotonic <= 0)
1051 *usec = m->monotonic;
1055 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1056 assert_return(m, -EINVAL);
1057 assert_return(usec, -EINVAL);
1059 if (m->realtime <= 0)
1062 *usec = m->realtime;
1066 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1067 assert_return(m, -EINVAL);
1068 assert_return(seqnum, -EINVAL);
1073 *seqnum = m->seqnum;
1078 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1079 assert_return(m, NULL);
1081 if (m->creds.mask == 0)
1087 /// UNNEEDED by elogind
1089 _public_ int sd_bus_message_is_signal(
1091 const char *interface,
1092 const char *member) {
1094 assert_return(m, -EINVAL);
1096 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1099 if (interface && (!m->interface || !streq(m->interface, interface)))
1102 if (member && (!m->member || !streq(m->member, member)))
1109 _public_ int sd_bus_message_is_method_call(
1111 const char *interface,
1112 const char *member) {
1114 assert_return(m, -EINVAL);
1116 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1119 if (interface && (!m->interface || !streq(m->interface, interface)))
1122 if (member && (!m->member || !streq(m->member, member)))
1128 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1129 assert_return(m, -EINVAL);
1131 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1134 if (name && (!m->error.name || !streq(m->error.name, name)))
1140 /// UNNEEDED by elogind
1142 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1143 assert_return(m, -EINVAL);
1144 assert_return(!m->sealed, -EPERM);
1145 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1148 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1150 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1156 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1157 assert_return(m, -EINVAL);
1158 assert_return(!m->sealed, -EPERM);
1161 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1163 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1168 /// UNNEEDED by elogind
1170 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1171 assert_return(m, -EINVAL);
1172 assert_return(!m->sealed, -EPERM);
1175 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1177 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1183 static struct bus_container *message_get_container(sd_bus_message *m) {
1186 if (m->n_containers == 0)
1187 return &m->root_container;
1189 assert(m->containers);
1190 return m->containers + m->n_containers - 1;
1193 struct bus_body_part *message_append_part(sd_bus_message *m) {
1194 struct bus_body_part *part;
1201 if (m->n_body_parts <= 0) {
1205 assert(m->body_end);
1207 part = new0(struct bus_body_part, 1);
1213 m->body_end->next = part;
1223 static void part_zero(struct bus_body_part *part, size_t sz) {
1228 /* All other fields can be left in their defaults */
1229 assert(!part->data);
1230 assert(part->memfd < 0);
1233 part->is_zero = true;
1234 part->sealed = true;
1237 static int part_make_space(
1238 struct sd_bus_message *m,
1239 struct bus_body_part *part,
1248 assert(!part->sealed);
1253 if (!part->data && part->memfd < 0) {
1254 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1255 part->mmap_begin = part->data;
1258 if (part->memfd >= 0) {
1260 if (part->allocated == 0 || sz > part->allocated) {
1261 uint64_t new_allocated;
1263 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1264 r = memfd_set_size(part->memfd, new_allocated);
1270 part->allocated = new_allocated;
1273 if (!part->data || sz > part->mapped) {
1276 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1277 if (part->mapped <= 0)
1278 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1280 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1282 if (n == MAP_FAILED) {
1287 part->mmap_begin = part->data = n;
1289 part->memfd_offset = 0;
1292 part->munmap_this = true;
1294 if (part->allocated == 0 || sz > part->allocated) {
1295 size_t new_allocated;
1297 new_allocated = sz > 0 ? 2 * sz : 64;
1298 n = realloc(part->data, new_allocated);
1305 part->allocated = new_allocated;
1306 part->free_this = true;
1311 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1317 static int message_add_offset(sd_bus_message *m, size_t offset) {
1318 struct bus_container *c;
1321 assert(BUS_MESSAGE_IS_GVARIANT(m));
1323 /* Add offset to current container, unless this is the first
1324 * item in it, which will have the 0 offset, which we can
1326 c = message_get_container(m);
1328 if (!c->need_offsets)
1331 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1334 c->offsets[c->n_offsets++] = offset;
1338 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1339 struct bus_container *c;
1346 /* Update counters */
1347 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1350 *c->array_size += expand;
1354 static void *message_extend_body(
1359 bool force_inline) {
1361 size_t start_body, end_body, padding, added;
1372 start_body = ALIGN_TO((size_t) m->body_size, align);
1373 end_body = start_body + sz;
1375 padding = start_body - m->body_size;
1376 added = padding + sz;
1378 /* Check for 32bit overflows */
1379 if (end_body > (size_t) ((uint32_t) -1) ||
1380 end_body < start_body) {
1386 struct bus_body_part *part = NULL;
1390 m->n_body_parts <= 0 ||
1391 m->body_end->sealed ||
1392 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1393 (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 */
1397 part = message_append_part(m);
1401 part_zero(part, padding);
1404 part = message_append_part(m);
1408 r = part_make_space(m, part, sz, &p);
1412 struct bus_container *c;
1414 size_t os, start_part, end_part;
1420 start_part = ALIGN_TO(part->size, align);
1421 end_part = start_part + sz;
1423 r = part_make_space(m, part, end_part, &p);
1428 memzero(p, padding);
1429 p = (uint8_t*) p + padding;
1432 /* Readjust pointers */
1433 for (c = m->containers; c < m->containers + m->n_containers; c++)
1434 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1436 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1439 /* Return something that is not NULL and is aligned */
1440 p = (uint8_t *) NULL + align;
1442 m->body_size = end_body;
1443 message_extend_containers(m, added);
1446 r = message_add_offset(m, end_body);
1456 static int message_push_fd(sd_bus_message *m, int fd) {
1467 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1471 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1479 m->fds[m->n_fds] = copy;
1485 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1486 _cleanup_close_ int fd = -1;
1487 struct bus_container *c;
1491 assert_return(m, -EINVAL);
1492 assert_return(!m->sealed, -EPERM);
1493 assert_return(bus_type_is_basic(type), -EINVAL);
1494 assert_return(!m->poisoned, -ESTALE);
1496 c = message_get_container(m);
1498 if (c->signature && c->signature[c->index]) {
1499 /* Container signature is already set */
1501 if (c->signature[c->index] != type)
1506 /* Maybe we can append to the signature? But only if this is the top-level container */
1507 if (c->enclosing != 0)
1510 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1517 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1523 case SD_BUS_TYPE_SIGNATURE:
1524 case SD_BUS_TYPE_STRING:
1527 /* Fall through... */
1528 case SD_BUS_TYPE_OBJECT_PATH:
1536 case SD_BUS_TYPE_BOOLEAN:
1538 u8 = p && *(int*) p;
1544 case SD_BUS_TYPE_UNIX_FD:
1549 fd = message_push_fd(m, *(int*) p);
1560 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1561 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1568 a = message_extend_body(m, align, sz, true, false);
1575 *stored = (const uint8_t*) a;
1582 case SD_BUS_TYPE_STRING:
1583 /* To make things easy we'll serialize a NULL string
1584 * into the empty string */
1587 /* Fall through... */
1588 case SD_BUS_TYPE_OBJECT_PATH:
1594 sz = 4 + strlen(p) + 1;
1597 case SD_BUS_TYPE_SIGNATURE:
1602 sz = 1 + strlen(p) + 1;
1605 case SD_BUS_TYPE_BOOLEAN:
1607 u32 = p && *(int*) p;
1613 case SD_BUS_TYPE_UNIX_FD:
1618 fd = message_push_fd(m, *(int*) p);
1629 align = bus_type_get_alignment(type);
1630 sz = bus_type_get_size(type);
1637 a = message_extend_body(m, align, sz, false, false);
1641 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1642 *(uint32_t*) a = sz - 5;
1643 memcpy((uint8_t*) a + 4, p, sz - 4);
1646 *stored = (const uint8_t*) a + 4;
1648 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1649 *(uint8_t*) a = sz - 2;
1650 memcpy((uint8_t*) a + 1, p, sz - 1);
1653 *stored = (const uint8_t*) a + 1;
1662 if (type == SD_BUS_TYPE_UNIX_FD)
1665 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1672 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1673 return message_append_basic(m, type, p, NULL);
1676 _public_ int sd_bus_message_append_string_space(
1681 struct bus_container *c;
1684 assert_return(m, -EINVAL);
1685 assert_return(s, -EINVAL);
1686 assert_return(!m->sealed, -EPERM);
1687 assert_return(!m->poisoned, -ESTALE);
1689 c = message_get_container(m);
1691 if (c->signature && c->signature[c->index]) {
1692 /* Container signature is already set */
1694 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1699 /* Maybe we can append to the signature? But only if this is the top-level container */
1700 if (c->enclosing != 0)
1703 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1710 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1711 a = message_extend_body(m, 1, size + 1, true, false);
1717 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1721 *(uint32_t*) a = size;
1727 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1733 /// UNNEEDED by elogind
1735 _public_ int sd_bus_message_append_string_iovec(
1737 const struct iovec *iov,
1745 assert_return(m, -EINVAL);
1746 assert_return(!m->sealed, -EPERM);
1747 assert_return(iov || n == 0, -EINVAL);
1748 assert_return(!m->poisoned, -ESTALE);
1750 size = IOVEC_TOTAL_SIZE(iov, n);
1752 r = sd_bus_message_append_string_space(m, size, &p);
1756 for (i = 0; i < n; i++) {
1758 if (iov[i].iov_base)
1759 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1761 memset(p, ' ', iov[i].iov_len);
1763 p += iov[i].iov_len;
1770 static int bus_message_open_array(
1772 struct bus_container *c,
1773 const char *contents,
1774 uint32_t **array_size,
1776 bool *need_offsets) {
1786 assert(need_offsets);
1788 if (!signature_is_single(contents, true))
1791 if (c->signature && c->signature[c->index]) {
1793 /* Verify the existing signature */
1795 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1798 if (!startswith(c->signature + c->index + 1, contents))
1801 nindex = c->index + 1 + strlen(contents);
1805 if (c->enclosing != 0)
1808 /* Extend the existing signature */
1810 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1816 nindex = e - c->signature;
1819 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1820 alignment = bus_gvariant_get_alignment(contents);
1824 /* Add alignment padding and add to offset list */
1825 if (!message_extend_body(m, alignment, 0, false, false))
1828 r = bus_gvariant_is_fixed_size(contents);
1832 *begin = m->body_size;
1833 *need_offsets = r == 0;
1837 struct bus_body_part *o;
1839 alignment = bus_type_get_alignment(contents[0]);
1843 a = message_extend_body(m, 4, 4, false, false);
1848 op = m->body_end->data;
1849 os = m->body_end->size;
1851 /* Add alignment between size and first element */
1852 if (!message_extend_body(m, alignment, 0, false, false))
1855 /* location of array size might have changed so let's readjust a */
1856 if (o == m->body_end)
1857 a = adjust_pointer(a, op, os, m->body_end->data);
1863 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1869 static int bus_message_open_variant(
1871 struct bus_container *c,
1872 const char *contents) {
1878 if (!signature_is_single(contents, false))
1881 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1884 if (c->signature && c->signature[c->index]) {
1886 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1892 if (c->enclosing != 0)
1895 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1902 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1903 /* Variants are always aligned to 8 */
1905 if (!message_extend_body(m, 8, 0, false, false))
1912 l = strlen(contents);
1913 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1918 memcpy((uint8_t*) a + 1, contents, l + 1);
1921 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1927 static int bus_message_open_struct(
1929 struct bus_container *c,
1930 const char *contents,
1932 bool *need_offsets) {
1941 assert(need_offsets);
1943 if (!signature_is_valid(contents, false))
1946 if (c->signature && c->signature[c->index]) {
1949 l = strlen(contents);
1951 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1952 !startswith(c->signature + c->index + 1, contents) ||
1953 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1956 nindex = c->index + 1 + l + 1;
1960 if (c->enclosing != 0)
1963 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1969 nindex = e - c->signature;
1972 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1975 alignment = bus_gvariant_get_alignment(contents);
1979 if (!message_extend_body(m, alignment, 0, false, false))
1982 r = bus_gvariant_is_fixed_size(contents);
1986 *begin = m->body_size;
1987 *need_offsets = r == 0;
1989 /* Align contents to 8 byte boundary */
1990 if (!message_extend_body(m, 8, 0, false, false))
1994 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2000 static int bus_message_open_dict_entry(
2002 struct bus_container *c,
2003 const char *contents,
2005 bool *need_offsets) {
2013 assert(need_offsets);
2015 if (!signature_is_pair(contents))
2018 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2021 if (c->signature && c->signature[c->index]) {
2024 l = strlen(contents);
2026 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2027 !startswith(c->signature + c->index + 1, contents) ||
2028 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2033 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2036 alignment = bus_gvariant_get_alignment(contents);
2040 if (!message_extend_body(m, alignment, 0, false, false))
2043 r = bus_gvariant_is_fixed_size(contents);
2047 *begin = m->body_size;
2048 *need_offsets = r == 0;
2050 /* Align contents to 8 byte boundary */
2051 if (!message_extend_body(m, 8, 0, false, false))
2058 _public_ int sd_bus_message_open_container(
2061 const char *contents) {
2063 struct bus_container *c, *w;
2064 uint32_t *array_size = NULL;
2066 size_t before, begin = 0;
2067 bool need_offsets = false;
2070 assert_return(m, -EINVAL);
2071 assert_return(!m->sealed, -EPERM);
2072 assert_return(contents, -EINVAL);
2073 assert_return(!m->poisoned, -ESTALE);
2075 /* Make sure we have space for one more container */
2076 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2081 c = message_get_container(m);
2083 signature = strdup(contents);
2089 /* Save old index in the parent container, in case we have to
2090 * abort this container */
2091 c->saved_index = c->index;
2092 before = m->body_size;
2094 if (type == SD_BUS_TYPE_ARRAY)
2095 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2096 else if (type == SD_BUS_TYPE_VARIANT)
2097 r = bus_message_open_variant(m, c, contents);
2098 else if (type == SD_BUS_TYPE_STRUCT)
2099 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2100 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2101 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2110 /* OK, let's fill it in */
2111 w = m->containers + m->n_containers++;
2112 w->enclosing = type;
2113 w->signature = signature;
2115 w->array_size = array_size;
2118 w->n_offsets = w->offsets_allocated = 0;
2120 w->need_offsets = need_offsets;
2125 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2130 if (!BUS_MESSAGE_IS_GVARIANT(m))
2133 if (c->need_offsets) {
2134 size_t payload, sz, i;
2137 /* Variable-width arrays */
2139 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2140 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2142 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2146 for (i = 0; i < c->n_offsets; i++)
2147 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2151 /* Fixed-width or empty arrays */
2153 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2161 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2167 assert(c->signature);
2169 if (!BUS_MESSAGE_IS_GVARIANT(m))
2172 l = strlen(c->signature);
2174 a = message_extend_body(m, 1, 1 + l, true, false);
2179 memcpy(a+1, c->signature, l);
2184 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2185 bool fixed_size = true;
2186 size_t n_variable = 0;
2195 if (!BUS_MESSAGE_IS_GVARIANT(m))
2198 p = strempty(c->signature);
2202 r = signature_element_length(p, &n);
2211 r = bus_gvariant_is_fixed_size(t);
2216 assert(!c->need_offsets || i <= c->n_offsets);
2218 /* We need to add an offset for each item that has a
2219 * variable size and that is not the last one in the
2223 if (r == 0 && p[n] != 0)
2230 assert(!c->need_offsets || i == c->n_offsets);
2231 assert(c->need_offsets || n_variable == 0);
2233 if (isempty(c->signature)) {
2234 /* The unary type is encoded as fixed 1 byte padding */
2235 a = message_extend_body(m, 1, 1, add_offset, false);
2240 } else if (n_variable <= 0) {
2243 /* Structures with fixed-size members only have to be
2244 * fixed-size themselves. But gvariant requires all fixed-size
2245 * elements to be sized a multiple of their alignment. Hence,
2246 * we must *always* add final padding after the last member so
2247 * the overall size of the structure is properly aligned. */
2249 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2251 assert(alignment > 0);
2253 a = message_extend_body(m, alignment, 0, add_offset, false);
2260 assert(c->offsets[c->n_offsets-1] == m->body_size);
2262 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2264 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2268 p = strempty(c->signature);
2269 for (i = 0, j = 0; i < c->n_offsets; i++) {
2273 r = signature_element_length(p, &n);
2284 r = bus_gvariant_is_fixed_size(t);
2287 if (r > 0 || p[0] == 0)
2291 k = n_variable - 1 - j;
2293 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2302 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2303 struct bus_container *c;
2306 assert_return(m, -EINVAL);
2307 assert_return(!m->sealed, -EPERM);
2308 assert_return(m->n_containers > 0, -EINVAL);
2309 assert_return(!m->poisoned, -ESTALE);
2311 c = message_get_container(m);
2313 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2314 if (c->signature && c->signature[c->index] != 0)
2319 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2320 r = bus_message_close_array(m, c);
2321 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2322 r = bus_message_close_variant(m, c);
2323 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2324 r = bus_message_close_struct(m, c, true);
2326 assert_not_reached("Unknown container type");
2340 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2347 stack[*i].types = types;
2348 stack[*i].n_struct = n_struct;
2349 stack[*i].n_array = n_array;
2355 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2366 *types = stack[*i].types;
2367 *n_struct = stack[*i].n_struct;
2368 *n_array = stack[*i].n_array;
2373 int bus_message_append_ap(
2378 unsigned n_array, n_struct;
2379 TypeStack stack[BUS_CONTAINER_DEPTH];
2380 unsigned stack_ptr = 0;
2388 n_array = (unsigned) -1;
2389 n_struct = strlen(types);
2394 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2395 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2401 r = sd_bus_message_close_container(m);
2409 if (n_array != (unsigned) -1)
2418 case SD_BUS_TYPE_BYTE: {
2421 x = (uint8_t) va_arg(ap, int);
2422 r = sd_bus_message_append_basic(m, *t, &x);
2426 case SD_BUS_TYPE_BOOLEAN:
2427 case SD_BUS_TYPE_INT32:
2428 case SD_BUS_TYPE_UINT32:
2429 case SD_BUS_TYPE_UNIX_FD: {
2432 /* We assume a boolean is the same as int32_t */
2433 assert_cc(sizeof(int32_t) == sizeof(int));
2435 x = va_arg(ap, uint32_t);
2436 r = sd_bus_message_append_basic(m, *t, &x);
2440 case SD_BUS_TYPE_INT16:
2441 case SD_BUS_TYPE_UINT16: {
2444 x = (uint16_t) va_arg(ap, int);
2445 r = sd_bus_message_append_basic(m, *t, &x);
2449 case SD_BUS_TYPE_INT64:
2450 case SD_BUS_TYPE_UINT64: {
2453 x = va_arg(ap, uint64_t);
2454 r = sd_bus_message_append_basic(m, *t, &x);
2458 case SD_BUS_TYPE_DOUBLE: {
2461 x = va_arg(ap, double);
2462 r = sd_bus_message_append_basic(m, *t, &x);
2466 case SD_BUS_TYPE_STRING:
2467 case SD_BUS_TYPE_OBJECT_PATH:
2468 case SD_BUS_TYPE_SIGNATURE: {
2471 x = va_arg(ap, const char*);
2472 r = sd_bus_message_append_basic(m, *t, x);
2476 case SD_BUS_TYPE_ARRAY: {
2479 r = signature_element_length(t + 1, &k);
2485 memcpy(s, t + 1, k);
2488 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2493 if (n_array == (unsigned) -1) {
2498 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2504 n_array = va_arg(ap, unsigned);
2509 case SD_BUS_TYPE_VARIANT: {
2512 s = va_arg(ap, const char*);
2516 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2520 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2525 n_struct = strlen(s);
2526 n_array = (unsigned) -1;
2531 case SD_BUS_TYPE_STRUCT_BEGIN:
2532 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2535 r = signature_element_length(t, &k);
2542 memcpy(s, t + 1, k - 2);
2545 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2550 if (n_array == (unsigned) -1) {
2555 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2561 n_array = (unsigned) -1;
2577 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2581 assert_return(m, -EINVAL);
2582 assert_return(types, -EINVAL);
2583 assert_return(!m->sealed, -EPERM);
2584 assert_return(!m->poisoned, -ESTALE);
2586 va_start(ap, types);
2587 r = bus_message_append_ap(m, types, ap);
2593 _public_ int sd_bus_message_append_array_space(
2603 assert_return(m, -EINVAL);
2604 assert_return(!m->sealed, -EPERM);
2605 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2606 assert_return(ptr || size == 0, -EINVAL);
2607 assert_return(!m->poisoned, -ESTALE);
2609 /* alignment and size of the trivial types (except bool) is
2610 * identical for gvariant and dbus1 marshalling */
2611 align = bus_type_get_alignment(type);
2612 sz = bus_type_get_size(type);
2614 assert_se(align > 0);
2620 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2624 a = message_extend_body(m, align, size, false, false);
2628 r = sd_bus_message_close_container(m);
2636 _public_ int sd_bus_message_append_array(
2644 assert_return(m, -EINVAL);
2645 assert_return(!m->sealed, -EPERM);
2646 assert_return(bus_type_is_trivial(type), -EINVAL);
2647 assert_return(ptr || size == 0, -EINVAL);
2648 assert_return(!m->poisoned, -ESTALE);
2650 r = sd_bus_message_append_array_space(m, type, size, &p);
2655 memcpy(p, ptr, size);
2660 /// UNNEEDED by elogind
2662 _public_ int sd_bus_message_append_array_iovec(
2665 const struct iovec *iov,
2673 assert_return(m, -EINVAL);
2674 assert_return(!m->sealed, -EPERM);
2675 assert_return(bus_type_is_trivial(type), -EINVAL);
2676 assert_return(iov || n == 0, -EINVAL);
2677 assert_return(!m->poisoned, -ESTALE);
2679 size = IOVEC_TOTAL_SIZE(iov, n);
2681 r = sd_bus_message_append_array_space(m, type, size, &p);
2685 for (i = 0; i < n; i++) {
2687 if (iov[i].iov_base)
2688 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2690 memzero(p, iov[i].iov_len);
2692 p = (uint8_t*) p + iov[i].iov_len;
2698 _public_ int sd_bus_message_append_array_memfd(
2705 _cleanup_close_ int copy_fd = -1;
2706 struct bus_body_part *part;
2712 assert_return(m, -EINVAL);
2713 assert_return(memfd >= 0, -EINVAL);
2714 assert_return(bus_type_is_trivial(type), -EINVAL);
2715 assert_return(size > 0, -EINVAL);
2716 assert_return(!m->sealed, -EPERM);
2717 assert_return(!m->poisoned, -ESTALE);
2719 r = memfd_set_sealed(memfd);
2723 copy_fd = dup(memfd);
2727 r = memfd_get_size(memfd, &real_size);
2731 if (offset == 0 && size == (uint64_t) -1)
2733 else if (offset + size > real_size)
2736 align = bus_type_get_alignment(type);
2737 sz = bus_type_get_size(type);
2739 assert_se(align > 0);
2742 if (offset % align != 0)
2748 if (size > (uint64_t) (uint32_t) -1)
2751 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2755 a = message_extend_body(m, align, 0, false, false);
2759 part = message_append_part(m);
2763 part->memfd = copy_fd;
2764 part->memfd_offset = offset;
2765 part->sealed = true;
2769 m->body_size += size;
2770 message_extend_containers(m, size);
2772 return sd_bus_message_close_container(m);
2775 _public_ int sd_bus_message_append_string_memfd(
2781 _cleanup_close_ int copy_fd = -1;
2782 struct bus_body_part *part;
2783 struct bus_container *c;
2788 assert_return(m, -EINVAL);
2789 assert_return(memfd >= 0, -EINVAL);
2790 assert_return(size > 0, -EINVAL);
2791 assert_return(!m->sealed, -EPERM);
2792 assert_return(!m->poisoned, -ESTALE);
2794 r = memfd_set_sealed(memfd);
2798 copy_fd = dup(memfd);
2802 r = memfd_get_size(memfd, &real_size);
2806 if (offset == 0 && size == (uint64_t) -1)
2808 else if (offset + size > real_size)
2811 /* We require this to be NUL terminated */
2815 if (size > (uint64_t) (uint32_t) -1)
2818 c = message_get_container(m);
2819 if (c->signature && c->signature[c->index]) {
2820 /* Container signature is already set */
2822 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2827 /* Maybe we can append to the signature? But only if this is the top-level container */
2828 if (c->enclosing != 0)
2831 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2838 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2839 a = message_extend_body(m, 4, 4, false, false);
2843 *(uint32_t*) a = size - 1;
2846 part = message_append_part(m);
2850 part->memfd = copy_fd;
2851 part->memfd_offset = offset;
2852 part->sealed = true;
2856 m->body_size += size;
2857 message_extend_containers(m, size);
2859 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2860 r = message_add_offset(m, m->body_size);
2867 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2874 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2878 assert_return(m, -EINVAL);
2879 assert_return(!m->sealed, -EPERM);
2880 assert_return(!m->poisoned, -ESTALE);
2882 r = sd_bus_message_open_container(m, 'a', "s");
2886 STRV_FOREACH(i, l) {
2887 r = sd_bus_message_append_basic(m, 's', *i);
2892 return sd_bus_message_close_container(m);
2895 static int bus_message_close_header(sd_bus_message *m) {
2899 /* The actual user data is finished now, we just complete the
2900 variant and struct now (at least on gvariant). Remember
2901 this position, so that during parsing we know where to to
2902 put the outer container end. */
2903 m->user_body_size = m->body_size;
2905 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2906 const char *signature;
2910 /* Add offset table to end of fields array */
2911 if (m->n_header_offsets >= 1) {
2915 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2917 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2918 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2922 for (i = 0; i < m->n_header_offsets; i++)
2923 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2926 /* Add gvariant NUL byte plus signature to the end of
2927 * the body, followed by the final offset pointing to
2928 * the end of the fields array */
2930 signature = strempty(m->root_container.signature);
2931 l = strlen(signature);
2933 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2934 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2939 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2940 memcpy((uint8_t*) d + 2, signature, l);
2941 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2943 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2946 m->footer_accessible = 1 + l + 2 + sz;
2948 m->header->dbus1.fields_size = m->fields_size;
2949 m->header->dbus1.body_size = m->body_size;
2955 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2956 struct bus_body_part *part;
2966 if (m->n_containers > 0)
2972 if (cookie > 0xffffffffULL &&
2973 !BUS_MESSAGE_IS_GVARIANT(m))
2976 /* In vtables the return signature of method calls is listed,
2977 * let's check if they match if this is a response */
2978 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2979 m->enforced_reply_signature &&
2980 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2983 /* If gvariant marshalling is used we need to close the body structure */
2984 r = bus_message_close_struct(m, &m->root_container, false);
2988 /* If there's a non-trivial signature set, then add it in
2989 * here, but only on dbus1 */
2990 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2991 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2997 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
3002 r = bus_message_close_header(m);
3006 if (BUS_MESSAGE_IS_GVARIANT(m))
3007 m->header->dbus2.cookie = cookie;
3009 m->header->dbus1.serial = (uint32_t) cookie;
3011 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
3013 /* Add padding at the end of the fields part, since we know
3014 * the body needs to start at an 8 byte alignment. We made
3015 * sure we allocated enough space for this, so all we need to
3016 * do here is to zero it out. */
3017 a = ALIGN8(m->fields_size) - m->fields_size;
3019 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
3021 /* If this is something we can send as memfd, then let's seal
3022 the memfd now. Note that we can send memfds as payload only
3023 for directed messages, and not for broadcasts. */
3024 if (m->destination && m->bus->use_memfd) {
3025 MESSAGE_FOREACH_PART(part, i, m)
3026 if (part->memfd >= 0 &&
3028 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3029 part != m->body_end) { /* The last part may never be sent as memfd */
3032 /* Try to seal it if that makes
3033 * sense. First, unmap our own map to
3034 * make sure we don't keep it busy. */
3035 bus_body_part_unmap(part);
3037 /* Then, sync up real memfd size */
3039 r = memfd_set_size(part->memfd, sz);
3043 /* Finally, try to seal */
3044 if (memfd_set_sealed(part->memfd) >= 0)
3045 part->sealed = true;
3049 m->root_container.end = m->user_body_size;
3050 m->root_container.index = 0;
3051 m->root_container.offset_index = 0;
3052 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3059 int bus_body_part_map(struct bus_body_part *part) {
3068 if (part->size <= 0)
3071 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3072 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3073 static const uint8_t zeroes[7] = { };
3074 part->data = (void*) zeroes;
3078 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3079 psz = PAGE_ALIGN(part->size + shift);
3081 if (part->memfd >= 0)
3082 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3083 else if (part->is_zero)
3084 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3088 if (p == MAP_FAILED)
3092 part->mmap_begin = p;
3093 part->data = (uint8_t*) p + shift;
3094 part->munmap_this = true;
3099 void bus_body_part_unmap(struct bus_body_part *part) {
3103 if (part->memfd < 0)
3106 if (!part->mmap_begin)
3109 if (!part->munmap_this)
3112 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3114 part->mmap_begin = NULL;
3117 part->munmap_this = false;
3122 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3123 size_t k, start, end;
3128 start = ALIGN_TO((size_t) *rindex, align);
3129 end = start + nbytes;
3134 /* Verify that padding is 0 */
3135 for (k = *rindex; k < start; k++)
3136 if (((const uint8_t*) p)[k] != 0)
3140 *r = (uint8_t*) p + start;
3147 static bool message_end_of_signature(sd_bus_message *m) {
3148 struct bus_container *c;
3152 c = message_get_container(m);
3153 return !c->signature || c->signature[c->index] == 0;
3156 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3157 struct bus_container *c;
3161 c = message_get_container(m);
3162 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3165 if (BUS_MESSAGE_IS_GVARIANT(m))
3166 return index >= c->end;
3168 assert(c->array_size);
3169 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3173 /// UNNEEDED by elogind
3175 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3176 assert_return(m, -EINVAL);
3177 assert_return(m->sealed, -EPERM);
3179 if (complete && m->n_containers > 0)
3182 if (message_end_of_signature(m))
3185 if (message_end_of_array(m, m->rindex))
3192 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3193 struct bus_body_part *part;
3199 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3200 part = m->cached_rindex_part;
3201 begin = m->cached_rindex_part_begin;
3211 if (index + sz <= begin + part->size) {
3213 r = bus_body_part_map(part);
3218 *p = (uint8_t*) part->data + index - begin;
3220 m->cached_rindex_part = part;
3221 m->cached_rindex_part_begin = begin;
3226 begin += part->size;
3233 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3240 if (!BUS_MESSAGE_IS_GVARIANT(m))
3243 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3246 sz = bus_gvariant_get_size(c->signature);
3250 if (c->offset_index+1 >= c->n_offsets)
3253 /* Variable-size array */
3255 alignment = bus_gvariant_get_alignment(c->signature);
3256 assert(alignment > 0);
3258 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3259 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3262 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3265 /* Fixed-size array */
3266 *rindex = c->begin + (c->offset_index+1) * sz;
3272 } else if (c->enclosing == 0 ||
3273 c->enclosing == SD_BUS_TYPE_STRUCT ||
3274 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3279 if (c->offset_index+1 >= c->n_offsets)
3282 r = signature_element_length(c->signature + c->index, &n);
3286 r = signature_element_length(c->signature + c->index + n, &j);
3291 memcpy(t, c->signature + c->index + n, j);
3294 alignment = bus_gvariant_get_alignment(t);
3297 assert(alignment > 0);
3299 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3300 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3304 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3307 assert_not_reached("Unknown container type");
3312 /* Reached the end */
3319 static int message_peek_body(
3326 size_t k, start, end, padding;
3327 struct bus_body_part *part;
3334 start = ALIGN_TO((size_t) *rindex, align);
3335 padding = start - *rindex;
3336 end = start + nbytes;
3338 if (end > m->user_body_size)
3341 part = find_part(m, *rindex, padding, (void**) &q);
3346 /* Verify padding */
3347 for (k = 0; k < padding; k++)
3352 part = find_part(m, start, nbytes, (void**) &q);
3353 if (!part || (nbytes > 0 && !q))
3364 static bool validate_nul(const char *s, size_t l) {
3366 /* Check for NUL chars in the string */
3367 if (memchr(s, 0, l))
3370 /* Check for NUL termination */
3377 static bool validate_string(const char *s, size_t l) {
3379 if (!validate_nul(s, l))
3382 /* Check if valid UTF8 */
3383 if (!utf8_is_valid(s))
3389 static bool validate_signature(const char *s, size_t l) {
3391 if (!validate_nul(s, l))
3394 /* Check if valid signature */
3395 if (!signature_is_valid(s, true))
3401 static bool validate_object_path(const char *s, size_t l) {
3403 if (!validate_nul(s, l))
3406 if (!object_path_is_valid(s))
3412 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3413 struct bus_container *c;
3418 assert_return(m, -EINVAL);
3419 assert_return(m->sealed, -EPERM);
3420 assert_return(bus_type_is_basic(type), -EINVAL);
3422 if (message_end_of_signature(m))
3425 if (message_end_of_array(m, m->rindex))
3428 c = message_get_container(m);
3429 if (c->signature[c->index] != type)
3434 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3436 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3439 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3443 if (type == SD_BUS_TYPE_STRING)
3444 ok = validate_string(q, c->item_size-1);
3445 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3446 ok = validate_object_path(q, c->item_size-1);
3448 ok = validate_signature(q, c->item_size-1);
3454 *(const char**) p = q;
3458 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3460 if ((size_t) sz != c->item_size)
3463 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3466 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3472 case SD_BUS_TYPE_BYTE:
3474 *(uint8_t*) p = *(uint8_t*) q;
3477 case SD_BUS_TYPE_BOOLEAN:
3479 *(int*) p = !!*(uint8_t*) q;
3482 case SD_BUS_TYPE_INT16:
3483 case SD_BUS_TYPE_UINT16:
3485 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3488 case SD_BUS_TYPE_INT32:
3489 case SD_BUS_TYPE_UINT32:
3491 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3494 case SD_BUS_TYPE_INT64:
3495 case SD_BUS_TYPE_UINT64:
3496 case SD_BUS_TYPE_DOUBLE:
3498 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3501 case SD_BUS_TYPE_UNIX_FD: {
3504 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3509 *(int*) p = m->fds[j];
3515 assert_not_reached("unexpected type");
3519 r = container_next_item(m, c, &rindex);
3524 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3528 r = message_peek_body(m, &rindex, 4, 4, &q);
3532 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3533 r = message_peek_body(m, &rindex, 1, l+1, &q);
3537 if (type == SD_BUS_TYPE_OBJECT_PATH)
3538 ok = validate_object_path(q, l);
3540 ok = validate_string(q, l);
3545 *(const char**) p = q;
3547 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3550 r = message_peek_body(m, &rindex, 1, 1, &q);
3555 r = message_peek_body(m, &rindex, 1, l+1, &q);
3559 if (!validate_signature(q, l))
3563 *(const char**) p = q;
3568 align = bus_type_get_alignment(type);
3571 sz = bus_type_get_size(type);
3574 r = message_peek_body(m, &rindex, align, sz, &q);
3580 case SD_BUS_TYPE_BYTE:
3582 *(uint8_t*) p = *(uint8_t*) q;
3585 case SD_BUS_TYPE_BOOLEAN:
3587 *(int*) p = !!*(uint32_t*) q;
3590 case SD_BUS_TYPE_INT16:
3591 case SD_BUS_TYPE_UINT16:
3593 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3596 case SD_BUS_TYPE_INT32:
3597 case SD_BUS_TYPE_UINT32:
3599 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3602 case SD_BUS_TYPE_INT64:
3603 case SD_BUS_TYPE_UINT64:
3604 case SD_BUS_TYPE_DOUBLE:
3606 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3609 case SD_BUS_TYPE_UNIX_FD: {
3612 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3617 *(int*) p = m->fds[j];
3622 assert_not_reached("Unknown basic type...");
3629 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3635 static int bus_message_enter_array(
3637 struct bus_container *c,
3638 const char *contents,
3639 uint32_t **array_size,
3642 size_t *n_offsets) {
3656 if (!signature_is_single(contents, true))
3659 if (!c->signature || c->signature[c->index] == 0)
3662 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3665 if (!startswith(c->signature + c->index + 1, contents))
3670 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3673 r = message_peek_body(m, &rindex, 4, 4, &q);
3677 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3680 alignment = bus_type_get_alignment(contents[0]);
3684 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3688 *array_size = (uint32_t*) q;
3690 } else if (c->item_size <= 0) {
3692 /* gvariant: empty array */
3697 } else if (bus_gvariant_is_fixed_size(contents)) {
3699 /* gvariant: fixed length array */
3700 *item_size = bus_gvariant_get_size(contents);
3705 size_t where, p = 0, framing, sz;
3708 /* gvariant: variable length array */
3709 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3711 where = rindex + c->item_size - sz;
3712 r = message_peek_body(m, &where, 1, sz, &q);
3716 framing = bus_gvariant_read_word_le(q, sz);
3717 if (framing > c->item_size - sz)
3719 if ((c->item_size - framing) % sz != 0)
3722 *n_offsets = (c->item_size - framing) / sz;
3724 where = rindex + framing;
3725 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3729 *offsets = new(size_t, *n_offsets);
3733 for (i = 0; i < *n_offsets; i++) {
3736 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3737 if (x > c->item_size - sz)
3742 (*offsets)[i] = rindex + x;
3746 *item_size = (*offsets)[0] - rindex;
3751 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3752 c->index += 1 + strlen(contents);
3757 static int bus_message_enter_variant(
3759 struct bus_container *c,
3760 const char *contents,
3761 size_t *item_size) {
3773 if (!signature_is_single(contents, false))
3776 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3779 if (!c->signature || c->signature[c->index] == 0)
3782 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3787 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3790 k = strlen(contents);
3791 if (1+k > c->item_size)
3794 where = rindex + c->item_size - (1+k);
3795 r = message_peek_body(m, &where, 1, 1+k, &q);
3799 if (*(char*) q != 0)
3802 if (memcmp((uint8_t*) q+1, contents, k))
3805 *item_size = c->item_size - (1+k);
3808 r = message_peek_body(m, &rindex, 1, 1, &q);
3813 r = message_peek_body(m, &rindex, 1, l+1, &q);
3817 if (!validate_signature(q, l))
3820 if (!streq(q, contents))
3826 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3832 static int build_struct_offsets(
3834 const char *signature,
3838 size_t *n_offsets) {
3840 unsigned n_variable = 0, n_total = 0, v;
3841 size_t previous = 0, where;
3852 if (isempty(signature)) {
3853 /* Unary type is encoded as *fixed* 1 byte padding */
3854 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3858 if (*(uint8_t *) q != 0)
3867 sz = bus_gvariant_determine_word_size(size, 0);
3871 /* First, loop over signature and count variable elements and
3872 * elements in general. We use this to know how large the
3873 * offset array is at the end of the structure. Note that
3874 * GVariant only stores offsets for all variable size elements
3875 * that are not the last item. */
3881 r = signature_element_length(p, &n);
3890 r = bus_gvariant_is_fixed_size(t);
3895 if (r == 0 && p[n] != 0) /* except the last item */
3902 if (size < n_variable * sz)
3905 where = m->rindex + size - (n_variable * sz);
3906 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3912 *offsets = new(size_t, n_total);
3918 /* Second, loop again and build an offset table */
3924 r = signature_element_length(p, &n);
3933 k = bus_gvariant_get_size(t);
3941 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3944 if (m->rindex + x < previous)
3947 /* The last item's end
3948 * is determined from
3951 x = size - (n_variable * sz);
3953 offset = m->rindex + x;
3959 align = bus_gvariant_get_alignment(t);
3962 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3966 previous = (*offsets)[(*n_offsets)++] = offset;
3971 assert(*n_offsets == n_total);
3973 *item_size = (*offsets)[0] - m->rindex;
3977 static int enter_struct_or_dict_entry(
3979 struct bus_container *c,
3980 const char *contents,
3983 size_t *n_offsets) {
3994 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3997 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
4002 /* gvariant with contents */
4003 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
4008 static int bus_message_enter_struct(
4010 struct bus_container *c,
4011 const char *contents,
4014 size_t *n_offsets) {
4026 if (!signature_is_valid(contents, false))
4029 if (!c->signature || c->signature[c->index] == 0)
4032 l = strlen(contents);
4034 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4035 !startswith(c->signature + c->index + 1, contents) ||
4036 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4039 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4043 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4044 c->index += 1 + l + 1;
4049 static int bus_message_enter_dict_entry(
4051 struct bus_container *c,
4052 const char *contents,
4055 size_t *n_offsets) {
4064 if (!signature_is_pair(contents))
4067 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4070 if (!c->signature || c->signature[c->index] == 0)
4073 l = strlen(contents);
4075 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4076 !startswith(c->signature + c->index + 1, contents) ||
4077 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4080 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4084 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4085 c->index += 1 + l + 1;
4090 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4092 const char *contents) {
4093 struct bus_container *c, *w;
4094 uint32_t *array_size = NULL;
4097 size_t *offsets = NULL;
4098 size_t n_offsets = 0, item_size = 0;
4101 assert_return(m, -EINVAL);
4102 assert_return(m->sealed, -EPERM);
4103 assert_return(type != 0 || !contents, -EINVAL);
4105 if (type == 0 || !contents) {
4109 /* Allow entering into anonymous containers */
4110 r = sd_bus_message_peek_type(m, &tt, &cc);
4114 if (type != 0 && type != tt)
4117 if (contents && !streq(contents, cc))
4125 * We enforce a global limit on container depth, that is much
4126 * higher than the 32 structs and 32 arrays the specification
4127 * mandates. This is simpler to implement for us, and we need
4128 * this only to ensure our container array doesn't grow
4129 * without bounds. We are happy to return any data from a
4130 * message as long as the data itself is valid, even if the
4131 * overall message might be not.
4133 * Note that the message signature is validated when
4134 * parsing the headers, and that validation does check the
4137 * Note that the specification defines no limits on the depth
4138 * of stacked variants, but we do.
4140 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4143 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4146 if (message_end_of_signature(m))
4149 if (message_end_of_array(m, m->rindex))
4152 c = message_get_container(m);
4154 signature = strdup(contents);
4158 c->saved_index = c->index;
4161 if (type == SD_BUS_TYPE_ARRAY)
4162 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4163 else if (type == SD_BUS_TYPE_VARIANT)
4164 r = bus_message_enter_variant(m, c, contents, &item_size);
4165 else if (type == SD_BUS_TYPE_STRUCT)
4166 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4167 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4168 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4178 /* OK, let's fill it in */
4179 w = m->containers + m->n_containers++;
4180 w->enclosing = type;
4181 w->signature = signature;
4182 w->peeked_signature = NULL;
4186 w->begin = m->rindex;
4188 /* Unary type has fixed size of 1, but virtual size of 0 */
4189 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4190 type == SD_BUS_TYPE_STRUCT &&
4192 w->end = m->rindex + 0;
4194 w->end = m->rindex + c->item_size;
4196 w->array_size = array_size;
4197 w->item_size = item_size;
4198 w->offsets = offsets;
4199 w->n_offsets = n_offsets;
4200 w->offset_index = 0;
4205 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4206 struct bus_container *c;
4210 assert_return(m, -EINVAL);
4211 assert_return(m->sealed, -EPERM);
4212 assert_return(m->n_containers > 0, -ENXIO);
4214 c = message_get_container(m);
4216 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4217 if (c->signature && c->signature[c->index] != 0)
4221 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4222 if (m->rindex < c->end)
4225 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4228 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4229 if (c->begin + l != m->rindex)
4234 free(c->peeked_signature);
4238 c = message_get_container(m);
4241 c->index = c->saved_index;
4242 r = container_next_item(m, c, &m->rindex);
4250 static void message_quit_container(sd_bus_message *m) {
4251 struct bus_container *c;
4255 assert(m->n_containers > 0);
4257 c = message_get_container(m);
4260 assert(m->rindex >= c->before);
4261 m->rindex = c->before;
4263 /* Free container */
4268 /* Correct index of new top-level container */
4269 c = message_get_container(m);
4270 c->index = c->saved_index;
4273 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4274 struct bus_container *c;
4277 assert_return(m, -EINVAL);
4278 assert_return(m->sealed, -EPERM);
4280 if (message_end_of_signature(m))
4283 if (message_end_of_array(m, m->rindex))
4286 c = message_get_container(m);
4288 if (bus_type_is_basic(c->signature[c->index])) {
4292 *type = c->signature[c->index];
4296 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4302 r = signature_element_length(c->signature+c->index+1, &l);
4308 sig = strndup(c->signature + c->index + 1, l);
4312 free(c->peeked_signature);
4313 *contents = c->peeked_signature = sig;
4317 *type = SD_BUS_TYPE_ARRAY;
4322 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4323 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4329 r = signature_element_length(c->signature+c->index, &l);
4334 sig = strndup(c->signature + c->index + 1, l - 2);
4338 free(c->peeked_signature);
4339 *contents = c->peeked_signature = sig;
4343 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4348 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4352 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4355 if (c->item_size < 2)
4358 /* Look for the NUL delimiter that
4359 separates the payload from the
4360 signature. Since the body might be
4361 in a different part that then the
4362 signature we map byte by byte. */
4364 for (k = 2; k <= c->item_size; k++) {
4367 where = m->rindex + c->item_size - k;
4368 r = message_peek_body(m, &where, 1, k, &q);
4372 if (*(char*) q == 0)
4376 if (k > c->item_size)
4379 free(c->peeked_signature);
4380 c->peeked_signature = strndup((char*) q + 1, k - 1);
4381 if (!c->peeked_signature)
4384 if (!signature_is_valid(c->peeked_signature, true))
4387 *contents = c->peeked_signature;
4392 r = message_peek_body(m, &rindex, 1, 1, &q);
4397 r = message_peek_body(m, &rindex, 1, l+1, &q);
4401 if (!validate_signature(q, l))
4409 *type = SD_BUS_TYPE_VARIANT;
4424 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4425 struct bus_container *c;
4427 assert_return(m, -EINVAL);
4428 assert_return(m->sealed, -EPERM);
4431 message_reset_containers(m);
4434 c = message_get_container(m);
4436 c = message_get_container(m);
4438 c->offset_index = 0;
4440 m->rindex = c->begin;
4443 c->offset_index = 0;
4444 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4446 return !isempty(c->signature);
4449 static int message_read_ap(
4454 unsigned n_array, n_struct;
4455 TypeStack stack[BUS_CONTAINER_DEPTH];
4456 unsigned stack_ptr = 0;
4457 unsigned n_loop = 0;
4465 /* Ideally, we'd just call ourselves recursively on every
4466 * complex type. However, the state of a va_list that is
4467 * passed to a function is undefined after that function
4468 * returns. This means we need to docode the va_list linearly
4469 * in a single stackframe. We hence implement our own
4470 * home-grown stack in an array. */
4472 n_array = (unsigned) -1; /* length of current array entries */
4473 n_struct = strlen(types); /* length of current struct contents signature */
4480 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4481 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4487 r = sd_bus_message_exit_container(m);
4495 if (n_array != (unsigned) -1)
4504 case SD_BUS_TYPE_BYTE:
4505 case SD_BUS_TYPE_BOOLEAN:
4506 case SD_BUS_TYPE_INT16:
4507 case SD_BUS_TYPE_UINT16:
4508 case SD_BUS_TYPE_INT32:
4509 case SD_BUS_TYPE_UINT32:
4510 case SD_BUS_TYPE_INT64:
4511 case SD_BUS_TYPE_UINT64:
4512 case SD_BUS_TYPE_DOUBLE:
4513 case SD_BUS_TYPE_STRING:
4514 case SD_BUS_TYPE_OBJECT_PATH:
4515 case SD_BUS_TYPE_SIGNATURE:
4516 case SD_BUS_TYPE_UNIX_FD: {
4519 p = va_arg(ap, void*);
4520 r = sd_bus_message_read_basic(m, *t, p);
4533 case SD_BUS_TYPE_ARRAY: {
4536 r = signature_element_length(t + 1, &k);
4542 memcpy(s, t + 1, k);
4545 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4556 if (n_array == (unsigned) -1) {
4561 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4567 n_array = va_arg(ap, unsigned);
4572 case SD_BUS_TYPE_VARIANT: {
4575 s = va_arg(ap, const char *);
4579 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4589 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4594 n_struct = strlen(s);
4595 n_array = (unsigned) -1;
4600 case SD_BUS_TYPE_STRUCT_BEGIN:
4601 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4604 r = signature_element_length(t, &k);
4610 memcpy(s, t + 1, k - 2);
4613 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4623 if (n_array == (unsigned) -1) {
4628 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4634 n_array = (unsigned) -1;
4647 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4651 assert_return(m, -EINVAL);
4652 assert_return(m->sealed, -EPERM);
4653 assert_return(types, -EINVAL);
4655 va_start(ap, types);
4656 r = message_read_ap(m, types, ap);
4662 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4665 assert_return(m, -EINVAL);
4666 assert_return(m->sealed, -EPERM);
4668 /* If types is NULL, read exactly one element */
4670 struct bus_container *c;
4673 if (message_end_of_signature(m))
4676 if (message_end_of_array(m, m->rindex))
4679 c = message_get_container(m);
4681 r = signature_element_length(c->signature + c->index, &l);
4685 types = strndupa(c->signature + c->index, l);
4690 case 0: /* Nothing to drop */
4693 case SD_BUS_TYPE_BYTE:
4694 case SD_BUS_TYPE_BOOLEAN:
4695 case SD_BUS_TYPE_INT16:
4696 case SD_BUS_TYPE_UINT16:
4697 case SD_BUS_TYPE_INT32:
4698 case SD_BUS_TYPE_UINT32:
4699 case SD_BUS_TYPE_INT64:
4700 case SD_BUS_TYPE_UINT64:
4701 case SD_BUS_TYPE_DOUBLE:
4702 case SD_BUS_TYPE_STRING:
4703 case SD_BUS_TYPE_OBJECT_PATH:
4704 case SD_BUS_TYPE_SIGNATURE:
4705 case SD_BUS_TYPE_UNIX_FD:
4707 r = sd_bus_message_read_basic(m, *types, NULL);
4711 r = sd_bus_message_skip(m, types + 1);
4717 case SD_BUS_TYPE_ARRAY: {
4720 r = signature_element_length(types + 1, &k);
4726 memcpy(s, types+1, k);
4729 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4734 r = sd_bus_message_skip(m, s);
4741 r = sd_bus_message_exit_container(m);
4746 r = sd_bus_message_skip(m, types + 1 + k);
4753 case SD_BUS_TYPE_VARIANT: {
4754 const char *contents;
4757 r = sd_bus_message_peek_type(m, &x, &contents);
4761 if (x != SD_BUS_TYPE_VARIANT)
4764 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4768 r = sd_bus_message_skip(m, contents);
4773 r = sd_bus_message_exit_container(m);
4777 r = sd_bus_message_skip(m, types + 1);
4784 case SD_BUS_TYPE_STRUCT_BEGIN:
4785 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4788 r = signature_element_length(types, &k);
4794 memcpy(s, types+1, k-2);
4797 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4801 r = sd_bus_message_skip(m, s);
4805 r = sd_bus_message_exit_container(m);
4810 r = sd_bus_message_skip(m, types + k);
4822 _public_ int sd_bus_message_read_array(
4828 struct bus_container *c;
4834 assert_return(m, -EINVAL);
4835 assert_return(m->sealed, -EPERM);
4836 assert_return(bus_type_is_trivial(type), -EINVAL);
4837 assert_return(ptr, -EINVAL);
4838 assert_return(size, -EINVAL);
4839 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4841 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4845 c = message_get_container(m);
4847 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4848 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4852 sz = c->end - c->begin;
4854 align = bus_type_get_alignment(type);
4858 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4862 /* Zero length array, let's return some aligned
4863 * pointer that is not NULL */
4864 p = (uint8_t*) NULL + align;
4866 r = message_peek_body(m, &m->rindex, align, sz, &p);
4871 r = sd_bus_message_exit_container(m);
4875 *ptr = (const void*) p;
4881 message_quit_container(m);
4885 static int message_peek_fields(
4896 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4899 static int message_peek_field_uint32(
4911 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4914 /* identical for gvariant and dbus1 */
4916 r = message_peek_fields(m, ri, 4, 4, &q);
4921 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4926 static int message_peek_field_uint64(
4938 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4941 /* identical for gvariant and dbus1 */
4943 r = message_peek_fields(m, ri, 8, 8, &q);
4948 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4953 static int message_peek_field_string(
4955 bool (*validate)(const char *p),
4967 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4972 r = message_peek_fields(m, ri, 1, item_size, &q);
4978 r = message_peek_field_uint32(m, ri, 4, &l);
4982 r = message_peek_fields(m, ri, 1, l+1, &q);
4988 if (!validate_nul(q, l))
4994 if (!validate_string(q, l))
5004 static int message_peek_field_signature(
5017 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5022 r = message_peek_fields(m, ri, 1, item_size, &q);
5028 r = message_peek_fields(m, ri, 1, 1, &q);
5033 r = message_peek_fields(m, ri, 1, l+1, &q);
5038 if (!validate_signature(q, l))
5047 static int message_skip_fields(
5050 uint32_t array_size,
5051 const char **signature) {
5053 size_t original_index;
5059 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5061 original_index = *ri;
5067 if (array_size != (uint32_t) -1 &&
5068 array_size <= *ri - original_index)
5075 if (t == SD_BUS_TYPE_STRING) {
5077 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5083 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5085 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5091 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5093 r = message_peek_field_signature(m, ri, 0, NULL);
5099 } else if (bus_type_is_basic(t)) {
5102 align = bus_type_get_alignment(t);
5103 k = bus_type_get_size(t);
5104 assert(align > 0 && k > 0);
5106 r = message_peek_fields(m, ri, align, k, NULL);
5112 } else if (t == SD_BUS_TYPE_ARRAY) {
5114 r = signature_element_length(*signature+1, &l);
5124 strncpy(sig, *signature + 1, l-1);
5127 alignment = bus_type_get_alignment(sig[0]);
5131 r = message_peek_field_uint32(m, ri, 0, &nas);
5134 if (nas > BUS_ARRAY_MAX_SIZE)
5137 r = message_peek_fields(m, ri, alignment, 0, NULL);
5141 r = message_skip_fields(m, ri, nas, (const char**) &s);
5146 (*signature) += 1 + l;
5148 } else if (t == SD_BUS_TYPE_VARIANT) {
5151 r = message_peek_field_signature(m, ri, 0, &s);
5155 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5161 } else if (t == SD_BUS_TYPE_STRUCT ||
5162 t == SD_BUS_TYPE_DICT_ENTRY) {
5164 r = signature_element_length(*signature, &l);
5171 strncpy(sig, *signature + 1, l-1);
5174 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5185 int bus_message_parse_fields(sd_bus_message *m) {
5188 uint32_t unix_fds = 0;
5189 bool unix_fds_set = false;
5190 void *offsets = NULL;
5191 unsigned n_offsets = 0;
5197 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5200 /* Read the signature from the end of the body variant first */
5201 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5202 if (m->footer_accessible < 1 + sz)
5205 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5207 if (p < (char*) m->footer)
5214 /* We found the beginning of the signature
5215 * string, yay! We require the body to be a
5216 * structure, so verify it and then strip the
5217 * opening/closing brackets. */
5219 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5221 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5222 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5225 c = strndup(p + 1 + 1, l - 2);
5229 free(m->root_container.signature);
5230 m->root_container.signature = c;
5237 /* Calculate the actual user body size, by removing
5238 * the trailing variant signature and struct offset
5240 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5242 /* Pull out the offset table for the fields array */
5243 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5248 ri = m->fields_size - sz;
5249 r = message_peek_fields(m, &ri, 1, sz, &q);
5253 framing = bus_gvariant_read_word_le(q, sz);
5254 if (framing >= m->fields_size - sz)
5256 if ((m->fields_size - framing) % sz != 0)
5260 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5264 n_offsets = (m->fields_size - framing) / sz;
5267 m->user_body_size = m->body_size;
5270 while (ri < m->fields_size) {
5271 _cleanup_free_ char *sig = NULL;
5272 const char *signature;
5273 uint64_t field_type;
5274 size_t item_size = (size_t) -1;
5276 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5285 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5287 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5291 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5295 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5302 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5307 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5312 where = ri = ALIGN_TO(ri, 8);
5313 item_size = end - ri;
5314 r = message_peek_fields(m, &where, 1, item_size, &q);
5318 b = memrchr(q, 0, item_size);
5322 sig = strndup(b+1, item_size - (b+1-(char*) q));
5327 item_size = b - (char*) q;
5329 r = message_peek_field_signature(m, &ri, 0, &signature);
5334 switch (field_type) {
5336 case _BUS_MESSAGE_HEADER_INVALID:
5339 case BUS_MESSAGE_HEADER_PATH:
5344 if (!streq(signature, "o"))
5347 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5350 case BUS_MESSAGE_HEADER_INTERFACE:
5355 if (!streq(signature, "s"))
5358 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5361 case BUS_MESSAGE_HEADER_MEMBER:
5366 if (!streq(signature, "s"))
5369 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5372 case BUS_MESSAGE_HEADER_ERROR_NAME:
5377 if (!streq(signature, "s"))
5380 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5382 m->error._need_free = -1;
5386 case BUS_MESSAGE_HEADER_DESTINATION:
5391 if (!streq(signature, "s"))
5394 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5397 case BUS_MESSAGE_HEADER_SENDER:
5402 if (!streq(signature, "s"))
5405 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5407 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5408 m->creds.unique_name = (char*) m->sender;
5409 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5415 case BUS_MESSAGE_HEADER_SIGNATURE: {
5419 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5422 if (m->root_container.signature)
5425 if (!streq(signature, "g"))
5428 r = message_peek_field_signature(m, &ri, item_size, &s);
5436 free(m->root_container.signature);
5437 m->root_container.signature = c;
5441 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5443 if (m->reply_cookie != 0)
5446 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5447 /* 64bit on dbus2 */
5449 if (!streq(signature, "t"))
5452 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5456 /* 32bit on dbus1 */
5459 if (!streq(signature, "u"))
5462 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5466 m->reply_cookie = serial;
5469 if (m->reply_cookie == 0)
5474 case BUS_MESSAGE_HEADER_UNIX_FDS:
5478 if (!streq(signature, "u"))
5481 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5485 unix_fds_set = true;
5489 if (!BUS_MESSAGE_IS_GVARIANT(m))
5490 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5499 if (m->n_fds != unix_fds)
5502 switch (m->header->type) {
5504 case SD_BUS_MESSAGE_SIGNAL:
5505 if (!m->path || !m->interface || !m->member)
5508 if (m->reply_cookie != 0)
5513 case SD_BUS_MESSAGE_METHOD_CALL:
5515 if (!m->path || !m->member)
5518 if (m->reply_cookie != 0)
5523 case SD_BUS_MESSAGE_METHOD_RETURN:
5525 if (m->reply_cookie == 0)
5529 case SD_BUS_MESSAGE_METHOD_ERROR:
5531 if (m->reply_cookie == 0 || !m->error.name)
5536 /* Refuse non-local messages that claim they are local */
5537 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5539 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5541 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5544 m->root_container.end = m->user_body_size;
5546 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5547 r = build_struct_offsets(
5549 m->root_container.signature,
5551 &m->root_container.item_size,
5552 &m->root_container.offsets,
5553 &m->root_container.n_offsets);
5558 /* Try to read the error message, but if we can't it's a non-issue */
5559 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5560 (void) sd_bus_message_read(m, "s", &m->error.message);
5565 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5566 assert_return(m, -EINVAL);
5567 assert_return(destination, -EINVAL);
5568 assert_return(!m->sealed, -EPERM);
5569 assert_return(!m->destination, -EEXIST);
5571 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5574 /// UNNEEDED by elogind
5576 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5580 struct bus_body_part *part;
5586 total = BUS_MESSAGE_SIZE(m);
5592 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5593 MESSAGE_FOREACH_PART(part, i, m)
5594 e = mempcpy(e, part->data, part->size);
5596 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5605 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5612 r = sd_bus_message_enter_container(m, 'a', "s");
5616 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5617 r = strv_extend(l, s);
5624 r = sd_bus_message_exit_container(m);
5631 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5635 assert_return(m, -EINVAL);
5636 assert_return(m->sealed, -EPERM);
5637 assert_return(l, -EINVAL);
5639 r = bus_message_read_strv_extend(m, &strv);
5649 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5650 const char *contents;
5659 r = sd_bus_message_rewind(m, true);
5664 r = sd_bus_message_peek_type(m, &type, &contents);
5670 /* Don't match against arguments after the first one we don't understand */
5671 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5672 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5678 r = sd_bus_message_skip(m, NULL);
5683 if (type == SD_BUS_TYPE_ARRAY) {
5685 r = sd_bus_message_read_strv(m, strv);
5692 r = sd_bus_message_read_basic(m, type, str);
5702 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5703 assert_return(m, EINVAL);
5705 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5708 return sd_bus_error_get_errno(&m->error);
5711 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5712 struct bus_container *c;
5714 assert_return(m, NULL);
5716 c = complete ? &m->root_container : message_get_container(m);
5717 return strempty(c->signature);
5720 /// UNNEEDED by elogind
5722 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5723 assert_return(m, -EINVAL);
5725 return isempty(m->root_container.signature);
5728 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5729 assert_return(m, -EINVAL);
5731 return streq(strempty(m->root_container.signature), strempty(signature));
5735 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5736 bool done_something = false;
5739 assert_return(m, -EINVAL);
5740 assert_return(source, -EINVAL);
5741 assert_return(!m->sealed, -EPERM);
5742 assert_return(source->sealed, -EPERM);
5745 const char *contents;
5760 r = sd_bus_message_peek_type(source, &type, &contents);
5766 done_something = true;
5768 if (bus_type_is_container(type) > 0) {
5770 r = sd_bus_message_enter_container(source, type, contents);
5774 r = sd_bus_message_open_container(m, type, contents);
5778 r = sd_bus_message_copy(m, source, true);
5782 r = sd_bus_message_close_container(m);
5786 r = sd_bus_message_exit_container(source);
5793 r = sd_bus_message_read_basic(source, type, &basic);
5799 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5800 type == SD_BUS_TYPE_SIGNATURE ||
5801 type == SD_BUS_TYPE_STRING)
5802 r = sd_bus_message_append_basic(m, type, basic.string);
5804 r = sd_bus_message_append_basic(m, type, &basic);
5811 return done_something;
5814 /// UNNEEDED by elogind
5816 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5821 assert_return(m, -EINVAL);
5822 assert_return(m->sealed, -EPERM);
5823 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5824 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5825 assert_return(type || contents, -EINVAL);
5826 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5828 r = sd_bus_message_peek_type(m, &t, &c);
5832 if (type != 0 && type != t)
5835 if (contents && !streq_ptr(contents, c))
5842 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5843 assert_return(m, NULL);
5848 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5849 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5857 switch ((*m)->header->type) {
5859 case SD_BUS_MESSAGE_SIGNAL:
5860 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5866 case SD_BUS_MESSAGE_METHOD_CALL:
5867 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5873 case SD_BUS_MESSAGE_METHOD_RETURN:
5874 case SD_BUS_MESSAGE_METHOD_ERROR:
5876 n = message_new(bus, (*m)->header->type);
5880 n->reply_cookie = (*m)->reply_cookie;
5882 r = message_append_reply_cookie(n, n->reply_cookie);
5886 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5887 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5891 n->error._need_free = -1;
5900 if ((*m)->destination && !n->destination) {
5901 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5906 if ((*m)->sender && !n->sender) {
5907 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5912 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5914 r = sd_bus_message_copy(n, *m, true);
5918 timeout = (*m)->timeout;
5919 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5920 timeout = BUS_DEFAULT_TIMEOUT;
5922 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5926 sd_bus_message_unref(*m);
5933 /// UNNEEDED by elogind
5935 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5939 assert_return(!m->sealed, -EPERM);
5940 assert_return(!m->sender, -EPERM);
5942 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5945 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5946 assert_return(m, -EINVAL);
5947 assert_return(priority, -EINVAL);
5949 *priority = m->priority;
5953 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5954 assert_return(m, -EINVAL);
5955 assert_return(!m->sealed, -EPERM);
5957 m->priority = priority;