1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
14 #include "alloc-util.h"
15 #include "bus-gvariant.h"
16 #include "bus-internal.h"
17 #include "bus-message.h"
18 #include "bus-signature.h"
23 #include "memfd-util.h"
24 #include "string-util.h"
26 #include "time-util.h"
30 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
32 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
37 if (old_base == new_base)
40 if ((uint8_t*) p < (uint8_t*) old_base)
43 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
46 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
49 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
54 close_and_munmap(part->memfd, part->mmap_begin, part->mapped);
55 else if (part->munmap_this)
56 munmap(part->mmap_begin, part->mapped);
57 else if (part->free_this)
64 static void message_reset_parts(sd_bus_message *m) {
65 struct bus_body_part *part;
70 while (m->n_body_parts > 0) {
71 struct bus_body_part *next = part->next;
72 message_free_part(m, part);
79 m->cached_rindex_part = NULL;
80 m->cached_rindex_part_begin = 0;
83 static void message_reset_containers(sd_bus_message *m) {
88 for (i = 0; i < m->n_containers; i++) {
89 free(m->containers[i].signature);
90 free(m->containers[i].offsets);
93 m->containers = mfree(m->containers);
95 m->n_containers = m->containers_allocated = 0;
96 m->root_container.index = 0;
99 static sd_bus_message* message_free(sd_bus_message *m) {
105 message_reset_parts(m);
107 sd_bus_unref(m->bus);
110 close_many(m->fds, m->n_fds);
114 if (m->iovec != m->iovec_fixed)
117 message_reset_containers(m);
118 free(m->root_container.signature);
119 free(m->root_container.offsets);
121 free(m->root_container.peeked_signature);
123 bus_creds_done(&m->creds);
127 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, message_free);
129 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
131 size_t old_size, new_size, start;
138 old_size = sizeof(struct bus_header) + m->fields_size;
139 start = ALIGN_TO(old_size, align);
140 new_size = start + sz;
142 if (new_size < start ||
143 new_size > (size_t) ((uint32_t) -1))
146 if (old_size == new_size)
147 return (uint8_t*) m->header + old_size;
149 if (m->free_header) {
150 np = realloc(m->header, ALIGN8(new_size));
154 /* Initially, the header is allocated as part of
155 * the sd_bus_message itself, let's replace it by
158 np = malloc(ALIGN8(new_size));
162 memcpy(np, m->header, sizeof(struct bus_header));
165 /* Zero out padding */
166 if (start > old_size)
167 memzero((uint8_t*) np + old_size, start - old_size);
171 m->fields_size = new_size - sizeof(struct bus_header);
173 /* Adjust quick access pointers */
174 m->path = adjust_pointer(m->path, op, old_size, m->header);
175 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
176 m->member = adjust_pointer(m->member, op, old_size, m->header);
177 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
178 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
179 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
181 m->free_header = true;
184 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
187 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
190 return (uint8_t*) np + start;
197 static int message_append_field_string(
209 /* dbus1 only allows 8bit header field ids */
213 /* dbus1 doesn't allow strings over 32bit, let's enforce this
214 * globally, to not risk convertability */
216 if (l > (size_t) (uint32_t) -1)
219 /* Signature "(yv)" where the variant contains "s" */
221 if (BUS_MESSAGE_IS_GVARIANT(m)) {
223 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
224 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
228 *((uint64_t*) p) = h;
235 *ret = (char*) p + 8;
238 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
239 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
248 ((uint32_t*) p)[1] = l;
249 memcpy(p + 8, s, l + 1);
252 *ret = (char*) p + 8;
258 static int message_append_field_signature(
269 /* dbus1 only allows 8bit header field ids */
273 /* dbus1 doesn't allow signatures over 8bit, let's enforce
274 * this globally, to not risk convertability */
279 /* Signature "(yv)" where the variant contains "g" */
281 if (BUS_MESSAGE_IS_GVARIANT(m))
282 /* For gvariant the serialization is the same as for normal strings */
283 return message_append_field_string(m, h, 'g', s, ret);
285 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
286 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
292 p[2] = SD_BUS_TYPE_SIGNATURE;
295 memcpy(p + 5, s, l + 1);
298 *ret = (const char*) p + 5;
304 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
309 /* dbus1 only allows 8bit header field ids */
313 if (BUS_MESSAGE_IS_GVARIANT(m)) {
314 /* (field id 64bit + ((value + NUL + signature string 'u') */
316 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
320 *((uint64_t*) p) = h;
321 *((uint32_t*) (p + 8)) = x;
325 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
326 p = message_extend_fields(m, 8, 4 + 4, false);
335 ((uint32_t*) p)[1] = x;
341 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
346 /* dbus1 only allows 8bit header field ids */
350 if (BUS_MESSAGE_IS_GVARIANT(m)) {
351 /* (field id 64bit + ((value + NUL + signature string 't') */
353 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
357 *((uint64_t*) p) = h;
358 *((uint64_t*) (p + 8)) = x;
362 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
363 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
376 ((uint64_t*) p)[1] = x;
382 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
385 if (BUS_MESSAGE_IS_GVARIANT(m))
386 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
388 /* 64bit cookies are not supported on dbus1 */
389 if (cookie > 0xffffffffUL)
392 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
396 int bus_message_from_header(
399 size_t header_accessible,
401 size_t footer_accessible,
407 sd_bus_message **ret) {
409 _cleanup_free_ sd_bus_message *m = NULL;
410 struct bus_header *h;
414 assert(header || header_accessible <= 0);
415 assert(footer || footer_accessible <= 0);
416 assert(fds || n_fds <= 0);
419 if (header_accessible < sizeof(struct bus_header))
422 if (header_accessible > message_size)
424 if (footer_accessible > message_size)
428 if (!IN_SET(h->version, 1, 2))
431 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
434 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
437 /* Note that we are happy with unknown flags in the flags header! */
439 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
442 label_sz = strlen(label);
453 m->header_accessible = header_accessible;
455 m->footer_accessible = footer_accessible;
457 if (BUS_MESSAGE_IS_GVARIANT(m)) {
460 if (h->dbus2.cookie == 0)
463 /* dbus2 derives the sizes from the message size and
464 the offset table at the end, since it is formatted as
465 gvariant "yyyyuta{tv}v". Since the message itself is a
466 structure with precisely to variable sized entries,
467 there's only one offset in the table, which marks the
468 end of the fields array. */
470 ws = bus_gvariant_determine_word_size(message_size, 0);
471 if (footer_accessible < ws)
474 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
475 if (ALIGN8(m->fields_size) > message_size - ws)
477 if (m->fields_size < sizeof(struct bus_header))
480 m->fields_size -= sizeof(struct bus_header);
481 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
483 if (h->dbus1.serial == 0)
486 /* dbus1 has the sizes in the header */
487 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
488 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
490 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
498 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
499 memcpy(m->creds.label, label, label_sz + 1);
501 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
504 m->bus = sd_bus_ref(bus);
510 int bus_message_from_malloc(
517 sd_bus_message **ret) {
519 _cleanup_(message_freep) sd_bus_message *m = NULL;
523 r = bus_message_from_header(
525 buffer, length, /* in this case the initial bytes and the final bytes are the same */
534 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
537 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
539 m->body.sealed = true;
544 m->iovec = m->iovec_fixed;
545 m->iovec[0].iov_base = buffer;
546 m->iovec[0].iov_len = length;
548 r = bus_message_parse_fields(m);
552 /* We take possession of the memory and fds now */
553 m->free_header = true;
560 _public_ int sd_bus_message_new(
567 assert_return(bus, -ENOTCONN);
568 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
569 assert_return(m, -EINVAL);
570 assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
572 t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
577 t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message)));
578 t->header->endian = BUS_NATIVE_ENDIAN;
579 t->header->type = type;
580 t->header->version = bus->message_version;
581 t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING);
582 t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t);
583 t->bus = sd_bus_ref(bus);
585 if (bus->allow_interactive_authorization)
586 t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
592 _public_ int sd_bus_message_new_signal(
596 const char *interface,
597 const char *member) {
599 _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
602 assert_return(bus, -ENOTCONN);
603 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
604 assert_return(object_path_is_valid(path), -EINVAL);
605 assert_return(interface_name_is_valid(interface), -EINVAL);
606 assert_return(member_name_is_valid(member), -EINVAL);
607 assert_return(m, -EINVAL);
609 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_SIGNAL);
615 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
617 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
620 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
623 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
631 _public_ int sd_bus_message_new_method_call(
634 const char *destination,
636 const char *interface,
637 const char *member) {
639 _cleanup_(message_freep) sd_bus_message *t = NULL;
642 assert_return(bus, -ENOTCONN);
643 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
644 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
645 assert_return(object_path_is_valid(path), -EINVAL);
646 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
647 assert_return(member_name_is_valid(member), -EINVAL);
648 assert_return(m, -EINVAL);
650 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_CALL);
656 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
659 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
664 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
670 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
679 static int message_new_reply(
680 sd_bus_message *call,
682 sd_bus_message **m) {
684 _cleanup_(message_freep) sd_bus_message *t = NULL;
688 assert_return(call, -EINVAL);
689 assert_return(call->sealed, -EPERM);
690 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
691 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
692 assert_return(m, -EINVAL);
694 cookie = BUS_MESSAGE_COOKIE(call);
698 r = sd_bus_message_new(call->bus, &t, type);
704 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
705 t->reply_cookie = cookie;
706 r = message_append_reply_cookie(t, t->reply_cookie);
711 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
716 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
717 t->enforced_reply_signature = call->enforced_reply_signature;
723 _public_ int sd_bus_message_new_method_return(
724 sd_bus_message *call,
725 sd_bus_message **m) {
727 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
730 _public_ int sd_bus_message_new_method_error(
731 sd_bus_message *call,
733 const sd_bus_error *e) {
735 _cleanup_(message_freep) sd_bus_message *t = NULL;
738 assert_return(sd_bus_error_is_set(e), -EINVAL);
739 assert_return(m, -EINVAL);
741 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
745 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
750 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
755 t->error._need_free = -1;
761 _public_ int sd_bus_message_new_method_errorf(
762 sd_bus_message *call,
768 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
771 assert_return(name, -EINVAL);
772 assert_return(m, -EINVAL);
774 va_start(ap, format);
775 bus_error_setfv(&error, name, format, ap);
778 return sd_bus_message_new_method_error(call, m, &error);
781 _public_ int sd_bus_message_new_method_errno(
782 sd_bus_message *call,
785 const sd_bus_error *p) {
787 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
789 if (sd_bus_error_is_set(p))
790 return sd_bus_message_new_method_error(call, m, p);
792 sd_bus_error_set_errno(&berror, error);
794 return sd_bus_message_new_method_error(call, m, &berror);
797 _public_ int sd_bus_message_new_method_errnof(
798 sd_bus_message *call,
804 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
807 va_start(ap, format);
808 sd_bus_error_set_errnofv(&berror, error, format, ap);
811 return sd_bus_message_new_method_error(call, m, &berror);
814 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
818 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
819 m->creds.well_known_names_local = true;
820 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
823 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
827 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
828 m->creds.well_known_names_driver = true;
829 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
832 int bus_message_new_synthetic_error(
835 const sd_bus_error *e,
836 sd_bus_message **m) {
838 _cleanup_(message_freep) sd_bus_message *t = NULL;
842 assert(sd_bus_error_is_set(e));
845 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_ERROR);
851 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
852 t->reply_cookie = cookie;
854 r = message_append_reply_cookie(t, t->reply_cookie);
858 if (bus && bus->unique_name) {
859 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
864 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
869 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
874 t->error._need_free = -1;
876 bus_message_set_sender_driver(bus, t);
882 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
887 assert(m->n_ref > 0);
893 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
898 assert(m->n_ref > 0);
904 return message_free(m);
907 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
908 assert_return(m, -EINVAL);
909 assert_return(type, -EINVAL);
911 *type = m->header->type;
915 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
918 assert_return(m, -EINVAL);
919 assert_return(cookie, -EINVAL);
921 c = BUS_MESSAGE_COOKIE(m);
925 *cookie = BUS_MESSAGE_COOKIE(m);
929 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
930 assert_return(m, -EINVAL);
931 assert_return(cookie, -EINVAL);
933 if (m->reply_cookie == 0)
936 *cookie = m->reply_cookie;
940 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
941 assert_return(m, -EINVAL);
943 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
944 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
947 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
948 assert_return(m, -EINVAL);
950 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
953 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
954 assert_return(m, -EINVAL);
956 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
957 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
960 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
961 assert_return(m, NULL);
966 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
967 assert_return(m, NULL);
972 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
973 assert_return(m, NULL);
978 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
979 assert_return(m, NULL);
981 return m->destination;
984 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
985 assert_return(m, NULL);
990 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
991 assert_return(m, NULL);
993 if (!sd_bus_error_is_set(&m->error))
999 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1000 assert_return(m, -EINVAL);
1001 assert_return(usec, -EINVAL);
1003 if (m->monotonic <= 0)
1006 *usec = m->monotonic;
1010 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1011 assert_return(m, -EINVAL);
1012 assert_return(usec, -EINVAL);
1014 if (m->realtime <= 0)
1017 *usec = m->realtime;
1021 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1022 assert_return(m, -EINVAL);
1023 assert_return(seqnum, -EINVAL);
1028 *seqnum = m->seqnum;
1032 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1033 assert_return(m, NULL);
1035 if (m->creds.mask == 0)
1041 _public_ int sd_bus_message_is_signal(
1043 const char *interface,
1044 const char *member) {
1046 assert_return(m, -EINVAL);
1048 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1051 if (interface && !streq_ptr(m->interface, interface))
1054 if (member && !streq_ptr(m->member, member))
1060 _public_ int sd_bus_message_is_method_call(
1062 const char *interface,
1063 const char *member) {
1065 assert_return(m, -EINVAL);
1067 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1070 if (interface && !streq_ptr(m->interface, interface))
1073 if (member && !streq_ptr(m->member, member))
1079 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1080 assert_return(m, -EINVAL);
1082 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1085 if (name && !streq_ptr(m->error.name, name))
1091 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1092 assert_return(m, -EINVAL);
1093 assert_return(!m->sealed, -EPERM);
1094 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1096 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
1101 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1102 assert_return(m, -EINVAL);
1103 assert_return(!m->sealed, -EPERM);
1105 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
1110 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1111 assert_return(m, -EINVAL);
1112 assert_return(!m->sealed, -EPERM);
1114 SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
1119 static struct bus_container *message_get_container(sd_bus_message *m) {
1122 if (m->n_containers == 0)
1123 return &m->root_container;
1125 assert(m->containers);
1126 return m->containers + m->n_containers - 1;
1129 struct bus_body_part *message_append_part(sd_bus_message *m) {
1130 struct bus_body_part *part;
1137 if (m->n_body_parts <= 0) {
1141 assert(m->body_end);
1143 part = new0(struct bus_body_part, 1);
1149 m->body_end->next = part;
1159 static void part_zero(struct bus_body_part *part, size_t sz) {
1164 /* All other fields can be left in their defaults */
1165 assert(!part->data);
1166 assert(part->memfd < 0);
1169 part->is_zero = true;
1170 part->sealed = true;
1173 static int part_make_space(
1174 struct sd_bus_message *m,
1175 struct bus_body_part *part,
1183 assert(!part->sealed);
1188 if (part->allocated == 0 || sz > part->allocated) {
1189 size_t new_allocated;
1191 new_allocated = sz > 0 ? 2 * sz : 64;
1192 n = realloc(part->data, new_allocated);
1199 part->allocated = new_allocated;
1200 part->free_this = true;
1204 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1210 static int message_add_offset(sd_bus_message *m, size_t offset) {
1211 struct bus_container *c;
1214 assert(BUS_MESSAGE_IS_GVARIANT(m));
1216 /* Add offset to current container, unless this is the first
1217 * item in it, which will have the 0 offset, which we can
1219 c = message_get_container(m);
1221 if (!c->need_offsets)
1224 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1227 c->offsets[c->n_offsets++] = offset;
1231 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1232 struct bus_container *c;
1239 /* Update counters */
1240 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1243 *c->array_size += expand;
1247 static void *message_extend_body(
1252 bool force_inline) {
1254 size_t start_body, end_body, padding, added;
1265 start_body = ALIGN_TO((size_t) m->body_size, align);
1266 end_body = start_body + sz;
1268 padding = start_body - m->body_size;
1269 added = padding + sz;
1271 /* Check for 32bit overflows */
1272 if (end_body > (size_t) ((uint32_t) -1) ||
1273 end_body < start_body) {
1279 struct bus_body_part *part = NULL;
1283 m->n_body_parts <= 0 ||
1284 m->body_end->sealed ||
1285 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1286 (force_inline && m->body_end->size > MEMFD_MIN_SIZE);
1287 /* If this must be an inlined extension, let's create a new part if
1288 * the previous part is large enough to be inlined. */
1292 part = message_append_part(m);
1296 part_zero(part, padding);
1299 part = message_append_part(m);
1303 r = part_make_space(m, part, sz, &p);
1307 struct bus_container *c;
1309 size_t os, start_part, end_part;
1315 start_part = ALIGN_TO(part->size, align);
1316 end_part = start_part + sz;
1318 r = part_make_space(m, part, end_part, &p);
1323 memzero(p, padding);
1324 p = (uint8_t*) p + padding;
1327 /* Readjust pointers */
1328 for (c = m->containers; c < m->containers + m->n_containers; c++)
1329 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1331 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1334 /* Return something that is not NULL and is aligned */
1335 p = (uint8_t*) align;
1337 m->body_size = end_body;
1338 message_extend_containers(m, added);
1341 r = message_add_offset(m, end_body);
1351 static int message_push_fd(sd_bus_message *m, int fd) {
1362 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1366 f = reallocarray(m->fds, sizeof(int), m->n_fds + 1);
1374 m->fds[m->n_fds] = copy;
1380 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1381 _cleanup_close_ int fd = -1;
1382 struct bus_container *c;
1386 assert_return(m, -EINVAL);
1387 assert_return(!m->sealed, -EPERM);
1388 assert_return(bus_type_is_basic(type), -EINVAL);
1389 assert_return(!m->poisoned, -ESTALE);
1391 c = message_get_container(m);
1393 if (c->signature && c->signature[c->index]) {
1394 /* Container signature is already set */
1396 if (c->signature[c->index] != type)
1401 /* Maybe we can append to the signature? But only if this is the top-level container */
1402 if (c->enclosing != 0)
1405 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1412 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1418 case SD_BUS_TYPE_SIGNATURE:
1419 case SD_BUS_TYPE_STRING:
1423 case SD_BUS_TYPE_OBJECT_PATH:
1431 case SD_BUS_TYPE_BOOLEAN:
1433 u8 = p && *(int*) p;
1439 case SD_BUS_TYPE_UNIX_FD:
1444 fd = message_push_fd(m, *(int*) p);
1455 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1456 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1463 a = message_extend_body(m, align, sz, true, false);
1470 *stored = (const uint8_t*) a;
1477 case SD_BUS_TYPE_STRING:
1478 /* To make things easy we'll serialize a NULL string
1479 * into the empty string */
1483 case SD_BUS_TYPE_OBJECT_PATH:
1489 sz = 4 + strlen(p) + 1;
1492 case SD_BUS_TYPE_SIGNATURE:
1497 sz = 1 + strlen(p) + 1;
1500 case SD_BUS_TYPE_BOOLEAN:
1502 u32 = p && *(int*) p;
1508 case SD_BUS_TYPE_UNIX_FD:
1513 fd = message_push_fd(m, *(int*) p);
1524 align = bus_type_get_alignment(type);
1525 sz = bus_type_get_size(type);
1532 a = message_extend_body(m, align, sz, false, false);
1536 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
1537 *(uint32_t*) a = sz - 5;
1538 memcpy((uint8_t*) a + 4, p, sz - 4);
1541 *stored = (const uint8_t*) a + 4;
1543 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1544 *(uint8_t*) a = sz - 2;
1545 memcpy((uint8_t*) a + 1, p, sz - 1);
1548 *stored = (const uint8_t*) a + 1;
1557 if (type == SD_BUS_TYPE_UNIX_FD)
1560 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1567 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1568 return message_append_basic(m, type, p, NULL);
1571 _public_ int sd_bus_message_append_string_space(
1576 struct bus_container *c;
1579 assert_return(m, -EINVAL);
1580 assert_return(s, -EINVAL);
1581 assert_return(!m->sealed, -EPERM);
1582 assert_return(!m->poisoned, -ESTALE);
1584 c = message_get_container(m);
1586 if (c->signature && c->signature[c->index]) {
1587 /* Container signature is already set */
1589 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1594 /* Maybe we can append to the signature? But only if this is the top-level container */
1595 if (c->enclosing != 0)
1598 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1605 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1606 a = message_extend_body(m, 1, size + 1, true, false);
1612 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1616 *(uint32_t*) a = size;
1622 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1628 _public_ int sd_bus_message_append_string_iovec(
1630 const struct iovec *iov,
1631 unsigned n /* should be size_t, but is API now… 😞 */) {
1638 assert_return(m, -EINVAL);
1639 assert_return(!m->sealed, -EPERM);
1640 assert_return(iov || n == 0, -EINVAL);
1641 assert_return(!m->poisoned, -ESTALE);
1643 size = IOVEC_TOTAL_SIZE(iov, n);
1645 r = sd_bus_message_append_string_space(m, size, &p);
1649 for (i = 0; i < n; i++) {
1651 if (iov[i].iov_base)
1652 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1654 memset(p, ' ', iov[i].iov_len);
1656 p += iov[i].iov_len;
1662 static int bus_message_open_array(
1664 struct bus_container *c,
1665 const char *contents,
1666 uint32_t **array_size,
1668 bool *need_offsets) {
1678 assert(need_offsets);
1680 if (!signature_is_single(contents, true))
1683 if (c->signature && c->signature[c->index]) {
1685 /* Verify the existing signature */
1687 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1690 if (!startswith(c->signature + c->index + 1, contents))
1693 nindex = c->index + 1 + strlen(contents);
1697 if (c->enclosing != 0)
1700 /* Extend the existing signature */
1702 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1708 nindex = e - c->signature;
1711 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1712 alignment = bus_gvariant_get_alignment(contents);
1716 /* Add alignment padding and add to offset list */
1717 if (!message_extend_body(m, alignment, 0, false, false))
1720 r = bus_gvariant_is_fixed_size(contents);
1724 *begin = m->body_size;
1725 *need_offsets = r == 0;
1729 struct bus_body_part *o;
1731 alignment = bus_type_get_alignment(contents[0]);
1735 a = message_extend_body(m, 4, 4, false, false);
1740 op = m->body_end->data;
1741 os = m->body_end->size;
1743 /* Add alignment between size and first element */
1744 if (!message_extend_body(m, alignment, 0, false, false))
1747 /* location of array size might have changed so let's readjust a */
1748 if (o == m->body_end)
1749 a = adjust_pointer(a, op, os, m->body_end->data);
1755 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1761 static int bus_message_open_variant(
1763 struct bus_container *c,
1764 const char *contents) {
1770 if (!signature_is_single(contents, false))
1773 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1776 if (c->signature && c->signature[c->index]) {
1778 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1784 if (c->enclosing != 0)
1787 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1794 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1795 /* Variants are always aligned to 8 */
1797 if (!message_extend_body(m, 8, 0, false, false))
1804 l = strlen(contents);
1805 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1810 memcpy((uint8_t*) a + 1, contents, l + 1);
1813 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1819 static int bus_message_open_struct(
1821 struct bus_container *c,
1822 const char *contents,
1824 bool *need_offsets) {
1833 assert(need_offsets);
1835 if (!signature_is_valid(contents, false))
1838 if (c->signature && c->signature[c->index]) {
1841 l = strlen(contents);
1843 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1844 !startswith(c->signature + c->index + 1, contents) ||
1845 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1848 nindex = c->index + 1 + l + 1;
1852 if (c->enclosing != 0)
1855 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1861 nindex = e - c->signature;
1864 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1867 alignment = bus_gvariant_get_alignment(contents);
1871 if (!message_extend_body(m, alignment, 0, false, false))
1874 r = bus_gvariant_is_fixed_size(contents);
1878 *begin = m->body_size;
1879 *need_offsets = r == 0;
1881 /* Align contents to 8 byte boundary */
1882 if (!message_extend_body(m, 8, 0, false, false))
1886 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1892 static int bus_message_open_dict_entry(
1894 struct bus_container *c,
1895 const char *contents,
1897 bool *need_offsets) {
1905 assert(need_offsets);
1907 if (!signature_is_pair(contents))
1910 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1913 if (c->signature && c->signature[c->index]) {
1916 l = strlen(contents);
1918 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1919 !startswith(c->signature + c->index + 1, contents) ||
1920 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1925 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1928 alignment = bus_gvariant_get_alignment(contents);
1932 if (!message_extend_body(m, alignment, 0, false, false))
1935 r = bus_gvariant_is_fixed_size(contents);
1939 *begin = m->body_size;
1940 *need_offsets = r == 0;
1942 /* Align contents to 8 byte boundary */
1943 if (!message_extend_body(m, 8, 0, false, false))
1950 _public_ int sd_bus_message_open_container(
1953 const char *contents) {
1955 struct bus_container *c, *w;
1956 uint32_t *array_size = NULL;
1957 _cleanup_free_ char *signature = NULL;
1958 size_t before, begin = 0;
1959 bool need_offsets = false;
1962 assert_return(m, -EINVAL);
1963 assert_return(!m->sealed, -EPERM);
1964 assert_return(contents, -EINVAL);
1965 assert_return(!m->poisoned, -ESTALE);
1967 /* Make sure we have space for one more container */
1968 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1973 c = message_get_container(m);
1975 signature = strdup(contents);
1981 /* Save old index in the parent container, in case we have to
1982 * abort this container */
1983 c->saved_index = c->index;
1984 before = m->body_size;
1986 if (type == SD_BUS_TYPE_ARRAY)
1987 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1988 else if (type == SD_BUS_TYPE_VARIANT)
1989 r = bus_message_open_variant(m, c, contents);
1990 else if (type == SD_BUS_TYPE_STRUCT)
1991 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1992 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1993 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1999 /* OK, let's fill it in */
2000 w = m->containers + m->n_containers++;
2001 w->enclosing = type;
2002 w->signature = TAKE_PTR(signature);
2004 w->array_size = array_size;
2007 w->n_offsets = w->offsets_allocated = 0;
2009 w->need_offsets = need_offsets;
2014 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2019 if (!BUS_MESSAGE_IS_GVARIANT(m))
2022 if (c->need_offsets) {
2023 size_t payload, sz, i;
2026 /* Variable-width arrays */
2028 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2029 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2031 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2035 for (i = 0; i < c->n_offsets; i++)
2036 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2040 /* Fixed-width or empty arrays */
2042 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2050 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2056 assert(c->signature);
2058 if (!BUS_MESSAGE_IS_GVARIANT(m))
2061 l = strlen(c->signature);
2063 a = message_extend_body(m, 1, 1 + l, true, false);
2068 memcpy(a+1, c->signature, l);
2073 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2074 bool fixed_size = true;
2075 size_t n_variable = 0;
2084 if (!BUS_MESSAGE_IS_GVARIANT(m))
2087 p = strempty(c->signature);
2091 r = signature_element_length(p, &n);
2100 r = bus_gvariant_is_fixed_size(t);
2105 assert(!c->need_offsets || i <= c->n_offsets);
2107 /* We need to add an offset for each item that has a
2108 * variable size and that is not the last one in the
2112 if (r == 0 && p[n] != 0)
2119 assert(!c->need_offsets || i == c->n_offsets);
2120 assert(c->need_offsets || n_variable == 0);
2122 if (isempty(c->signature)) {
2123 /* The unary type is encoded as fixed 1 byte padding */
2124 a = message_extend_body(m, 1, 1, add_offset, false);
2129 } else if (n_variable <= 0) {
2132 /* Structures with fixed-size members only have to be
2133 * fixed-size themselves. But gvariant requires all fixed-size
2134 * elements to be sized a multiple of their alignment. Hence,
2135 * we must *always* add final padding after the last member so
2136 * the overall size of the structure is properly aligned. */
2138 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2140 assert(alignment > 0);
2142 a = message_extend_body(m, alignment, 0, add_offset, false);
2149 assert(c->offsets[c->n_offsets-1] == m->body_size);
2151 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2153 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2157 p = strempty(c->signature);
2158 for (i = 0, j = 0; i < c->n_offsets; i++) {
2162 r = signature_element_length(p, &n);
2173 r = bus_gvariant_is_fixed_size(t);
2176 if (r > 0 || p[0] == 0)
2180 k = n_variable - 1 - j;
2182 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2191 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2192 struct bus_container *c;
2195 assert_return(m, -EINVAL);
2196 assert_return(!m->sealed, -EPERM);
2197 assert_return(m->n_containers > 0, -EINVAL);
2198 assert_return(!m->poisoned, -ESTALE);
2200 c = message_get_container(m);
2202 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2203 if (c->signature && c->signature[c->index] != 0)
2208 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2209 r = bus_message_close_array(m, c);
2210 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2211 r = bus_message_close_variant(m, c);
2212 else if (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY))
2213 r = bus_message_close_struct(m, c, true);
2215 assert_not_reached("Unknown container type");
2229 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2236 stack[*i].types = types;
2237 stack[*i].n_struct = n_struct;
2238 stack[*i].n_array = n_array;
2244 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2255 *types = stack[*i].types;
2256 *n_struct = stack[*i].n_struct;
2257 *n_array = stack[*i].n_array;
2262 _public_ int sd_bus_message_appendv(
2267 unsigned n_array, n_struct;
2268 TypeStack stack[BUS_CONTAINER_DEPTH];
2269 unsigned stack_ptr = 0;
2272 assert_return(m, -EINVAL);
2273 assert_return(types, -EINVAL);
2274 assert_return(!m->sealed, -EPERM);
2275 assert_return(!m->poisoned, -ESTALE);
2277 n_array = (unsigned) -1;
2278 n_struct = strlen(types);
2283 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2284 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2290 r = sd_bus_message_close_container(m);
2298 if (n_array != (unsigned) -1)
2307 case SD_BUS_TYPE_BYTE: {
2310 x = (uint8_t) va_arg(ap, int);
2311 r = sd_bus_message_append_basic(m, *t, &x);
2315 case SD_BUS_TYPE_BOOLEAN:
2316 case SD_BUS_TYPE_INT32:
2317 case SD_BUS_TYPE_UINT32:
2318 case SD_BUS_TYPE_UNIX_FD: {
2321 /* We assume a boolean is the same as int32_t */
2322 assert_cc(sizeof(int32_t) == sizeof(int));
2324 x = va_arg(ap, uint32_t);
2325 r = sd_bus_message_append_basic(m, *t, &x);
2329 case SD_BUS_TYPE_INT16:
2330 case SD_BUS_TYPE_UINT16: {
2333 x = (uint16_t) va_arg(ap, int);
2334 r = sd_bus_message_append_basic(m, *t, &x);
2338 case SD_BUS_TYPE_INT64:
2339 case SD_BUS_TYPE_UINT64: {
2342 x = va_arg(ap, uint64_t);
2343 r = sd_bus_message_append_basic(m, *t, &x);
2347 case SD_BUS_TYPE_DOUBLE: {
2350 x = va_arg(ap, double);
2351 r = sd_bus_message_append_basic(m, *t, &x);
2355 case SD_BUS_TYPE_STRING:
2356 case SD_BUS_TYPE_OBJECT_PATH:
2357 case SD_BUS_TYPE_SIGNATURE: {
2360 x = va_arg(ap, const char*);
2361 r = sd_bus_message_append_basic(m, *t, x);
2365 case SD_BUS_TYPE_ARRAY: {
2368 r = signature_element_length(t + 1, &k);
2374 memcpy(s, t + 1, k);
2377 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2382 if (n_array == (unsigned) -1) {
2387 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2393 n_array = va_arg(ap, unsigned);
2398 case SD_BUS_TYPE_VARIANT: {
2401 s = va_arg(ap, const char*);
2405 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2409 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2414 n_struct = strlen(s);
2415 n_array = (unsigned) -1;
2420 case SD_BUS_TYPE_STRUCT_BEGIN:
2421 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2424 r = signature_element_length(t, &k);
2431 memcpy(s, t + 1, k - 2);
2434 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2439 if (n_array == (unsigned) -1) {
2444 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2450 n_array = (unsigned) -1;
2466 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2470 assert_return(m, -EINVAL);
2471 assert_return(types, -EINVAL);
2472 assert_return(!m->sealed, -EPERM);
2473 assert_return(!m->poisoned, -ESTALE);
2475 va_start(ap, types);
2476 r = sd_bus_message_appendv(m, types, ap);
2482 _public_ int sd_bus_message_append_array_space(
2492 assert_return(m, -EINVAL);
2493 assert_return(!m->sealed, -EPERM);
2494 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2495 assert_return(ptr || size == 0, -EINVAL);
2496 assert_return(!m->poisoned, -ESTALE);
2498 /* alignment and size of the trivial types (except bool) is
2499 * identical for gvariant and dbus1 marshalling */
2500 align = bus_type_get_alignment(type);
2501 sz = bus_type_get_size(type);
2503 assert_se(align > 0);
2509 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2513 a = message_extend_body(m, align, size, false, false);
2517 r = sd_bus_message_close_container(m);
2525 _public_ int sd_bus_message_append_array(
2533 assert_return(m, -EINVAL);
2534 assert_return(!m->sealed, -EPERM);
2535 assert_return(bus_type_is_trivial(type), -EINVAL);
2536 assert_return(ptr || size == 0, -EINVAL);
2537 assert_return(!m->poisoned, -ESTALE);
2539 r = sd_bus_message_append_array_space(m, type, size, &p);
2543 memcpy_safe(p, ptr, size);
2548 _public_ int sd_bus_message_append_array_iovec(
2551 const struct iovec *iov,
2552 unsigned n /* should be size_t, but is API now… 😞 */) {
2559 assert_return(m, -EINVAL);
2560 assert_return(!m->sealed, -EPERM);
2561 assert_return(bus_type_is_trivial(type), -EINVAL);
2562 assert_return(iov || n == 0, -EINVAL);
2563 assert_return(!m->poisoned, -ESTALE);
2565 size = IOVEC_TOTAL_SIZE(iov, n);
2567 r = sd_bus_message_append_array_space(m, type, size, &p);
2571 for (i = 0; i < n; i++) {
2573 if (iov[i].iov_base)
2574 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2576 memzero(p, iov[i].iov_len);
2578 p = (uint8_t*) p + iov[i].iov_len;
2584 _public_ int sd_bus_message_append_array_memfd(
2591 _cleanup_close_ int copy_fd = -1;
2592 struct bus_body_part *part;
2598 assert_return(m, -EINVAL);
2599 assert_return(memfd >= 0, -EBADF);
2600 assert_return(bus_type_is_trivial(type), -EINVAL);
2601 assert_return(size > 0, -EINVAL);
2602 assert_return(!m->sealed, -EPERM);
2603 assert_return(!m->poisoned, -ESTALE);
2605 r = memfd_set_sealed(memfd);
2609 copy_fd = fcntl(memfd, F_DUPFD_CLOEXEC, 3);
2613 r = memfd_get_size(memfd, &real_size);
2617 if (offset == 0 && size == (uint64_t) -1)
2619 else if (offset + size > real_size)
2622 align = bus_type_get_alignment(type);
2623 sz = bus_type_get_size(type);
2625 assert_se(align > 0);
2628 if (offset % align != 0)
2634 if (size > (uint64_t) (uint32_t) -1)
2637 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2641 a = message_extend_body(m, align, 0, false, false);
2645 part = message_append_part(m);
2649 part->memfd = copy_fd;
2650 part->memfd_offset = offset;
2651 part->sealed = true;
2655 m->body_size += size;
2656 message_extend_containers(m, size);
2658 return sd_bus_message_close_container(m);
2661 _public_ int sd_bus_message_append_string_memfd(
2667 _cleanup_close_ int copy_fd = -1;
2668 struct bus_body_part *part;
2669 struct bus_container *c;
2674 assert_return(m, -EINVAL);
2675 assert_return(memfd >= 0, -EBADF);
2676 assert_return(size > 0, -EINVAL);
2677 assert_return(!m->sealed, -EPERM);
2678 assert_return(!m->poisoned, -ESTALE);
2680 r = memfd_set_sealed(memfd);
2684 copy_fd = fcntl(memfd, FD_CLOEXEC, 3);
2688 r = memfd_get_size(memfd, &real_size);
2692 if (offset == 0 && size == (uint64_t) -1)
2694 else if (offset + size > real_size)
2697 /* We require this to be NUL terminated */
2701 if (size > (uint64_t) (uint32_t) -1)
2704 c = message_get_container(m);
2705 if (c->signature && c->signature[c->index]) {
2706 /* Container signature is already set */
2708 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2713 /* Maybe we can append to the signature? But only if this is the top-level container */
2714 if (c->enclosing != 0)
2717 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2724 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2725 a = message_extend_body(m, 4, 4, false, false);
2729 *(uint32_t*) a = size - 1;
2732 part = message_append_part(m);
2736 part->memfd = copy_fd;
2737 part->memfd_offset = offset;
2738 part->sealed = true;
2742 m->body_size += size;
2743 message_extend_containers(m, size);
2745 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2746 r = message_add_offset(m, m->body_size);
2753 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2759 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2763 assert_return(m, -EINVAL);
2764 assert_return(!m->sealed, -EPERM);
2765 assert_return(!m->poisoned, -ESTALE);
2767 r = sd_bus_message_open_container(m, 'a', "s");
2771 STRV_FOREACH(i, l) {
2772 r = sd_bus_message_append_basic(m, 's', *i);
2777 return sd_bus_message_close_container(m);
2780 static int bus_message_close_header(sd_bus_message *m) {
2784 /* The actual user data is finished now, we just complete the
2785 variant and struct now (at least on gvariant). Remember
2786 this position, so that during parsing we know where to
2787 put the outer container end. */
2788 m->user_body_size = m->body_size;
2790 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2791 const char *signature;
2795 /* Add offset table to end of fields array */
2796 if (m->n_header_offsets >= 1) {
2800 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2802 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2803 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2807 for (i = 0; i < m->n_header_offsets; i++)
2808 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2811 /* Add gvariant NUL byte plus signature to the end of
2812 * the body, followed by the final offset pointing to
2813 * the end of the fields array */
2815 signature = strempty(m->root_container.signature);
2816 l = strlen(signature);
2818 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2819 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2824 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2825 memcpy((uint8_t*) d + 2, signature, l);
2826 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2828 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2831 m->footer_accessible = 1 + l + 2 + sz;
2833 m->header->dbus1.fields_size = m->fields_size;
2834 m->header->dbus1.body_size = m->body_size;
2840 _public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t timeout_usec) {
2841 struct bus_body_part *part;
2846 assert_return(m, -EINVAL);
2851 if (m->n_containers > 0)
2857 if (cookie > 0xffffffffULL &&
2858 !BUS_MESSAGE_IS_GVARIANT(m))
2861 /* In vtables the return signature of method calls is listed,
2862 * let's check if they match if this is a response */
2863 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2864 m->enforced_reply_signature &&
2865 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2868 /* If gvariant marshalling is used we need to close the body structure */
2869 r = bus_message_close_struct(m, &m->root_container, false);
2873 /* If there's a non-trivial signature set, then add it in
2874 * here, but only on dbus1 */
2875 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2876 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2882 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2887 r = bus_message_close_header(m);
2891 if (BUS_MESSAGE_IS_GVARIANT(m))
2892 m->header->dbus2.cookie = cookie;
2894 m->header->dbus1.serial = (uint32_t) cookie;
2896 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout_usec;
2898 /* Add padding at the end of the fields part, since we know
2899 * the body needs to start at an 8 byte alignment. We made
2900 * sure we allocated enough space for this, so all we need to
2901 * do here is to zero it out. */
2902 a = ALIGN8(m->fields_size) - m->fields_size;
2904 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2906 /* If this is something we can send as memfd, then let's seal
2907 the memfd now. Note that we can send memfds as payload only
2908 for directed messages, and not for broadcasts. */
2909 if (m->destination && m->bus->use_memfd) {
2910 MESSAGE_FOREACH_PART(part, i, m)
2911 if (part->memfd >= 0 &&
2913 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2914 part != m->body_end) { /* The last part may never be sent as memfd */
2917 /* Try to seal it if that makes
2918 * sense. First, unmap our own map to
2919 * make sure we don't keep it busy. */
2920 bus_body_part_unmap(part);
2922 /* Then, sync up real memfd size */
2924 r = memfd_set_size(part->memfd, sz);
2928 /* Finally, try to seal */
2929 if (memfd_set_sealed(part->memfd) >= 0)
2930 part->sealed = true;
2934 m->root_container.end = m->user_body_size;
2935 m->root_container.index = 0;
2936 m->root_container.offset_index = 0;
2937 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2944 int bus_body_part_map(struct bus_body_part *part) {
2953 if (part->size <= 0)
2956 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2957 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2958 static const uint8_t zeroes[7] = { };
2959 part->data = (void*) zeroes;
2963 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
2964 psz = PAGE_ALIGN(part->size + shift);
2966 if (part->memfd >= 0)
2967 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
2968 else if (part->is_zero)
2969 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2973 if (p == MAP_FAILED)
2977 part->mmap_begin = p;
2978 part->data = (uint8_t*) p + shift;
2979 part->munmap_this = true;
2984 void bus_body_part_unmap(struct bus_body_part *part) {
2988 if (part->memfd < 0)
2991 if (!part->mmap_begin)
2994 if (!part->munmap_this)
2997 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
2999 part->mmap_begin = NULL;
3002 part->munmap_this = false;
3007 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3008 size_t k, start, end;
3013 start = ALIGN_TO((size_t) *rindex, align);
3014 end = start + nbytes;
3019 /* Verify that padding is 0 */
3020 for (k = *rindex; k < start; k++)
3021 if (((const uint8_t*) p)[k] != 0)
3025 *r = (uint8_t*) p + start;
3032 static bool message_end_of_signature(sd_bus_message *m) {
3033 struct bus_container *c;
3037 c = message_get_container(m);
3038 return !c->signature || c->signature[c->index] == 0;
3041 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3042 struct bus_container *c;
3046 c = message_get_container(m);
3047 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3050 if (BUS_MESSAGE_IS_GVARIANT(m))
3051 return index >= c->end;
3053 assert(c->array_size);
3054 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3058 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3059 assert_return(m, -EINVAL);
3060 assert_return(m->sealed, -EPERM);
3062 if (complete && m->n_containers > 0)
3065 if (message_end_of_signature(m))
3068 if (message_end_of_array(m, m->rindex))
3074 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3075 struct bus_body_part *part;
3081 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3082 part = m->cached_rindex_part;
3083 begin = m->cached_rindex_part_begin;
3093 if (index + sz <= begin + part->size) {
3095 r = bus_body_part_map(part);
3100 *p = (uint8_t*) part->data + index - begin;
3102 m->cached_rindex_part = part;
3103 m->cached_rindex_part_begin = begin;
3108 begin += part->size;
3115 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3122 if (!BUS_MESSAGE_IS_GVARIANT(m))
3125 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3128 sz = bus_gvariant_get_size(c->signature);
3132 if (c->offset_index+1 >= c->n_offsets)
3135 /* Variable-size array */
3137 alignment = bus_gvariant_get_alignment(c->signature);
3138 assert(alignment > 0);
3140 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3141 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3144 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3147 /* Fixed-size array */
3148 *rindex = c->begin + (c->offset_index+1) * sz;
3154 } else if (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
3159 if (c->offset_index+1 >= c->n_offsets)
3162 r = signature_element_length(c->signature + c->index, &n);
3166 r = signature_element_length(c->signature + c->index + n, &j);
3171 memcpy(t, c->signature + c->index + n, j);
3174 alignment = bus_gvariant_get_alignment(t);
3177 assert(alignment > 0);
3179 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3180 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3184 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3187 assert_not_reached("Unknown container type");
3192 /* Reached the end */
3198 static int message_peek_body(
3205 size_t k, start, end, padding;
3206 struct bus_body_part *part;
3213 start = ALIGN_TO((size_t) *rindex, align);
3214 padding = start - *rindex;
3215 end = start + nbytes;
3217 if (end > m->user_body_size)
3220 part = find_part(m, *rindex, padding, (void**) &q);
3225 /* Verify padding */
3226 for (k = 0; k < padding; k++)
3231 part = find_part(m, start, nbytes, (void**) &q);
3232 if (!part || (nbytes > 0 && !q))
3243 static bool validate_nul(const char *s, size_t l) {
3245 /* Check for NUL chars in the string */
3246 if (memchr(s, 0, l))
3249 /* Check for NUL termination */
3256 static bool validate_string(const char *s, size_t l) {
3258 if (!validate_nul(s, l))
3261 /* Check if valid UTF8 */
3262 if (!utf8_is_valid(s))
3268 static bool validate_signature(const char *s, size_t l) {
3270 if (!validate_nul(s, l))
3273 /* Check if valid signature */
3274 if (!signature_is_valid(s, true))
3280 static bool validate_object_path(const char *s, size_t l) {
3282 if (!validate_nul(s, l))
3285 if (!object_path_is_valid(s))
3291 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3292 struct bus_container *c;
3297 assert_return(m, -EINVAL);
3298 assert_return(m->sealed, -EPERM);
3299 assert_return(bus_type_is_basic(type), -EINVAL);
3301 if (message_end_of_signature(m))
3304 if (message_end_of_array(m, m->rindex))
3307 c = message_get_container(m);
3308 if (c->signature[c->index] != type)
3313 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3315 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3318 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3322 if (type == SD_BUS_TYPE_STRING)
3323 ok = validate_string(q, c->item_size-1);
3324 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3325 ok = validate_object_path(q, c->item_size-1);
3327 ok = validate_signature(q, c->item_size-1);
3333 *(const char**) p = q;
3337 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3339 if ((size_t) sz != c->item_size)
3342 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3345 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3351 case SD_BUS_TYPE_BYTE:
3353 *(uint8_t*) p = *(uint8_t*) q;
3356 case SD_BUS_TYPE_BOOLEAN:
3358 *(int*) p = !!*(uint8_t*) q;
3361 case SD_BUS_TYPE_INT16:
3362 case SD_BUS_TYPE_UINT16:
3364 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3367 case SD_BUS_TYPE_INT32:
3368 case SD_BUS_TYPE_UINT32:
3370 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3373 case SD_BUS_TYPE_INT64:
3374 case SD_BUS_TYPE_UINT64:
3375 case SD_BUS_TYPE_DOUBLE:
3377 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3380 case SD_BUS_TYPE_UNIX_FD: {
3383 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3388 *(int*) p = m->fds[j];
3394 assert_not_reached("unexpected type");
3398 r = container_next_item(m, c, &rindex);
3403 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3407 r = message_peek_body(m, &rindex, 4, 4, &q);
3411 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3412 r = message_peek_body(m, &rindex, 1, l+1, &q);
3416 if (type == SD_BUS_TYPE_OBJECT_PATH)
3417 ok = validate_object_path(q, l);
3419 ok = validate_string(q, l);
3424 *(const char**) p = q;
3426 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3429 r = message_peek_body(m, &rindex, 1, 1, &q);
3434 r = message_peek_body(m, &rindex, 1, l+1, &q);
3438 if (!validate_signature(q, l))
3442 *(const char**) p = q;
3447 align = bus_type_get_alignment(type);
3450 sz = bus_type_get_size(type);
3453 r = message_peek_body(m, &rindex, align, sz, &q);
3459 case SD_BUS_TYPE_BYTE:
3461 *(uint8_t*) p = *(uint8_t*) q;
3464 case SD_BUS_TYPE_BOOLEAN:
3466 *(int*) p = !!*(uint32_t*) q;
3469 case SD_BUS_TYPE_INT16:
3470 case SD_BUS_TYPE_UINT16:
3472 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3475 case SD_BUS_TYPE_INT32:
3476 case SD_BUS_TYPE_UINT32:
3478 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3481 case SD_BUS_TYPE_INT64:
3482 case SD_BUS_TYPE_UINT64:
3483 case SD_BUS_TYPE_DOUBLE:
3485 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3488 case SD_BUS_TYPE_UNIX_FD: {
3491 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3496 *(int*) p = m->fds[j];
3501 assert_not_reached("Unknown basic type...");
3508 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3514 static int bus_message_enter_array(
3516 struct bus_container *c,
3517 const char *contents,
3518 uint32_t **array_size,
3521 size_t *n_offsets) {
3535 if (!signature_is_single(contents, true))
3538 if (!c->signature || c->signature[c->index] == 0)
3541 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3544 if (!startswith(c->signature + c->index + 1, contents))
3549 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3552 r = message_peek_body(m, &rindex, 4, 4, &q);
3556 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3559 alignment = bus_type_get_alignment(contents[0]);
3563 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3567 *array_size = (uint32_t*) q;
3569 } else if (c->item_size <= 0) {
3571 /* gvariant: empty array */
3576 } else if (bus_gvariant_is_fixed_size(contents)) {
3578 /* gvariant: fixed length array */
3579 *item_size = bus_gvariant_get_size(contents);
3584 size_t where, p = 0, framing, sz;
3587 /* gvariant: variable length array */
3588 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3590 where = rindex + c->item_size - sz;
3591 r = message_peek_body(m, &where, 1, sz, &q);
3595 framing = bus_gvariant_read_word_le(q, sz);
3596 if (framing > c->item_size - sz)
3598 if ((c->item_size - framing) % sz != 0)
3601 *n_offsets = (c->item_size - framing) / sz;
3603 where = rindex + framing;
3604 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3608 *offsets = new(size_t, *n_offsets);
3612 for (i = 0; i < *n_offsets; i++) {
3615 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3616 if (x > c->item_size - sz)
3621 (*offsets)[i] = rindex + x;
3625 *item_size = (*offsets)[0] - rindex;
3630 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3631 c->index += 1 + strlen(contents);
3636 static int bus_message_enter_variant(
3638 struct bus_container *c,
3639 const char *contents,
3640 size_t *item_size) {
3652 if (!signature_is_single(contents, false))
3655 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3658 if (!c->signature || c->signature[c->index] == 0)
3661 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3666 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3669 k = strlen(contents);
3670 if (1+k > c->item_size)
3673 where = rindex + c->item_size - (1+k);
3674 r = message_peek_body(m, &where, 1, 1+k, &q);
3678 if (*(char*) q != 0)
3681 if (memcmp((uint8_t*) q+1, contents, k))
3684 *item_size = c->item_size - (1+k);
3687 r = message_peek_body(m, &rindex, 1, 1, &q);
3692 r = message_peek_body(m, &rindex, 1, l+1, &q);
3696 if (!validate_signature(q, l))
3699 if (!streq(q, contents))
3705 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3711 static int build_struct_offsets(
3713 const char *signature,
3717 size_t *n_offsets) {
3719 unsigned n_variable = 0, n_total = 0, v;
3720 size_t previous = 0, where;
3731 if (isempty(signature)) {
3732 /* Unary type is encoded as *fixed* 1 byte padding */
3733 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3737 if (*(uint8_t *) q != 0)
3746 sz = bus_gvariant_determine_word_size(size, 0);
3750 /* First, loop over signature and count variable elements and
3751 * elements in general. We use this to know how large the
3752 * offset array is at the end of the structure. Note that
3753 * GVariant only stores offsets for all variable size elements
3754 * that are not the last item. */
3760 r = signature_element_length(p, &n);
3769 r = bus_gvariant_is_fixed_size(t);
3774 if (r == 0 && p[n] != 0) /* except the last item */
3781 if (size < n_variable * sz)
3784 where = m->rindex + size - (n_variable * sz);
3785 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3791 *offsets = new(size_t, n_total);
3797 /* Second, loop again and build an offset table */
3803 r = signature_element_length(p, &n);
3812 k = bus_gvariant_get_size(t);
3820 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3823 if (m->rindex + x < previous)
3826 /* The last item's end
3827 * is determined from
3830 x = size - (n_variable * sz);
3832 offset = m->rindex + x;
3838 align = bus_gvariant_get_alignment(t);
3841 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3845 previous = (*offsets)[(*n_offsets)++] = offset;
3850 assert(*n_offsets == n_total);
3852 *item_size = (*offsets)[0] - m->rindex;
3856 static int enter_struct_or_dict_entry(
3858 struct bus_container *c,
3859 const char *contents,
3862 size_t *n_offsets) {
3873 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3876 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3881 /* gvariant with contents */
3882 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3887 static int bus_message_enter_struct(
3889 struct bus_container *c,
3890 const char *contents,
3893 size_t *n_offsets) {
3905 if (!signature_is_valid(contents, false))
3908 if (!c->signature || c->signature[c->index] == 0)
3911 l = strlen(contents);
3913 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3914 !startswith(c->signature + c->index + 1, contents) ||
3915 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3918 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3922 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3923 c->index += 1 + l + 1;
3928 static int bus_message_enter_dict_entry(
3930 struct bus_container *c,
3931 const char *contents,
3934 size_t *n_offsets) {
3943 if (!signature_is_pair(contents))
3946 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3949 if (!c->signature || c->signature[c->index] == 0)
3952 l = strlen(contents);
3954 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3955 !startswith(c->signature + c->index + 1, contents) ||
3956 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3959 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3963 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3964 c->index += 1 + l + 1;
3969 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3971 const char *contents) {
3972 struct bus_container *c, *w;
3973 uint32_t *array_size = NULL;
3974 _cleanup_free_ char *signature = NULL;
3976 _cleanup_free_ size_t *offsets = NULL;
3977 size_t n_offsets = 0, item_size = 0;
3980 assert_return(m, -EINVAL);
3981 assert_return(m->sealed, -EPERM);
3982 assert_return(type != 0 || !contents, -EINVAL);
3984 if (type == 0 || !contents) {
3988 /* Allow entering into anonymous containers */
3989 r = sd_bus_message_peek_type(m, &tt, &cc);
3993 if (type != 0 && type != tt)
3996 if (contents && !streq(contents, cc))
4004 * We enforce a global limit on container depth, that is much
4005 * higher than the 32 structs and 32 arrays the specification
4006 * mandates. This is simpler to implement for us, and we need
4007 * this only to ensure our container array doesn't grow
4008 * without bounds. We are happy to return any data from a
4009 * message as long as the data itself is valid, even if the
4010 * overall message might be not.
4012 * Note that the message signature is validated when
4013 * parsing the headers, and that validation does check the
4016 * Note that the specification defines no limits on the depth
4017 * of stacked variants, but we do.
4019 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4022 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4025 if (message_end_of_signature(m))
4028 if (message_end_of_array(m, m->rindex))
4031 c = message_get_container(m);
4033 signature = strdup(contents);
4037 c->saved_index = c->index;
4040 if (type == SD_BUS_TYPE_ARRAY)
4041 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4042 else if (type == SD_BUS_TYPE_VARIANT)
4043 r = bus_message_enter_variant(m, c, contents, &item_size);
4044 else if (type == SD_BUS_TYPE_STRUCT)
4045 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4046 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4047 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4053 /* OK, let's fill it in */
4054 w = m->containers + m->n_containers++;
4055 w->enclosing = type;
4056 w->signature = TAKE_PTR(signature);
4057 w->peeked_signature = NULL;
4061 w->begin = m->rindex;
4063 /* Unary type has fixed size of 1, but virtual size of 0 */
4064 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4065 type == SD_BUS_TYPE_STRUCT &&
4067 w->end = m->rindex + 0;
4069 w->end = m->rindex + c->item_size;
4071 w->array_size = array_size;
4072 w->item_size = item_size;
4073 w->offsets = TAKE_PTR(offsets);
4074 w->n_offsets = n_offsets;
4075 w->offset_index = 0;
4080 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4081 struct bus_container *c;
4085 assert_return(m, -EINVAL);
4086 assert_return(m->sealed, -EPERM);
4087 assert_return(m->n_containers > 0, -ENXIO);
4089 c = message_get_container(m);
4091 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4092 if (c->signature && c->signature[c->index] != 0)
4096 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4097 if (m->rindex < c->end)
4100 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4103 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4104 if (c->begin + l != m->rindex)
4109 free(c->peeked_signature);
4113 c = message_get_container(m);
4116 c->index = c->saved_index;
4117 r = container_next_item(m, c, &m->rindex);
4125 static void message_quit_container(sd_bus_message *m) {
4126 struct bus_container *c;
4130 assert(m->n_containers > 0);
4132 c = message_get_container(m);
4135 assert(m->rindex >= c->before);
4136 m->rindex = c->before;
4138 /* Free container */
4143 /* Correct index of new top-level container */
4144 c = message_get_container(m);
4145 c->index = c->saved_index;
4148 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4149 struct bus_container *c;
4152 assert_return(m, -EINVAL);
4153 assert_return(m->sealed, -EPERM);
4155 if (message_end_of_signature(m))
4158 if (message_end_of_array(m, m->rindex))
4161 c = message_get_container(m);
4163 if (bus_type_is_basic(c->signature[c->index])) {
4167 *type = c->signature[c->index];
4171 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4177 r = signature_element_length(c->signature+c->index+1, &l);
4183 sig = strndup(c->signature + c->index + 1, l);
4187 free(c->peeked_signature);
4188 *contents = c->peeked_signature = sig;
4192 *type = SD_BUS_TYPE_ARRAY;
4197 if (IN_SET(c->signature[c->index], SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN)) {
4203 r = signature_element_length(c->signature+c->index, &l);
4208 sig = strndup(c->signature + c->index + 1, l - 2);
4212 free(c->peeked_signature);
4213 *contents = c->peeked_signature = sig;
4217 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4222 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4226 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4229 if (c->item_size < 2)
4232 /* Look for the NUL delimiter that
4233 separates the payload from the
4234 signature. Since the body might be
4235 in a different part that then the
4236 signature we map byte by byte. */
4238 for (k = 2; k <= c->item_size; k++) {
4241 where = m->rindex + c->item_size - k;
4242 r = message_peek_body(m, &where, 1, k, &q);
4246 if (*(char*) q == 0)
4250 if (k > c->item_size)
4253 free(c->peeked_signature);
4254 c->peeked_signature = strndup((char*) q + 1, k - 1);
4255 if (!c->peeked_signature)
4258 if (!signature_is_valid(c->peeked_signature, true))
4261 *contents = c->peeked_signature;
4266 r = message_peek_body(m, &rindex, 1, 1, &q);
4271 r = message_peek_body(m, &rindex, 1, l+1, &q);
4275 if (!validate_signature(q, l))
4283 *type = SD_BUS_TYPE_VARIANT;
4298 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4299 struct bus_container *c;
4301 assert_return(m, -EINVAL);
4302 assert_return(m->sealed, -EPERM);
4305 message_reset_containers(m);
4308 c = message_get_container(m);
4310 c = message_get_container(m);
4312 c->offset_index = 0;
4314 m->rindex = c->begin;
4317 c->offset_index = 0;
4318 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4320 return !isempty(c->signature);
4323 static int message_read_ap(
4328 unsigned n_array, n_struct;
4329 TypeStack stack[BUS_CONTAINER_DEPTH];
4330 unsigned stack_ptr = 0;
4331 unsigned n_loop = 0;
4339 /* Ideally, we'd just call ourselves recursively on every
4340 * complex type. However, the state of a va_list that is
4341 * passed to a function is undefined after that function
4342 * returns. This means we need to docode the va_list linearly
4343 * in a single stackframe. We hence implement our own
4344 * home-grown stack in an array. */
4346 n_array = (unsigned) -1; /* length of current array entries */
4347 n_struct = strlen(types); /* length of current struct contents signature */
4354 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4355 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4361 r = sd_bus_message_exit_container(m);
4369 if (n_array != (unsigned) -1)
4378 case SD_BUS_TYPE_BYTE:
4379 case SD_BUS_TYPE_BOOLEAN:
4380 case SD_BUS_TYPE_INT16:
4381 case SD_BUS_TYPE_UINT16:
4382 case SD_BUS_TYPE_INT32:
4383 case SD_BUS_TYPE_UINT32:
4384 case SD_BUS_TYPE_INT64:
4385 case SD_BUS_TYPE_UINT64:
4386 case SD_BUS_TYPE_DOUBLE:
4387 case SD_BUS_TYPE_STRING:
4388 case SD_BUS_TYPE_OBJECT_PATH:
4389 case SD_BUS_TYPE_SIGNATURE:
4390 case SD_BUS_TYPE_UNIX_FD: {
4393 p = va_arg(ap, void*);
4394 r = sd_bus_message_read_basic(m, *t, p);
4407 case SD_BUS_TYPE_ARRAY: {
4410 r = signature_element_length(t + 1, &k);
4416 memcpy(s, t + 1, k);
4419 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4430 if (n_array == (unsigned) -1) {
4435 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4441 n_array = va_arg(ap, unsigned);
4446 case SD_BUS_TYPE_VARIANT: {
4449 s = va_arg(ap, const char *);
4453 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4463 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4468 n_struct = strlen(s);
4469 n_array = (unsigned) -1;
4474 case SD_BUS_TYPE_STRUCT_BEGIN:
4475 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4478 r = signature_element_length(t, &k);
4484 memcpy(s, t + 1, k - 2);
4487 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4497 if (n_array == (unsigned) -1) {
4502 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4508 n_array = (unsigned) -1;
4521 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4525 assert_return(m, -EINVAL);
4526 assert_return(m->sealed, -EPERM);
4527 assert_return(types, -EINVAL);
4529 va_start(ap, types);
4530 r = message_read_ap(m, types, ap);
4536 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4539 assert_return(m, -EINVAL);
4540 assert_return(m->sealed, -EPERM);
4542 /* If types is NULL, read exactly one element */
4544 struct bus_container *c;
4547 if (message_end_of_signature(m))
4550 if (message_end_of_array(m, m->rindex))
4553 c = message_get_container(m);
4555 r = signature_element_length(c->signature + c->index, &l);
4559 types = strndupa(c->signature + c->index, l);
4564 case 0: /* Nothing to drop */
4567 case SD_BUS_TYPE_BYTE:
4568 case SD_BUS_TYPE_BOOLEAN:
4569 case SD_BUS_TYPE_INT16:
4570 case SD_BUS_TYPE_UINT16:
4571 case SD_BUS_TYPE_INT32:
4572 case SD_BUS_TYPE_UINT32:
4573 case SD_BUS_TYPE_INT64:
4574 case SD_BUS_TYPE_UINT64:
4575 case SD_BUS_TYPE_DOUBLE:
4576 case SD_BUS_TYPE_STRING:
4577 case SD_BUS_TYPE_OBJECT_PATH:
4578 case SD_BUS_TYPE_SIGNATURE:
4579 case SD_BUS_TYPE_UNIX_FD:
4581 r = sd_bus_message_read_basic(m, *types, NULL);
4585 r = sd_bus_message_skip(m, types + 1);
4591 case SD_BUS_TYPE_ARRAY: {
4594 r = signature_element_length(types + 1, &k);
4600 memcpy(s, types+1, k);
4603 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4608 r = sd_bus_message_skip(m, s);
4615 r = sd_bus_message_exit_container(m);
4620 r = sd_bus_message_skip(m, types + 1 + k);
4627 case SD_BUS_TYPE_VARIANT: {
4628 const char *contents;
4631 r = sd_bus_message_peek_type(m, &x, &contents);
4635 if (x != SD_BUS_TYPE_VARIANT)
4638 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4642 r = sd_bus_message_skip(m, contents);
4647 r = sd_bus_message_exit_container(m);
4651 r = sd_bus_message_skip(m, types + 1);
4658 case SD_BUS_TYPE_STRUCT_BEGIN:
4659 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4662 r = signature_element_length(types, &k);
4668 memcpy(s, types+1, k-2);
4671 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4675 r = sd_bus_message_skip(m, s);
4679 r = sd_bus_message_exit_container(m);
4684 r = sd_bus_message_skip(m, types + k);
4696 _public_ int sd_bus_message_read_array(
4702 struct bus_container *c;
4708 assert_return(m, -EINVAL);
4709 assert_return(m->sealed, -EPERM);
4710 assert_return(bus_type_is_trivial(type), -EINVAL);
4711 assert_return(ptr, -EINVAL);
4712 assert_return(size, -EINVAL);
4713 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4715 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4719 c = message_get_container(m);
4721 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4722 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4726 sz = c->end - c->begin;
4728 align = bus_type_get_alignment(type);
4732 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4736 /* Zero length array, let's return some aligned
4737 * pointer that is not NULL */
4738 p = (uint8_t*) align;
4740 r = message_peek_body(m, &m->rindex, align, sz, &p);
4745 r = sd_bus_message_exit_container(m);
4749 *ptr = (const void*) p;
4755 message_quit_container(m);
4759 static int message_peek_fields(
4770 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4773 static int message_peek_field_uint32(
4785 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4788 /* identical for gvariant and dbus1 */
4790 r = message_peek_fields(m, ri, 4, 4, &q);
4795 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4800 static int message_peek_field_uint64(
4812 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4815 /* identical for gvariant and dbus1 */
4817 r = message_peek_fields(m, ri, 8, 8, &q);
4822 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4827 static int message_peek_field_string(
4829 bool (*validate)(const char *p),
4841 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4846 r = message_peek_fields(m, ri, 1, item_size, &q);
4852 r = message_peek_field_uint32(m, ri, 4, &l);
4856 r = message_peek_fields(m, ri, 1, l+1, &q);
4862 if (!validate_nul(q, l))
4868 if (!validate_string(q, l))
4878 static int message_peek_field_signature(
4891 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4896 r = message_peek_fields(m, ri, 1, item_size, &q);
4902 r = message_peek_fields(m, ri, 1, 1, &q);
4907 r = message_peek_fields(m, ri, 1, l+1, &q);
4912 if (!validate_signature(q, l))
4921 static int message_skip_fields(
4924 uint32_t array_size,
4925 const char **signature) {
4927 size_t original_index;
4933 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4935 original_index = *ri;
4941 if (array_size != (uint32_t) -1 &&
4942 array_size <= *ri - original_index)
4949 if (t == SD_BUS_TYPE_STRING) {
4951 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4957 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4959 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4965 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4967 r = message_peek_field_signature(m, ri, 0, NULL);
4973 } else if (bus_type_is_basic(t)) {
4976 align = bus_type_get_alignment(t);
4977 k = bus_type_get_size(t);
4978 assert(align > 0 && k > 0);
4980 r = message_peek_fields(m, ri, align, k, NULL);
4986 } else if (t == SD_BUS_TYPE_ARRAY) {
4988 r = signature_element_length(*signature+1, &l);
4998 strncpy(sig, *signature + 1, l-1);
5001 alignment = bus_type_get_alignment(sig[0]);
5005 r = message_peek_field_uint32(m, ri, 0, &nas);
5008 if (nas > BUS_ARRAY_MAX_SIZE)
5011 r = message_peek_fields(m, ri, alignment, 0, NULL);
5015 r = message_skip_fields(m, ri, nas, (const char**) &s);
5020 (*signature) += 1 + l;
5022 } else if (t == SD_BUS_TYPE_VARIANT) {
5025 r = message_peek_field_signature(m, ri, 0, &s);
5029 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5035 } else if (IN_SET(t, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
5037 r = signature_element_length(*signature, &l);
5044 strncpy(sig, *signature + 1, l-1);
5047 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5058 int bus_message_parse_fields(sd_bus_message *m) {
5061 uint32_t unix_fds = 0;
5062 bool unix_fds_set = false;
5063 void *offsets = NULL;
5064 unsigned n_offsets = 0;
5070 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5073 /* Read the signature from the end of the body variant first */
5074 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5075 if (m->footer_accessible < 1 + sz)
5078 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5080 if (p < (char*) m->footer)
5087 /* We found the beginning of the signature
5088 * string, yay! We require the body to be a
5089 * structure, so verify it and then strip the
5090 * opening/closing brackets. */
5092 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5094 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5095 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5098 c = strndup(p + 1 + 1, l - 2);
5102 free(m->root_container.signature);
5103 m->root_container.signature = c;
5110 /* Calculate the actual user body size, by removing
5111 * the trailing variant signature and struct offset
5113 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5115 /* Pull out the offset table for the fields array */
5116 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5121 ri = m->fields_size - sz;
5122 r = message_peek_fields(m, &ri, 1, sz, &q);
5126 framing = bus_gvariant_read_word_le(q, sz);
5127 if (framing >= m->fields_size - sz)
5129 if ((m->fields_size - framing) % sz != 0)
5133 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5137 n_offsets = (m->fields_size - framing) / sz;
5140 m->user_body_size = m->body_size;
5143 while (ri < m->fields_size) {
5144 _cleanup_free_ char *sig = NULL;
5145 const char *signature;
5146 uint64_t field_type;
5147 size_t item_size = (size_t) -1;
5149 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5158 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5160 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5164 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5168 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5175 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5180 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5185 where = ri = ALIGN_TO(ri, 8);
5186 item_size = end - ri;
5187 r = message_peek_fields(m, &where, 1, item_size, &q);
5191 b = memrchr(q, 0, item_size);
5195 sig = strndup(b+1, item_size - (b+1-(char*) q));
5200 item_size = b - (char*) q;
5202 r = message_peek_field_signature(m, &ri, 0, &signature);
5207 switch (field_type) {
5209 case _BUS_MESSAGE_HEADER_INVALID:
5212 case BUS_MESSAGE_HEADER_PATH:
5217 if (!streq(signature, "o"))
5220 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5223 case BUS_MESSAGE_HEADER_INTERFACE:
5228 if (!streq(signature, "s"))
5231 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5234 case BUS_MESSAGE_HEADER_MEMBER:
5239 if (!streq(signature, "s"))
5242 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5245 case BUS_MESSAGE_HEADER_ERROR_NAME:
5250 if (!streq(signature, "s"))
5253 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5255 m->error._need_free = -1;
5259 case BUS_MESSAGE_HEADER_DESTINATION:
5264 if (!streq(signature, "s"))
5267 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5270 case BUS_MESSAGE_HEADER_SENDER:
5275 if (!streq(signature, "s"))
5278 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5280 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client) {
5281 m->creds.unique_name = (char*) m->sender;
5282 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5287 case BUS_MESSAGE_HEADER_SIGNATURE: {
5291 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5294 if (m->root_container.signature)
5297 if (!streq(signature, "g"))
5300 r = message_peek_field_signature(m, &ri, item_size, &s);
5308 free_and_replace(m->root_container.signature, c);
5312 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5314 if (m->reply_cookie != 0)
5317 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5318 /* 64bit on dbus2 */
5320 if (!streq(signature, "t"))
5323 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5327 /* 32bit on dbus1 */
5330 if (!streq(signature, "u"))
5333 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5337 m->reply_cookie = serial;
5340 if (m->reply_cookie == 0)
5345 case BUS_MESSAGE_HEADER_UNIX_FDS:
5349 if (!streq(signature, "u"))
5352 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5356 unix_fds_set = true;
5360 if (!BUS_MESSAGE_IS_GVARIANT(m))
5361 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5370 if (m->n_fds != unix_fds)
5373 switch (m->header->type) {
5375 case SD_BUS_MESSAGE_SIGNAL:
5376 if (!m->path || !m->interface || !m->member)
5379 if (m->reply_cookie != 0)
5384 case SD_BUS_MESSAGE_METHOD_CALL:
5386 if (!m->path || !m->member)
5389 if (m->reply_cookie != 0)
5394 case SD_BUS_MESSAGE_METHOD_RETURN:
5396 if (m->reply_cookie == 0)
5400 case SD_BUS_MESSAGE_METHOD_ERROR:
5402 if (m->reply_cookie == 0 || !m->error.name)
5407 /* Refuse non-local messages that claim they are local */
5408 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5410 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5412 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5415 m->root_container.end = m->user_body_size;
5417 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5418 r = build_struct_offsets(
5420 m->root_container.signature,
5422 &m->root_container.item_size,
5423 &m->root_container.offsets,
5424 &m->root_container.n_offsets);
5429 /* Try to read the error message, but if we can't it's a non-issue */
5430 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5431 (void) sd_bus_message_read(m, "s", &m->error.message);
5436 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5437 assert_return(m, -EINVAL);
5438 assert_return(destination, -EINVAL);
5439 assert_return(!m->sealed, -EPERM);
5440 assert_return(!m->destination, -EEXIST);
5442 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5445 _public_ int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) {
5446 assert_return(m, -EINVAL);
5447 assert_return(sender, -EINVAL);
5448 assert_return(!m->sealed, -EPERM);
5449 assert_return(!m->sender, -EEXIST);
5451 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5454 #if 0 /// UNNEEDED by elogind
5455 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5459 struct bus_body_part *part;
5465 total = BUS_MESSAGE_SIZE(m);
5471 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5472 MESSAGE_FOREACH_PART(part, i, m)
5473 e = mempcpy(e, part->data, part->size);
5475 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5484 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5491 r = sd_bus_message_enter_container(m, 'a', "s");
5495 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5496 r = strv_extend(l, s);
5503 r = sd_bus_message_exit_container(m);
5510 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5511 _cleanup_strv_free_ char **strv = NULL;
5514 assert_return(m, -EINVAL);
5515 assert_return(m->sealed, -EPERM);
5516 assert_return(l, -EINVAL);
5518 r = bus_message_read_strv_extend(m, &strv);
5522 *l = TAKE_PTR(strv);
5526 static int bus_message_get_arg_skip(
5530 const char **_contents) {
5535 r = sd_bus_message_rewind(m, true);
5540 const char *contents;
5543 r = sd_bus_message_peek_type(m, &type, &contents);
5549 /* Don't match against arguments after the first one we don't understand */
5550 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5551 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5556 *_contents = contents;
5562 r = sd_bus_message_skip(m, NULL);
5569 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5576 r = bus_message_get_arg_skip(m, i, &type, NULL);
5580 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5583 return sd_bus_message_read_basic(m, type, str);
5586 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5587 const char *contents;
5594 r = bus_message_get_arg_skip(m, i, &type, &contents);
5598 if (type != SD_BUS_TYPE_ARRAY)
5600 if (!STR_IN_SET(contents, "s", "o", "g"))
5603 return sd_bus_message_read_strv(m, strv);
5606 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5607 assert_return(m, EINVAL);
5609 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5612 return sd_bus_error_get_errno(&m->error);
5615 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5616 struct bus_container *c;
5618 assert_return(m, NULL);
5620 c = complete ? &m->root_container : message_get_container(m);
5621 return strempty(c->signature);
5624 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5625 assert_return(m, -EINVAL);
5627 return isempty(m->root_container.signature);
5630 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5631 assert_return(m, -EINVAL);
5633 return streq(strempty(m->root_container.signature), strempty(signature));
5636 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5637 bool done_something = false;
5640 assert_return(m, -EINVAL);
5641 assert_return(source, -EINVAL);
5642 assert_return(!m->sealed, -EPERM);
5643 assert_return(source->sealed, -EPERM);
5646 const char *contents;
5661 r = sd_bus_message_peek_type(source, &type, &contents);
5667 done_something = true;
5669 if (bus_type_is_container(type) > 0) {
5671 r = sd_bus_message_enter_container(source, type, contents);
5675 r = sd_bus_message_open_container(m, type, contents);
5679 r = sd_bus_message_copy(m, source, true);
5683 r = sd_bus_message_close_container(m);
5687 r = sd_bus_message_exit_container(source);
5694 r = sd_bus_message_read_basic(source, type, &basic);
5700 if (IN_SET(type, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_STRING))
5701 r = sd_bus_message_append_basic(m, type, basic.string);
5703 r = sd_bus_message_append_basic(m, type, &basic);
5710 return done_something;
5713 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5718 assert_return(m, -EINVAL);
5719 assert_return(m->sealed, -EPERM);
5720 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5721 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5722 assert_return(type || contents, -EINVAL);
5723 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5725 r = sd_bus_message_peek_type(m, &t, &c);
5729 if (type != 0 && type != t)
5732 if (contents && !streq_ptr(contents, c))
5738 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5739 assert_return(m, NULL);
5744 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5745 _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5753 switch ((*m)->header->type) {
5755 case SD_BUS_MESSAGE_SIGNAL:
5756 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5762 case SD_BUS_MESSAGE_METHOD_CALL:
5763 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5769 case SD_BUS_MESSAGE_METHOD_RETURN:
5770 case SD_BUS_MESSAGE_METHOD_ERROR:
5772 r = sd_bus_message_new(bus, &n, (*m)->header->type);
5778 n->reply_cookie = (*m)->reply_cookie;
5780 r = message_append_reply_cookie(n, n->reply_cookie);
5784 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5785 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5789 n->error._need_free = -1;
5798 if ((*m)->destination && !n->destination) {
5799 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5804 if ((*m)->sender && !n->sender) {
5805 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5810 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5812 r = sd_bus_message_copy(n, *m, true);
5816 timeout = (*m)->timeout;
5817 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5818 timeout = BUS_DEFAULT_TIMEOUT;
5820 r = sd_bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5824 sd_bus_message_unref(*m);
5830 #if 0 /// UNNEEDED by elogind
5831 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5835 assert_return(!m->sealed, -EPERM);
5836 assert_return(!m->sender, -EPERM);
5838 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5842 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5843 assert_return(m, -EINVAL);
5844 assert_return(priority, -EINVAL);
5846 *priority = m->priority;
5850 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5851 assert_return(m, -EINVAL);
5852 assert_return(!m->sealed, -EPERM);
5854 m->priority = priority;