1 /* SPDX-License-Identifier: LGPL-2.1+ */
11 #include "alloc-util.h"
12 #include "bus-gvariant.h"
13 #include "bus-internal.h"
14 #include "bus-message.h"
15 #include "bus-signature.h"
20 #include "memfd-util.h"
21 #include "string-util.h"
23 #include "time-util.h"
27 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
29 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
34 if (old_base == new_base)
37 if ((uint8_t*) p < (uint8_t*) old_base)
40 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
43 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
46 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
51 close_and_munmap(part->memfd, part->mmap_begin, part->mapped);
52 else if (part->munmap_this)
53 munmap(part->mmap_begin, part->mapped);
54 else if (part->free_this)
61 static void message_reset_parts(sd_bus_message *m) {
62 struct bus_body_part *part;
67 while (m->n_body_parts > 0) {
68 struct bus_body_part *next = part->next;
69 message_free_part(m, part);
76 m->cached_rindex_part = NULL;
77 m->cached_rindex_part_begin = 0;
80 static void message_reset_containers(sd_bus_message *m) {
85 for (i = 0; i < m->n_containers; i++) {
86 free(m->containers[i].signature);
87 free(m->containers[i].offsets);
90 m->containers = mfree(m->containers);
92 m->n_containers = m->containers_allocated = 0;
93 m->root_container.index = 0;
96 static sd_bus_message* message_free(sd_bus_message *m) {
102 message_reset_parts(m);
104 sd_bus_unref(m->bus);
107 close_many(m->fds, m->n_fds);
111 if (m->iovec != m->iovec_fixed)
114 message_reset_containers(m);
115 free(m->root_container.signature);
116 free(m->root_container.offsets);
118 free(m->root_container.peeked_signature);
120 bus_creds_done(&m->creds);
124 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, message_free);
126 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
128 size_t old_size, new_size, start;
135 old_size = sizeof(struct bus_header) + m->fields_size;
136 start = ALIGN_TO(old_size, align);
137 new_size = start + sz;
139 if (new_size < start ||
140 new_size > (size_t) ((uint32_t) -1))
143 if (old_size == new_size)
144 return (uint8_t*) m->header + old_size;
146 if (m->free_header) {
147 np = realloc(m->header, ALIGN8(new_size));
151 /* Initially, the header is allocated as part of
152 * the sd_bus_message itself, let's replace it by
155 np = malloc(ALIGN8(new_size));
159 memcpy(np, m->header, sizeof(struct bus_header));
162 /* Zero out padding */
163 if (start > old_size)
164 memzero((uint8_t*) np + old_size, start - old_size);
168 m->fields_size = new_size - sizeof(struct bus_header);
170 /* Adjust quick access pointers */
171 m->path = adjust_pointer(m->path, op, old_size, m->header);
172 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
173 m->member = adjust_pointer(m->member, op, old_size, m->header);
174 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
175 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
176 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
178 m->free_header = true;
181 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
184 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
187 return (uint8_t*) np + start;
194 static int message_append_field_string(
206 /* dbus1 only allows 8bit header field ids */
210 /* dbus1 doesn't allow strings over 32bit, let's enforce this
211 * globally, to not risk convertability */
213 if (l > (size_t) (uint32_t) -1)
216 /* Signature "(yv)" where the variant contains "s" */
218 if (BUS_MESSAGE_IS_GVARIANT(m)) {
220 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
221 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
225 *((uint64_t*) p) = h;
232 *ret = (char*) p + 8;
235 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
236 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
245 ((uint32_t*) p)[1] = l;
246 memcpy(p + 8, s, l + 1);
249 *ret = (char*) p + 8;
255 static int message_append_field_signature(
266 /* dbus1 only allows 8bit header field ids */
270 /* dbus1 doesn't allow signatures over 8bit, let's enforce
271 * this globally, to not risk convertability */
276 /* Signature "(yv)" where the variant contains "g" */
278 if (BUS_MESSAGE_IS_GVARIANT(m))
279 /* For gvariant the serialization is the same as for normal strings */
280 return message_append_field_string(m, h, 'g', s, ret);
282 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
283 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
289 p[2] = SD_BUS_TYPE_SIGNATURE;
292 memcpy(p + 5, s, l + 1);
295 *ret = (const char*) p + 5;
301 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
306 /* dbus1 only allows 8bit header field ids */
310 if (BUS_MESSAGE_IS_GVARIANT(m)) {
311 /* (field id 64bit + ((value + NUL + signature string 'u') */
313 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
317 *((uint64_t*) p) = h;
318 *((uint32_t*) (p + 8)) = x;
322 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
323 p = message_extend_fields(m, 8, 4 + 4, false);
332 ((uint32_t*) p)[1] = x;
338 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
343 /* dbus1 only allows 8bit header field ids */
347 if (BUS_MESSAGE_IS_GVARIANT(m)) {
348 /* (field id 64bit + ((value + NUL + signature string 't') */
350 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
354 *((uint64_t*) p) = h;
355 *((uint64_t*) (p + 8)) = x;
359 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
360 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
373 ((uint64_t*) p)[1] = x;
379 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
382 if (BUS_MESSAGE_IS_GVARIANT(m))
383 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
385 /* 64bit cookies are not supported on dbus1 */
386 if (cookie > 0xffffffffUL)
389 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
393 int bus_message_from_header(
396 size_t header_accessible,
398 size_t footer_accessible,
404 sd_bus_message **ret) {
406 _cleanup_free_ sd_bus_message *m = NULL;
407 struct bus_header *h;
411 assert(header || header_accessible <= 0);
412 assert(footer || footer_accessible <= 0);
413 assert(fds || n_fds <= 0);
416 if (header_accessible < sizeof(struct bus_header))
419 if (header_accessible > message_size)
421 if (footer_accessible > message_size)
425 if (!IN_SET(h->version, 1, 2))
428 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
431 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
434 /* Note that we are happy with unknown flags in the flags header! */
436 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
439 label_sz = strlen(label);
450 m->header_accessible = header_accessible;
452 m->footer_accessible = footer_accessible;
454 if (BUS_MESSAGE_IS_GVARIANT(m)) {
457 if (h->dbus2.cookie == 0)
460 /* dbus2 derives the sizes from the message size and
461 the offset table at the end, since it is formatted as
462 gvariant "yyyyuta{tv}v". Since the message itself is a
463 structure with precisely to variable sized entries,
464 there's only one offset in the table, which marks the
465 end of the fields array. */
467 ws = bus_gvariant_determine_word_size(message_size, 0);
468 if (footer_accessible < ws)
471 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
472 if (ALIGN8(m->fields_size) > message_size - ws)
474 if (m->fields_size < sizeof(struct bus_header))
477 m->fields_size -= sizeof(struct bus_header);
478 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
480 if (h->dbus1.serial == 0)
483 /* dbus1 has the sizes in the header */
484 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
485 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
487 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
495 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
496 memcpy(m->creds.label, label, label_sz + 1);
498 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
501 m->bus = sd_bus_ref(bus);
507 int bus_message_from_malloc(
514 sd_bus_message **ret) {
516 _cleanup_(message_freep) sd_bus_message *m = NULL;
520 r = bus_message_from_header(
522 buffer, length, /* in this case the initial bytes and the final bytes are the same */
531 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
534 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
536 m->body.sealed = true;
541 m->iovec = m->iovec_fixed;
542 m->iovec[0].iov_base = buffer;
543 m->iovec[0].iov_len = length;
545 r = bus_message_parse_fields(m);
549 /* We take possession of the memory and fds now */
550 m->free_header = true;
557 _public_ int sd_bus_message_new(
564 assert_return(bus, -ENOTCONN);
565 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
566 assert_return(m, -EINVAL);
567 assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
569 t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
574 t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message)));
575 t->header->endian = BUS_NATIVE_ENDIAN;
576 t->header->type = type;
577 t->header->version = bus->message_version;
578 t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING);
579 t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t);
580 t->bus = sd_bus_ref(bus);
582 if (bus->allow_interactive_authorization)
583 t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
589 _public_ int sd_bus_message_new_signal(
593 const char *interface,
594 const char *member) {
596 _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
599 assert_return(bus, -ENOTCONN);
600 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
601 assert_return(object_path_is_valid(path), -EINVAL);
602 assert_return(interface_name_is_valid(interface), -EINVAL);
603 assert_return(member_name_is_valid(member), -EINVAL);
604 assert_return(m, -EINVAL);
606 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_SIGNAL);
612 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
614 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
617 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
620 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
628 _public_ int sd_bus_message_new_method_call(
631 const char *destination,
633 const char *interface,
634 const char *member) {
636 _cleanup_(message_freep) sd_bus_message *t = NULL;
639 assert_return(bus, -ENOTCONN);
640 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
641 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
642 assert_return(object_path_is_valid(path), -EINVAL);
643 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
644 assert_return(member_name_is_valid(member), -EINVAL);
645 assert_return(m, -EINVAL);
647 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_CALL);
653 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
656 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
661 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
667 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
676 static int message_new_reply(
677 sd_bus_message *call,
679 sd_bus_message **m) {
681 _cleanup_(message_freep) sd_bus_message *t = NULL;
685 assert_return(call, -EINVAL);
686 assert_return(call->sealed, -EPERM);
687 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
688 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
689 assert_return(m, -EINVAL);
691 cookie = BUS_MESSAGE_COOKIE(call);
695 r = sd_bus_message_new(call->bus, &t, type);
701 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
702 t->reply_cookie = cookie;
703 r = message_append_reply_cookie(t, t->reply_cookie);
708 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
713 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
714 t->enforced_reply_signature = call->enforced_reply_signature;
720 _public_ int sd_bus_message_new_method_return(
721 sd_bus_message *call,
722 sd_bus_message **m) {
724 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
727 _public_ int sd_bus_message_new_method_error(
728 sd_bus_message *call,
730 const sd_bus_error *e) {
732 _cleanup_(message_freep) sd_bus_message *t = NULL;
735 assert_return(sd_bus_error_is_set(e), -EINVAL);
736 assert_return(m, -EINVAL);
738 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
742 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
747 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
752 t->error._need_free = -1;
758 _public_ int sd_bus_message_new_method_errorf(
759 sd_bus_message *call,
765 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
768 assert_return(name, -EINVAL);
769 assert_return(m, -EINVAL);
771 va_start(ap, format);
772 bus_error_setfv(&error, name, format, ap);
775 return sd_bus_message_new_method_error(call, m, &error);
778 _public_ int sd_bus_message_new_method_errno(
779 sd_bus_message *call,
782 const sd_bus_error *p) {
784 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
786 if (sd_bus_error_is_set(p))
787 return sd_bus_message_new_method_error(call, m, p);
789 sd_bus_error_set_errno(&berror, error);
791 return sd_bus_message_new_method_error(call, m, &berror);
794 _public_ int sd_bus_message_new_method_errnof(
795 sd_bus_message *call,
801 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
804 va_start(ap, format);
805 sd_bus_error_set_errnofv(&berror, error, format, ap);
808 return sd_bus_message_new_method_error(call, m, &berror);
811 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
815 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
816 m->creds.well_known_names_local = true;
817 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
820 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
824 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
825 m->creds.well_known_names_driver = true;
826 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
829 int bus_message_new_synthetic_error(
832 const sd_bus_error *e,
833 sd_bus_message **m) {
835 _cleanup_(message_freep) sd_bus_message *t = NULL;
839 assert(sd_bus_error_is_set(e));
842 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_ERROR);
848 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
849 t->reply_cookie = cookie;
851 r = message_append_reply_cookie(t, t->reply_cookie);
855 if (bus && bus->unique_name) {
856 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
861 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
866 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
871 t->error._need_free = -1;
873 bus_message_set_sender_driver(bus, t);
879 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
884 assert(m->n_ref > 0);
890 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
895 assert(m->n_ref > 0);
901 return message_free(m);
904 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
905 assert_return(m, -EINVAL);
906 assert_return(type, -EINVAL);
908 *type = m->header->type;
912 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
915 assert_return(m, -EINVAL);
916 assert_return(cookie, -EINVAL);
918 c = BUS_MESSAGE_COOKIE(m);
922 *cookie = BUS_MESSAGE_COOKIE(m);
926 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
927 assert_return(m, -EINVAL);
928 assert_return(cookie, -EINVAL);
930 if (m->reply_cookie == 0)
933 *cookie = m->reply_cookie;
937 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
938 assert_return(m, -EINVAL);
940 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
941 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
944 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
945 assert_return(m, -EINVAL);
947 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
950 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
951 assert_return(m, -EINVAL);
953 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
954 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
957 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
958 assert_return(m, NULL);
963 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
964 assert_return(m, NULL);
969 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
970 assert_return(m, NULL);
975 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
976 assert_return(m, NULL);
978 return m->destination;
981 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
982 assert_return(m, NULL);
987 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
988 assert_return(m, NULL);
990 if (!sd_bus_error_is_set(&m->error))
996 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
997 assert_return(m, -EINVAL);
998 assert_return(usec, -EINVAL);
1000 if (m->monotonic <= 0)
1003 *usec = m->monotonic;
1007 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1008 assert_return(m, -EINVAL);
1009 assert_return(usec, -EINVAL);
1011 if (m->realtime <= 0)
1014 *usec = m->realtime;
1018 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1019 assert_return(m, -EINVAL);
1020 assert_return(seqnum, -EINVAL);
1025 *seqnum = m->seqnum;
1029 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1030 assert_return(m, NULL);
1032 if (m->creds.mask == 0)
1038 _public_ int sd_bus_message_is_signal(
1040 const char *interface,
1041 const char *member) {
1043 assert_return(m, -EINVAL);
1045 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1048 if (interface && !streq_ptr(m->interface, interface))
1051 if (member && !streq_ptr(m->member, member))
1057 _public_ int sd_bus_message_is_method_call(
1059 const char *interface,
1060 const char *member) {
1062 assert_return(m, -EINVAL);
1064 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1067 if (interface && !streq_ptr(m->interface, interface))
1070 if (member && !streq_ptr(m->member, member))
1076 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1077 assert_return(m, -EINVAL);
1079 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1082 if (name && !streq_ptr(m->error.name, name))
1088 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1089 assert_return(m, -EINVAL);
1090 assert_return(!m->sealed, -EPERM);
1091 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1093 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
1098 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1099 assert_return(m, -EINVAL);
1100 assert_return(!m->sealed, -EPERM);
1102 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
1107 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1108 assert_return(m, -EINVAL);
1109 assert_return(!m->sealed, -EPERM);
1111 SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
1116 static struct bus_container *message_get_container(sd_bus_message *m) {
1119 if (m->n_containers == 0)
1120 return &m->root_container;
1122 assert(m->containers);
1123 return m->containers + m->n_containers - 1;
1126 struct bus_body_part *message_append_part(sd_bus_message *m) {
1127 struct bus_body_part *part;
1134 if (m->n_body_parts <= 0) {
1138 assert(m->body_end);
1140 part = new0(struct bus_body_part, 1);
1146 m->body_end->next = part;
1156 static void part_zero(struct bus_body_part *part, size_t sz) {
1161 /* All other fields can be left in their defaults */
1162 assert(!part->data);
1163 assert(part->memfd < 0);
1166 part->is_zero = true;
1167 part->sealed = true;
1170 static int part_make_space(
1171 struct sd_bus_message *m,
1172 struct bus_body_part *part,
1180 assert(!part->sealed);
1185 if (part->allocated == 0 || sz > part->allocated) {
1186 size_t new_allocated;
1188 new_allocated = sz > 0 ? 2 * sz : 64;
1189 n = realloc(part->data, new_allocated);
1196 part->allocated = new_allocated;
1197 part->free_this = true;
1201 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1207 static int message_add_offset(sd_bus_message *m, size_t offset) {
1208 struct bus_container *c;
1211 assert(BUS_MESSAGE_IS_GVARIANT(m));
1213 /* Add offset to current container, unless this is the first
1214 * item in it, which will have the 0 offset, which we can
1216 c = message_get_container(m);
1218 if (!c->need_offsets)
1221 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1224 c->offsets[c->n_offsets++] = offset;
1228 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1229 struct bus_container *c;
1236 /* Update counters */
1237 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1240 *c->array_size += expand;
1244 static void *message_extend_body(
1249 bool force_inline) {
1251 size_t start_body, end_body, padding, added;
1262 start_body = ALIGN_TO((size_t) m->body_size, align);
1263 end_body = start_body + sz;
1265 padding = start_body - m->body_size;
1266 added = padding + sz;
1268 /* Check for 32bit overflows */
1269 if (end_body > (size_t) ((uint32_t) -1) ||
1270 end_body < start_body) {
1276 struct bus_body_part *part = NULL;
1280 m->n_body_parts <= 0 ||
1281 m->body_end->sealed ||
1282 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1283 (force_inline && m->body_end->size > MEMFD_MIN_SIZE);
1284 /* If this must be an inlined extension, let's create a new part if
1285 * the previous part is large enough to be inlined. */
1289 part = message_append_part(m);
1293 part_zero(part, padding);
1296 part = message_append_part(m);
1300 r = part_make_space(m, part, sz, &p);
1304 struct bus_container *c;
1306 size_t os, start_part, end_part;
1312 start_part = ALIGN_TO(part->size, align);
1313 end_part = start_part + sz;
1315 r = part_make_space(m, part, end_part, &p);
1320 memzero(p, padding);
1321 p = (uint8_t*) p + padding;
1324 /* Readjust pointers */
1325 for (c = m->containers; c < m->containers + m->n_containers; c++)
1326 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1328 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1331 /* Return something that is not NULL and is aligned */
1332 p = (uint8_t*) align;
1334 m->body_size = end_body;
1335 message_extend_containers(m, added);
1338 r = message_add_offset(m, end_body);
1348 static int message_push_fd(sd_bus_message *m, int fd) {
1359 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1363 f = reallocarray(m->fds, sizeof(int), m->n_fds + 1);
1371 m->fds[m->n_fds] = copy;
1377 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1378 _cleanup_close_ int fd = -1;
1379 struct bus_container *c;
1383 assert_return(m, -EINVAL);
1384 assert_return(!m->sealed, -EPERM);
1385 assert_return(bus_type_is_basic(type), -EINVAL);
1386 assert_return(!m->poisoned, -ESTALE);
1388 c = message_get_container(m);
1390 if (c->signature && c->signature[c->index]) {
1391 /* Container signature is already set */
1393 if (c->signature[c->index] != type)
1398 /* Maybe we can append to the signature? But only if this is the top-level container */
1399 if (c->enclosing != 0)
1402 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1409 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1415 case SD_BUS_TYPE_SIGNATURE:
1416 case SD_BUS_TYPE_STRING:
1420 case SD_BUS_TYPE_OBJECT_PATH:
1428 case SD_BUS_TYPE_BOOLEAN:
1430 u8 = p && *(int*) p;
1436 case SD_BUS_TYPE_UNIX_FD:
1441 fd = message_push_fd(m, *(int*) p);
1452 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1453 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1460 a = message_extend_body(m, align, sz, true, false);
1467 *stored = (const uint8_t*) a;
1474 case SD_BUS_TYPE_STRING:
1475 /* To make things easy we'll serialize a NULL string
1476 * into the empty string */
1480 case SD_BUS_TYPE_OBJECT_PATH:
1486 sz = 4 + strlen(p) + 1;
1489 case SD_BUS_TYPE_SIGNATURE:
1494 sz = 1 + strlen(p) + 1;
1497 case SD_BUS_TYPE_BOOLEAN:
1499 u32 = p && *(int*) p;
1505 case SD_BUS_TYPE_UNIX_FD:
1510 fd = message_push_fd(m, *(int*) p);
1521 align = bus_type_get_alignment(type);
1522 sz = bus_type_get_size(type);
1529 a = message_extend_body(m, align, sz, false, false);
1533 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
1534 *(uint32_t*) a = sz - 5;
1535 memcpy((uint8_t*) a + 4, p, sz - 4);
1538 *stored = (const uint8_t*) a + 4;
1540 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1541 *(uint8_t*) a = sz - 2;
1542 memcpy((uint8_t*) a + 1, p, sz - 1);
1545 *stored = (const uint8_t*) a + 1;
1554 if (type == SD_BUS_TYPE_UNIX_FD)
1557 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1564 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1565 return message_append_basic(m, type, p, NULL);
1568 _public_ int sd_bus_message_append_string_space(
1573 struct bus_container *c;
1576 assert_return(m, -EINVAL);
1577 assert_return(s, -EINVAL);
1578 assert_return(!m->sealed, -EPERM);
1579 assert_return(!m->poisoned, -ESTALE);
1581 c = message_get_container(m);
1583 if (c->signature && c->signature[c->index]) {
1584 /* Container signature is already set */
1586 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1591 /* Maybe we can append to the signature? But only if this is the top-level container */
1592 if (c->enclosing != 0)
1595 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1602 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1603 a = message_extend_body(m, 1, size + 1, true, false);
1609 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1613 *(uint32_t*) a = size;
1619 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1625 _public_ int sd_bus_message_append_string_iovec(
1627 const struct iovec *iov,
1628 unsigned n /* should be size_t, but is API now… 😞 */) {
1635 assert_return(m, -EINVAL);
1636 assert_return(!m->sealed, -EPERM);
1637 assert_return(iov || n == 0, -EINVAL);
1638 assert_return(!m->poisoned, -ESTALE);
1640 size = IOVEC_TOTAL_SIZE(iov, n);
1642 r = sd_bus_message_append_string_space(m, size, &p);
1646 for (i = 0; i < n; i++) {
1648 if (iov[i].iov_base)
1649 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1651 memset(p, ' ', iov[i].iov_len);
1653 p += iov[i].iov_len;
1659 static int bus_message_open_array(
1661 struct bus_container *c,
1662 const char *contents,
1663 uint32_t **array_size,
1665 bool *need_offsets) {
1675 assert(need_offsets);
1677 if (!signature_is_single(contents, true))
1680 if (c->signature && c->signature[c->index]) {
1682 /* Verify the existing signature */
1684 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1687 if (!startswith(c->signature + c->index + 1, contents))
1690 nindex = c->index + 1 + strlen(contents);
1694 if (c->enclosing != 0)
1697 /* Extend the existing signature */
1699 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1705 nindex = e - c->signature;
1708 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1709 alignment = bus_gvariant_get_alignment(contents);
1713 /* Add alignment padding and add to offset list */
1714 if (!message_extend_body(m, alignment, 0, false, false))
1717 r = bus_gvariant_is_fixed_size(contents);
1721 *begin = m->body_size;
1722 *need_offsets = r == 0;
1726 struct bus_body_part *o;
1728 alignment = bus_type_get_alignment(contents[0]);
1732 a = message_extend_body(m, 4, 4, false, false);
1737 op = m->body_end->data;
1738 os = m->body_end->size;
1740 /* Add alignment between size and first element */
1741 if (!message_extend_body(m, alignment, 0, false, false))
1744 /* location of array size might have changed so let's readjust a */
1745 if (o == m->body_end)
1746 a = adjust_pointer(a, op, os, m->body_end->data);
1752 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1758 static int bus_message_open_variant(
1760 struct bus_container *c,
1761 const char *contents) {
1767 if (!signature_is_single(contents, false))
1770 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1773 if (c->signature && c->signature[c->index]) {
1775 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1781 if (c->enclosing != 0)
1784 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1791 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1792 /* Variants are always aligned to 8 */
1794 if (!message_extend_body(m, 8, 0, false, false))
1801 l = strlen(contents);
1802 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1807 memcpy((uint8_t*) a + 1, contents, l + 1);
1810 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1816 static int bus_message_open_struct(
1818 struct bus_container *c,
1819 const char *contents,
1821 bool *need_offsets) {
1830 assert(need_offsets);
1832 if (!signature_is_valid(contents, false))
1835 if (c->signature && c->signature[c->index]) {
1838 l = strlen(contents);
1840 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1841 !startswith(c->signature + c->index + 1, contents) ||
1842 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1845 nindex = c->index + 1 + l + 1;
1849 if (c->enclosing != 0)
1852 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1858 nindex = e - c->signature;
1861 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1864 alignment = bus_gvariant_get_alignment(contents);
1868 if (!message_extend_body(m, alignment, 0, false, false))
1871 r = bus_gvariant_is_fixed_size(contents);
1875 *begin = m->body_size;
1876 *need_offsets = r == 0;
1878 /* Align contents to 8 byte boundary */
1879 if (!message_extend_body(m, 8, 0, false, false))
1883 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1889 static int bus_message_open_dict_entry(
1891 struct bus_container *c,
1892 const char *contents,
1894 bool *need_offsets) {
1902 assert(need_offsets);
1904 if (!signature_is_pair(contents))
1907 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1910 if (c->signature && c->signature[c->index]) {
1913 l = strlen(contents);
1915 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1916 !startswith(c->signature + c->index + 1, contents) ||
1917 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1922 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1925 alignment = bus_gvariant_get_alignment(contents);
1929 if (!message_extend_body(m, alignment, 0, false, false))
1932 r = bus_gvariant_is_fixed_size(contents);
1936 *begin = m->body_size;
1937 *need_offsets = r == 0;
1939 /* Align contents to 8 byte boundary */
1940 if (!message_extend_body(m, 8, 0, false, false))
1947 _public_ int sd_bus_message_open_container(
1950 const char *contents) {
1952 struct bus_container *c, *w;
1953 uint32_t *array_size = NULL;
1954 _cleanup_free_ char *signature = NULL;
1955 size_t before, begin = 0;
1956 bool need_offsets = false;
1959 assert_return(m, -EINVAL);
1960 assert_return(!m->sealed, -EPERM);
1961 assert_return(contents, -EINVAL);
1962 assert_return(!m->poisoned, -ESTALE);
1964 /* Make sure we have space for one more container */
1965 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1970 c = message_get_container(m);
1972 signature = strdup(contents);
1978 /* Save old index in the parent container, in case we have to
1979 * abort this container */
1980 c->saved_index = c->index;
1981 before = m->body_size;
1983 if (type == SD_BUS_TYPE_ARRAY)
1984 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1985 else if (type == SD_BUS_TYPE_VARIANT)
1986 r = bus_message_open_variant(m, c, contents);
1987 else if (type == SD_BUS_TYPE_STRUCT)
1988 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1989 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1990 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1996 /* OK, let's fill it in */
1997 w = m->containers + m->n_containers++;
1998 w->enclosing = type;
1999 w->signature = TAKE_PTR(signature);
2001 w->array_size = array_size;
2004 w->n_offsets = w->offsets_allocated = 0;
2006 w->need_offsets = need_offsets;
2011 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2016 if (!BUS_MESSAGE_IS_GVARIANT(m))
2019 if (c->need_offsets) {
2020 size_t payload, sz, i;
2023 /* Variable-width arrays */
2025 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2026 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2028 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2032 for (i = 0; i < c->n_offsets; i++)
2033 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2037 /* Fixed-width or empty arrays */
2039 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2047 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2053 assert(c->signature);
2055 if (!BUS_MESSAGE_IS_GVARIANT(m))
2058 l = strlen(c->signature);
2060 a = message_extend_body(m, 1, 1 + l, true, false);
2065 memcpy(a+1, c->signature, l);
2070 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2071 bool fixed_size = true;
2072 size_t n_variable = 0;
2081 if (!BUS_MESSAGE_IS_GVARIANT(m))
2084 p = strempty(c->signature);
2088 r = signature_element_length(p, &n);
2097 r = bus_gvariant_is_fixed_size(t);
2102 assert(!c->need_offsets || i <= c->n_offsets);
2104 /* We need to add an offset for each item that has a
2105 * variable size and that is not the last one in the
2109 if (r == 0 && p[n] != 0)
2116 assert(!c->need_offsets || i == c->n_offsets);
2117 assert(c->need_offsets || n_variable == 0);
2119 if (isempty(c->signature)) {
2120 /* The unary type is encoded as fixed 1 byte padding */
2121 a = message_extend_body(m, 1, 1, add_offset, false);
2126 } else if (n_variable <= 0) {
2129 /* Structures with fixed-size members only have to be
2130 * fixed-size themselves. But gvariant requires all fixed-size
2131 * elements to be sized a multiple of their alignment. Hence,
2132 * we must *always* add final padding after the last member so
2133 * the overall size of the structure is properly aligned. */
2135 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2137 assert(alignment > 0);
2139 a = message_extend_body(m, alignment, 0, add_offset, false);
2146 assert(c->offsets[c->n_offsets-1] == m->body_size);
2148 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2150 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2154 p = strempty(c->signature);
2155 for (i = 0, j = 0; i < c->n_offsets; i++) {
2159 r = signature_element_length(p, &n);
2170 r = bus_gvariant_is_fixed_size(t);
2173 if (r > 0 || p[0] == 0)
2177 k = n_variable - 1 - j;
2179 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2188 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2189 struct bus_container *c;
2192 assert_return(m, -EINVAL);
2193 assert_return(!m->sealed, -EPERM);
2194 assert_return(m->n_containers > 0, -EINVAL);
2195 assert_return(!m->poisoned, -ESTALE);
2197 c = message_get_container(m);
2199 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2200 if (c->signature && c->signature[c->index] != 0)
2205 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2206 r = bus_message_close_array(m, c);
2207 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2208 r = bus_message_close_variant(m, c);
2209 else if (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY))
2210 r = bus_message_close_struct(m, c, true);
2212 assert_not_reached("Unknown container type");
2226 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2233 stack[*i].types = types;
2234 stack[*i].n_struct = n_struct;
2235 stack[*i].n_array = n_array;
2241 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2252 *types = stack[*i].types;
2253 *n_struct = stack[*i].n_struct;
2254 *n_array = stack[*i].n_array;
2259 _public_ int sd_bus_message_appendv(
2264 unsigned n_array, n_struct;
2265 TypeStack stack[BUS_CONTAINER_DEPTH];
2266 unsigned stack_ptr = 0;
2269 assert_return(m, -EINVAL);
2270 assert_return(types, -EINVAL);
2271 assert_return(!m->sealed, -EPERM);
2272 assert_return(!m->poisoned, -ESTALE);
2274 n_array = (unsigned) -1;
2275 n_struct = strlen(types);
2280 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2281 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2287 r = sd_bus_message_close_container(m);
2295 if (n_array != (unsigned) -1)
2304 case SD_BUS_TYPE_BYTE: {
2307 x = (uint8_t) va_arg(ap, int);
2308 r = sd_bus_message_append_basic(m, *t, &x);
2312 case SD_BUS_TYPE_BOOLEAN:
2313 case SD_BUS_TYPE_INT32:
2314 case SD_BUS_TYPE_UINT32:
2315 case SD_BUS_TYPE_UNIX_FD: {
2318 /* We assume a boolean is the same as int32_t */
2319 assert_cc(sizeof(int32_t) == sizeof(int));
2321 x = va_arg(ap, uint32_t);
2322 r = sd_bus_message_append_basic(m, *t, &x);
2326 case SD_BUS_TYPE_INT16:
2327 case SD_BUS_TYPE_UINT16: {
2330 x = (uint16_t) va_arg(ap, int);
2331 r = sd_bus_message_append_basic(m, *t, &x);
2335 case SD_BUS_TYPE_INT64:
2336 case SD_BUS_TYPE_UINT64: {
2339 x = va_arg(ap, uint64_t);
2340 r = sd_bus_message_append_basic(m, *t, &x);
2344 case SD_BUS_TYPE_DOUBLE: {
2347 x = va_arg(ap, double);
2348 r = sd_bus_message_append_basic(m, *t, &x);
2352 case SD_BUS_TYPE_STRING:
2353 case SD_BUS_TYPE_OBJECT_PATH:
2354 case SD_BUS_TYPE_SIGNATURE: {
2357 x = va_arg(ap, const char*);
2358 r = sd_bus_message_append_basic(m, *t, x);
2362 case SD_BUS_TYPE_ARRAY: {
2365 r = signature_element_length(t + 1, &k);
2371 memcpy(s, t + 1, k);
2374 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2379 if (n_array == (unsigned) -1) {
2384 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2390 n_array = va_arg(ap, unsigned);
2395 case SD_BUS_TYPE_VARIANT: {
2398 s = va_arg(ap, const char*);
2402 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2406 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2411 n_struct = strlen(s);
2412 n_array = (unsigned) -1;
2417 case SD_BUS_TYPE_STRUCT_BEGIN:
2418 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2421 r = signature_element_length(t, &k);
2428 memcpy(s, t + 1, k - 2);
2431 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2436 if (n_array == (unsigned) -1) {
2441 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2447 n_array = (unsigned) -1;
2463 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2467 assert_return(m, -EINVAL);
2468 assert_return(types, -EINVAL);
2469 assert_return(!m->sealed, -EPERM);
2470 assert_return(!m->poisoned, -ESTALE);
2472 va_start(ap, types);
2473 r = sd_bus_message_appendv(m, types, ap);
2479 _public_ int sd_bus_message_append_array_space(
2489 assert_return(m, -EINVAL);
2490 assert_return(!m->sealed, -EPERM);
2491 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2492 assert_return(ptr || size == 0, -EINVAL);
2493 assert_return(!m->poisoned, -ESTALE);
2495 /* alignment and size of the trivial types (except bool) is
2496 * identical for gvariant and dbus1 marshalling */
2497 align = bus_type_get_alignment(type);
2498 sz = bus_type_get_size(type);
2500 assert_se(align > 0);
2506 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2510 a = message_extend_body(m, align, size, false, false);
2514 r = sd_bus_message_close_container(m);
2522 _public_ int sd_bus_message_append_array(
2530 assert_return(m, -EINVAL);
2531 assert_return(!m->sealed, -EPERM);
2532 assert_return(bus_type_is_trivial(type), -EINVAL);
2533 assert_return(ptr || size == 0, -EINVAL);
2534 assert_return(!m->poisoned, -ESTALE);
2536 r = sd_bus_message_append_array_space(m, type, size, &p);
2540 memcpy_safe(p, ptr, size);
2545 _public_ int sd_bus_message_append_array_iovec(
2548 const struct iovec *iov,
2549 unsigned n /* should be size_t, but is API now… 😞 */) {
2556 assert_return(m, -EINVAL);
2557 assert_return(!m->sealed, -EPERM);
2558 assert_return(bus_type_is_trivial(type), -EINVAL);
2559 assert_return(iov || n == 0, -EINVAL);
2560 assert_return(!m->poisoned, -ESTALE);
2562 size = IOVEC_TOTAL_SIZE(iov, n);
2564 r = sd_bus_message_append_array_space(m, type, size, &p);
2568 for (i = 0; i < n; i++) {
2570 if (iov[i].iov_base)
2571 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2573 memzero(p, iov[i].iov_len);
2575 p = (uint8_t*) p + iov[i].iov_len;
2581 _public_ int sd_bus_message_append_array_memfd(
2588 _cleanup_close_ int copy_fd = -1;
2589 struct bus_body_part *part;
2595 assert_return(m, -EINVAL);
2596 assert_return(memfd >= 0, -EBADF);
2597 assert_return(bus_type_is_trivial(type), -EINVAL);
2598 assert_return(size > 0, -EINVAL);
2599 assert_return(!m->sealed, -EPERM);
2600 assert_return(!m->poisoned, -ESTALE);
2602 r = memfd_set_sealed(memfd);
2606 copy_fd = fcntl(memfd, F_DUPFD_CLOEXEC, 3);
2610 r = memfd_get_size(memfd, &real_size);
2614 if (offset == 0 && size == (uint64_t) -1)
2616 else if (offset + size > real_size)
2619 align = bus_type_get_alignment(type);
2620 sz = bus_type_get_size(type);
2622 assert_se(align > 0);
2625 if (offset % align != 0)
2631 if (size > (uint64_t) (uint32_t) -1)
2634 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2638 a = message_extend_body(m, align, 0, false, false);
2642 part = message_append_part(m);
2646 part->memfd = copy_fd;
2647 part->memfd_offset = offset;
2648 part->sealed = true;
2652 m->body_size += size;
2653 message_extend_containers(m, size);
2655 return sd_bus_message_close_container(m);
2658 _public_ int sd_bus_message_append_string_memfd(
2664 _cleanup_close_ int copy_fd = -1;
2665 struct bus_body_part *part;
2666 struct bus_container *c;
2671 assert_return(m, -EINVAL);
2672 assert_return(memfd >= 0, -EBADF);
2673 assert_return(size > 0, -EINVAL);
2674 assert_return(!m->sealed, -EPERM);
2675 assert_return(!m->poisoned, -ESTALE);
2677 r = memfd_set_sealed(memfd);
2681 copy_fd = fcntl(memfd, FD_CLOEXEC, 3);
2685 r = memfd_get_size(memfd, &real_size);
2689 if (offset == 0 && size == (uint64_t) -1)
2691 else if (offset + size > real_size)
2694 /* We require this to be NUL terminated */
2698 if (size > (uint64_t) (uint32_t) -1)
2701 c = message_get_container(m);
2702 if (c->signature && c->signature[c->index]) {
2703 /* Container signature is already set */
2705 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2710 /* Maybe we can append to the signature? But only if this is the top-level container */
2711 if (c->enclosing != 0)
2714 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2721 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2722 a = message_extend_body(m, 4, 4, false, false);
2726 *(uint32_t*) a = size - 1;
2729 part = message_append_part(m);
2733 part->memfd = copy_fd;
2734 part->memfd_offset = offset;
2735 part->sealed = true;
2739 m->body_size += size;
2740 message_extend_containers(m, size);
2742 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2743 r = message_add_offset(m, m->body_size);
2750 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2756 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2760 assert_return(m, -EINVAL);
2761 assert_return(!m->sealed, -EPERM);
2762 assert_return(!m->poisoned, -ESTALE);
2764 r = sd_bus_message_open_container(m, 'a', "s");
2768 STRV_FOREACH(i, l) {
2769 r = sd_bus_message_append_basic(m, 's', *i);
2774 return sd_bus_message_close_container(m);
2777 static int bus_message_close_header(sd_bus_message *m) {
2781 /* The actual user data is finished now, we just complete the
2782 variant and struct now (at least on gvariant). Remember
2783 this position, so that during parsing we know where to
2784 put the outer container end. */
2785 m->user_body_size = m->body_size;
2787 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2788 const char *signature;
2792 /* Add offset table to end of fields array */
2793 if (m->n_header_offsets >= 1) {
2797 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2799 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2800 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2804 for (i = 0; i < m->n_header_offsets; i++)
2805 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2808 /* Add gvariant NUL byte plus signature to the end of
2809 * the body, followed by the final offset pointing to
2810 * the end of the fields array */
2812 signature = strempty(m->root_container.signature);
2813 l = strlen(signature);
2815 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2816 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2821 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2822 memcpy((uint8_t*) d + 2, signature, l);
2823 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2825 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2828 m->footer_accessible = 1 + l + 2 + sz;
2830 m->header->dbus1.fields_size = m->fields_size;
2831 m->header->dbus1.body_size = m->body_size;
2837 _public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t timeout_usec) {
2838 struct bus_body_part *part;
2843 assert_return(m, -EINVAL);
2848 if (m->n_containers > 0)
2854 if (cookie > 0xffffffffULL &&
2855 !BUS_MESSAGE_IS_GVARIANT(m))
2858 /* In vtables the return signature of method calls is listed,
2859 * let's check if they match if this is a response */
2860 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2861 m->enforced_reply_signature &&
2862 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2865 /* If gvariant marshalling is used we need to close the body structure */
2866 r = bus_message_close_struct(m, &m->root_container, false);
2870 /* If there's a non-trivial signature set, then add it in
2871 * here, but only on dbus1 */
2872 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2873 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2879 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2884 r = bus_message_close_header(m);
2888 if (BUS_MESSAGE_IS_GVARIANT(m))
2889 m->header->dbus2.cookie = cookie;
2891 m->header->dbus1.serial = (uint32_t) cookie;
2893 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout_usec;
2895 /* Add padding at the end of the fields part, since we know
2896 * the body needs to start at an 8 byte alignment. We made
2897 * sure we allocated enough space for this, so all we need to
2898 * do here is to zero it out. */
2899 a = ALIGN8(m->fields_size) - m->fields_size;
2901 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2903 /* If this is something we can send as memfd, then let's seal
2904 the memfd now. Note that we can send memfds as payload only
2905 for directed messages, and not for broadcasts. */
2906 if (m->destination && m->bus->use_memfd) {
2907 MESSAGE_FOREACH_PART(part, i, m)
2908 if (part->memfd >= 0 &&
2910 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2911 part != m->body_end) { /* The last part may never be sent as memfd */
2914 /* Try to seal it if that makes
2915 * sense. First, unmap our own map to
2916 * make sure we don't keep it busy. */
2917 bus_body_part_unmap(part);
2919 /* Then, sync up real memfd size */
2921 r = memfd_set_size(part->memfd, sz);
2925 /* Finally, try to seal */
2926 if (memfd_set_sealed(part->memfd) >= 0)
2927 part->sealed = true;
2931 m->root_container.end = m->user_body_size;
2932 m->root_container.index = 0;
2933 m->root_container.offset_index = 0;
2934 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2941 int bus_body_part_map(struct bus_body_part *part) {
2950 if (part->size <= 0)
2953 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2954 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2955 static const uint8_t zeroes[7] = { };
2956 part->data = (void*) zeroes;
2960 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
2961 psz = PAGE_ALIGN(part->size + shift);
2963 if (part->memfd >= 0)
2964 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
2965 else if (part->is_zero)
2966 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2970 if (p == MAP_FAILED)
2974 part->mmap_begin = p;
2975 part->data = (uint8_t*) p + shift;
2976 part->munmap_this = true;
2981 void bus_body_part_unmap(struct bus_body_part *part) {
2985 if (part->memfd < 0)
2988 if (!part->mmap_begin)
2991 if (!part->munmap_this)
2994 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
2996 part->mmap_begin = NULL;
2999 part->munmap_this = false;
3004 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3005 size_t k, start, end;
3010 start = ALIGN_TO((size_t) *rindex, align);
3011 end = start + nbytes;
3016 /* Verify that padding is 0 */
3017 for (k = *rindex; k < start; k++)
3018 if (((const uint8_t*) p)[k] != 0)
3022 *r = (uint8_t*) p + start;
3029 static bool message_end_of_signature(sd_bus_message *m) {
3030 struct bus_container *c;
3034 c = message_get_container(m);
3035 return !c->signature || c->signature[c->index] == 0;
3038 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3039 struct bus_container *c;
3043 c = message_get_container(m);
3044 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3047 if (BUS_MESSAGE_IS_GVARIANT(m))
3048 return index >= c->end;
3050 assert(c->array_size);
3051 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3055 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3056 assert_return(m, -EINVAL);
3057 assert_return(m->sealed, -EPERM);
3059 if (complete && m->n_containers > 0)
3062 if (message_end_of_signature(m))
3065 if (message_end_of_array(m, m->rindex))
3071 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3072 struct bus_body_part *part;
3078 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3079 part = m->cached_rindex_part;
3080 begin = m->cached_rindex_part_begin;
3090 if (index + sz <= begin + part->size) {
3092 r = bus_body_part_map(part);
3097 *p = (uint8_t*) part->data + index - begin;
3099 m->cached_rindex_part = part;
3100 m->cached_rindex_part_begin = begin;
3105 begin += part->size;
3112 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3119 if (!BUS_MESSAGE_IS_GVARIANT(m))
3122 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3125 sz = bus_gvariant_get_size(c->signature);
3129 if (c->offset_index+1 >= c->n_offsets)
3132 /* Variable-size array */
3134 alignment = bus_gvariant_get_alignment(c->signature);
3135 assert(alignment > 0);
3137 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3138 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3141 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3144 /* Fixed-size array */
3145 *rindex = c->begin + (c->offset_index+1) * sz;
3151 } else if (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
3156 if (c->offset_index+1 >= c->n_offsets)
3159 r = signature_element_length(c->signature + c->index, &n);
3163 r = signature_element_length(c->signature + c->index + n, &j);
3168 memcpy(t, c->signature + c->index + n, j);
3171 alignment = bus_gvariant_get_alignment(t);
3174 assert(alignment > 0);
3176 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3177 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3181 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3184 assert_not_reached("Unknown container type");
3189 /* Reached the end */
3195 static int message_peek_body(
3202 size_t k, start, end, padding;
3203 struct bus_body_part *part;
3210 start = ALIGN_TO((size_t) *rindex, align);
3211 padding = start - *rindex;
3212 end = start + nbytes;
3214 if (end > m->user_body_size)
3217 part = find_part(m, *rindex, padding, (void**) &q);
3222 /* Verify padding */
3223 for (k = 0; k < padding; k++)
3228 part = find_part(m, start, nbytes, (void**) &q);
3229 if (!part || (nbytes > 0 && !q))
3240 static bool validate_nul(const char *s, size_t l) {
3242 /* Check for NUL chars in the string */
3243 if (memchr(s, 0, l))
3246 /* Check for NUL termination */
3253 static bool validate_string(const char *s, size_t l) {
3255 if (!validate_nul(s, l))
3258 /* Check if valid UTF8 */
3259 if (!utf8_is_valid(s))
3265 static bool validate_signature(const char *s, size_t l) {
3267 if (!validate_nul(s, l))
3270 /* Check if valid signature */
3271 if (!signature_is_valid(s, true))
3277 static bool validate_object_path(const char *s, size_t l) {
3279 if (!validate_nul(s, l))
3282 if (!object_path_is_valid(s))
3288 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3289 struct bus_container *c;
3294 assert_return(m, -EINVAL);
3295 assert_return(m->sealed, -EPERM);
3296 assert_return(bus_type_is_basic(type), -EINVAL);
3298 if (message_end_of_signature(m))
3301 if (message_end_of_array(m, m->rindex))
3304 c = message_get_container(m);
3305 if (c->signature[c->index] != type)
3310 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3312 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3315 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3319 if (type == SD_BUS_TYPE_STRING)
3320 ok = validate_string(q, c->item_size-1);
3321 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3322 ok = validate_object_path(q, c->item_size-1);
3324 ok = validate_signature(q, c->item_size-1);
3330 *(const char**) p = q;
3334 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3336 if ((size_t) sz != c->item_size)
3339 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3342 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3348 case SD_BUS_TYPE_BYTE:
3350 *(uint8_t*) p = *(uint8_t*) q;
3353 case SD_BUS_TYPE_BOOLEAN:
3355 *(int*) p = !!*(uint8_t*) q;
3358 case SD_BUS_TYPE_INT16:
3359 case SD_BUS_TYPE_UINT16:
3361 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3364 case SD_BUS_TYPE_INT32:
3365 case SD_BUS_TYPE_UINT32:
3367 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3370 case SD_BUS_TYPE_INT64:
3371 case SD_BUS_TYPE_UINT64:
3372 case SD_BUS_TYPE_DOUBLE:
3374 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3377 case SD_BUS_TYPE_UNIX_FD: {
3380 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3385 *(int*) p = m->fds[j];
3391 assert_not_reached("unexpected type");
3395 r = container_next_item(m, c, &rindex);
3400 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3404 r = message_peek_body(m, &rindex, 4, 4, &q);
3408 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3409 r = message_peek_body(m, &rindex, 1, l+1, &q);
3413 if (type == SD_BUS_TYPE_OBJECT_PATH)
3414 ok = validate_object_path(q, l);
3416 ok = validate_string(q, l);
3421 *(const char**) p = q;
3423 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3426 r = message_peek_body(m, &rindex, 1, 1, &q);
3431 r = message_peek_body(m, &rindex, 1, l+1, &q);
3435 if (!validate_signature(q, l))
3439 *(const char**) p = q;
3444 align = bus_type_get_alignment(type);
3447 sz = bus_type_get_size(type);
3450 r = message_peek_body(m, &rindex, align, sz, &q);
3456 case SD_BUS_TYPE_BYTE:
3458 *(uint8_t*) p = *(uint8_t*) q;
3461 case SD_BUS_TYPE_BOOLEAN:
3463 *(int*) p = !!*(uint32_t*) q;
3466 case SD_BUS_TYPE_INT16:
3467 case SD_BUS_TYPE_UINT16:
3469 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3472 case SD_BUS_TYPE_INT32:
3473 case SD_BUS_TYPE_UINT32:
3475 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3478 case SD_BUS_TYPE_INT64:
3479 case SD_BUS_TYPE_UINT64:
3480 case SD_BUS_TYPE_DOUBLE:
3482 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3485 case SD_BUS_TYPE_UNIX_FD: {
3488 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3493 *(int*) p = m->fds[j];
3498 assert_not_reached("Unknown basic type...");
3505 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3511 static int bus_message_enter_array(
3513 struct bus_container *c,
3514 const char *contents,
3515 uint32_t **array_size,
3518 size_t *n_offsets) {
3532 if (!signature_is_single(contents, true))
3535 if (!c->signature || c->signature[c->index] == 0)
3538 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3541 if (!startswith(c->signature + c->index + 1, contents))
3546 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3549 r = message_peek_body(m, &rindex, 4, 4, &q);
3553 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3556 alignment = bus_type_get_alignment(contents[0]);
3560 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3564 *array_size = (uint32_t*) q;
3566 } else if (c->item_size <= 0) {
3568 /* gvariant: empty array */
3573 } else if (bus_gvariant_is_fixed_size(contents)) {
3575 /* gvariant: fixed length array */
3576 *item_size = bus_gvariant_get_size(contents);
3581 size_t where, p = 0, framing, sz;
3584 /* gvariant: variable length array */
3585 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3587 where = rindex + c->item_size - sz;
3588 r = message_peek_body(m, &where, 1, sz, &q);
3592 framing = bus_gvariant_read_word_le(q, sz);
3593 if (framing > c->item_size - sz)
3595 if ((c->item_size - framing) % sz != 0)
3598 *n_offsets = (c->item_size - framing) / sz;
3600 where = rindex + framing;
3601 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3605 *offsets = new(size_t, *n_offsets);
3609 for (i = 0; i < *n_offsets; i++) {
3612 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3613 if (x > c->item_size - sz)
3618 (*offsets)[i] = rindex + x;
3622 *item_size = (*offsets)[0] - rindex;
3627 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3628 c->index += 1 + strlen(contents);
3633 static int bus_message_enter_variant(
3635 struct bus_container *c,
3636 const char *contents,
3637 size_t *item_size) {
3649 if (!signature_is_single(contents, false))
3652 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3655 if (!c->signature || c->signature[c->index] == 0)
3658 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3663 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3666 k = strlen(contents);
3667 if (1+k > c->item_size)
3670 where = rindex + c->item_size - (1+k);
3671 r = message_peek_body(m, &where, 1, 1+k, &q);
3675 if (*(char*) q != 0)
3678 if (memcmp((uint8_t*) q+1, contents, k))
3681 *item_size = c->item_size - (1+k);
3684 r = message_peek_body(m, &rindex, 1, 1, &q);
3689 r = message_peek_body(m, &rindex, 1, l+1, &q);
3693 if (!validate_signature(q, l))
3696 if (!streq(q, contents))
3702 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3708 static int build_struct_offsets(
3710 const char *signature,
3714 size_t *n_offsets) {
3716 unsigned n_variable = 0, n_total = 0, v;
3717 size_t previous = 0, where;
3728 if (isempty(signature)) {
3729 /* Unary type is encoded as *fixed* 1 byte padding */
3730 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3734 if (*(uint8_t *) q != 0)
3743 sz = bus_gvariant_determine_word_size(size, 0);
3747 /* First, loop over signature and count variable elements and
3748 * elements in general. We use this to know how large the
3749 * offset array is at the end of the structure. Note that
3750 * GVariant only stores offsets for all variable size elements
3751 * that are not the last item. */
3757 r = signature_element_length(p, &n);
3766 r = bus_gvariant_is_fixed_size(t);
3771 if (r == 0 && p[n] != 0) /* except the last item */
3778 if (size < n_variable * sz)
3781 where = m->rindex + size - (n_variable * sz);
3782 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3788 *offsets = new(size_t, n_total);
3794 /* Second, loop again and build an offset table */
3800 r = signature_element_length(p, &n);
3809 k = bus_gvariant_get_size(t);
3817 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3820 if (m->rindex + x < previous)
3823 /* The last item's end
3824 * is determined from
3827 x = size - (n_variable * sz);
3829 offset = m->rindex + x;
3835 align = bus_gvariant_get_alignment(t);
3838 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3842 previous = (*offsets)[(*n_offsets)++] = offset;
3847 assert(*n_offsets == n_total);
3849 *item_size = (*offsets)[0] - m->rindex;
3853 static int enter_struct_or_dict_entry(
3855 struct bus_container *c,
3856 const char *contents,
3859 size_t *n_offsets) {
3870 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3873 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3878 /* gvariant with contents */
3879 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3884 static int bus_message_enter_struct(
3886 struct bus_container *c,
3887 const char *contents,
3890 size_t *n_offsets) {
3902 if (!signature_is_valid(contents, false))
3905 if (!c->signature || c->signature[c->index] == 0)
3908 l = strlen(contents);
3910 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3911 !startswith(c->signature + c->index + 1, contents) ||
3912 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3915 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3919 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3920 c->index += 1 + l + 1;
3925 static int bus_message_enter_dict_entry(
3927 struct bus_container *c,
3928 const char *contents,
3931 size_t *n_offsets) {
3940 if (!signature_is_pair(contents))
3943 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3946 if (!c->signature || c->signature[c->index] == 0)
3949 l = strlen(contents);
3951 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3952 !startswith(c->signature + c->index + 1, contents) ||
3953 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3956 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3960 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3961 c->index += 1 + l + 1;
3966 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3968 const char *contents) {
3969 struct bus_container *c, *w;
3970 uint32_t *array_size = NULL;
3971 _cleanup_free_ char *signature = NULL;
3973 _cleanup_free_ size_t *offsets = NULL;
3974 size_t n_offsets = 0, item_size = 0;
3977 assert_return(m, -EINVAL);
3978 assert_return(m->sealed, -EPERM);
3979 assert_return(type != 0 || !contents, -EINVAL);
3981 if (type == 0 || !contents) {
3985 /* Allow entering into anonymous containers */
3986 r = sd_bus_message_peek_type(m, &tt, &cc);
3990 if (type != 0 && type != tt)
3993 if (contents && !streq(contents, cc))
4001 * We enforce a global limit on container depth, that is much
4002 * higher than the 32 structs and 32 arrays the specification
4003 * mandates. This is simpler to implement for us, and we need
4004 * this only to ensure our container array doesn't grow
4005 * without bounds. We are happy to return any data from a
4006 * message as long as the data itself is valid, even if the
4007 * overall message might be not.
4009 * Note that the message signature is validated when
4010 * parsing the headers, and that validation does check the
4013 * Note that the specification defines no limits on the depth
4014 * of stacked variants, but we do.
4016 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4019 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4022 if (message_end_of_signature(m))
4025 if (message_end_of_array(m, m->rindex))
4028 c = message_get_container(m);
4030 signature = strdup(contents);
4034 c->saved_index = c->index;
4037 if (type == SD_BUS_TYPE_ARRAY)
4038 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4039 else if (type == SD_BUS_TYPE_VARIANT)
4040 r = bus_message_enter_variant(m, c, contents, &item_size);
4041 else if (type == SD_BUS_TYPE_STRUCT)
4042 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4043 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4044 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4050 /* OK, let's fill it in */
4051 w = m->containers + m->n_containers++;
4052 w->enclosing = type;
4053 w->signature = TAKE_PTR(signature);
4054 w->peeked_signature = NULL;
4058 w->begin = m->rindex;
4060 /* Unary type has fixed size of 1, but virtual size of 0 */
4061 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4062 type == SD_BUS_TYPE_STRUCT &&
4064 w->end = m->rindex + 0;
4066 w->end = m->rindex + c->item_size;
4068 w->array_size = array_size;
4069 w->item_size = item_size;
4070 w->offsets = TAKE_PTR(offsets);
4071 w->n_offsets = n_offsets;
4072 w->offset_index = 0;
4077 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4078 struct bus_container *c;
4082 assert_return(m, -EINVAL);
4083 assert_return(m->sealed, -EPERM);
4084 assert_return(m->n_containers > 0, -ENXIO);
4086 c = message_get_container(m);
4088 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4089 if (c->signature && c->signature[c->index] != 0)
4093 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4094 if (m->rindex < c->end)
4097 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4100 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4101 if (c->begin + l != m->rindex)
4106 free(c->peeked_signature);
4110 c = message_get_container(m);
4113 c->index = c->saved_index;
4114 r = container_next_item(m, c, &m->rindex);
4122 static void message_quit_container(sd_bus_message *m) {
4123 struct bus_container *c;
4127 assert(m->n_containers > 0);
4129 c = message_get_container(m);
4132 assert(m->rindex >= c->before);
4133 m->rindex = c->before;
4135 /* Free container */
4140 /* Correct index of new top-level container */
4141 c = message_get_container(m);
4142 c->index = c->saved_index;
4145 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4146 struct bus_container *c;
4149 assert_return(m, -EINVAL);
4150 assert_return(m->sealed, -EPERM);
4152 if (message_end_of_signature(m))
4155 if (message_end_of_array(m, m->rindex))
4158 c = message_get_container(m);
4160 if (bus_type_is_basic(c->signature[c->index])) {
4164 *type = c->signature[c->index];
4168 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4174 r = signature_element_length(c->signature+c->index+1, &l);
4180 sig = strndup(c->signature + c->index + 1, l);
4184 free(c->peeked_signature);
4185 *contents = c->peeked_signature = sig;
4189 *type = SD_BUS_TYPE_ARRAY;
4194 if (IN_SET(c->signature[c->index], SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN)) {
4200 r = signature_element_length(c->signature+c->index, &l);
4205 sig = strndup(c->signature + c->index + 1, l - 2);
4209 free(c->peeked_signature);
4210 *contents = c->peeked_signature = sig;
4214 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4219 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4223 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4226 if (c->item_size < 2)
4229 /* Look for the NUL delimiter that
4230 separates the payload from the
4231 signature. Since the body might be
4232 in a different part that then the
4233 signature we map byte by byte. */
4235 for (k = 2; k <= c->item_size; k++) {
4238 where = m->rindex + c->item_size - k;
4239 r = message_peek_body(m, &where, 1, k, &q);
4243 if (*(char*) q == 0)
4247 if (k > c->item_size)
4250 free(c->peeked_signature);
4251 c->peeked_signature = strndup((char*) q + 1, k - 1);
4252 if (!c->peeked_signature)
4255 if (!signature_is_valid(c->peeked_signature, true))
4258 *contents = c->peeked_signature;
4263 r = message_peek_body(m, &rindex, 1, 1, &q);
4268 r = message_peek_body(m, &rindex, 1, l+1, &q);
4272 if (!validate_signature(q, l))
4280 *type = SD_BUS_TYPE_VARIANT;
4295 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4296 struct bus_container *c;
4298 assert_return(m, -EINVAL);
4299 assert_return(m->sealed, -EPERM);
4302 message_reset_containers(m);
4305 c = message_get_container(m);
4307 c = message_get_container(m);
4309 c->offset_index = 0;
4311 m->rindex = c->begin;
4314 c->offset_index = 0;
4315 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4317 return !isempty(c->signature);
4320 static int message_read_ap(
4325 unsigned n_array, n_struct;
4326 TypeStack stack[BUS_CONTAINER_DEPTH];
4327 unsigned stack_ptr = 0;
4328 unsigned n_loop = 0;
4336 /* Ideally, we'd just call ourselves recursively on every
4337 * complex type. However, the state of a va_list that is
4338 * passed to a function is undefined after that function
4339 * returns. This means we need to decode the va_list linearly
4340 * in a single stackframe. We hence implement our own
4341 * home-grown stack in an array. */
4343 n_array = (unsigned) -1; /* length of current array entries */
4344 n_struct = strlen(types); /* length of current struct contents signature */
4351 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4352 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4358 r = sd_bus_message_exit_container(m);
4366 if (n_array != (unsigned) -1)
4375 case SD_BUS_TYPE_BYTE:
4376 case SD_BUS_TYPE_BOOLEAN:
4377 case SD_BUS_TYPE_INT16:
4378 case SD_BUS_TYPE_UINT16:
4379 case SD_BUS_TYPE_INT32:
4380 case SD_BUS_TYPE_UINT32:
4381 case SD_BUS_TYPE_INT64:
4382 case SD_BUS_TYPE_UINT64:
4383 case SD_BUS_TYPE_DOUBLE:
4384 case SD_BUS_TYPE_STRING:
4385 case SD_BUS_TYPE_OBJECT_PATH:
4386 case SD_BUS_TYPE_SIGNATURE:
4387 case SD_BUS_TYPE_UNIX_FD: {
4390 p = va_arg(ap, void*);
4391 r = sd_bus_message_read_basic(m, *t, p);
4404 case SD_BUS_TYPE_ARRAY: {
4407 r = signature_element_length(t + 1, &k);
4413 memcpy(s, t + 1, k);
4416 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4427 if (n_array == (unsigned) -1) {
4432 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4438 n_array = va_arg(ap, unsigned);
4443 case SD_BUS_TYPE_VARIANT: {
4446 s = va_arg(ap, const char *);
4450 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4460 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4465 n_struct = strlen(s);
4466 n_array = (unsigned) -1;
4471 case SD_BUS_TYPE_STRUCT_BEGIN:
4472 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4475 r = signature_element_length(t, &k);
4481 memcpy(s, t + 1, k - 2);
4484 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4494 if (n_array == (unsigned) -1) {
4499 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4505 n_array = (unsigned) -1;
4518 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4522 assert_return(m, -EINVAL);
4523 assert_return(m->sealed, -EPERM);
4524 assert_return(types, -EINVAL);
4526 va_start(ap, types);
4527 r = message_read_ap(m, types, ap);
4533 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4536 assert_return(m, -EINVAL);
4537 assert_return(m->sealed, -EPERM);
4539 /* If types is NULL, read exactly one element */
4541 struct bus_container *c;
4544 if (message_end_of_signature(m))
4547 if (message_end_of_array(m, m->rindex))
4550 c = message_get_container(m);
4552 r = signature_element_length(c->signature + c->index, &l);
4556 types = strndupa(c->signature + c->index, l);
4561 case 0: /* Nothing to drop */
4564 case SD_BUS_TYPE_BYTE:
4565 case SD_BUS_TYPE_BOOLEAN:
4566 case SD_BUS_TYPE_INT16:
4567 case SD_BUS_TYPE_UINT16:
4568 case SD_BUS_TYPE_INT32:
4569 case SD_BUS_TYPE_UINT32:
4570 case SD_BUS_TYPE_INT64:
4571 case SD_BUS_TYPE_UINT64:
4572 case SD_BUS_TYPE_DOUBLE:
4573 case SD_BUS_TYPE_STRING:
4574 case SD_BUS_TYPE_OBJECT_PATH:
4575 case SD_BUS_TYPE_SIGNATURE:
4576 case SD_BUS_TYPE_UNIX_FD:
4578 r = sd_bus_message_read_basic(m, *types, NULL);
4582 r = sd_bus_message_skip(m, types + 1);
4588 case SD_BUS_TYPE_ARRAY: {
4591 r = signature_element_length(types + 1, &k);
4597 memcpy(s, types+1, k);
4600 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4605 r = sd_bus_message_skip(m, s);
4612 r = sd_bus_message_exit_container(m);
4617 r = sd_bus_message_skip(m, types + 1 + k);
4624 case SD_BUS_TYPE_VARIANT: {
4625 const char *contents;
4628 r = sd_bus_message_peek_type(m, &x, &contents);
4632 if (x != SD_BUS_TYPE_VARIANT)
4635 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4639 r = sd_bus_message_skip(m, contents);
4644 r = sd_bus_message_exit_container(m);
4648 r = sd_bus_message_skip(m, types + 1);
4655 case SD_BUS_TYPE_STRUCT_BEGIN:
4656 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4659 r = signature_element_length(types, &k);
4665 memcpy(s, types+1, k-2);
4668 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4672 r = sd_bus_message_skip(m, s);
4676 r = sd_bus_message_exit_container(m);
4681 r = sd_bus_message_skip(m, types + k);
4693 _public_ int sd_bus_message_read_array(
4699 struct bus_container *c;
4705 assert_return(m, -EINVAL);
4706 assert_return(m->sealed, -EPERM);
4707 assert_return(bus_type_is_trivial(type), -EINVAL);
4708 assert_return(ptr, -EINVAL);
4709 assert_return(size, -EINVAL);
4710 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4712 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4716 c = message_get_container(m);
4718 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4719 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4723 sz = c->end - c->begin;
4725 align = bus_type_get_alignment(type);
4729 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4733 /* Zero length array, let's return some aligned
4734 * pointer that is not NULL */
4735 p = (uint8_t*) align;
4737 r = message_peek_body(m, &m->rindex, align, sz, &p);
4742 r = sd_bus_message_exit_container(m);
4746 *ptr = (const void*) p;
4752 message_quit_container(m);
4756 static int message_peek_fields(
4767 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4770 static int message_peek_field_uint32(
4782 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4785 /* identical for gvariant and dbus1 */
4787 r = message_peek_fields(m, ri, 4, 4, &q);
4792 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4797 static int message_peek_field_uint64(
4809 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4812 /* identical for gvariant and dbus1 */
4814 r = message_peek_fields(m, ri, 8, 8, &q);
4819 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4824 static int message_peek_field_string(
4826 bool (*validate)(const char *p),
4838 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4843 r = message_peek_fields(m, ri, 1, item_size, &q);
4849 r = message_peek_field_uint32(m, ri, 4, &l);
4853 r = message_peek_fields(m, ri, 1, l+1, &q);
4859 if (!validate_nul(q, l))
4865 if (!validate_string(q, l))
4875 static int message_peek_field_signature(
4888 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4893 r = message_peek_fields(m, ri, 1, item_size, &q);
4899 r = message_peek_fields(m, ri, 1, 1, &q);
4904 r = message_peek_fields(m, ri, 1, l+1, &q);
4909 if (!validate_signature(q, l))
4918 static int message_skip_fields(
4921 uint32_t array_size,
4922 const char **signature) {
4924 size_t original_index;
4930 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4932 original_index = *ri;
4938 if (array_size != (uint32_t) -1 &&
4939 array_size <= *ri - original_index)
4946 if (t == SD_BUS_TYPE_STRING) {
4948 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4954 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4956 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4962 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4964 r = message_peek_field_signature(m, ri, 0, NULL);
4970 } else if (bus_type_is_basic(t)) {
4973 align = bus_type_get_alignment(t);
4974 k = bus_type_get_size(t);
4975 assert(align > 0 && k > 0);
4977 r = message_peek_fields(m, ri, align, k, NULL);
4983 } else if (t == SD_BUS_TYPE_ARRAY) {
4985 r = signature_element_length(*signature+1, &l);
4995 strncpy(sig, *signature + 1, l-1);
4998 alignment = bus_type_get_alignment(sig[0]);
5002 r = message_peek_field_uint32(m, ri, 0, &nas);
5005 if (nas > BUS_ARRAY_MAX_SIZE)
5008 r = message_peek_fields(m, ri, alignment, 0, NULL);
5012 r = message_skip_fields(m, ri, nas, (const char**) &s);
5017 (*signature) += 1 + l;
5019 } else if (t == SD_BUS_TYPE_VARIANT) {
5022 r = message_peek_field_signature(m, ri, 0, &s);
5026 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5032 } else if (IN_SET(t, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
5034 r = signature_element_length(*signature, &l);
5041 strncpy(sig, *signature + 1, l-1);
5044 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5055 int bus_message_parse_fields(sd_bus_message *m) {
5058 uint32_t unix_fds = 0;
5059 bool unix_fds_set = false;
5060 void *offsets = NULL;
5061 unsigned n_offsets = 0;
5067 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5070 /* Read the signature from the end of the body variant first */
5071 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5072 if (m->footer_accessible < 1 + sz)
5075 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5077 if (p < (char*) m->footer)
5084 /* We found the beginning of the signature
5085 * string, yay! We require the body to be a
5086 * structure, so verify it and then strip the
5087 * opening/closing brackets. */
5089 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5091 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5092 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5095 c = strndup(p + 1 + 1, l - 2);
5099 free(m->root_container.signature);
5100 m->root_container.signature = c;
5107 /* Calculate the actual user body size, by removing
5108 * the trailing variant signature and struct offset
5110 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5112 /* Pull out the offset table for the fields array */
5113 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5118 ri = m->fields_size - sz;
5119 r = message_peek_fields(m, &ri, 1, sz, &q);
5123 framing = bus_gvariant_read_word_le(q, sz);
5124 if (framing >= m->fields_size - sz)
5126 if ((m->fields_size - framing) % sz != 0)
5130 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5134 n_offsets = (m->fields_size - framing) / sz;
5137 m->user_body_size = m->body_size;
5140 while (ri < m->fields_size) {
5141 _cleanup_free_ char *sig = NULL;
5142 const char *signature;
5143 uint64_t field_type;
5144 size_t item_size = (size_t) -1;
5146 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5155 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5157 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5161 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5165 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5172 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5177 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5182 where = ri = ALIGN_TO(ri, 8);
5183 item_size = end - ri;
5184 r = message_peek_fields(m, &where, 1, item_size, &q);
5188 b = memrchr(q, 0, item_size);
5192 sig = strndup(b+1, item_size - (b+1-(char*) q));
5197 item_size = b - (char*) q;
5199 r = message_peek_field_signature(m, &ri, 0, &signature);
5204 switch (field_type) {
5206 case _BUS_MESSAGE_HEADER_INVALID:
5209 case BUS_MESSAGE_HEADER_PATH:
5214 if (!streq(signature, "o"))
5217 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5220 case BUS_MESSAGE_HEADER_INTERFACE:
5225 if (!streq(signature, "s"))
5228 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5231 case BUS_MESSAGE_HEADER_MEMBER:
5236 if (!streq(signature, "s"))
5239 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5242 case BUS_MESSAGE_HEADER_ERROR_NAME:
5247 if (!streq(signature, "s"))
5250 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5252 m->error._need_free = -1;
5256 case BUS_MESSAGE_HEADER_DESTINATION:
5261 if (!streq(signature, "s"))
5264 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5267 case BUS_MESSAGE_HEADER_SENDER:
5272 if (!streq(signature, "s"))
5275 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5277 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client) {
5278 m->creds.unique_name = (char*) m->sender;
5279 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5284 case BUS_MESSAGE_HEADER_SIGNATURE: {
5288 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5291 if (m->root_container.signature)
5294 if (!streq(signature, "g"))
5297 r = message_peek_field_signature(m, &ri, item_size, &s);
5305 free_and_replace(m->root_container.signature, c);
5309 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5311 if (m->reply_cookie != 0)
5314 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5315 /* 64bit on dbus2 */
5317 if (!streq(signature, "t"))
5320 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5324 /* 32bit on dbus1 */
5327 if (!streq(signature, "u"))
5330 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5334 m->reply_cookie = serial;
5337 if (m->reply_cookie == 0)
5342 case BUS_MESSAGE_HEADER_UNIX_FDS:
5346 if (!streq(signature, "u"))
5349 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5353 unix_fds_set = true;
5357 if (!BUS_MESSAGE_IS_GVARIANT(m))
5358 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5367 if (m->n_fds != unix_fds)
5370 switch (m->header->type) {
5372 case SD_BUS_MESSAGE_SIGNAL:
5373 if (!m->path || !m->interface || !m->member)
5376 if (m->reply_cookie != 0)
5381 case SD_BUS_MESSAGE_METHOD_CALL:
5383 if (!m->path || !m->member)
5386 if (m->reply_cookie != 0)
5391 case SD_BUS_MESSAGE_METHOD_RETURN:
5393 if (m->reply_cookie == 0)
5397 case SD_BUS_MESSAGE_METHOD_ERROR:
5399 if (m->reply_cookie == 0 || !m->error.name)
5404 /* Refuse non-local messages that claim they are local */
5405 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5407 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5409 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5412 m->root_container.end = m->user_body_size;
5414 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5415 r = build_struct_offsets(
5417 m->root_container.signature,
5419 &m->root_container.item_size,
5420 &m->root_container.offsets,
5421 &m->root_container.n_offsets);
5426 /* Try to read the error message, but if we can't it's a non-issue */
5427 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5428 (void) sd_bus_message_read(m, "s", &m->error.message);
5433 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5434 assert_return(m, -EINVAL);
5435 assert_return(destination, -EINVAL);
5436 assert_return(!m->sealed, -EPERM);
5437 assert_return(!m->destination, -EEXIST);
5439 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5442 _public_ int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) {
5443 assert_return(m, -EINVAL);
5444 assert_return(sender, -EINVAL);
5445 assert_return(!m->sealed, -EPERM);
5446 assert_return(!m->sender, -EEXIST);
5448 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5451 #if 0 /// UNNEEDED by elogind
5452 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5456 struct bus_body_part *part;
5462 total = BUS_MESSAGE_SIZE(m);
5468 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5469 MESSAGE_FOREACH_PART(part, i, m)
5470 e = mempcpy(e, part->data, part->size);
5472 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5481 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5488 r = sd_bus_message_enter_container(m, 'a', "s");
5492 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5493 r = strv_extend(l, s);
5500 r = sd_bus_message_exit_container(m);
5507 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5508 _cleanup_strv_free_ char **strv = NULL;
5511 assert_return(m, -EINVAL);
5512 assert_return(m->sealed, -EPERM);
5513 assert_return(l, -EINVAL);
5515 r = bus_message_read_strv_extend(m, &strv);
5519 *l = TAKE_PTR(strv);
5523 static int bus_message_get_arg_skip(
5527 const char **_contents) {
5532 r = sd_bus_message_rewind(m, true);
5537 const char *contents;
5540 r = sd_bus_message_peek_type(m, &type, &contents);
5546 /* Don't match against arguments after the first one we don't understand */
5547 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5548 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5553 *_contents = contents;
5559 r = sd_bus_message_skip(m, NULL);
5566 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5573 r = bus_message_get_arg_skip(m, i, &type, NULL);
5577 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5580 return sd_bus_message_read_basic(m, type, str);
5583 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5584 const char *contents;
5591 r = bus_message_get_arg_skip(m, i, &type, &contents);
5595 if (type != SD_BUS_TYPE_ARRAY)
5597 if (!STR_IN_SET(contents, "s", "o", "g"))
5600 return sd_bus_message_read_strv(m, strv);
5603 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5604 assert_return(m, EINVAL);
5606 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5609 return sd_bus_error_get_errno(&m->error);
5612 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5613 struct bus_container *c;
5615 assert_return(m, NULL);
5617 c = complete ? &m->root_container : message_get_container(m);
5618 return strempty(c->signature);
5621 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5622 assert_return(m, -EINVAL);
5624 return isempty(m->root_container.signature);
5627 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5628 assert_return(m, -EINVAL);
5630 return streq(strempty(m->root_container.signature), strempty(signature));
5633 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5634 bool done_something = false;
5637 assert_return(m, -EINVAL);
5638 assert_return(source, -EINVAL);
5639 assert_return(!m->sealed, -EPERM);
5640 assert_return(source->sealed, -EPERM);
5643 const char *contents;
5658 r = sd_bus_message_peek_type(source, &type, &contents);
5664 done_something = true;
5666 if (bus_type_is_container(type) > 0) {
5668 r = sd_bus_message_enter_container(source, type, contents);
5672 r = sd_bus_message_open_container(m, type, contents);
5676 r = sd_bus_message_copy(m, source, true);
5680 r = sd_bus_message_close_container(m);
5684 r = sd_bus_message_exit_container(source);
5691 r = sd_bus_message_read_basic(source, type, &basic);
5697 if (IN_SET(type, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_STRING))
5698 r = sd_bus_message_append_basic(m, type, basic.string);
5700 r = sd_bus_message_append_basic(m, type, &basic);
5707 return done_something;
5710 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5715 assert_return(m, -EINVAL);
5716 assert_return(m->sealed, -EPERM);
5717 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5718 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5719 assert_return(type || contents, -EINVAL);
5720 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5722 r = sd_bus_message_peek_type(m, &t, &c);
5726 if (type != 0 && type != t)
5729 if (contents && !streq_ptr(contents, c))
5735 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5736 assert_return(m, NULL);
5741 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5742 _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5750 switch ((*m)->header->type) {
5752 case SD_BUS_MESSAGE_SIGNAL:
5753 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5759 case SD_BUS_MESSAGE_METHOD_CALL:
5760 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5766 case SD_BUS_MESSAGE_METHOD_RETURN:
5767 case SD_BUS_MESSAGE_METHOD_ERROR:
5769 r = sd_bus_message_new(bus, &n, (*m)->header->type);
5775 n->reply_cookie = (*m)->reply_cookie;
5777 r = message_append_reply_cookie(n, n->reply_cookie);
5781 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5782 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5786 n->error._need_free = -1;
5795 if ((*m)->destination && !n->destination) {
5796 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5801 if ((*m)->sender && !n->sender) {
5802 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5807 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5809 r = sd_bus_message_copy(n, *m, true);
5813 timeout = (*m)->timeout;
5814 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5815 timeout = BUS_DEFAULT_TIMEOUT;
5817 r = sd_bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5821 sd_bus_message_unref(*m);
5827 #if 0 /// UNNEEDED by elogind
5828 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5832 assert_return(!m->sealed, -EPERM);
5833 assert_return(!m->sender, -EPERM);
5835 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5839 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5840 assert_return(m, -EINVAL);
5841 assert_return(priority, -EINVAL);
5843 *priority = m->priority;
5847 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5848 assert_return(m, -EINVAL);
5849 assert_return(!m->sealed, -EPERM);
5851 m->priority = priority;