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 void 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 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
129 size_t old_size, new_size, start;
136 old_size = sizeof(struct bus_header) + m->fields_size;
137 start = ALIGN_TO(old_size, align);
138 new_size = start + sz;
140 if (new_size < start ||
141 new_size > (size_t) ((uint32_t) -1))
144 if (old_size == new_size)
145 return (uint8_t*) m->header + old_size;
147 if (m->free_header) {
148 np = realloc(m->header, ALIGN8(new_size));
152 /* Initially, the header is allocated as part of
153 * the sd_bus_message itself, let's replace it by
156 np = malloc(ALIGN8(new_size));
160 memcpy(np, m->header, sizeof(struct bus_header));
163 /* Zero out padding */
164 if (start > old_size)
165 memzero((uint8_t*) np + old_size, start - old_size);
169 m->fields_size = new_size - sizeof(struct bus_header);
171 /* Adjust quick access pointers */
172 m->path = adjust_pointer(m->path, op, old_size, m->header);
173 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
174 m->member = adjust_pointer(m->member, op, old_size, m->header);
175 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
176 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
177 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
179 m->free_header = true;
182 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
185 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
188 return (uint8_t*) np + start;
195 static int message_append_field_string(
207 /* dbus1 only allows 8bit header field ids */
211 /* dbus1 doesn't allow strings over 32bit, let's enforce this
212 * globally, to not risk convertability */
214 if (l > (size_t) (uint32_t) -1)
217 /* Signature "(yv)" where the variant contains "s" */
219 if (BUS_MESSAGE_IS_GVARIANT(m)) {
221 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
222 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
226 *((uint64_t*) p) = h;
233 *ret = (char*) p + 8;
236 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
237 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
246 ((uint32_t*) p)[1] = l;
247 memcpy(p + 8, s, l + 1);
250 *ret = (char*) p + 8;
256 static int message_append_field_signature(
267 /* dbus1 only allows 8bit header field ids */
271 /* dbus1 doesn't allow signatures over 8bit, let's enforce
272 * this globally, to not risk convertability */
277 /* Signature "(yv)" where the variant contains "g" */
279 if (BUS_MESSAGE_IS_GVARIANT(m))
280 /* For gvariant the serialization is the same as for normal strings */
281 return message_append_field_string(m, h, 'g', s, ret);
283 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
284 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
290 p[2] = SD_BUS_TYPE_SIGNATURE;
293 memcpy(p + 5, s, l + 1);
296 *ret = (const char*) p + 5;
302 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
307 /* dbus1 only allows 8bit header field ids */
311 if (BUS_MESSAGE_IS_GVARIANT(m)) {
312 /* (field id 64bit + ((value + NUL + signature string 'u') */
314 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
318 *((uint64_t*) p) = h;
319 *((uint32_t*) (p + 8)) = x;
323 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
324 p = message_extend_fields(m, 8, 4 + 4, false);
333 ((uint32_t*) p)[1] = x;
339 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
344 /* dbus1 only allows 8bit header field ids */
348 if (BUS_MESSAGE_IS_GVARIANT(m)) {
349 /* (field id 64bit + ((value + NUL + signature string 't') */
351 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
355 *((uint64_t*) p) = h;
356 *((uint64_t*) (p + 8)) = x;
360 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
361 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
374 ((uint64_t*) p)[1] = x;
380 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
383 if (BUS_MESSAGE_IS_GVARIANT(m))
384 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
386 /* 64bit cookies are not supported on dbus1 */
387 if (cookie > 0xffffffffUL)
390 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
394 int bus_message_from_header(
397 size_t header_accessible,
399 size_t footer_accessible,
405 sd_bus_message **ret) {
407 _cleanup_free_ sd_bus_message *m = NULL;
408 struct bus_header *h;
412 assert(header || header_accessible <= 0);
413 assert(footer || footer_accessible <= 0);
414 assert(fds || n_fds <= 0);
417 if (header_accessible < sizeof(struct bus_header))
420 if (header_accessible > message_size)
422 if (footer_accessible > message_size)
426 if (!IN_SET(h->version, 1, 2))
429 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
432 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
435 /* Note that we are happy with unknown flags in the flags header! */
437 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
440 label_sz = strlen(label);
451 m->header_accessible = header_accessible;
453 m->footer_accessible = footer_accessible;
455 if (BUS_MESSAGE_IS_GVARIANT(m)) {
458 if (h->dbus2.cookie == 0)
461 /* dbus2 derives the sizes from the message size and
462 the offset table at the end, since it is formatted as
463 gvariant "yyyyuta{tv}v". Since the message itself is a
464 structure with precisely to variable sized entries,
465 there's only one offset in the table, which marks the
466 end of the fields array. */
468 ws = bus_gvariant_determine_word_size(message_size, 0);
469 if (footer_accessible < ws)
472 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
473 if (ALIGN8(m->fields_size) > message_size - ws)
475 if (m->fields_size < sizeof(struct bus_header))
478 m->fields_size -= sizeof(struct bus_header);
479 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
481 if (h->dbus1.serial == 0)
484 /* dbus1 has the sizes in the header */
485 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
486 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
488 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
496 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
497 memcpy(m->creds.label, label, label_sz + 1);
499 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
502 m->bus = sd_bus_ref(bus);
508 int bus_message_from_malloc(
515 sd_bus_message **ret) {
521 r = bus_message_from_header(
523 buffer, length, /* in this case the initial bytes and the final bytes are the same */
532 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
535 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
537 m->body.sealed = true;
542 m->iovec = m->iovec_fixed;
543 m->iovec[0].iov_base = buffer;
544 m->iovec[0].iov_len = length;
546 r = bus_message_parse_fields(m);
550 /* We take possession of the memory and fds now */
551 m->free_header = true;
562 _public_ int sd_bus_message_new(
569 assert_return(bus, -ENOTCONN);
570 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
571 assert_return(m, -EINVAL);
572 assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
574 t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
579 t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message)));
580 t->header->endian = BUS_NATIVE_ENDIAN;
581 t->header->type = type;
582 t->header->version = bus->message_version;
583 t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING);
584 t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t);
585 t->bus = sd_bus_ref(bus);
587 if (bus->allow_interactive_authorization)
588 t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
594 _public_ int sd_bus_message_new_signal(
598 const char *interface,
599 const char *member) {
604 assert_return(bus, -ENOTCONN);
605 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
606 assert_return(object_path_is_valid(path), -EINVAL);
607 assert_return(interface_name_is_valid(interface), -EINVAL);
608 assert_return(member_name_is_valid(member), -EINVAL);
609 assert_return(m, -EINVAL);
611 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_SIGNAL);
617 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
619 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
622 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
625 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
633 sd_bus_message_unref(t);
637 _public_ int sd_bus_message_new_method_call(
640 const char *destination,
642 const char *interface,
643 const char *member) {
648 assert_return(bus, -ENOTCONN);
649 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
650 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
651 assert_return(object_path_is_valid(path), -EINVAL);
652 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
653 assert_return(member_name_is_valid(member), -EINVAL);
654 assert_return(m, -EINVAL);
656 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_CALL);
662 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
665 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
670 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
676 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
689 static int message_new_reply(
690 sd_bus_message *call,
692 sd_bus_message **m) {
698 assert_return(call, -EINVAL);
699 assert_return(call->sealed, -EPERM);
700 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
701 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
702 assert_return(m, -EINVAL);
704 cookie = BUS_MESSAGE_COOKIE(call);
708 r = sd_bus_message_new(call->bus, &t, type);
714 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
715 t->reply_cookie = cookie;
716 r = message_append_reply_cookie(t, t->reply_cookie);
721 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
726 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
727 t->enforced_reply_signature = call->enforced_reply_signature;
737 _public_ int sd_bus_message_new_method_return(
738 sd_bus_message *call,
739 sd_bus_message **m) {
741 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
744 _public_ int sd_bus_message_new_method_error(
745 sd_bus_message *call,
747 const sd_bus_error *e) {
752 assert_return(sd_bus_error_is_set(e), -EINVAL);
753 assert_return(m, -EINVAL);
755 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
759 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
764 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
769 t->error._need_free = -1;
779 _public_ int sd_bus_message_new_method_errorf(
780 sd_bus_message *call,
786 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
789 assert_return(name, -EINVAL);
790 assert_return(m, -EINVAL);
792 va_start(ap, format);
793 bus_error_setfv(&error, name, format, ap);
796 return sd_bus_message_new_method_error(call, m, &error);
799 _public_ int sd_bus_message_new_method_errno(
800 sd_bus_message *call,
803 const sd_bus_error *p) {
805 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
807 if (sd_bus_error_is_set(p))
808 return sd_bus_message_new_method_error(call, m, p);
810 sd_bus_error_set_errno(&berror, error);
812 return sd_bus_message_new_method_error(call, m, &berror);
815 _public_ int sd_bus_message_new_method_errnof(
816 sd_bus_message *call,
822 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
825 va_start(ap, format);
826 sd_bus_error_set_errnofv(&berror, error, format, ap);
829 return sd_bus_message_new_method_error(call, m, &berror);
832 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
836 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
837 m->creds.well_known_names_local = true;
838 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
841 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
845 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
846 m->creds.well_known_names_driver = true;
847 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
850 int bus_message_new_synthetic_error(
853 const sd_bus_error *e,
854 sd_bus_message **m) {
860 assert(sd_bus_error_is_set(e));
863 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_ERROR);
869 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
870 t->reply_cookie = cookie;
872 r = message_append_reply_cookie(t, t->reply_cookie);
876 if (bus && bus->unique_name) {
877 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
882 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
887 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
892 t->error._need_free = -1;
894 bus_message_set_sender_driver(bus, t);
904 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
909 assert(m->n_ref > 0);
915 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
920 assert(m->n_ref > 0);
930 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
931 assert_return(m, -EINVAL);
932 assert_return(type, -EINVAL);
934 *type = m->header->type;
938 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
941 assert_return(m, -EINVAL);
942 assert_return(cookie, -EINVAL);
944 c = BUS_MESSAGE_COOKIE(m);
948 *cookie = BUS_MESSAGE_COOKIE(m);
952 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
953 assert_return(m, -EINVAL);
954 assert_return(cookie, -EINVAL);
956 if (m->reply_cookie == 0)
959 *cookie = m->reply_cookie;
963 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
964 assert_return(m, -EINVAL);
966 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
967 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
970 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
971 assert_return(m, -EINVAL);
973 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
976 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
977 assert_return(m, -EINVAL);
979 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
980 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
983 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
984 assert_return(m, NULL);
989 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
990 assert_return(m, NULL);
995 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
996 assert_return(m, NULL);
1001 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1002 assert_return(m, NULL);
1004 return m->destination;
1007 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1008 assert_return(m, NULL);
1013 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1014 assert_return(m, NULL);
1016 if (!sd_bus_error_is_set(&m->error))
1022 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1023 assert_return(m, -EINVAL);
1024 assert_return(usec, -EINVAL);
1026 if (m->monotonic <= 0)
1029 *usec = m->monotonic;
1033 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1034 assert_return(m, -EINVAL);
1035 assert_return(usec, -EINVAL);
1037 if (m->realtime <= 0)
1040 *usec = m->realtime;
1044 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1045 assert_return(m, -EINVAL);
1046 assert_return(seqnum, -EINVAL);
1051 *seqnum = m->seqnum;
1055 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1056 assert_return(m, NULL);
1058 if (m->creds.mask == 0)
1064 _public_ int sd_bus_message_is_signal(
1066 const char *interface,
1067 const char *member) {
1069 assert_return(m, -EINVAL);
1071 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1074 if (interface && (!m->interface || !streq(m->interface, interface)))
1077 if (member && (!m->member || !streq(m->member, member)))
1083 _public_ int sd_bus_message_is_method_call(
1085 const char *interface,
1086 const char *member) {
1088 assert_return(m, -EINVAL);
1090 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1093 if (interface && (!m->interface || !streq(m->interface, interface)))
1096 if (member && (!m->member || !streq(m->member, member)))
1102 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1103 assert_return(m, -EINVAL);
1105 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1108 if (name && (!m->error.name || !streq(m->error.name, name)))
1114 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1115 assert_return(m, -EINVAL);
1116 assert_return(!m->sealed, -EPERM);
1117 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1119 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
1124 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1125 assert_return(m, -EINVAL);
1126 assert_return(!m->sealed, -EPERM);
1128 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
1133 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1134 assert_return(m, -EINVAL);
1135 assert_return(!m->sealed, -EPERM);
1137 SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
1142 static struct bus_container *message_get_container(sd_bus_message *m) {
1145 if (m->n_containers == 0)
1146 return &m->root_container;
1148 assert(m->containers);
1149 return m->containers + m->n_containers - 1;
1152 struct bus_body_part *message_append_part(sd_bus_message *m) {
1153 struct bus_body_part *part;
1160 if (m->n_body_parts <= 0) {
1164 assert(m->body_end);
1166 part = new0(struct bus_body_part, 1);
1172 m->body_end->next = part;
1182 static void part_zero(struct bus_body_part *part, size_t sz) {
1187 /* All other fields can be left in their defaults */
1188 assert(!part->data);
1189 assert(part->memfd < 0);
1192 part->is_zero = true;
1193 part->sealed = true;
1196 static int part_make_space(
1197 struct sd_bus_message *m,
1198 struct bus_body_part *part,
1206 assert(!part->sealed);
1211 if (part->allocated == 0 || sz > part->allocated) {
1212 size_t new_allocated;
1214 new_allocated = sz > 0 ? 2 * sz : 64;
1215 n = realloc(part->data, new_allocated);
1222 part->allocated = new_allocated;
1223 part->free_this = true;
1227 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1233 static int message_add_offset(sd_bus_message *m, size_t offset) {
1234 struct bus_container *c;
1237 assert(BUS_MESSAGE_IS_GVARIANT(m));
1239 /* Add offset to current container, unless this is the first
1240 * item in it, which will have the 0 offset, which we can
1242 c = message_get_container(m);
1244 if (!c->need_offsets)
1247 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1250 c->offsets[c->n_offsets++] = offset;
1254 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1255 struct bus_container *c;
1262 /* Update counters */
1263 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1266 *c->array_size += expand;
1270 static void *message_extend_body(
1275 bool force_inline) {
1277 size_t start_body, end_body, padding, added;
1288 start_body = ALIGN_TO((size_t) m->body_size, align);
1289 end_body = start_body + sz;
1291 padding = start_body - m->body_size;
1292 added = padding + sz;
1294 /* Check for 32bit overflows */
1295 if (end_body > (size_t) ((uint32_t) -1) ||
1296 end_body < start_body) {
1302 struct bus_body_part *part = NULL;
1306 m->n_body_parts <= 0 ||
1307 m->body_end->sealed ||
1308 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1309 (force_inline && m->body_end->size > MEMFD_MIN_SIZE);
1310 /* If this must be an inlined extension, let's create a new part if
1311 * the previous part is large enough to be inlined. */
1315 part = message_append_part(m);
1319 part_zero(part, padding);
1322 part = message_append_part(m);
1326 r = part_make_space(m, part, sz, &p);
1330 struct bus_container *c;
1332 size_t os, start_part, end_part;
1338 start_part = ALIGN_TO(part->size, align);
1339 end_part = start_part + sz;
1341 r = part_make_space(m, part, end_part, &p);
1346 memzero(p, padding);
1347 p = (uint8_t*) p + padding;
1350 /* Readjust pointers */
1351 for (c = m->containers; c < m->containers + m->n_containers; c++)
1352 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1354 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1357 /* Return something that is not NULL and is aligned */
1358 p = (uint8_t*) align;
1360 m->body_size = end_body;
1361 message_extend_containers(m, added);
1364 r = message_add_offset(m, end_body);
1374 static int message_push_fd(sd_bus_message *m, int fd) {
1385 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1389 f = reallocarray(m->fds, sizeof(int), m->n_fds + 1);
1397 m->fds[m->n_fds] = copy;
1403 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1404 _cleanup_close_ int fd = -1;
1405 struct bus_container *c;
1409 assert_return(m, -EINVAL);
1410 assert_return(!m->sealed, -EPERM);
1411 assert_return(bus_type_is_basic(type), -EINVAL);
1412 assert_return(!m->poisoned, -ESTALE);
1414 c = message_get_container(m);
1416 if (c->signature && c->signature[c->index]) {
1417 /* Container signature is already set */
1419 if (c->signature[c->index] != type)
1424 /* Maybe we can append to the signature? But only if this is the top-level container */
1425 if (c->enclosing != 0)
1428 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1435 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1441 case SD_BUS_TYPE_SIGNATURE:
1442 case SD_BUS_TYPE_STRING:
1446 case SD_BUS_TYPE_OBJECT_PATH:
1454 case SD_BUS_TYPE_BOOLEAN:
1456 u8 = p && *(int*) p;
1462 case SD_BUS_TYPE_UNIX_FD:
1467 fd = message_push_fd(m, *(int*) p);
1478 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1479 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1486 a = message_extend_body(m, align, sz, true, false);
1493 *stored = (const uint8_t*) a;
1500 case SD_BUS_TYPE_STRING:
1501 /* To make things easy we'll serialize a NULL string
1502 * into the empty string */
1506 case SD_BUS_TYPE_OBJECT_PATH:
1512 sz = 4 + strlen(p) + 1;
1515 case SD_BUS_TYPE_SIGNATURE:
1520 sz = 1 + strlen(p) + 1;
1523 case SD_BUS_TYPE_BOOLEAN:
1525 u32 = p && *(int*) p;
1531 case SD_BUS_TYPE_UNIX_FD:
1536 fd = message_push_fd(m, *(int*) p);
1547 align = bus_type_get_alignment(type);
1548 sz = bus_type_get_size(type);
1555 a = message_extend_body(m, align, sz, false, false);
1559 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
1560 *(uint32_t*) a = sz - 5;
1561 memcpy((uint8_t*) a + 4, p, sz - 4);
1564 *stored = (const uint8_t*) a + 4;
1566 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1567 *(uint8_t*) a = sz - 2;
1568 memcpy((uint8_t*) a + 1, p, sz - 1);
1571 *stored = (const uint8_t*) a + 1;
1580 if (type == SD_BUS_TYPE_UNIX_FD)
1583 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1590 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1591 return message_append_basic(m, type, p, NULL);
1594 _public_ int sd_bus_message_append_string_space(
1599 struct bus_container *c;
1602 assert_return(m, -EINVAL);
1603 assert_return(s, -EINVAL);
1604 assert_return(!m->sealed, -EPERM);
1605 assert_return(!m->poisoned, -ESTALE);
1607 c = message_get_container(m);
1609 if (c->signature && c->signature[c->index]) {
1610 /* Container signature is already set */
1612 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1617 /* Maybe we can append to the signature? But only if this is the top-level container */
1618 if (c->enclosing != 0)
1621 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1628 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1629 a = message_extend_body(m, 1, size + 1, true, false);
1635 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1639 *(uint32_t*) a = size;
1645 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1651 _public_ int sd_bus_message_append_string_iovec(
1653 const struct iovec *iov,
1661 assert_return(m, -EINVAL);
1662 assert_return(!m->sealed, -EPERM);
1663 assert_return(iov || n == 0, -EINVAL);
1664 assert_return(!m->poisoned, -ESTALE);
1666 size = IOVEC_TOTAL_SIZE(iov, n);
1668 r = sd_bus_message_append_string_space(m, size, &p);
1672 for (i = 0; i < n; i++) {
1674 if (iov[i].iov_base)
1675 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1677 memset(p, ' ', iov[i].iov_len);
1679 p += iov[i].iov_len;
1685 static int bus_message_open_array(
1687 struct bus_container *c,
1688 const char *contents,
1689 uint32_t **array_size,
1691 bool *need_offsets) {
1701 assert(need_offsets);
1703 if (!signature_is_single(contents, true))
1706 if (c->signature && c->signature[c->index]) {
1708 /* Verify the existing signature */
1710 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1713 if (!startswith(c->signature + c->index + 1, contents))
1716 nindex = c->index + 1 + strlen(contents);
1720 if (c->enclosing != 0)
1723 /* Extend the existing signature */
1725 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1731 nindex = e - c->signature;
1734 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1735 alignment = bus_gvariant_get_alignment(contents);
1739 /* Add alignment padding and add to offset list */
1740 if (!message_extend_body(m, alignment, 0, false, false))
1743 r = bus_gvariant_is_fixed_size(contents);
1747 *begin = m->body_size;
1748 *need_offsets = r == 0;
1752 struct bus_body_part *o;
1754 alignment = bus_type_get_alignment(contents[0]);
1758 a = message_extend_body(m, 4, 4, false, false);
1763 op = m->body_end->data;
1764 os = m->body_end->size;
1766 /* Add alignment between size and first element */
1767 if (!message_extend_body(m, alignment, 0, false, false))
1770 /* location of array size might have changed so let's readjust a */
1771 if (o == m->body_end)
1772 a = adjust_pointer(a, op, os, m->body_end->data);
1778 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1784 static int bus_message_open_variant(
1786 struct bus_container *c,
1787 const char *contents) {
1793 if (!signature_is_single(contents, false))
1796 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1799 if (c->signature && c->signature[c->index]) {
1801 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1807 if (c->enclosing != 0)
1810 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1817 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1818 /* Variants are always aligned to 8 */
1820 if (!message_extend_body(m, 8, 0, false, false))
1827 l = strlen(contents);
1828 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1833 memcpy((uint8_t*) a + 1, contents, l + 1);
1836 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1842 static int bus_message_open_struct(
1844 struct bus_container *c,
1845 const char *contents,
1847 bool *need_offsets) {
1856 assert(need_offsets);
1858 if (!signature_is_valid(contents, false))
1861 if (c->signature && c->signature[c->index]) {
1864 l = strlen(contents);
1866 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1867 !startswith(c->signature + c->index + 1, contents) ||
1868 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1871 nindex = c->index + 1 + l + 1;
1875 if (c->enclosing != 0)
1878 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1884 nindex = e - c->signature;
1887 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1890 alignment = bus_gvariant_get_alignment(contents);
1894 if (!message_extend_body(m, alignment, 0, false, false))
1897 r = bus_gvariant_is_fixed_size(contents);
1901 *begin = m->body_size;
1902 *need_offsets = r == 0;
1904 /* Align contents to 8 byte boundary */
1905 if (!message_extend_body(m, 8, 0, false, false))
1909 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1915 static int bus_message_open_dict_entry(
1917 struct bus_container *c,
1918 const char *contents,
1920 bool *need_offsets) {
1928 assert(need_offsets);
1930 if (!signature_is_pair(contents))
1933 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1936 if (c->signature && c->signature[c->index]) {
1939 l = strlen(contents);
1941 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1942 !startswith(c->signature + c->index + 1, contents) ||
1943 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1948 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1951 alignment = bus_gvariant_get_alignment(contents);
1955 if (!message_extend_body(m, alignment, 0, false, false))
1958 r = bus_gvariant_is_fixed_size(contents);
1962 *begin = m->body_size;
1963 *need_offsets = r == 0;
1965 /* Align contents to 8 byte boundary */
1966 if (!message_extend_body(m, 8, 0, false, false))
1973 _public_ int sd_bus_message_open_container(
1976 const char *contents) {
1978 struct bus_container *c, *w;
1979 uint32_t *array_size = NULL;
1981 size_t before, begin = 0;
1982 bool need_offsets = false;
1985 assert_return(m, -EINVAL);
1986 assert_return(!m->sealed, -EPERM);
1987 assert_return(contents, -EINVAL);
1988 assert_return(!m->poisoned, -ESTALE);
1990 /* Make sure we have space for one more container */
1991 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1996 c = message_get_container(m);
1998 signature = strdup(contents);
2004 /* Save old index in the parent container, in case we have to
2005 * abort this container */
2006 c->saved_index = c->index;
2007 before = m->body_size;
2009 if (type == SD_BUS_TYPE_ARRAY)
2010 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2011 else if (type == SD_BUS_TYPE_VARIANT)
2012 r = bus_message_open_variant(m, c, contents);
2013 else if (type == SD_BUS_TYPE_STRUCT)
2014 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2015 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2016 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2025 /* OK, let's fill it in */
2026 w = m->containers + m->n_containers++;
2027 w->enclosing = type;
2028 w->signature = signature;
2030 w->array_size = array_size;
2033 w->n_offsets = w->offsets_allocated = 0;
2035 w->need_offsets = need_offsets;
2040 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2045 if (!BUS_MESSAGE_IS_GVARIANT(m))
2048 if (c->need_offsets) {
2049 size_t payload, sz, i;
2052 /* Variable-width arrays */
2054 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2055 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2057 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2061 for (i = 0; i < c->n_offsets; i++)
2062 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2066 /* Fixed-width or empty arrays */
2068 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2076 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2082 assert(c->signature);
2084 if (!BUS_MESSAGE_IS_GVARIANT(m))
2087 l = strlen(c->signature);
2089 a = message_extend_body(m, 1, 1 + l, true, false);
2094 memcpy(a+1, c->signature, l);
2099 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2100 bool fixed_size = true;
2101 size_t n_variable = 0;
2110 if (!BUS_MESSAGE_IS_GVARIANT(m))
2113 p = strempty(c->signature);
2117 r = signature_element_length(p, &n);
2126 r = bus_gvariant_is_fixed_size(t);
2131 assert(!c->need_offsets || i <= c->n_offsets);
2133 /* We need to add an offset for each item that has a
2134 * variable size and that is not the last one in the
2138 if (r == 0 && p[n] != 0)
2145 assert(!c->need_offsets || i == c->n_offsets);
2146 assert(c->need_offsets || n_variable == 0);
2148 if (isempty(c->signature)) {
2149 /* The unary type is encoded as fixed 1 byte padding */
2150 a = message_extend_body(m, 1, 1, add_offset, false);
2155 } else if (n_variable <= 0) {
2158 /* Structures with fixed-size members only have to be
2159 * fixed-size themselves. But gvariant requires all fixed-size
2160 * elements to be sized a multiple of their alignment. Hence,
2161 * we must *always* add final padding after the last member so
2162 * the overall size of the structure is properly aligned. */
2164 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2166 assert(alignment > 0);
2168 a = message_extend_body(m, alignment, 0, add_offset, false);
2175 assert(c->offsets[c->n_offsets-1] == m->body_size);
2177 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2179 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2183 p = strempty(c->signature);
2184 for (i = 0, j = 0; i < c->n_offsets; i++) {
2188 r = signature_element_length(p, &n);
2199 r = bus_gvariant_is_fixed_size(t);
2202 if (r > 0 || p[0] == 0)
2206 k = n_variable - 1 - j;
2208 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2217 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2218 struct bus_container *c;
2221 assert_return(m, -EINVAL);
2222 assert_return(!m->sealed, -EPERM);
2223 assert_return(m->n_containers > 0, -EINVAL);
2224 assert_return(!m->poisoned, -ESTALE);
2226 c = message_get_container(m);
2228 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2229 if (c->signature && c->signature[c->index] != 0)
2234 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2235 r = bus_message_close_array(m, c);
2236 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2237 r = bus_message_close_variant(m, c);
2238 else if (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY))
2239 r = bus_message_close_struct(m, c, true);
2241 assert_not_reached("Unknown container type");
2255 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2262 stack[*i].types = types;
2263 stack[*i].n_struct = n_struct;
2264 stack[*i].n_array = n_array;
2270 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2281 *types = stack[*i].types;
2282 *n_struct = stack[*i].n_struct;
2283 *n_array = stack[*i].n_array;
2288 _public_ int sd_bus_message_appendv(
2293 unsigned n_array, n_struct;
2294 TypeStack stack[BUS_CONTAINER_DEPTH];
2295 unsigned stack_ptr = 0;
2298 assert_return(m, -EINVAL);
2299 assert_return(types, -EINVAL);
2300 assert_return(!m->sealed, -EPERM);
2301 assert_return(!m->poisoned, -ESTALE);
2303 n_array = (unsigned) -1;
2304 n_struct = strlen(types);
2309 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2310 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2316 r = sd_bus_message_close_container(m);
2324 if (n_array != (unsigned) -1)
2333 case SD_BUS_TYPE_BYTE: {
2336 x = (uint8_t) va_arg(ap, int);
2337 r = sd_bus_message_append_basic(m, *t, &x);
2341 case SD_BUS_TYPE_BOOLEAN:
2342 case SD_BUS_TYPE_INT32:
2343 case SD_BUS_TYPE_UINT32:
2344 case SD_BUS_TYPE_UNIX_FD: {
2347 /* We assume a boolean is the same as int32_t */
2348 assert_cc(sizeof(int32_t) == sizeof(int));
2350 x = va_arg(ap, uint32_t);
2351 r = sd_bus_message_append_basic(m, *t, &x);
2355 case SD_BUS_TYPE_INT16:
2356 case SD_BUS_TYPE_UINT16: {
2359 x = (uint16_t) va_arg(ap, int);
2360 r = sd_bus_message_append_basic(m, *t, &x);
2364 case SD_BUS_TYPE_INT64:
2365 case SD_BUS_TYPE_UINT64: {
2368 x = va_arg(ap, uint64_t);
2369 r = sd_bus_message_append_basic(m, *t, &x);
2373 case SD_BUS_TYPE_DOUBLE: {
2376 x = va_arg(ap, double);
2377 r = sd_bus_message_append_basic(m, *t, &x);
2381 case SD_BUS_TYPE_STRING:
2382 case SD_BUS_TYPE_OBJECT_PATH:
2383 case SD_BUS_TYPE_SIGNATURE: {
2386 x = va_arg(ap, const char*);
2387 r = sd_bus_message_append_basic(m, *t, x);
2391 case SD_BUS_TYPE_ARRAY: {
2394 r = signature_element_length(t + 1, &k);
2400 memcpy(s, t + 1, k);
2403 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2408 if (n_array == (unsigned) -1) {
2413 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2419 n_array = va_arg(ap, unsigned);
2424 case SD_BUS_TYPE_VARIANT: {
2427 s = va_arg(ap, const char*);
2431 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2435 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2440 n_struct = strlen(s);
2441 n_array = (unsigned) -1;
2446 case SD_BUS_TYPE_STRUCT_BEGIN:
2447 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2450 r = signature_element_length(t, &k);
2457 memcpy(s, t + 1, k - 2);
2460 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2465 if (n_array == (unsigned) -1) {
2470 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2476 n_array = (unsigned) -1;
2492 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2496 assert_return(m, -EINVAL);
2497 assert_return(types, -EINVAL);
2498 assert_return(!m->sealed, -EPERM);
2499 assert_return(!m->poisoned, -ESTALE);
2501 va_start(ap, types);
2502 r = sd_bus_message_appendv(m, types, ap);
2508 _public_ int sd_bus_message_append_array_space(
2518 assert_return(m, -EINVAL);
2519 assert_return(!m->sealed, -EPERM);
2520 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2521 assert_return(ptr || size == 0, -EINVAL);
2522 assert_return(!m->poisoned, -ESTALE);
2524 /* alignment and size of the trivial types (except bool) is
2525 * identical for gvariant and dbus1 marshalling */
2526 align = bus_type_get_alignment(type);
2527 sz = bus_type_get_size(type);
2529 assert_se(align > 0);
2535 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2539 a = message_extend_body(m, align, size, false, false);
2543 r = sd_bus_message_close_container(m);
2551 _public_ int sd_bus_message_append_array(
2559 assert_return(m, -EINVAL);
2560 assert_return(!m->sealed, -EPERM);
2561 assert_return(bus_type_is_trivial(type), -EINVAL);
2562 assert_return(ptr || size == 0, -EINVAL);
2563 assert_return(!m->poisoned, -ESTALE);
2565 r = sd_bus_message_append_array_space(m, type, size, &p);
2569 memcpy_safe(p, ptr, size);
2574 _public_ int sd_bus_message_append_array_iovec(
2577 const struct iovec *iov,
2585 assert_return(m, -EINVAL);
2586 assert_return(!m->sealed, -EPERM);
2587 assert_return(bus_type_is_trivial(type), -EINVAL);
2588 assert_return(iov || n == 0, -EINVAL);
2589 assert_return(!m->poisoned, -ESTALE);
2591 size = IOVEC_TOTAL_SIZE(iov, n);
2593 r = sd_bus_message_append_array_space(m, type, size, &p);
2597 for (i = 0; i < n; i++) {
2599 if (iov[i].iov_base)
2600 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2602 memzero(p, iov[i].iov_len);
2604 p = (uint8_t*) p + iov[i].iov_len;
2610 _public_ int sd_bus_message_append_array_memfd(
2617 _cleanup_close_ int copy_fd = -1;
2618 struct bus_body_part *part;
2624 assert_return(m, -EINVAL);
2625 assert_return(memfd >= 0, -EBADF);
2626 assert_return(bus_type_is_trivial(type), -EINVAL);
2627 assert_return(size > 0, -EINVAL);
2628 assert_return(!m->sealed, -EPERM);
2629 assert_return(!m->poisoned, -ESTALE);
2631 r = memfd_set_sealed(memfd);
2635 copy_fd = fcntl(memfd, F_DUPFD_CLOEXEC, 3);
2639 r = memfd_get_size(memfd, &real_size);
2643 if (offset == 0 && size == (uint64_t) -1)
2645 else if (offset + size > real_size)
2648 align = bus_type_get_alignment(type);
2649 sz = bus_type_get_size(type);
2651 assert_se(align > 0);
2654 if (offset % align != 0)
2660 if (size > (uint64_t) (uint32_t) -1)
2663 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2667 a = message_extend_body(m, align, 0, false, false);
2671 part = message_append_part(m);
2675 part->memfd = copy_fd;
2676 part->memfd_offset = offset;
2677 part->sealed = true;
2681 m->body_size += size;
2682 message_extend_containers(m, size);
2684 return sd_bus_message_close_container(m);
2687 _public_ int sd_bus_message_append_string_memfd(
2693 _cleanup_close_ int copy_fd = -1;
2694 struct bus_body_part *part;
2695 struct bus_container *c;
2700 assert_return(m, -EINVAL);
2701 assert_return(memfd >= 0, -EBADF);
2702 assert_return(size > 0, -EINVAL);
2703 assert_return(!m->sealed, -EPERM);
2704 assert_return(!m->poisoned, -ESTALE);
2706 r = memfd_set_sealed(memfd);
2710 copy_fd = fcntl(memfd, FD_CLOEXEC, 3);
2714 r = memfd_get_size(memfd, &real_size);
2718 if (offset == 0 && size == (uint64_t) -1)
2720 else if (offset + size > real_size)
2723 /* We require this to be NUL terminated */
2727 if (size > (uint64_t) (uint32_t) -1)
2730 c = message_get_container(m);
2731 if (c->signature && c->signature[c->index]) {
2732 /* Container signature is already set */
2734 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2739 /* Maybe we can append to the signature? But only if this is the top-level container */
2740 if (c->enclosing != 0)
2743 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2750 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2751 a = message_extend_body(m, 4, 4, false, false);
2755 *(uint32_t*) a = size - 1;
2758 part = message_append_part(m);
2762 part->memfd = copy_fd;
2763 part->memfd_offset = offset;
2764 part->sealed = true;
2768 m->body_size += size;
2769 message_extend_containers(m, size);
2771 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2772 r = message_add_offset(m, m->body_size);
2779 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2785 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2789 assert_return(m, -EINVAL);
2790 assert_return(!m->sealed, -EPERM);
2791 assert_return(!m->poisoned, -ESTALE);
2793 r = sd_bus_message_open_container(m, 'a', "s");
2797 STRV_FOREACH(i, l) {
2798 r = sd_bus_message_append_basic(m, 's', *i);
2803 return sd_bus_message_close_container(m);
2806 static int bus_message_close_header(sd_bus_message *m) {
2810 /* The actual user data is finished now, we just complete the
2811 variant and struct now (at least on gvariant). Remember
2812 this position, so that during parsing we know where to
2813 put the outer container end. */
2814 m->user_body_size = m->body_size;
2816 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2817 const char *signature;
2821 /* Add offset table to end of fields array */
2822 if (m->n_header_offsets >= 1) {
2826 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2828 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2829 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2833 for (i = 0; i < m->n_header_offsets; i++)
2834 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2837 /* Add gvariant NUL byte plus signature to the end of
2838 * the body, followed by the final offset pointing to
2839 * the end of the fields array */
2841 signature = strempty(m->root_container.signature);
2842 l = strlen(signature);
2844 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2845 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2850 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2851 memcpy((uint8_t*) d + 2, signature, l);
2852 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2854 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2857 m->footer_accessible = 1 + l + 2 + sz;
2859 m->header->dbus1.fields_size = m->fields_size;
2860 m->header->dbus1.body_size = m->body_size;
2866 _public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t timeout_usec) {
2867 struct bus_body_part *part;
2872 assert_return(m, -EINVAL);
2877 if (m->n_containers > 0)
2883 if (cookie > 0xffffffffULL &&
2884 !BUS_MESSAGE_IS_GVARIANT(m))
2887 /* In vtables the return signature of method calls is listed,
2888 * let's check if they match if this is a response */
2889 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2890 m->enforced_reply_signature &&
2891 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2894 /* If gvariant marshalling is used we need to close the body structure */
2895 r = bus_message_close_struct(m, &m->root_container, false);
2899 /* If there's a non-trivial signature set, then add it in
2900 * here, but only on dbus1 */
2901 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2902 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2908 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2913 r = bus_message_close_header(m);
2917 if (BUS_MESSAGE_IS_GVARIANT(m))
2918 m->header->dbus2.cookie = cookie;
2920 m->header->dbus1.serial = (uint32_t) cookie;
2922 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout_usec;
2924 /* Add padding at the end of the fields part, since we know
2925 * the body needs to start at an 8 byte alignment. We made
2926 * sure we allocated enough space for this, so all we need to
2927 * do here is to zero it out. */
2928 a = ALIGN8(m->fields_size) - m->fields_size;
2930 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2932 /* If this is something we can send as memfd, then let's seal
2933 the memfd now. Note that we can send memfds as payload only
2934 for directed messages, and not for broadcasts. */
2935 if (m->destination && m->bus->use_memfd) {
2936 MESSAGE_FOREACH_PART(part, i, m)
2937 if (part->memfd >= 0 &&
2939 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2940 part != m->body_end) { /* The last part may never be sent as memfd */
2943 /* Try to seal it if that makes
2944 * sense. First, unmap our own map to
2945 * make sure we don't keep it busy. */
2946 bus_body_part_unmap(part);
2948 /* Then, sync up real memfd size */
2950 r = memfd_set_size(part->memfd, sz);
2954 /* Finally, try to seal */
2955 if (memfd_set_sealed(part->memfd) >= 0)
2956 part->sealed = true;
2960 m->root_container.end = m->user_body_size;
2961 m->root_container.index = 0;
2962 m->root_container.offset_index = 0;
2963 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2970 int bus_body_part_map(struct bus_body_part *part) {
2979 if (part->size <= 0)
2982 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2983 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2984 static const uint8_t zeroes[7] = { };
2985 part->data = (void*) zeroes;
2989 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
2990 psz = PAGE_ALIGN(part->size + shift);
2992 if (part->memfd >= 0)
2993 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
2994 else if (part->is_zero)
2995 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2999 if (p == MAP_FAILED)
3003 part->mmap_begin = p;
3004 part->data = (uint8_t*) p + shift;
3005 part->munmap_this = true;
3010 void bus_body_part_unmap(struct bus_body_part *part) {
3014 if (part->memfd < 0)
3017 if (!part->mmap_begin)
3020 if (!part->munmap_this)
3023 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3025 part->mmap_begin = NULL;
3028 part->munmap_this = false;
3033 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3034 size_t k, start, end;
3039 start = ALIGN_TO((size_t) *rindex, align);
3040 end = start + nbytes;
3045 /* Verify that padding is 0 */
3046 for (k = *rindex; k < start; k++)
3047 if (((const uint8_t*) p)[k] != 0)
3051 *r = (uint8_t*) p + start;
3058 static bool message_end_of_signature(sd_bus_message *m) {
3059 struct bus_container *c;
3063 c = message_get_container(m);
3064 return !c->signature || c->signature[c->index] == 0;
3067 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3068 struct bus_container *c;
3072 c = message_get_container(m);
3073 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3076 if (BUS_MESSAGE_IS_GVARIANT(m))
3077 return index >= c->end;
3079 assert(c->array_size);
3080 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3084 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3085 assert_return(m, -EINVAL);
3086 assert_return(m->sealed, -EPERM);
3088 if (complete && m->n_containers > 0)
3091 if (message_end_of_signature(m))
3094 if (message_end_of_array(m, m->rindex))
3100 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3101 struct bus_body_part *part;
3107 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3108 part = m->cached_rindex_part;
3109 begin = m->cached_rindex_part_begin;
3119 if (index + sz <= begin + part->size) {
3121 r = bus_body_part_map(part);
3126 *p = (uint8_t*) part->data + index - begin;
3128 m->cached_rindex_part = part;
3129 m->cached_rindex_part_begin = begin;
3134 begin += part->size;
3141 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3148 if (!BUS_MESSAGE_IS_GVARIANT(m))
3151 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3154 sz = bus_gvariant_get_size(c->signature);
3158 if (c->offset_index+1 >= c->n_offsets)
3161 /* Variable-size array */
3163 alignment = bus_gvariant_get_alignment(c->signature);
3164 assert(alignment > 0);
3166 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3167 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3170 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3173 /* Fixed-size array */
3174 *rindex = c->begin + (c->offset_index+1) * sz;
3180 } else if (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
3185 if (c->offset_index+1 >= c->n_offsets)
3188 r = signature_element_length(c->signature + c->index, &n);
3192 r = signature_element_length(c->signature + c->index + n, &j);
3197 memcpy(t, c->signature + c->index + n, j);
3200 alignment = bus_gvariant_get_alignment(t);
3203 assert(alignment > 0);
3205 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3206 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3210 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3213 assert_not_reached("Unknown container type");
3218 /* Reached the end */
3224 static int message_peek_body(
3231 size_t k, start, end, padding;
3232 struct bus_body_part *part;
3239 start = ALIGN_TO((size_t) *rindex, align);
3240 padding = start - *rindex;
3241 end = start + nbytes;
3243 if (end > m->user_body_size)
3246 part = find_part(m, *rindex, padding, (void**) &q);
3251 /* Verify padding */
3252 for (k = 0; k < padding; k++)
3257 part = find_part(m, start, nbytes, (void**) &q);
3258 if (!part || (nbytes > 0 && !q))
3269 static bool validate_nul(const char *s, size_t l) {
3271 /* Check for NUL chars in the string */
3272 if (memchr(s, 0, l))
3275 /* Check for NUL termination */
3282 static bool validate_string(const char *s, size_t l) {
3284 if (!validate_nul(s, l))
3287 /* Check if valid UTF8 */
3288 if (!utf8_is_valid(s))
3294 static bool validate_signature(const char *s, size_t l) {
3296 if (!validate_nul(s, l))
3299 /* Check if valid signature */
3300 if (!signature_is_valid(s, true))
3306 static bool validate_object_path(const char *s, size_t l) {
3308 if (!validate_nul(s, l))
3311 if (!object_path_is_valid(s))
3317 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3318 struct bus_container *c;
3323 assert_return(m, -EINVAL);
3324 assert_return(m->sealed, -EPERM);
3325 assert_return(bus_type_is_basic(type), -EINVAL);
3327 if (message_end_of_signature(m))
3330 if (message_end_of_array(m, m->rindex))
3333 c = message_get_container(m);
3334 if (c->signature[c->index] != type)
3339 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3341 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3344 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3348 if (type == SD_BUS_TYPE_STRING)
3349 ok = validate_string(q, c->item_size-1);
3350 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3351 ok = validate_object_path(q, c->item_size-1);
3353 ok = validate_signature(q, c->item_size-1);
3359 *(const char**) p = q;
3363 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3365 if ((size_t) sz != c->item_size)
3368 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3371 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3377 case SD_BUS_TYPE_BYTE:
3379 *(uint8_t*) p = *(uint8_t*) q;
3382 case SD_BUS_TYPE_BOOLEAN:
3384 *(int*) p = !!*(uint8_t*) q;
3387 case SD_BUS_TYPE_INT16:
3388 case SD_BUS_TYPE_UINT16:
3390 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3393 case SD_BUS_TYPE_INT32:
3394 case SD_BUS_TYPE_UINT32:
3396 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3399 case SD_BUS_TYPE_INT64:
3400 case SD_BUS_TYPE_UINT64:
3401 case SD_BUS_TYPE_DOUBLE:
3403 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3406 case SD_BUS_TYPE_UNIX_FD: {
3409 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3414 *(int*) p = m->fds[j];
3420 assert_not_reached("unexpected type");
3424 r = container_next_item(m, c, &rindex);
3429 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3433 r = message_peek_body(m, &rindex, 4, 4, &q);
3437 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3438 r = message_peek_body(m, &rindex, 1, l+1, &q);
3442 if (type == SD_BUS_TYPE_OBJECT_PATH)
3443 ok = validate_object_path(q, l);
3445 ok = validate_string(q, l);
3450 *(const char**) p = q;
3452 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3455 r = message_peek_body(m, &rindex, 1, 1, &q);
3460 r = message_peek_body(m, &rindex, 1, l+1, &q);
3464 if (!validate_signature(q, l))
3468 *(const char**) p = q;
3473 align = bus_type_get_alignment(type);
3476 sz = bus_type_get_size(type);
3479 r = message_peek_body(m, &rindex, align, sz, &q);
3485 case SD_BUS_TYPE_BYTE:
3487 *(uint8_t*) p = *(uint8_t*) q;
3490 case SD_BUS_TYPE_BOOLEAN:
3492 *(int*) p = !!*(uint32_t*) q;
3495 case SD_BUS_TYPE_INT16:
3496 case SD_BUS_TYPE_UINT16:
3498 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3501 case SD_BUS_TYPE_INT32:
3502 case SD_BUS_TYPE_UINT32:
3504 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3507 case SD_BUS_TYPE_INT64:
3508 case SD_BUS_TYPE_UINT64:
3509 case SD_BUS_TYPE_DOUBLE:
3511 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3514 case SD_BUS_TYPE_UNIX_FD: {
3517 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3522 *(int*) p = m->fds[j];
3527 assert_not_reached("Unknown basic type...");
3534 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3540 static int bus_message_enter_array(
3542 struct bus_container *c,
3543 const char *contents,
3544 uint32_t **array_size,
3547 size_t *n_offsets) {
3561 if (!signature_is_single(contents, true))
3564 if (!c->signature || c->signature[c->index] == 0)
3567 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3570 if (!startswith(c->signature + c->index + 1, contents))
3575 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3578 r = message_peek_body(m, &rindex, 4, 4, &q);
3582 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3585 alignment = bus_type_get_alignment(contents[0]);
3589 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3593 *array_size = (uint32_t*) q;
3595 } else if (c->item_size <= 0) {
3597 /* gvariant: empty array */
3602 } else if (bus_gvariant_is_fixed_size(contents)) {
3604 /* gvariant: fixed length array */
3605 *item_size = bus_gvariant_get_size(contents);
3610 size_t where, p = 0, framing, sz;
3613 /* gvariant: variable length array */
3614 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3616 where = rindex + c->item_size - sz;
3617 r = message_peek_body(m, &where, 1, sz, &q);
3621 framing = bus_gvariant_read_word_le(q, sz);
3622 if (framing > c->item_size - sz)
3624 if ((c->item_size - framing) % sz != 0)
3627 *n_offsets = (c->item_size - framing) / sz;
3629 where = rindex + framing;
3630 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3634 *offsets = new(size_t, *n_offsets);
3638 for (i = 0; i < *n_offsets; i++) {
3641 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3642 if (x > c->item_size - sz)
3647 (*offsets)[i] = rindex + x;
3651 *item_size = (*offsets)[0] - rindex;
3656 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3657 c->index += 1 + strlen(contents);
3662 static int bus_message_enter_variant(
3664 struct bus_container *c,
3665 const char *contents,
3666 size_t *item_size) {
3678 if (!signature_is_single(contents, false))
3681 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3684 if (!c->signature || c->signature[c->index] == 0)
3687 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3692 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3695 k = strlen(contents);
3696 if (1+k > c->item_size)
3699 where = rindex + c->item_size - (1+k);
3700 r = message_peek_body(m, &where, 1, 1+k, &q);
3704 if (*(char*) q != 0)
3707 if (memcmp((uint8_t*) q+1, contents, k))
3710 *item_size = c->item_size - (1+k);
3713 r = message_peek_body(m, &rindex, 1, 1, &q);
3718 r = message_peek_body(m, &rindex, 1, l+1, &q);
3722 if (!validate_signature(q, l))
3725 if (!streq(q, contents))
3731 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3737 static int build_struct_offsets(
3739 const char *signature,
3743 size_t *n_offsets) {
3745 unsigned n_variable = 0, n_total = 0, v;
3746 size_t previous = 0, where;
3757 if (isempty(signature)) {
3758 /* Unary type is encoded as *fixed* 1 byte padding */
3759 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3763 if (*(uint8_t *) q != 0)
3772 sz = bus_gvariant_determine_word_size(size, 0);
3776 /* First, loop over signature and count variable elements and
3777 * elements in general. We use this to know how large the
3778 * offset array is at the end of the structure. Note that
3779 * GVariant only stores offsets for all variable size elements
3780 * that are not the last item. */
3786 r = signature_element_length(p, &n);
3795 r = bus_gvariant_is_fixed_size(t);
3800 if (r == 0 && p[n] != 0) /* except the last item */
3807 if (size < n_variable * sz)
3810 where = m->rindex + size - (n_variable * sz);
3811 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3817 *offsets = new(size_t, n_total);
3823 /* Second, loop again and build an offset table */
3829 r = signature_element_length(p, &n);
3838 k = bus_gvariant_get_size(t);
3846 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3849 if (m->rindex + x < previous)
3852 /* The last item's end
3853 * is determined from
3856 x = size - (n_variable * sz);
3858 offset = m->rindex + x;
3864 align = bus_gvariant_get_alignment(t);
3867 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3871 previous = (*offsets)[(*n_offsets)++] = offset;
3876 assert(*n_offsets == n_total);
3878 *item_size = (*offsets)[0] - m->rindex;
3882 static int enter_struct_or_dict_entry(
3884 struct bus_container *c,
3885 const char *contents,
3888 size_t *n_offsets) {
3899 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3902 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3907 /* gvariant with contents */
3908 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3913 static int bus_message_enter_struct(
3915 struct bus_container *c,
3916 const char *contents,
3919 size_t *n_offsets) {
3931 if (!signature_is_valid(contents, false))
3934 if (!c->signature || c->signature[c->index] == 0)
3937 l = strlen(contents);
3939 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3940 !startswith(c->signature + c->index + 1, contents) ||
3941 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3944 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3948 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3949 c->index += 1 + l + 1;
3954 static int bus_message_enter_dict_entry(
3956 struct bus_container *c,
3957 const char *contents,
3960 size_t *n_offsets) {
3969 if (!signature_is_pair(contents))
3972 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3975 if (!c->signature || c->signature[c->index] == 0)
3978 l = strlen(contents);
3980 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3981 !startswith(c->signature + c->index + 1, contents) ||
3982 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3985 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3989 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3990 c->index += 1 + l + 1;
3995 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3997 const char *contents) {
3998 struct bus_container *c, *w;
3999 uint32_t *array_size = NULL;
4002 size_t *offsets = NULL;
4003 size_t n_offsets = 0, item_size = 0;
4006 assert_return(m, -EINVAL);
4007 assert_return(m->sealed, -EPERM);
4008 assert_return(type != 0 || !contents, -EINVAL);
4010 if (type == 0 || !contents) {
4014 /* Allow entering into anonymous containers */
4015 r = sd_bus_message_peek_type(m, &tt, &cc);
4019 if (type != 0 && type != tt)
4022 if (contents && !streq(contents, cc))
4030 * We enforce a global limit on container depth, that is much
4031 * higher than the 32 structs and 32 arrays the specification
4032 * mandates. This is simpler to implement for us, and we need
4033 * this only to ensure our container array doesn't grow
4034 * without bounds. We are happy to return any data from a
4035 * message as long as the data itself is valid, even if the
4036 * overall message might be not.
4038 * Note that the message signature is validated when
4039 * parsing the headers, and that validation does check the
4042 * Note that the specification defines no limits on the depth
4043 * of stacked variants, but we do.
4045 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4048 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4051 if (message_end_of_signature(m))
4054 if (message_end_of_array(m, m->rindex))
4057 c = message_get_container(m);
4059 signature = strdup(contents);
4063 c->saved_index = c->index;
4066 if (type == SD_BUS_TYPE_ARRAY)
4067 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4068 else if (type == SD_BUS_TYPE_VARIANT)
4069 r = bus_message_enter_variant(m, c, contents, &item_size);
4070 else if (type == SD_BUS_TYPE_STRUCT)
4071 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4072 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4073 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4083 /* OK, let's fill it in */
4084 w = m->containers + m->n_containers++;
4085 w->enclosing = type;
4086 w->signature = signature;
4087 w->peeked_signature = NULL;
4091 w->begin = m->rindex;
4093 /* Unary type has fixed size of 1, but virtual size of 0 */
4094 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4095 type == SD_BUS_TYPE_STRUCT &&
4097 w->end = m->rindex + 0;
4099 w->end = m->rindex + c->item_size;
4101 w->array_size = array_size;
4102 w->item_size = item_size;
4103 w->offsets = offsets;
4104 w->n_offsets = n_offsets;
4105 w->offset_index = 0;
4110 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4111 struct bus_container *c;
4115 assert_return(m, -EINVAL);
4116 assert_return(m->sealed, -EPERM);
4117 assert_return(m->n_containers > 0, -ENXIO);
4119 c = message_get_container(m);
4121 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4122 if (c->signature && c->signature[c->index] != 0)
4126 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4127 if (m->rindex < c->end)
4130 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4133 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4134 if (c->begin + l != m->rindex)
4139 free(c->peeked_signature);
4143 c = message_get_container(m);
4146 c->index = c->saved_index;
4147 r = container_next_item(m, c, &m->rindex);
4155 static void message_quit_container(sd_bus_message *m) {
4156 struct bus_container *c;
4160 assert(m->n_containers > 0);
4162 c = message_get_container(m);
4165 assert(m->rindex >= c->before);
4166 m->rindex = c->before;
4168 /* Free container */
4173 /* Correct index of new top-level container */
4174 c = message_get_container(m);
4175 c->index = c->saved_index;
4178 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4179 struct bus_container *c;
4182 assert_return(m, -EINVAL);
4183 assert_return(m->sealed, -EPERM);
4185 if (message_end_of_signature(m))
4188 if (message_end_of_array(m, m->rindex))
4191 c = message_get_container(m);
4193 if (bus_type_is_basic(c->signature[c->index])) {
4197 *type = c->signature[c->index];
4201 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4207 r = signature_element_length(c->signature+c->index+1, &l);
4213 sig = strndup(c->signature + c->index + 1, l);
4217 free(c->peeked_signature);
4218 *contents = c->peeked_signature = sig;
4222 *type = SD_BUS_TYPE_ARRAY;
4227 if (IN_SET(c->signature[c->index], SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN)) {
4233 r = signature_element_length(c->signature+c->index, &l);
4238 sig = strndup(c->signature + c->index + 1, l - 2);
4242 free(c->peeked_signature);
4243 *contents = c->peeked_signature = sig;
4247 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4252 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4256 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4259 if (c->item_size < 2)
4262 /* Look for the NUL delimiter that
4263 separates the payload from the
4264 signature. Since the body might be
4265 in a different part that then the
4266 signature we map byte by byte. */
4268 for (k = 2; k <= c->item_size; k++) {
4271 where = m->rindex + c->item_size - k;
4272 r = message_peek_body(m, &where, 1, k, &q);
4276 if (*(char*) q == 0)
4280 if (k > c->item_size)
4283 free(c->peeked_signature);
4284 c->peeked_signature = strndup((char*) q + 1, k - 1);
4285 if (!c->peeked_signature)
4288 if (!signature_is_valid(c->peeked_signature, true))
4291 *contents = c->peeked_signature;
4296 r = message_peek_body(m, &rindex, 1, 1, &q);
4301 r = message_peek_body(m, &rindex, 1, l+1, &q);
4305 if (!validate_signature(q, l))
4313 *type = SD_BUS_TYPE_VARIANT;
4328 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4329 struct bus_container *c;
4331 assert_return(m, -EINVAL);
4332 assert_return(m->sealed, -EPERM);
4335 message_reset_containers(m);
4338 c = message_get_container(m);
4340 c = message_get_container(m);
4342 c->offset_index = 0;
4344 m->rindex = c->begin;
4347 c->offset_index = 0;
4348 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4350 return !isempty(c->signature);
4353 static int message_read_ap(
4358 unsigned n_array, n_struct;
4359 TypeStack stack[BUS_CONTAINER_DEPTH];
4360 unsigned stack_ptr = 0;
4361 unsigned n_loop = 0;
4369 /* Ideally, we'd just call ourselves recursively on every
4370 * complex type. However, the state of a va_list that is
4371 * passed to a function is undefined after that function
4372 * returns. This means we need to docode the va_list linearly
4373 * in a single stackframe. We hence implement our own
4374 * home-grown stack in an array. */
4376 n_array = (unsigned) -1; /* length of current array entries */
4377 n_struct = strlen(types); /* length of current struct contents signature */
4384 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4385 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4391 r = sd_bus_message_exit_container(m);
4399 if (n_array != (unsigned) -1)
4408 case SD_BUS_TYPE_BYTE:
4409 case SD_BUS_TYPE_BOOLEAN:
4410 case SD_BUS_TYPE_INT16:
4411 case SD_BUS_TYPE_UINT16:
4412 case SD_BUS_TYPE_INT32:
4413 case SD_BUS_TYPE_UINT32:
4414 case SD_BUS_TYPE_INT64:
4415 case SD_BUS_TYPE_UINT64:
4416 case SD_BUS_TYPE_DOUBLE:
4417 case SD_BUS_TYPE_STRING:
4418 case SD_BUS_TYPE_OBJECT_PATH:
4419 case SD_BUS_TYPE_SIGNATURE:
4420 case SD_BUS_TYPE_UNIX_FD: {
4423 p = va_arg(ap, void*);
4424 r = sd_bus_message_read_basic(m, *t, p);
4437 case SD_BUS_TYPE_ARRAY: {
4440 r = signature_element_length(t + 1, &k);
4446 memcpy(s, t + 1, k);
4449 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4460 if (n_array == (unsigned) -1) {
4465 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4471 n_array = va_arg(ap, unsigned);
4476 case SD_BUS_TYPE_VARIANT: {
4479 s = va_arg(ap, const char *);
4483 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4493 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4498 n_struct = strlen(s);
4499 n_array = (unsigned) -1;
4504 case SD_BUS_TYPE_STRUCT_BEGIN:
4505 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4508 r = signature_element_length(t, &k);
4514 memcpy(s, t + 1, k - 2);
4517 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4527 if (n_array == (unsigned) -1) {
4532 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4538 n_array = (unsigned) -1;
4551 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4555 assert_return(m, -EINVAL);
4556 assert_return(m->sealed, -EPERM);
4557 assert_return(types, -EINVAL);
4559 va_start(ap, types);
4560 r = message_read_ap(m, types, ap);
4566 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4569 assert_return(m, -EINVAL);
4570 assert_return(m->sealed, -EPERM);
4572 /* If types is NULL, read exactly one element */
4574 struct bus_container *c;
4577 if (message_end_of_signature(m))
4580 if (message_end_of_array(m, m->rindex))
4583 c = message_get_container(m);
4585 r = signature_element_length(c->signature + c->index, &l);
4589 types = strndupa(c->signature + c->index, l);
4594 case 0: /* Nothing to drop */
4597 case SD_BUS_TYPE_BYTE:
4598 case SD_BUS_TYPE_BOOLEAN:
4599 case SD_BUS_TYPE_INT16:
4600 case SD_BUS_TYPE_UINT16:
4601 case SD_BUS_TYPE_INT32:
4602 case SD_BUS_TYPE_UINT32:
4603 case SD_BUS_TYPE_INT64:
4604 case SD_BUS_TYPE_UINT64:
4605 case SD_BUS_TYPE_DOUBLE:
4606 case SD_BUS_TYPE_STRING:
4607 case SD_BUS_TYPE_OBJECT_PATH:
4608 case SD_BUS_TYPE_SIGNATURE:
4609 case SD_BUS_TYPE_UNIX_FD:
4611 r = sd_bus_message_read_basic(m, *types, NULL);
4615 r = sd_bus_message_skip(m, types + 1);
4621 case SD_BUS_TYPE_ARRAY: {
4624 r = signature_element_length(types + 1, &k);
4630 memcpy(s, types+1, k);
4633 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4638 r = sd_bus_message_skip(m, s);
4645 r = sd_bus_message_exit_container(m);
4650 r = sd_bus_message_skip(m, types + 1 + k);
4657 case SD_BUS_TYPE_VARIANT: {
4658 const char *contents;
4661 r = sd_bus_message_peek_type(m, &x, &contents);
4665 if (x != SD_BUS_TYPE_VARIANT)
4668 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4672 r = sd_bus_message_skip(m, contents);
4677 r = sd_bus_message_exit_container(m);
4681 r = sd_bus_message_skip(m, types + 1);
4688 case SD_BUS_TYPE_STRUCT_BEGIN:
4689 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4692 r = signature_element_length(types, &k);
4698 memcpy(s, types+1, k-2);
4701 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4705 r = sd_bus_message_skip(m, s);
4709 r = sd_bus_message_exit_container(m);
4714 r = sd_bus_message_skip(m, types + k);
4726 _public_ int sd_bus_message_read_array(
4732 struct bus_container *c;
4738 assert_return(m, -EINVAL);
4739 assert_return(m->sealed, -EPERM);
4740 assert_return(bus_type_is_trivial(type), -EINVAL);
4741 assert_return(ptr, -EINVAL);
4742 assert_return(size, -EINVAL);
4743 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4745 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4749 c = message_get_container(m);
4751 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4752 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4756 sz = c->end - c->begin;
4758 align = bus_type_get_alignment(type);
4762 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4766 /* Zero length array, let's return some aligned
4767 * pointer that is not NULL */
4768 p = (uint8_t*) align;
4770 r = message_peek_body(m, &m->rindex, align, sz, &p);
4775 r = sd_bus_message_exit_container(m);
4779 *ptr = (const void*) p;
4785 message_quit_container(m);
4789 static int message_peek_fields(
4800 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4803 static int message_peek_field_uint32(
4815 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4818 /* identical for gvariant and dbus1 */
4820 r = message_peek_fields(m, ri, 4, 4, &q);
4825 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4830 static int message_peek_field_uint64(
4842 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4845 /* identical for gvariant and dbus1 */
4847 r = message_peek_fields(m, ri, 8, 8, &q);
4852 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4857 static int message_peek_field_string(
4859 bool (*validate)(const char *p),
4871 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4876 r = message_peek_fields(m, ri, 1, item_size, &q);
4882 r = message_peek_field_uint32(m, ri, 4, &l);
4886 r = message_peek_fields(m, ri, 1, l+1, &q);
4892 if (!validate_nul(q, l))
4898 if (!validate_string(q, l))
4908 static int message_peek_field_signature(
4921 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4926 r = message_peek_fields(m, ri, 1, item_size, &q);
4932 r = message_peek_fields(m, ri, 1, 1, &q);
4937 r = message_peek_fields(m, ri, 1, l+1, &q);
4942 if (!validate_signature(q, l))
4951 static int message_skip_fields(
4954 uint32_t array_size,
4955 const char **signature) {
4957 size_t original_index;
4963 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4965 original_index = *ri;
4971 if (array_size != (uint32_t) -1 &&
4972 array_size <= *ri - original_index)
4979 if (t == SD_BUS_TYPE_STRING) {
4981 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4987 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4989 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4995 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4997 r = message_peek_field_signature(m, ri, 0, NULL);
5003 } else if (bus_type_is_basic(t)) {
5006 align = bus_type_get_alignment(t);
5007 k = bus_type_get_size(t);
5008 assert(align > 0 && k > 0);
5010 r = message_peek_fields(m, ri, align, k, NULL);
5016 } else if (t == SD_BUS_TYPE_ARRAY) {
5018 r = signature_element_length(*signature+1, &l);
5028 strncpy(sig, *signature + 1, l-1);
5031 alignment = bus_type_get_alignment(sig[0]);
5035 r = message_peek_field_uint32(m, ri, 0, &nas);
5038 if (nas > BUS_ARRAY_MAX_SIZE)
5041 r = message_peek_fields(m, ri, alignment, 0, NULL);
5045 r = message_skip_fields(m, ri, nas, (const char**) &s);
5050 (*signature) += 1 + l;
5052 } else if (t == SD_BUS_TYPE_VARIANT) {
5055 r = message_peek_field_signature(m, ri, 0, &s);
5059 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5065 } else if (IN_SET(t, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
5067 r = signature_element_length(*signature, &l);
5074 strncpy(sig, *signature + 1, l-1);
5077 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5088 int bus_message_parse_fields(sd_bus_message *m) {
5091 uint32_t unix_fds = 0;
5092 bool unix_fds_set = false;
5093 void *offsets = NULL;
5094 unsigned n_offsets = 0;
5100 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5103 /* Read the signature from the end of the body variant first */
5104 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5105 if (m->footer_accessible < 1 + sz)
5108 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5110 if (p < (char*) m->footer)
5117 /* We found the beginning of the signature
5118 * string, yay! We require the body to be a
5119 * structure, so verify it and then strip the
5120 * opening/closing brackets. */
5122 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5124 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5125 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5128 c = strndup(p + 1 + 1, l - 2);
5132 free(m->root_container.signature);
5133 m->root_container.signature = c;
5140 /* Calculate the actual user body size, by removing
5141 * the trailing variant signature and struct offset
5143 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5145 /* Pull out the offset table for the fields array */
5146 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5151 ri = m->fields_size - sz;
5152 r = message_peek_fields(m, &ri, 1, sz, &q);
5156 framing = bus_gvariant_read_word_le(q, sz);
5157 if (framing >= m->fields_size - sz)
5159 if ((m->fields_size - framing) % sz != 0)
5163 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5167 n_offsets = (m->fields_size - framing) / sz;
5170 m->user_body_size = m->body_size;
5173 while (ri < m->fields_size) {
5174 _cleanup_free_ char *sig = NULL;
5175 const char *signature;
5176 uint64_t field_type;
5177 size_t item_size = (size_t) -1;
5179 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5188 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5190 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5194 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5198 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5205 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5210 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5215 where = ri = ALIGN_TO(ri, 8);
5216 item_size = end - ri;
5217 r = message_peek_fields(m, &where, 1, item_size, &q);
5221 b = memrchr(q, 0, item_size);
5225 sig = strndup(b+1, item_size - (b+1-(char*) q));
5230 item_size = b - (char*) q;
5232 r = message_peek_field_signature(m, &ri, 0, &signature);
5237 switch (field_type) {
5239 case _BUS_MESSAGE_HEADER_INVALID:
5242 case BUS_MESSAGE_HEADER_PATH:
5247 if (!streq(signature, "o"))
5250 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5253 case BUS_MESSAGE_HEADER_INTERFACE:
5258 if (!streq(signature, "s"))
5261 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5264 case BUS_MESSAGE_HEADER_MEMBER:
5269 if (!streq(signature, "s"))
5272 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5275 case BUS_MESSAGE_HEADER_ERROR_NAME:
5280 if (!streq(signature, "s"))
5283 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5285 m->error._need_free = -1;
5289 case BUS_MESSAGE_HEADER_DESTINATION:
5294 if (!streq(signature, "s"))
5297 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5300 case BUS_MESSAGE_HEADER_SENDER:
5305 if (!streq(signature, "s"))
5308 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5310 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client) {
5311 m->creds.unique_name = (char*) m->sender;
5312 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5317 case BUS_MESSAGE_HEADER_SIGNATURE: {
5321 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5324 if (m->root_container.signature)
5327 if (!streq(signature, "g"))
5330 r = message_peek_field_signature(m, &ri, item_size, &s);
5338 free(m->root_container.signature);
5339 m->root_container.signature = c;
5343 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5345 if (m->reply_cookie != 0)
5348 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5349 /* 64bit on dbus2 */
5351 if (!streq(signature, "t"))
5354 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5358 /* 32bit on dbus1 */
5361 if (!streq(signature, "u"))
5364 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5368 m->reply_cookie = serial;
5371 if (m->reply_cookie == 0)
5376 case BUS_MESSAGE_HEADER_UNIX_FDS:
5380 if (!streq(signature, "u"))
5383 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5387 unix_fds_set = true;
5391 if (!BUS_MESSAGE_IS_GVARIANT(m))
5392 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5401 if (m->n_fds != unix_fds)
5404 switch (m->header->type) {
5406 case SD_BUS_MESSAGE_SIGNAL:
5407 if (!m->path || !m->interface || !m->member)
5410 if (m->reply_cookie != 0)
5415 case SD_BUS_MESSAGE_METHOD_CALL:
5417 if (!m->path || !m->member)
5420 if (m->reply_cookie != 0)
5425 case SD_BUS_MESSAGE_METHOD_RETURN:
5427 if (m->reply_cookie == 0)
5431 case SD_BUS_MESSAGE_METHOD_ERROR:
5433 if (m->reply_cookie == 0 || !m->error.name)
5438 /* Refuse non-local messages that claim they are local */
5439 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5441 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5443 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5446 m->root_container.end = m->user_body_size;
5448 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5449 r = build_struct_offsets(
5451 m->root_container.signature,
5453 &m->root_container.item_size,
5454 &m->root_container.offsets,
5455 &m->root_container.n_offsets);
5460 /* Try to read the error message, but if we can't it's a non-issue */
5461 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5462 (void) sd_bus_message_read(m, "s", &m->error.message);
5467 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5468 assert_return(m, -EINVAL);
5469 assert_return(destination, -EINVAL);
5470 assert_return(!m->sealed, -EPERM);
5471 assert_return(!m->destination, -EEXIST);
5473 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5476 _public_ int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) {
5477 assert_return(m, -EINVAL);
5478 assert_return(sender, -EINVAL);
5479 assert_return(!m->sealed, -EPERM);
5480 assert_return(!m->sender, -EEXIST);
5482 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5485 #if 0 /// UNNEEDED by elogind
5486 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5490 struct bus_body_part *part;
5496 total = BUS_MESSAGE_SIZE(m);
5502 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5503 MESSAGE_FOREACH_PART(part, i, m)
5504 e = mempcpy(e, part->data, part->size);
5506 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5515 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5522 r = sd_bus_message_enter_container(m, 'a', "s");
5526 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5527 r = strv_extend(l, s);
5534 r = sd_bus_message_exit_container(m);
5541 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5545 assert_return(m, -EINVAL);
5546 assert_return(m->sealed, -EPERM);
5547 assert_return(l, -EINVAL);
5549 r = bus_message_read_strv_extend(m, &strv);
5559 static int bus_message_get_arg_skip(
5563 const char **_contents) {
5568 r = sd_bus_message_rewind(m, true);
5573 const char *contents;
5576 r = sd_bus_message_peek_type(m, &type, &contents);
5582 /* Don't match against arguments after the first one we don't understand */
5583 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5584 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5589 *_contents = contents;
5595 r = sd_bus_message_skip(m, NULL);
5602 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5609 r = bus_message_get_arg_skip(m, i, &type, NULL);
5613 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5616 return sd_bus_message_read_basic(m, type, str);
5619 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5620 const char *contents;
5627 r = bus_message_get_arg_skip(m, i, &type, &contents);
5631 if (type != SD_BUS_TYPE_ARRAY)
5633 if (!STR_IN_SET(contents, "s", "o", "g"))
5636 return sd_bus_message_read_strv(m, strv);
5639 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5640 assert_return(m, EINVAL);
5642 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5645 return sd_bus_error_get_errno(&m->error);
5648 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5649 struct bus_container *c;
5651 assert_return(m, NULL);
5653 c = complete ? &m->root_container : message_get_container(m);
5654 return strempty(c->signature);
5657 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5658 assert_return(m, -EINVAL);
5660 return isempty(m->root_container.signature);
5663 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5664 assert_return(m, -EINVAL);
5666 return streq(strempty(m->root_container.signature), strempty(signature));
5669 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5670 bool done_something = false;
5673 assert_return(m, -EINVAL);
5674 assert_return(source, -EINVAL);
5675 assert_return(!m->sealed, -EPERM);
5676 assert_return(source->sealed, -EPERM);
5679 const char *contents;
5694 r = sd_bus_message_peek_type(source, &type, &contents);
5700 done_something = true;
5702 if (bus_type_is_container(type) > 0) {
5704 r = sd_bus_message_enter_container(source, type, contents);
5708 r = sd_bus_message_open_container(m, type, contents);
5712 r = sd_bus_message_copy(m, source, true);
5716 r = sd_bus_message_close_container(m);
5720 r = sd_bus_message_exit_container(source);
5727 r = sd_bus_message_read_basic(source, type, &basic);
5733 if (IN_SET(type, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_STRING))
5734 r = sd_bus_message_append_basic(m, type, basic.string);
5736 r = sd_bus_message_append_basic(m, type, &basic);
5743 return done_something;
5746 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5751 assert_return(m, -EINVAL);
5752 assert_return(m->sealed, -EPERM);
5753 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5754 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5755 assert_return(type || contents, -EINVAL);
5756 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5758 r = sd_bus_message_peek_type(m, &t, &c);
5762 if (type != 0 && type != t)
5765 if (contents && !streq_ptr(contents, c))
5771 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5772 assert_return(m, NULL);
5777 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5778 _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5786 switch ((*m)->header->type) {
5788 case SD_BUS_MESSAGE_SIGNAL:
5789 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5795 case SD_BUS_MESSAGE_METHOD_CALL:
5796 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5802 case SD_BUS_MESSAGE_METHOD_RETURN:
5803 case SD_BUS_MESSAGE_METHOD_ERROR:
5805 r = sd_bus_message_new(bus, &n, (*m)->header->type);
5811 n->reply_cookie = (*m)->reply_cookie;
5813 r = message_append_reply_cookie(n, n->reply_cookie);
5817 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5818 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5822 n->error._need_free = -1;
5831 if ((*m)->destination && !n->destination) {
5832 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5837 if ((*m)->sender && !n->sender) {
5838 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5843 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5845 r = sd_bus_message_copy(n, *m, true);
5849 timeout = (*m)->timeout;
5850 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5851 timeout = BUS_DEFAULT_TIMEOUT;
5853 r = sd_bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5857 sd_bus_message_unref(*m);
5863 #if 0 /// UNNEEDED by elogind
5864 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5868 assert_return(!m->sealed, -EPERM);
5869 assert_return(!m->sender, -EPERM);
5871 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5875 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5876 assert_return(m, -EINVAL);
5877 assert_return(priority, -EINVAL);
5879 *priority = m->priority;
5883 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5884 assert_return(m, -EINVAL);
5885 assert_return(!m->sealed, -EPERM);
5887 m->priority = priority;