1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
14 #include "alloc-util.h"
15 #include "bus-gvariant.h"
16 #include "bus-internal.h"
17 #include "bus-message.h"
18 #include "bus-signature.h"
23 #include "memfd-util.h"
24 #include "string-util.h"
26 #include "time-util.h"
30 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
32 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
37 if (old_base == new_base)
40 if ((uint8_t*) p < (uint8_t*) old_base)
43 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
46 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
49 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
54 close_and_munmap(part->memfd, part->mmap_begin, part->mapped);
55 else if (part->munmap_this)
56 munmap(part->mmap_begin, part->mapped);
57 else if (part->free_this)
64 static void message_reset_parts(sd_bus_message *m) {
65 struct bus_body_part *part;
70 while (m->n_body_parts > 0) {
71 struct bus_body_part *next = part->next;
72 message_free_part(m, part);
79 m->cached_rindex_part = NULL;
80 m->cached_rindex_part_begin = 0;
83 static void message_reset_containers(sd_bus_message *m) {
88 for (i = 0; i < m->n_containers; i++) {
89 free(m->containers[i].signature);
90 free(m->containers[i].offsets);
93 m->containers = mfree(m->containers);
95 m->n_containers = m->containers_allocated = 0;
96 m->root_container.index = 0;
99 static sd_bus_message* message_free(sd_bus_message *m) {
105 message_reset_parts(m);
107 sd_bus_unref(m->bus);
110 close_many(m->fds, m->n_fds);
114 if (m->iovec != m->iovec_fixed)
117 message_reset_containers(m);
118 free(m->root_container.signature);
119 free(m->root_container.offsets);
121 free(m->root_container.peeked_signature);
123 bus_creds_done(&m->creds);
127 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, message_free);
129 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
131 size_t old_size, new_size, start;
138 old_size = sizeof(struct bus_header) + m->fields_size;
139 start = ALIGN_TO(old_size, align);
140 new_size = start + sz;
142 if (new_size < start ||
143 new_size > (size_t) ((uint32_t) -1))
146 if (old_size == new_size)
147 return (uint8_t*) m->header + old_size;
149 if (m->free_header) {
150 np = realloc(m->header, ALIGN8(new_size));
154 /* Initially, the header is allocated as part of
155 * the sd_bus_message itself, let's replace it by
158 np = malloc(ALIGN8(new_size));
162 memcpy(np, m->header, sizeof(struct bus_header));
165 /* Zero out padding */
166 if (start > old_size)
167 memzero((uint8_t*) np + old_size, start - old_size);
171 m->fields_size = new_size - sizeof(struct bus_header);
173 /* Adjust quick access pointers */
174 m->path = adjust_pointer(m->path, op, old_size, m->header);
175 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
176 m->member = adjust_pointer(m->member, op, old_size, m->header);
177 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
178 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
179 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
181 m->free_header = true;
184 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
187 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
190 return (uint8_t*) np + start;
197 static int message_append_field_string(
209 /* dbus1 only allows 8bit header field ids */
213 /* dbus1 doesn't allow strings over 32bit, let's enforce this
214 * globally, to not risk convertability */
216 if (l > (size_t) (uint32_t) -1)
219 /* Signature "(yv)" where the variant contains "s" */
221 if (BUS_MESSAGE_IS_GVARIANT(m)) {
223 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
224 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
228 *((uint64_t*) p) = h;
235 *ret = (char*) p + 8;
238 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
239 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
248 ((uint32_t*) p)[1] = l;
249 memcpy(p + 8, s, l + 1);
252 *ret = (char*) p + 8;
258 static int message_append_field_signature(
269 /* dbus1 only allows 8bit header field ids */
273 /* dbus1 doesn't allow signatures over 8bit, let's enforce
274 * this globally, to not risk convertability */
279 /* Signature "(yv)" where the variant contains "g" */
281 if (BUS_MESSAGE_IS_GVARIANT(m))
282 /* For gvariant the serialization is the same as for normal strings */
283 return message_append_field_string(m, h, 'g', s, ret);
285 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
286 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
292 p[2] = SD_BUS_TYPE_SIGNATURE;
295 memcpy(p + 5, s, l + 1);
298 *ret = (const char*) p + 5;
304 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
309 /* dbus1 only allows 8bit header field ids */
313 if (BUS_MESSAGE_IS_GVARIANT(m)) {
314 /* (field id 64bit + ((value + NUL + signature string 'u') */
316 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
320 *((uint64_t*) p) = h;
321 *((uint32_t*) (p + 8)) = x;
325 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
326 p = message_extend_fields(m, 8, 4 + 4, false);
335 ((uint32_t*) p)[1] = x;
341 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
346 /* dbus1 only allows 8bit header field ids */
350 if (BUS_MESSAGE_IS_GVARIANT(m)) {
351 /* (field id 64bit + ((value + NUL + signature string 't') */
353 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
357 *((uint64_t*) p) = h;
358 *((uint64_t*) (p + 8)) = x;
362 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
363 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
376 ((uint64_t*) p)[1] = x;
382 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
385 if (BUS_MESSAGE_IS_GVARIANT(m))
386 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
388 /* 64bit cookies are not supported on dbus1 */
389 if (cookie > 0xffffffffUL)
392 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
396 int bus_message_from_header(
399 size_t header_accessible,
401 size_t footer_accessible,
407 sd_bus_message **ret) {
409 _cleanup_free_ sd_bus_message *m = NULL;
410 struct bus_header *h;
414 assert(header || header_accessible <= 0);
415 assert(footer || footer_accessible <= 0);
416 assert(fds || n_fds <= 0);
419 if (header_accessible < sizeof(struct bus_header))
422 if (header_accessible > message_size)
424 if (footer_accessible > message_size)
428 if (!IN_SET(h->version, 1, 2))
431 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
434 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
437 /* Note that we are happy with unknown flags in the flags header! */
439 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
442 label_sz = strlen(label);
453 m->header_accessible = header_accessible;
455 m->footer_accessible = footer_accessible;
457 if (BUS_MESSAGE_IS_GVARIANT(m)) {
460 if (h->dbus2.cookie == 0)
463 /* dbus2 derives the sizes from the message size and
464 the offset table at the end, since it is formatted as
465 gvariant "yyyyuta{tv}v". Since the message itself is a
466 structure with precisely to variable sized entries,
467 there's only one offset in the table, which marks the
468 end of the fields array. */
470 ws = bus_gvariant_determine_word_size(message_size, 0);
471 if (footer_accessible < ws)
474 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
475 if (ALIGN8(m->fields_size) > message_size - ws)
477 if (m->fields_size < sizeof(struct bus_header))
480 m->fields_size -= sizeof(struct bus_header);
481 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
483 if (h->dbus1.serial == 0)
486 /* dbus1 has the sizes in the header */
487 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
488 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
490 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
498 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
499 memcpy(m->creds.label, label, label_sz + 1);
501 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
504 m->bus = sd_bus_ref(bus);
510 int bus_message_from_malloc(
517 sd_bus_message **ret) {
519 _cleanup_(message_freep) sd_bus_message *m = NULL;
523 r = bus_message_from_header(
525 buffer, length, /* in this case the initial bytes and the final bytes are the same */
534 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
537 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
539 m->body.sealed = true;
544 m->iovec = m->iovec_fixed;
545 m->iovec[0].iov_base = buffer;
546 m->iovec[0].iov_len = length;
548 r = bus_message_parse_fields(m);
552 /* We take possession of the memory and fds now */
553 m->free_header = true;
560 _public_ int sd_bus_message_new(
567 assert_return(bus, -ENOTCONN);
568 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
569 assert_return(m, -EINVAL);
570 assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
572 t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
577 t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message)));
578 t->header->endian = BUS_NATIVE_ENDIAN;
579 t->header->type = type;
580 t->header->version = bus->message_version;
581 t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING);
582 t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t);
583 t->bus = sd_bus_ref(bus);
585 if (bus->allow_interactive_authorization)
586 t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
592 _public_ int sd_bus_message_new_signal(
596 const char *interface,
597 const char *member) {
599 _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
602 assert_return(bus, -ENOTCONN);
603 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
604 assert_return(object_path_is_valid(path), -EINVAL);
605 assert_return(interface_name_is_valid(interface), -EINVAL);
606 assert_return(member_name_is_valid(member), -EINVAL);
607 assert_return(m, -EINVAL);
609 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_SIGNAL);
615 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
617 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
620 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
623 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
631 _public_ int sd_bus_message_new_method_call(
634 const char *destination,
636 const char *interface,
637 const char *member) {
639 _cleanup_(message_freep) sd_bus_message *t = NULL;
642 assert_return(bus, -ENOTCONN);
643 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
644 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
645 assert_return(object_path_is_valid(path), -EINVAL);
646 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
647 assert_return(member_name_is_valid(member), -EINVAL);
648 assert_return(m, -EINVAL);
650 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_CALL);
656 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
659 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
664 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
670 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
679 static int message_new_reply(
680 sd_bus_message *call,
682 sd_bus_message **m) {
684 _cleanup_(message_freep) sd_bus_message *t = NULL;
688 assert_return(call, -EINVAL);
689 assert_return(call->sealed, -EPERM);
690 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
691 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
692 assert_return(m, -EINVAL);
694 cookie = BUS_MESSAGE_COOKIE(call);
698 r = sd_bus_message_new(call->bus, &t, type);
704 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
705 t->reply_cookie = cookie;
706 r = message_append_reply_cookie(t, t->reply_cookie);
711 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
716 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
717 t->enforced_reply_signature = call->enforced_reply_signature;
723 _public_ int sd_bus_message_new_method_return(
724 sd_bus_message *call,
725 sd_bus_message **m) {
727 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
730 _public_ int sd_bus_message_new_method_error(
731 sd_bus_message *call,
733 const sd_bus_error *e) {
735 _cleanup_(message_freep) sd_bus_message *t = NULL;
738 assert_return(sd_bus_error_is_set(e), -EINVAL);
739 assert_return(m, -EINVAL);
741 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
745 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
750 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
755 t->error._need_free = -1;
761 _public_ int sd_bus_message_new_method_errorf(
762 sd_bus_message *call,
768 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
771 assert_return(name, -EINVAL);
772 assert_return(m, -EINVAL);
774 va_start(ap, format);
775 bus_error_setfv(&error, name, format, ap);
778 return sd_bus_message_new_method_error(call, m, &error);
781 _public_ int sd_bus_message_new_method_errno(
782 sd_bus_message *call,
785 const sd_bus_error *p) {
787 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
789 if (sd_bus_error_is_set(p))
790 return sd_bus_message_new_method_error(call, m, p);
792 sd_bus_error_set_errno(&berror, error);
794 return sd_bus_message_new_method_error(call, m, &berror);
797 _public_ int sd_bus_message_new_method_errnof(
798 sd_bus_message *call,
804 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
807 va_start(ap, format);
808 sd_bus_error_set_errnofv(&berror, error, format, ap);
811 return sd_bus_message_new_method_error(call, m, &berror);
814 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
818 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
819 m->creds.well_known_names_local = true;
820 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
823 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
827 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
828 m->creds.well_known_names_driver = true;
829 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
832 int bus_message_new_synthetic_error(
835 const sd_bus_error *e,
836 sd_bus_message **m) {
838 _cleanup_(message_freep) sd_bus_message *t = NULL;
842 assert(sd_bus_error_is_set(e));
845 r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_ERROR);
851 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
852 t->reply_cookie = cookie;
854 r = message_append_reply_cookie(t, t->reply_cookie);
858 if (bus && bus->unique_name) {
859 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
864 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
869 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
874 t->error._need_free = -1;
876 bus_message_set_sender_driver(bus, t);
882 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
887 assert(m->n_ref > 0);
893 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
898 assert(m->n_ref > 0);
908 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
909 assert_return(m, -EINVAL);
910 assert_return(type, -EINVAL);
912 *type = m->header->type;
916 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
919 assert_return(m, -EINVAL);
920 assert_return(cookie, -EINVAL);
922 c = BUS_MESSAGE_COOKIE(m);
926 *cookie = BUS_MESSAGE_COOKIE(m);
930 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
931 assert_return(m, -EINVAL);
932 assert_return(cookie, -EINVAL);
934 if (m->reply_cookie == 0)
937 *cookie = m->reply_cookie;
941 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
942 assert_return(m, -EINVAL);
944 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
945 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
948 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
949 assert_return(m, -EINVAL);
951 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
954 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
955 assert_return(m, -EINVAL);
957 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
958 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
961 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
962 assert_return(m, NULL);
967 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
968 assert_return(m, NULL);
973 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
974 assert_return(m, NULL);
979 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
980 assert_return(m, NULL);
982 return m->destination;
985 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
986 assert_return(m, NULL);
991 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
992 assert_return(m, NULL);
994 if (!sd_bus_error_is_set(&m->error))
1000 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1001 assert_return(m, -EINVAL);
1002 assert_return(usec, -EINVAL);
1004 if (m->monotonic <= 0)
1007 *usec = m->monotonic;
1011 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1012 assert_return(m, -EINVAL);
1013 assert_return(usec, -EINVAL);
1015 if (m->realtime <= 0)
1018 *usec = m->realtime;
1022 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1023 assert_return(m, -EINVAL);
1024 assert_return(seqnum, -EINVAL);
1029 *seqnum = m->seqnum;
1033 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1034 assert_return(m, NULL);
1036 if (m->creds.mask == 0)
1042 _public_ int sd_bus_message_is_signal(
1044 const char *interface,
1045 const char *member) {
1047 assert_return(m, -EINVAL);
1049 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1052 if (interface && !streq_ptr(m->interface, interface))
1055 if (member && !streq_ptr(m->member, member))
1061 _public_ int sd_bus_message_is_method_call(
1063 const char *interface,
1064 const char *member) {
1066 assert_return(m, -EINVAL);
1068 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1071 if (interface && !streq_ptr(m->interface, interface))
1074 if (member && !streq_ptr(m->member, member))
1080 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1081 assert_return(m, -EINVAL);
1083 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1086 if (name && !streq_ptr(m->error.name, name))
1092 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1093 assert_return(m, -EINVAL);
1094 assert_return(!m->sealed, -EPERM);
1095 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1097 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
1102 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1103 assert_return(m, -EINVAL);
1104 assert_return(!m->sealed, -EPERM);
1106 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
1111 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1112 assert_return(m, -EINVAL);
1113 assert_return(!m->sealed, -EPERM);
1115 SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
1120 static struct bus_container *message_get_container(sd_bus_message *m) {
1123 if (m->n_containers == 0)
1124 return &m->root_container;
1126 assert(m->containers);
1127 return m->containers + m->n_containers - 1;
1130 struct bus_body_part *message_append_part(sd_bus_message *m) {
1131 struct bus_body_part *part;
1138 if (m->n_body_parts <= 0) {
1142 assert(m->body_end);
1144 part = new0(struct bus_body_part, 1);
1150 m->body_end->next = part;
1160 static void part_zero(struct bus_body_part *part, size_t sz) {
1165 /* All other fields can be left in their defaults */
1166 assert(!part->data);
1167 assert(part->memfd < 0);
1170 part->is_zero = true;
1171 part->sealed = true;
1174 static int part_make_space(
1175 struct sd_bus_message *m,
1176 struct bus_body_part *part,
1184 assert(!part->sealed);
1189 if (part->allocated == 0 || sz > part->allocated) {
1190 size_t new_allocated;
1192 new_allocated = sz > 0 ? 2 * sz : 64;
1193 n = realloc(part->data, new_allocated);
1200 part->allocated = new_allocated;
1201 part->free_this = true;
1205 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1211 static int message_add_offset(sd_bus_message *m, size_t offset) {
1212 struct bus_container *c;
1215 assert(BUS_MESSAGE_IS_GVARIANT(m));
1217 /* Add offset to current container, unless this is the first
1218 * item in it, which will have the 0 offset, which we can
1220 c = message_get_container(m);
1222 if (!c->need_offsets)
1225 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1228 c->offsets[c->n_offsets++] = offset;
1232 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1233 struct bus_container *c;
1240 /* Update counters */
1241 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1244 *c->array_size += expand;
1248 static void *message_extend_body(
1253 bool force_inline) {
1255 size_t start_body, end_body, padding, added;
1266 start_body = ALIGN_TO((size_t) m->body_size, align);
1267 end_body = start_body + sz;
1269 padding = start_body - m->body_size;
1270 added = padding + sz;
1272 /* Check for 32bit overflows */
1273 if (end_body > (size_t) ((uint32_t) -1) ||
1274 end_body < start_body) {
1280 struct bus_body_part *part = NULL;
1284 m->n_body_parts <= 0 ||
1285 m->body_end->sealed ||
1286 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1287 (force_inline && m->body_end->size > MEMFD_MIN_SIZE);
1288 /* If this must be an inlined extension, let's create a new part if
1289 * the previous part is large enough to be inlined. */
1293 part = message_append_part(m);
1297 part_zero(part, padding);
1300 part = message_append_part(m);
1304 r = part_make_space(m, part, sz, &p);
1308 struct bus_container *c;
1310 size_t os, start_part, end_part;
1316 start_part = ALIGN_TO(part->size, align);
1317 end_part = start_part + sz;
1319 r = part_make_space(m, part, end_part, &p);
1324 memzero(p, padding);
1325 p = (uint8_t*) p + padding;
1328 /* Readjust pointers */
1329 for (c = m->containers; c < m->containers + m->n_containers; c++)
1330 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1332 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1335 /* Return something that is not NULL and is aligned */
1336 p = (uint8_t*) align;
1338 m->body_size = end_body;
1339 message_extend_containers(m, added);
1342 r = message_add_offset(m, end_body);
1352 static int message_push_fd(sd_bus_message *m, int fd) {
1363 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1367 f = reallocarray(m->fds, sizeof(int), m->n_fds + 1);
1375 m->fds[m->n_fds] = copy;
1381 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1382 _cleanup_close_ int fd = -1;
1383 struct bus_container *c;
1387 assert_return(m, -EINVAL);
1388 assert_return(!m->sealed, -EPERM);
1389 assert_return(bus_type_is_basic(type), -EINVAL);
1390 assert_return(!m->poisoned, -ESTALE);
1392 c = message_get_container(m);
1394 if (c->signature && c->signature[c->index]) {
1395 /* Container signature is already set */
1397 if (c->signature[c->index] != type)
1402 /* Maybe we can append to the signature? But only if this is the top-level container */
1403 if (c->enclosing != 0)
1406 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1413 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1419 case SD_BUS_TYPE_SIGNATURE:
1420 case SD_BUS_TYPE_STRING:
1424 case SD_BUS_TYPE_OBJECT_PATH:
1432 case SD_BUS_TYPE_BOOLEAN:
1434 u8 = p && *(int*) p;
1440 case SD_BUS_TYPE_UNIX_FD:
1445 fd = message_push_fd(m, *(int*) p);
1456 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1457 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1464 a = message_extend_body(m, align, sz, true, false);
1471 *stored = (const uint8_t*) a;
1478 case SD_BUS_TYPE_STRING:
1479 /* To make things easy we'll serialize a NULL string
1480 * into the empty string */
1484 case SD_BUS_TYPE_OBJECT_PATH:
1490 sz = 4 + strlen(p) + 1;
1493 case SD_BUS_TYPE_SIGNATURE:
1498 sz = 1 + strlen(p) + 1;
1501 case SD_BUS_TYPE_BOOLEAN:
1503 u32 = p && *(int*) p;
1509 case SD_BUS_TYPE_UNIX_FD:
1514 fd = message_push_fd(m, *(int*) p);
1525 align = bus_type_get_alignment(type);
1526 sz = bus_type_get_size(type);
1533 a = message_extend_body(m, align, sz, false, false);
1537 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
1538 *(uint32_t*) a = sz - 5;
1539 memcpy((uint8_t*) a + 4, p, sz - 4);
1542 *stored = (const uint8_t*) a + 4;
1544 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1545 *(uint8_t*) a = sz - 2;
1546 memcpy((uint8_t*) a + 1, p, sz - 1);
1549 *stored = (const uint8_t*) a + 1;
1558 if (type == SD_BUS_TYPE_UNIX_FD)
1561 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1568 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1569 return message_append_basic(m, type, p, NULL);
1572 _public_ int sd_bus_message_append_string_space(
1577 struct bus_container *c;
1580 assert_return(m, -EINVAL);
1581 assert_return(s, -EINVAL);
1582 assert_return(!m->sealed, -EPERM);
1583 assert_return(!m->poisoned, -ESTALE);
1585 c = message_get_container(m);
1587 if (c->signature && c->signature[c->index]) {
1588 /* Container signature is already set */
1590 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1595 /* Maybe we can append to the signature? But only if this is the top-level container */
1596 if (c->enclosing != 0)
1599 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1606 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1607 a = message_extend_body(m, 1, size + 1, true, false);
1613 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1617 *(uint32_t*) a = size;
1623 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1629 _public_ int sd_bus_message_append_string_iovec(
1631 const struct iovec *iov,
1632 unsigned n /* should be size_t, but is API now… 😞 */) {
1639 assert_return(m, -EINVAL);
1640 assert_return(!m->sealed, -EPERM);
1641 assert_return(iov || n == 0, -EINVAL);
1642 assert_return(!m->poisoned, -ESTALE);
1644 size = IOVEC_TOTAL_SIZE(iov, n);
1646 r = sd_bus_message_append_string_space(m, size, &p);
1650 for (i = 0; i < n; i++) {
1652 if (iov[i].iov_base)
1653 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1655 memset(p, ' ', iov[i].iov_len);
1657 p += iov[i].iov_len;
1663 static int bus_message_open_array(
1665 struct bus_container *c,
1666 const char *contents,
1667 uint32_t **array_size,
1669 bool *need_offsets) {
1679 assert(need_offsets);
1681 if (!signature_is_single(contents, true))
1684 if (c->signature && c->signature[c->index]) {
1686 /* Verify the existing signature */
1688 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1691 if (!startswith(c->signature + c->index + 1, contents))
1694 nindex = c->index + 1 + strlen(contents);
1698 if (c->enclosing != 0)
1701 /* Extend the existing signature */
1703 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1709 nindex = e - c->signature;
1712 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1713 alignment = bus_gvariant_get_alignment(contents);
1717 /* Add alignment padding and add to offset list */
1718 if (!message_extend_body(m, alignment, 0, false, false))
1721 r = bus_gvariant_is_fixed_size(contents);
1725 *begin = m->body_size;
1726 *need_offsets = r == 0;
1730 struct bus_body_part *o;
1732 alignment = bus_type_get_alignment(contents[0]);
1736 a = message_extend_body(m, 4, 4, false, false);
1741 op = m->body_end->data;
1742 os = m->body_end->size;
1744 /* Add alignment between size and first element */
1745 if (!message_extend_body(m, alignment, 0, false, false))
1748 /* location of array size might have changed so let's readjust a */
1749 if (o == m->body_end)
1750 a = adjust_pointer(a, op, os, m->body_end->data);
1756 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1762 static int bus_message_open_variant(
1764 struct bus_container *c,
1765 const char *contents) {
1771 if (!signature_is_single(contents, false))
1774 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1777 if (c->signature && c->signature[c->index]) {
1779 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1785 if (c->enclosing != 0)
1788 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1795 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1796 /* Variants are always aligned to 8 */
1798 if (!message_extend_body(m, 8, 0, false, false))
1805 l = strlen(contents);
1806 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1811 memcpy((uint8_t*) a + 1, contents, l + 1);
1814 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1820 static int bus_message_open_struct(
1822 struct bus_container *c,
1823 const char *contents,
1825 bool *need_offsets) {
1834 assert(need_offsets);
1836 if (!signature_is_valid(contents, false))
1839 if (c->signature && c->signature[c->index]) {
1842 l = strlen(contents);
1844 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1845 !startswith(c->signature + c->index + 1, contents) ||
1846 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1849 nindex = c->index + 1 + l + 1;
1853 if (c->enclosing != 0)
1856 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1862 nindex = e - c->signature;
1865 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1868 alignment = bus_gvariant_get_alignment(contents);
1872 if (!message_extend_body(m, alignment, 0, false, false))
1875 r = bus_gvariant_is_fixed_size(contents);
1879 *begin = m->body_size;
1880 *need_offsets = r == 0;
1882 /* Align contents to 8 byte boundary */
1883 if (!message_extend_body(m, 8, 0, false, false))
1887 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1893 static int bus_message_open_dict_entry(
1895 struct bus_container *c,
1896 const char *contents,
1898 bool *need_offsets) {
1906 assert(need_offsets);
1908 if (!signature_is_pair(contents))
1911 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1914 if (c->signature && c->signature[c->index]) {
1917 l = strlen(contents);
1919 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1920 !startswith(c->signature + c->index + 1, contents) ||
1921 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1926 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1929 alignment = bus_gvariant_get_alignment(contents);
1933 if (!message_extend_body(m, alignment, 0, false, false))
1936 r = bus_gvariant_is_fixed_size(contents);
1940 *begin = m->body_size;
1941 *need_offsets = r == 0;
1943 /* Align contents to 8 byte boundary */
1944 if (!message_extend_body(m, 8, 0, false, false))
1951 _public_ int sd_bus_message_open_container(
1954 const char *contents) {
1956 struct bus_container *c, *w;
1957 uint32_t *array_size = NULL;
1959 size_t before, begin = 0;
1960 bool need_offsets = false;
1963 assert_return(m, -EINVAL);
1964 assert_return(!m->sealed, -EPERM);
1965 assert_return(contents, -EINVAL);
1966 assert_return(!m->poisoned, -ESTALE);
1968 /* Make sure we have space for one more container */
1969 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1974 c = message_get_container(m);
1976 signature = strdup(contents);
1982 /* Save old index in the parent container, in case we have to
1983 * abort this container */
1984 c->saved_index = c->index;
1985 before = m->body_size;
1987 if (type == SD_BUS_TYPE_ARRAY)
1988 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1989 else if (type == SD_BUS_TYPE_VARIANT)
1990 r = bus_message_open_variant(m, c, contents);
1991 else if (type == SD_BUS_TYPE_STRUCT)
1992 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1993 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1994 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2003 /* OK, let's fill it in */
2004 w = m->containers + m->n_containers++;
2005 w->enclosing = type;
2006 w->signature = signature;
2008 w->array_size = array_size;
2011 w->n_offsets = w->offsets_allocated = 0;
2013 w->need_offsets = need_offsets;
2018 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2023 if (!BUS_MESSAGE_IS_GVARIANT(m))
2026 if (c->need_offsets) {
2027 size_t payload, sz, i;
2030 /* Variable-width arrays */
2032 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2033 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2035 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2039 for (i = 0; i < c->n_offsets; i++)
2040 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2044 /* Fixed-width or empty arrays */
2046 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2054 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2060 assert(c->signature);
2062 if (!BUS_MESSAGE_IS_GVARIANT(m))
2065 l = strlen(c->signature);
2067 a = message_extend_body(m, 1, 1 + l, true, false);
2072 memcpy(a+1, c->signature, l);
2077 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2078 bool fixed_size = true;
2079 size_t n_variable = 0;
2088 if (!BUS_MESSAGE_IS_GVARIANT(m))
2091 p = strempty(c->signature);
2095 r = signature_element_length(p, &n);
2104 r = bus_gvariant_is_fixed_size(t);
2109 assert(!c->need_offsets || i <= c->n_offsets);
2111 /* We need to add an offset for each item that has a
2112 * variable size and that is not the last one in the
2116 if (r == 0 && p[n] != 0)
2123 assert(!c->need_offsets || i == c->n_offsets);
2124 assert(c->need_offsets || n_variable == 0);
2126 if (isempty(c->signature)) {
2127 /* The unary type is encoded as fixed 1 byte padding */
2128 a = message_extend_body(m, 1, 1, add_offset, false);
2133 } else if (n_variable <= 0) {
2136 /* Structures with fixed-size members only have to be
2137 * fixed-size themselves. But gvariant requires all fixed-size
2138 * elements to be sized a multiple of their alignment. Hence,
2139 * we must *always* add final padding after the last member so
2140 * the overall size of the structure is properly aligned. */
2142 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2144 assert(alignment > 0);
2146 a = message_extend_body(m, alignment, 0, add_offset, false);
2153 assert(c->offsets[c->n_offsets-1] == m->body_size);
2155 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2157 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2161 p = strempty(c->signature);
2162 for (i = 0, j = 0; i < c->n_offsets; i++) {
2166 r = signature_element_length(p, &n);
2177 r = bus_gvariant_is_fixed_size(t);
2180 if (r > 0 || p[0] == 0)
2184 k = n_variable - 1 - j;
2186 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2195 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2196 struct bus_container *c;
2199 assert_return(m, -EINVAL);
2200 assert_return(!m->sealed, -EPERM);
2201 assert_return(m->n_containers > 0, -EINVAL);
2202 assert_return(!m->poisoned, -ESTALE);
2204 c = message_get_container(m);
2206 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2207 if (c->signature && c->signature[c->index] != 0)
2212 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2213 r = bus_message_close_array(m, c);
2214 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2215 r = bus_message_close_variant(m, c);
2216 else if (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY))
2217 r = bus_message_close_struct(m, c, true);
2219 assert_not_reached("Unknown container type");
2233 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2240 stack[*i].types = types;
2241 stack[*i].n_struct = n_struct;
2242 stack[*i].n_array = n_array;
2248 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2259 *types = stack[*i].types;
2260 *n_struct = stack[*i].n_struct;
2261 *n_array = stack[*i].n_array;
2266 _public_ int sd_bus_message_appendv(
2271 unsigned n_array, n_struct;
2272 TypeStack stack[BUS_CONTAINER_DEPTH];
2273 unsigned stack_ptr = 0;
2276 assert_return(m, -EINVAL);
2277 assert_return(types, -EINVAL);
2278 assert_return(!m->sealed, -EPERM);
2279 assert_return(!m->poisoned, -ESTALE);
2281 n_array = (unsigned) -1;
2282 n_struct = strlen(types);
2287 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2288 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2294 r = sd_bus_message_close_container(m);
2302 if (n_array != (unsigned) -1)
2311 case SD_BUS_TYPE_BYTE: {
2314 x = (uint8_t) va_arg(ap, int);
2315 r = sd_bus_message_append_basic(m, *t, &x);
2319 case SD_BUS_TYPE_BOOLEAN:
2320 case SD_BUS_TYPE_INT32:
2321 case SD_BUS_TYPE_UINT32:
2322 case SD_BUS_TYPE_UNIX_FD: {
2325 /* We assume a boolean is the same as int32_t */
2326 assert_cc(sizeof(int32_t) == sizeof(int));
2328 x = va_arg(ap, uint32_t);
2329 r = sd_bus_message_append_basic(m, *t, &x);
2333 case SD_BUS_TYPE_INT16:
2334 case SD_BUS_TYPE_UINT16: {
2337 x = (uint16_t) va_arg(ap, int);
2338 r = sd_bus_message_append_basic(m, *t, &x);
2342 case SD_BUS_TYPE_INT64:
2343 case SD_BUS_TYPE_UINT64: {
2346 x = va_arg(ap, uint64_t);
2347 r = sd_bus_message_append_basic(m, *t, &x);
2351 case SD_BUS_TYPE_DOUBLE: {
2354 x = va_arg(ap, double);
2355 r = sd_bus_message_append_basic(m, *t, &x);
2359 case SD_BUS_TYPE_STRING:
2360 case SD_BUS_TYPE_OBJECT_PATH:
2361 case SD_BUS_TYPE_SIGNATURE: {
2364 x = va_arg(ap, const char*);
2365 r = sd_bus_message_append_basic(m, *t, x);
2369 case SD_BUS_TYPE_ARRAY: {
2372 r = signature_element_length(t + 1, &k);
2378 memcpy(s, t + 1, k);
2381 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2386 if (n_array == (unsigned) -1) {
2391 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2397 n_array = va_arg(ap, unsigned);
2402 case SD_BUS_TYPE_VARIANT: {
2405 s = va_arg(ap, const char*);
2409 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2413 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2418 n_struct = strlen(s);
2419 n_array = (unsigned) -1;
2424 case SD_BUS_TYPE_STRUCT_BEGIN:
2425 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2428 r = signature_element_length(t, &k);
2435 memcpy(s, t + 1, k - 2);
2438 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2443 if (n_array == (unsigned) -1) {
2448 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2454 n_array = (unsigned) -1;
2470 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2474 assert_return(m, -EINVAL);
2475 assert_return(types, -EINVAL);
2476 assert_return(!m->sealed, -EPERM);
2477 assert_return(!m->poisoned, -ESTALE);
2479 va_start(ap, types);
2480 r = sd_bus_message_appendv(m, types, ap);
2486 _public_ int sd_bus_message_append_array_space(
2496 assert_return(m, -EINVAL);
2497 assert_return(!m->sealed, -EPERM);
2498 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2499 assert_return(ptr || size == 0, -EINVAL);
2500 assert_return(!m->poisoned, -ESTALE);
2502 /* alignment and size of the trivial types (except bool) is
2503 * identical for gvariant and dbus1 marshalling */
2504 align = bus_type_get_alignment(type);
2505 sz = bus_type_get_size(type);
2507 assert_se(align > 0);
2513 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2517 a = message_extend_body(m, align, size, false, false);
2521 r = sd_bus_message_close_container(m);
2529 _public_ int sd_bus_message_append_array(
2537 assert_return(m, -EINVAL);
2538 assert_return(!m->sealed, -EPERM);
2539 assert_return(bus_type_is_trivial(type), -EINVAL);
2540 assert_return(ptr || size == 0, -EINVAL);
2541 assert_return(!m->poisoned, -ESTALE);
2543 r = sd_bus_message_append_array_space(m, type, size, &p);
2547 memcpy_safe(p, ptr, size);
2552 _public_ int sd_bus_message_append_array_iovec(
2555 const struct iovec *iov,
2556 unsigned n /* should be size_t, but is API now… 😞 */) {
2563 assert_return(m, -EINVAL);
2564 assert_return(!m->sealed, -EPERM);
2565 assert_return(bus_type_is_trivial(type), -EINVAL);
2566 assert_return(iov || n == 0, -EINVAL);
2567 assert_return(!m->poisoned, -ESTALE);
2569 size = IOVEC_TOTAL_SIZE(iov, n);
2571 r = sd_bus_message_append_array_space(m, type, size, &p);
2575 for (i = 0; i < n; i++) {
2577 if (iov[i].iov_base)
2578 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2580 memzero(p, iov[i].iov_len);
2582 p = (uint8_t*) p + iov[i].iov_len;
2588 _public_ int sd_bus_message_append_array_memfd(
2595 _cleanup_close_ int copy_fd = -1;
2596 struct bus_body_part *part;
2602 assert_return(m, -EINVAL);
2603 assert_return(memfd >= 0, -EBADF);
2604 assert_return(bus_type_is_trivial(type), -EINVAL);
2605 assert_return(size > 0, -EINVAL);
2606 assert_return(!m->sealed, -EPERM);
2607 assert_return(!m->poisoned, -ESTALE);
2609 r = memfd_set_sealed(memfd);
2613 copy_fd = fcntl(memfd, F_DUPFD_CLOEXEC, 3);
2617 r = memfd_get_size(memfd, &real_size);
2621 if (offset == 0 && size == (uint64_t) -1)
2623 else if (offset + size > real_size)
2626 align = bus_type_get_alignment(type);
2627 sz = bus_type_get_size(type);
2629 assert_se(align > 0);
2632 if (offset % align != 0)
2638 if (size > (uint64_t) (uint32_t) -1)
2641 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2645 a = message_extend_body(m, align, 0, false, false);
2649 part = message_append_part(m);
2653 part->memfd = copy_fd;
2654 part->memfd_offset = offset;
2655 part->sealed = true;
2659 m->body_size += size;
2660 message_extend_containers(m, size);
2662 return sd_bus_message_close_container(m);
2665 _public_ int sd_bus_message_append_string_memfd(
2671 _cleanup_close_ int copy_fd = -1;
2672 struct bus_body_part *part;
2673 struct bus_container *c;
2678 assert_return(m, -EINVAL);
2679 assert_return(memfd >= 0, -EBADF);
2680 assert_return(size > 0, -EINVAL);
2681 assert_return(!m->sealed, -EPERM);
2682 assert_return(!m->poisoned, -ESTALE);
2684 r = memfd_set_sealed(memfd);
2688 copy_fd = fcntl(memfd, FD_CLOEXEC, 3);
2692 r = memfd_get_size(memfd, &real_size);
2696 if (offset == 0 && size == (uint64_t) -1)
2698 else if (offset + size > real_size)
2701 /* We require this to be NUL terminated */
2705 if (size > (uint64_t) (uint32_t) -1)
2708 c = message_get_container(m);
2709 if (c->signature && c->signature[c->index]) {
2710 /* Container signature is already set */
2712 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2717 /* Maybe we can append to the signature? But only if this is the top-level container */
2718 if (c->enclosing != 0)
2721 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2728 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2729 a = message_extend_body(m, 4, 4, false, false);
2733 *(uint32_t*) a = size - 1;
2736 part = message_append_part(m);
2740 part->memfd = copy_fd;
2741 part->memfd_offset = offset;
2742 part->sealed = true;
2746 m->body_size += size;
2747 message_extend_containers(m, size);
2749 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2750 r = message_add_offset(m, m->body_size);
2757 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2763 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2767 assert_return(m, -EINVAL);
2768 assert_return(!m->sealed, -EPERM);
2769 assert_return(!m->poisoned, -ESTALE);
2771 r = sd_bus_message_open_container(m, 'a', "s");
2775 STRV_FOREACH(i, l) {
2776 r = sd_bus_message_append_basic(m, 's', *i);
2781 return sd_bus_message_close_container(m);
2784 static int bus_message_close_header(sd_bus_message *m) {
2788 /* The actual user data is finished now, we just complete the
2789 variant and struct now (at least on gvariant). Remember
2790 this position, so that during parsing we know where to
2791 put the outer container end. */
2792 m->user_body_size = m->body_size;
2794 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2795 const char *signature;
2799 /* Add offset table to end of fields array */
2800 if (m->n_header_offsets >= 1) {
2804 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2806 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2807 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2811 for (i = 0; i < m->n_header_offsets; i++)
2812 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2815 /* Add gvariant NUL byte plus signature to the end of
2816 * the body, followed by the final offset pointing to
2817 * the end of the fields array */
2819 signature = strempty(m->root_container.signature);
2820 l = strlen(signature);
2822 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2823 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2828 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2829 memcpy((uint8_t*) d + 2, signature, l);
2830 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2832 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2835 m->footer_accessible = 1 + l + 2 + sz;
2837 m->header->dbus1.fields_size = m->fields_size;
2838 m->header->dbus1.body_size = m->body_size;
2844 _public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t timeout_usec) {
2845 struct bus_body_part *part;
2850 assert_return(m, -EINVAL);
2855 if (m->n_containers > 0)
2861 if (cookie > 0xffffffffULL &&
2862 !BUS_MESSAGE_IS_GVARIANT(m))
2865 /* In vtables the return signature of method calls is listed,
2866 * let's check if they match if this is a response */
2867 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2868 m->enforced_reply_signature &&
2869 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2872 /* If gvariant marshalling is used we need to close the body structure */
2873 r = bus_message_close_struct(m, &m->root_container, false);
2877 /* If there's a non-trivial signature set, then add it in
2878 * here, but only on dbus1 */
2879 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2880 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2886 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2891 r = bus_message_close_header(m);
2895 if (BUS_MESSAGE_IS_GVARIANT(m))
2896 m->header->dbus2.cookie = cookie;
2898 m->header->dbus1.serial = (uint32_t) cookie;
2900 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout_usec;
2902 /* Add padding at the end of the fields part, since we know
2903 * the body needs to start at an 8 byte alignment. We made
2904 * sure we allocated enough space for this, so all we need to
2905 * do here is to zero it out. */
2906 a = ALIGN8(m->fields_size) - m->fields_size;
2908 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2910 /* If this is something we can send as memfd, then let's seal
2911 the memfd now. Note that we can send memfds as payload only
2912 for directed messages, and not for broadcasts. */
2913 if (m->destination && m->bus->use_memfd) {
2914 MESSAGE_FOREACH_PART(part, i, m)
2915 if (part->memfd >= 0 &&
2917 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2918 part != m->body_end) { /* The last part may never be sent as memfd */
2921 /* Try to seal it if that makes
2922 * sense. First, unmap our own map to
2923 * make sure we don't keep it busy. */
2924 bus_body_part_unmap(part);
2926 /* Then, sync up real memfd size */
2928 r = memfd_set_size(part->memfd, sz);
2932 /* Finally, try to seal */
2933 if (memfd_set_sealed(part->memfd) >= 0)
2934 part->sealed = true;
2938 m->root_container.end = m->user_body_size;
2939 m->root_container.index = 0;
2940 m->root_container.offset_index = 0;
2941 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2948 int bus_body_part_map(struct bus_body_part *part) {
2957 if (part->size <= 0)
2960 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2961 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2962 static const uint8_t zeroes[7] = { };
2963 part->data = (void*) zeroes;
2967 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
2968 psz = PAGE_ALIGN(part->size + shift);
2970 if (part->memfd >= 0)
2971 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
2972 else if (part->is_zero)
2973 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2977 if (p == MAP_FAILED)
2981 part->mmap_begin = p;
2982 part->data = (uint8_t*) p + shift;
2983 part->munmap_this = true;
2988 void bus_body_part_unmap(struct bus_body_part *part) {
2992 if (part->memfd < 0)
2995 if (!part->mmap_begin)
2998 if (!part->munmap_this)
3001 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3003 part->mmap_begin = NULL;
3006 part->munmap_this = false;
3011 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3012 size_t k, start, end;
3017 start = ALIGN_TO((size_t) *rindex, align);
3018 end = start + nbytes;
3023 /* Verify that padding is 0 */
3024 for (k = *rindex; k < start; k++)
3025 if (((const uint8_t*) p)[k] != 0)
3029 *r = (uint8_t*) p + start;
3036 static bool message_end_of_signature(sd_bus_message *m) {
3037 struct bus_container *c;
3041 c = message_get_container(m);
3042 return !c->signature || c->signature[c->index] == 0;
3045 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3046 struct bus_container *c;
3050 c = message_get_container(m);
3051 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3054 if (BUS_MESSAGE_IS_GVARIANT(m))
3055 return index >= c->end;
3057 assert(c->array_size);
3058 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3062 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3063 assert_return(m, -EINVAL);
3064 assert_return(m->sealed, -EPERM);
3066 if (complete && m->n_containers > 0)
3069 if (message_end_of_signature(m))
3072 if (message_end_of_array(m, m->rindex))
3078 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3079 struct bus_body_part *part;
3085 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3086 part = m->cached_rindex_part;
3087 begin = m->cached_rindex_part_begin;
3097 if (index + sz <= begin + part->size) {
3099 r = bus_body_part_map(part);
3104 *p = (uint8_t*) part->data + index - begin;
3106 m->cached_rindex_part = part;
3107 m->cached_rindex_part_begin = begin;
3112 begin += part->size;
3119 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3126 if (!BUS_MESSAGE_IS_GVARIANT(m))
3129 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3132 sz = bus_gvariant_get_size(c->signature);
3136 if (c->offset_index+1 >= c->n_offsets)
3139 /* Variable-size array */
3141 alignment = bus_gvariant_get_alignment(c->signature);
3142 assert(alignment > 0);
3144 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3145 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3148 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3151 /* Fixed-size array */
3152 *rindex = c->begin + (c->offset_index+1) * sz;
3158 } else if (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
3163 if (c->offset_index+1 >= c->n_offsets)
3166 r = signature_element_length(c->signature + c->index, &n);
3170 r = signature_element_length(c->signature + c->index + n, &j);
3175 memcpy(t, c->signature + c->index + n, j);
3178 alignment = bus_gvariant_get_alignment(t);
3181 assert(alignment > 0);
3183 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3184 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3188 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3191 assert_not_reached("Unknown container type");
3196 /* Reached the end */
3202 static int message_peek_body(
3209 size_t k, start, end, padding;
3210 struct bus_body_part *part;
3217 start = ALIGN_TO((size_t) *rindex, align);
3218 padding = start - *rindex;
3219 end = start + nbytes;
3221 if (end > m->user_body_size)
3224 part = find_part(m, *rindex, padding, (void**) &q);
3229 /* Verify padding */
3230 for (k = 0; k < padding; k++)
3235 part = find_part(m, start, nbytes, (void**) &q);
3236 if (!part || (nbytes > 0 && !q))
3247 static bool validate_nul(const char *s, size_t l) {
3249 /* Check for NUL chars in the string */
3250 if (memchr(s, 0, l))
3253 /* Check for NUL termination */
3260 static bool validate_string(const char *s, size_t l) {
3262 if (!validate_nul(s, l))
3265 /* Check if valid UTF8 */
3266 if (!utf8_is_valid(s))
3272 static bool validate_signature(const char *s, size_t l) {
3274 if (!validate_nul(s, l))
3277 /* Check if valid signature */
3278 if (!signature_is_valid(s, true))
3284 static bool validate_object_path(const char *s, size_t l) {
3286 if (!validate_nul(s, l))
3289 if (!object_path_is_valid(s))
3295 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3296 struct bus_container *c;
3301 assert_return(m, -EINVAL);
3302 assert_return(m->sealed, -EPERM);
3303 assert_return(bus_type_is_basic(type), -EINVAL);
3305 if (message_end_of_signature(m))
3308 if (message_end_of_array(m, m->rindex))
3311 c = message_get_container(m);
3312 if (c->signature[c->index] != type)
3317 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3319 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3322 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3326 if (type == SD_BUS_TYPE_STRING)
3327 ok = validate_string(q, c->item_size-1);
3328 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3329 ok = validate_object_path(q, c->item_size-1);
3331 ok = validate_signature(q, c->item_size-1);
3337 *(const char**) p = q;
3341 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3343 if ((size_t) sz != c->item_size)
3346 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3349 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3355 case SD_BUS_TYPE_BYTE:
3357 *(uint8_t*) p = *(uint8_t*) q;
3360 case SD_BUS_TYPE_BOOLEAN:
3362 *(int*) p = !!*(uint8_t*) q;
3365 case SD_BUS_TYPE_INT16:
3366 case SD_BUS_TYPE_UINT16:
3368 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3371 case SD_BUS_TYPE_INT32:
3372 case SD_BUS_TYPE_UINT32:
3374 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3377 case SD_BUS_TYPE_INT64:
3378 case SD_BUS_TYPE_UINT64:
3379 case SD_BUS_TYPE_DOUBLE:
3381 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3384 case SD_BUS_TYPE_UNIX_FD: {
3387 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3392 *(int*) p = m->fds[j];
3398 assert_not_reached("unexpected type");
3402 r = container_next_item(m, c, &rindex);
3407 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3411 r = message_peek_body(m, &rindex, 4, 4, &q);
3415 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3416 r = message_peek_body(m, &rindex, 1, l+1, &q);
3420 if (type == SD_BUS_TYPE_OBJECT_PATH)
3421 ok = validate_object_path(q, l);
3423 ok = validate_string(q, l);
3428 *(const char**) p = q;
3430 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3433 r = message_peek_body(m, &rindex, 1, 1, &q);
3438 r = message_peek_body(m, &rindex, 1, l+1, &q);
3442 if (!validate_signature(q, l))
3446 *(const char**) p = q;
3451 align = bus_type_get_alignment(type);
3454 sz = bus_type_get_size(type);
3457 r = message_peek_body(m, &rindex, align, sz, &q);
3463 case SD_BUS_TYPE_BYTE:
3465 *(uint8_t*) p = *(uint8_t*) q;
3468 case SD_BUS_TYPE_BOOLEAN:
3470 *(int*) p = !!*(uint32_t*) q;
3473 case SD_BUS_TYPE_INT16:
3474 case SD_BUS_TYPE_UINT16:
3476 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3479 case SD_BUS_TYPE_INT32:
3480 case SD_BUS_TYPE_UINT32:
3482 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3485 case SD_BUS_TYPE_INT64:
3486 case SD_BUS_TYPE_UINT64:
3487 case SD_BUS_TYPE_DOUBLE:
3489 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3492 case SD_BUS_TYPE_UNIX_FD: {
3495 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3500 *(int*) p = m->fds[j];
3505 assert_not_reached("Unknown basic type...");
3512 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3518 static int bus_message_enter_array(
3520 struct bus_container *c,
3521 const char *contents,
3522 uint32_t **array_size,
3525 size_t *n_offsets) {
3539 if (!signature_is_single(contents, true))
3542 if (!c->signature || c->signature[c->index] == 0)
3545 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3548 if (!startswith(c->signature + c->index + 1, contents))
3553 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3556 r = message_peek_body(m, &rindex, 4, 4, &q);
3560 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3563 alignment = bus_type_get_alignment(contents[0]);
3567 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3571 *array_size = (uint32_t*) q;
3573 } else if (c->item_size <= 0) {
3575 /* gvariant: empty array */
3580 } else if (bus_gvariant_is_fixed_size(contents)) {
3582 /* gvariant: fixed length array */
3583 *item_size = bus_gvariant_get_size(contents);
3588 size_t where, p = 0, framing, sz;
3591 /* gvariant: variable length array */
3592 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3594 where = rindex + c->item_size - sz;
3595 r = message_peek_body(m, &where, 1, sz, &q);
3599 framing = bus_gvariant_read_word_le(q, sz);
3600 if (framing > c->item_size - sz)
3602 if ((c->item_size - framing) % sz != 0)
3605 *n_offsets = (c->item_size - framing) / sz;
3607 where = rindex + framing;
3608 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3612 *offsets = new(size_t, *n_offsets);
3616 for (i = 0; i < *n_offsets; i++) {
3619 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3620 if (x > c->item_size - sz)
3625 (*offsets)[i] = rindex + x;
3629 *item_size = (*offsets)[0] - rindex;
3634 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3635 c->index += 1 + strlen(contents);
3640 static int bus_message_enter_variant(
3642 struct bus_container *c,
3643 const char *contents,
3644 size_t *item_size) {
3656 if (!signature_is_single(contents, false))
3659 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3662 if (!c->signature || c->signature[c->index] == 0)
3665 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3670 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3673 k = strlen(contents);
3674 if (1+k > c->item_size)
3677 where = rindex + c->item_size - (1+k);
3678 r = message_peek_body(m, &where, 1, 1+k, &q);
3682 if (*(char*) q != 0)
3685 if (memcmp((uint8_t*) q+1, contents, k))
3688 *item_size = c->item_size - (1+k);
3691 r = message_peek_body(m, &rindex, 1, 1, &q);
3696 r = message_peek_body(m, &rindex, 1, l+1, &q);
3700 if (!validate_signature(q, l))
3703 if (!streq(q, contents))
3709 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3715 static int build_struct_offsets(
3717 const char *signature,
3721 size_t *n_offsets) {
3723 unsigned n_variable = 0, n_total = 0, v;
3724 size_t previous = 0, where;
3735 if (isempty(signature)) {
3736 /* Unary type is encoded as *fixed* 1 byte padding */
3737 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3741 if (*(uint8_t *) q != 0)
3750 sz = bus_gvariant_determine_word_size(size, 0);
3754 /* First, loop over signature and count variable elements and
3755 * elements in general. We use this to know how large the
3756 * offset array is at the end of the structure. Note that
3757 * GVariant only stores offsets for all variable size elements
3758 * that are not the last item. */
3764 r = signature_element_length(p, &n);
3773 r = bus_gvariant_is_fixed_size(t);
3778 if (r == 0 && p[n] != 0) /* except the last item */
3785 if (size < n_variable * sz)
3788 where = m->rindex + size - (n_variable * sz);
3789 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3795 *offsets = new(size_t, n_total);
3801 /* Second, loop again and build an offset table */
3807 r = signature_element_length(p, &n);
3816 k = bus_gvariant_get_size(t);
3824 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3827 if (m->rindex + x < previous)
3830 /* The last item's end
3831 * is determined from
3834 x = size - (n_variable * sz);
3836 offset = m->rindex + x;
3842 align = bus_gvariant_get_alignment(t);
3845 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3849 previous = (*offsets)[(*n_offsets)++] = offset;
3854 assert(*n_offsets == n_total);
3856 *item_size = (*offsets)[0] - m->rindex;
3860 static int enter_struct_or_dict_entry(
3862 struct bus_container *c,
3863 const char *contents,
3866 size_t *n_offsets) {
3877 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3880 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3885 /* gvariant with contents */
3886 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3891 static int bus_message_enter_struct(
3893 struct bus_container *c,
3894 const char *contents,
3897 size_t *n_offsets) {
3909 if (!signature_is_valid(contents, false))
3912 if (!c->signature || c->signature[c->index] == 0)
3915 l = strlen(contents);
3917 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3918 !startswith(c->signature + c->index + 1, contents) ||
3919 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3922 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3926 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3927 c->index += 1 + l + 1;
3932 static int bus_message_enter_dict_entry(
3934 struct bus_container *c,
3935 const char *contents,
3938 size_t *n_offsets) {
3947 if (!signature_is_pair(contents))
3950 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3953 if (!c->signature || c->signature[c->index] == 0)
3956 l = strlen(contents);
3958 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3959 !startswith(c->signature + c->index + 1, contents) ||
3960 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3963 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3967 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3968 c->index += 1 + l + 1;
3973 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3975 const char *contents) {
3976 struct bus_container *c, *w;
3977 uint32_t *array_size = NULL;
3980 size_t *offsets = NULL;
3981 size_t n_offsets = 0, item_size = 0;
3984 assert_return(m, -EINVAL);
3985 assert_return(m->sealed, -EPERM);
3986 assert_return(type != 0 || !contents, -EINVAL);
3988 if (type == 0 || !contents) {
3992 /* Allow entering into anonymous containers */
3993 r = sd_bus_message_peek_type(m, &tt, &cc);
3997 if (type != 0 && type != tt)
4000 if (contents && !streq(contents, cc))
4008 * We enforce a global limit on container depth, that is much
4009 * higher than the 32 structs and 32 arrays the specification
4010 * mandates. This is simpler to implement for us, and we need
4011 * this only to ensure our container array doesn't grow
4012 * without bounds. We are happy to return any data from a
4013 * message as long as the data itself is valid, even if the
4014 * overall message might be not.
4016 * Note that the message signature is validated when
4017 * parsing the headers, and that validation does check the
4020 * Note that the specification defines no limits on the depth
4021 * of stacked variants, but we do.
4023 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4026 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4029 if (message_end_of_signature(m))
4032 if (message_end_of_array(m, m->rindex))
4035 c = message_get_container(m);
4037 signature = strdup(contents);
4041 c->saved_index = c->index;
4044 if (type == SD_BUS_TYPE_ARRAY)
4045 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4046 else if (type == SD_BUS_TYPE_VARIANT)
4047 r = bus_message_enter_variant(m, c, contents, &item_size);
4048 else if (type == SD_BUS_TYPE_STRUCT)
4049 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4050 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4051 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4061 /* OK, let's fill it in */
4062 w = m->containers + m->n_containers++;
4063 w->enclosing = type;
4064 w->signature = signature;
4065 w->peeked_signature = NULL;
4069 w->begin = m->rindex;
4071 /* Unary type has fixed size of 1, but virtual size of 0 */
4072 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4073 type == SD_BUS_TYPE_STRUCT &&
4075 w->end = m->rindex + 0;
4077 w->end = m->rindex + c->item_size;
4079 w->array_size = array_size;
4080 w->item_size = item_size;
4081 w->offsets = offsets;
4082 w->n_offsets = n_offsets;
4083 w->offset_index = 0;
4088 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4089 struct bus_container *c;
4093 assert_return(m, -EINVAL);
4094 assert_return(m->sealed, -EPERM);
4095 assert_return(m->n_containers > 0, -ENXIO);
4097 c = message_get_container(m);
4099 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4100 if (c->signature && c->signature[c->index] != 0)
4104 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4105 if (m->rindex < c->end)
4108 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4111 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4112 if (c->begin + l != m->rindex)
4117 free(c->peeked_signature);
4121 c = message_get_container(m);
4124 c->index = c->saved_index;
4125 r = container_next_item(m, c, &m->rindex);
4133 static void message_quit_container(sd_bus_message *m) {
4134 struct bus_container *c;
4138 assert(m->n_containers > 0);
4140 c = message_get_container(m);
4143 assert(m->rindex >= c->before);
4144 m->rindex = c->before;
4146 /* Free container */
4151 /* Correct index of new top-level container */
4152 c = message_get_container(m);
4153 c->index = c->saved_index;
4156 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4157 struct bus_container *c;
4160 assert_return(m, -EINVAL);
4161 assert_return(m->sealed, -EPERM);
4163 if (message_end_of_signature(m))
4166 if (message_end_of_array(m, m->rindex))
4169 c = message_get_container(m);
4171 if (bus_type_is_basic(c->signature[c->index])) {
4175 *type = c->signature[c->index];
4179 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4185 r = signature_element_length(c->signature+c->index+1, &l);
4191 sig = strndup(c->signature + c->index + 1, l);
4195 free(c->peeked_signature);
4196 *contents = c->peeked_signature = sig;
4200 *type = SD_BUS_TYPE_ARRAY;
4205 if (IN_SET(c->signature[c->index], SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN)) {
4211 r = signature_element_length(c->signature+c->index, &l);
4216 sig = strndup(c->signature + c->index + 1, l - 2);
4220 free(c->peeked_signature);
4221 *contents = c->peeked_signature = sig;
4225 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4230 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4234 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4237 if (c->item_size < 2)
4240 /* Look for the NUL delimiter that
4241 separates the payload from the
4242 signature. Since the body might be
4243 in a different part that then the
4244 signature we map byte by byte. */
4246 for (k = 2; k <= c->item_size; k++) {
4249 where = m->rindex + c->item_size - k;
4250 r = message_peek_body(m, &where, 1, k, &q);
4254 if (*(char*) q == 0)
4258 if (k > c->item_size)
4261 free(c->peeked_signature);
4262 c->peeked_signature = strndup((char*) q + 1, k - 1);
4263 if (!c->peeked_signature)
4266 if (!signature_is_valid(c->peeked_signature, true))
4269 *contents = c->peeked_signature;
4274 r = message_peek_body(m, &rindex, 1, 1, &q);
4279 r = message_peek_body(m, &rindex, 1, l+1, &q);
4283 if (!validate_signature(q, l))
4291 *type = SD_BUS_TYPE_VARIANT;
4306 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4307 struct bus_container *c;
4309 assert_return(m, -EINVAL);
4310 assert_return(m->sealed, -EPERM);
4313 message_reset_containers(m);
4316 c = message_get_container(m);
4318 c = message_get_container(m);
4320 c->offset_index = 0;
4322 m->rindex = c->begin;
4325 c->offset_index = 0;
4326 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4328 return !isempty(c->signature);
4331 static int message_read_ap(
4336 unsigned n_array, n_struct;
4337 TypeStack stack[BUS_CONTAINER_DEPTH];
4338 unsigned stack_ptr = 0;
4339 unsigned n_loop = 0;
4347 /* Ideally, we'd just call ourselves recursively on every
4348 * complex type. However, the state of a va_list that is
4349 * passed to a function is undefined after that function
4350 * returns. This means we need to docode the va_list linearly
4351 * in a single stackframe. We hence implement our own
4352 * home-grown stack in an array. */
4354 n_array = (unsigned) -1; /* length of current array entries */
4355 n_struct = strlen(types); /* length of current struct contents signature */
4362 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4363 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4369 r = sd_bus_message_exit_container(m);
4377 if (n_array != (unsigned) -1)
4386 case SD_BUS_TYPE_BYTE:
4387 case SD_BUS_TYPE_BOOLEAN:
4388 case SD_BUS_TYPE_INT16:
4389 case SD_BUS_TYPE_UINT16:
4390 case SD_BUS_TYPE_INT32:
4391 case SD_BUS_TYPE_UINT32:
4392 case SD_BUS_TYPE_INT64:
4393 case SD_BUS_TYPE_UINT64:
4394 case SD_BUS_TYPE_DOUBLE:
4395 case SD_BUS_TYPE_STRING:
4396 case SD_BUS_TYPE_OBJECT_PATH:
4397 case SD_BUS_TYPE_SIGNATURE:
4398 case SD_BUS_TYPE_UNIX_FD: {
4401 p = va_arg(ap, void*);
4402 r = sd_bus_message_read_basic(m, *t, p);
4415 case SD_BUS_TYPE_ARRAY: {
4418 r = signature_element_length(t + 1, &k);
4424 memcpy(s, t + 1, k);
4427 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4438 if (n_array == (unsigned) -1) {
4443 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4449 n_array = va_arg(ap, unsigned);
4454 case SD_BUS_TYPE_VARIANT: {
4457 s = va_arg(ap, const char *);
4461 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4471 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4476 n_struct = strlen(s);
4477 n_array = (unsigned) -1;
4482 case SD_BUS_TYPE_STRUCT_BEGIN:
4483 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4486 r = signature_element_length(t, &k);
4492 memcpy(s, t + 1, k - 2);
4495 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4505 if (n_array == (unsigned) -1) {
4510 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4516 n_array = (unsigned) -1;
4529 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4533 assert_return(m, -EINVAL);
4534 assert_return(m->sealed, -EPERM);
4535 assert_return(types, -EINVAL);
4537 va_start(ap, types);
4538 r = message_read_ap(m, types, ap);
4544 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4547 assert_return(m, -EINVAL);
4548 assert_return(m->sealed, -EPERM);
4550 /* If types is NULL, read exactly one element */
4552 struct bus_container *c;
4555 if (message_end_of_signature(m))
4558 if (message_end_of_array(m, m->rindex))
4561 c = message_get_container(m);
4563 r = signature_element_length(c->signature + c->index, &l);
4567 types = strndupa(c->signature + c->index, l);
4572 case 0: /* Nothing to drop */
4575 case SD_BUS_TYPE_BYTE:
4576 case SD_BUS_TYPE_BOOLEAN:
4577 case SD_BUS_TYPE_INT16:
4578 case SD_BUS_TYPE_UINT16:
4579 case SD_BUS_TYPE_INT32:
4580 case SD_BUS_TYPE_UINT32:
4581 case SD_BUS_TYPE_INT64:
4582 case SD_BUS_TYPE_UINT64:
4583 case SD_BUS_TYPE_DOUBLE:
4584 case SD_BUS_TYPE_STRING:
4585 case SD_BUS_TYPE_OBJECT_PATH:
4586 case SD_BUS_TYPE_SIGNATURE:
4587 case SD_BUS_TYPE_UNIX_FD:
4589 r = sd_bus_message_read_basic(m, *types, NULL);
4593 r = sd_bus_message_skip(m, types + 1);
4599 case SD_BUS_TYPE_ARRAY: {
4602 r = signature_element_length(types + 1, &k);
4608 memcpy(s, types+1, k);
4611 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4616 r = sd_bus_message_skip(m, s);
4623 r = sd_bus_message_exit_container(m);
4628 r = sd_bus_message_skip(m, types + 1 + k);
4635 case SD_BUS_TYPE_VARIANT: {
4636 const char *contents;
4639 r = sd_bus_message_peek_type(m, &x, &contents);
4643 if (x != SD_BUS_TYPE_VARIANT)
4646 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4650 r = sd_bus_message_skip(m, contents);
4655 r = sd_bus_message_exit_container(m);
4659 r = sd_bus_message_skip(m, types + 1);
4666 case SD_BUS_TYPE_STRUCT_BEGIN:
4667 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4670 r = signature_element_length(types, &k);
4676 memcpy(s, types+1, k-2);
4679 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4683 r = sd_bus_message_skip(m, s);
4687 r = sd_bus_message_exit_container(m);
4692 r = sd_bus_message_skip(m, types + k);
4704 _public_ int sd_bus_message_read_array(
4710 struct bus_container *c;
4716 assert_return(m, -EINVAL);
4717 assert_return(m->sealed, -EPERM);
4718 assert_return(bus_type_is_trivial(type), -EINVAL);
4719 assert_return(ptr, -EINVAL);
4720 assert_return(size, -EINVAL);
4721 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4723 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4727 c = message_get_container(m);
4729 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4730 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4734 sz = c->end - c->begin;
4736 align = bus_type_get_alignment(type);
4740 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4744 /* Zero length array, let's return some aligned
4745 * pointer that is not NULL */
4746 p = (uint8_t*) align;
4748 r = message_peek_body(m, &m->rindex, align, sz, &p);
4753 r = sd_bus_message_exit_container(m);
4757 *ptr = (const void*) p;
4763 message_quit_container(m);
4767 static int message_peek_fields(
4778 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4781 static int message_peek_field_uint32(
4793 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4796 /* identical for gvariant and dbus1 */
4798 r = message_peek_fields(m, ri, 4, 4, &q);
4803 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4808 static int message_peek_field_uint64(
4820 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4823 /* identical for gvariant and dbus1 */
4825 r = message_peek_fields(m, ri, 8, 8, &q);
4830 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4835 static int message_peek_field_string(
4837 bool (*validate)(const char *p),
4849 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4854 r = message_peek_fields(m, ri, 1, item_size, &q);
4860 r = message_peek_field_uint32(m, ri, 4, &l);
4864 r = message_peek_fields(m, ri, 1, l+1, &q);
4870 if (!validate_nul(q, l))
4876 if (!validate_string(q, l))
4886 static int message_peek_field_signature(
4899 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4904 r = message_peek_fields(m, ri, 1, item_size, &q);
4910 r = message_peek_fields(m, ri, 1, 1, &q);
4915 r = message_peek_fields(m, ri, 1, l+1, &q);
4920 if (!validate_signature(q, l))
4929 static int message_skip_fields(
4932 uint32_t array_size,
4933 const char **signature) {
4935 size_t original_index;
4941 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4943 original_index = *ri;
4949 if (array_size != (uint32_t) -1 &&
4950 array_size <= *ri - original_index)
4957 if (t == SD_BUS_TYPE_STRING) {
4959 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4965 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4967 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4973 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4975 r = message_peek_field_signature(m, ri, 0, NULL);
4981 } else if (bus_type_is_basic(t)) {
4984 align = bus_type_get_alignment(t);
4985 k = bus_type_get_size(t);
4986 assert(align > 0 && k > 0);
4988 r = message_peek_fields(m, ri, align, k, NULL);
4994 } else if (t == SD_BUS_TYPE_ARRAY) {
4996 r = signature_element_length(*signature+1, &l);
5006 strncpy(sig, *signature + 1, l-1);
5009 alignment = bus_type_get_alignment(sig[0]);
5013 r = message_peek_field_uint32(m, ri, 0, &nas);
5016 if (nas > BUS_ARRAY_MAX_SIZE)
5019 r = message_peek_fields(m, ri, alignment, 0, NULL);
5023 r = message_skip_fields(m, ri, nas, (const char**) &s);
5028 (*signature) += 1 + l;
5030 } else if (t == SD_BUS_TYPE_VARIANT) {
5033 r = message_peek_field_signature(m, ri, 0, &s);
5037 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5043 } else if (IN_SET(t, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
5045 r = signature_element_length(*signature, &l);
5052 strncpy(sig, *signature + 1, l-1);
5055 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5066 int bus_message_parse_fields(sd_bus_message *m) {
5069 uint32_t unix_fds = 0;
5070 bool unix_fds_set = false;
5071 void *offsets = NULL;
5072 unsigned n_offsets = 0;
5078 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5081 /* Read the signature from the end of the body variant first */
5082 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5083 if (m->footer_accessible < 1 + sz)
5086 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5088 if (p < (char*) m->footer)
5095 /* We found the beginning of the signature
5096 * string, yay! We require the body to be a
5097 * structure, so verify it and then strip the
5098 * opening/closing brackets. */
5100 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5102 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5103 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5106 c = strndup(p + 1 + 1, l - 2);
5110 free(m->root_container.signature);
5111 m->root_container.signature = c;
5118 /* Calculate the actual user body size, by removing
5119 * the trailing variant signature and struct offset
5121 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5123 /* Pull out the offset table for the fields array */
5124 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5129 ri = m->fields_size - sz;
5130 r = message_peek_fields(m, &ri, 1, sz, &q);
5134 framing = bus_gvariant_read_word_le(q, sz);
5135 if (framing >= m->fields_size - sz)
5137 if ((m->fields_size - framing) % sz != 0)
5141 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5145 n_offsets = (m->fields_size - framing) / sz;
5148 m->user_body_size = m->body_size;
5151 while (ri < m->fields_size) {
5152 _cleanup_free_ char *sig = NULL;
5153 const char *signature;
5154 uint64_t field_type;
5155 size_t item_size = (size_t) -1;
5157 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5166 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5168 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5172 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5176 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5183 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5188 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5193 where = ri = ALIGN_TO(ri, 8);
5194 item_size = end - ri;
5195 r = message_peek_fields(m, &where, 1, item_size, &q);
5199 b = memrchr(q, 0, item_size);
5203 sig = strndup(b+1, item_size - (b+1-(char*) q));
5208 item_size = b - (char*) q;
5210 r = message_peek_field_signature(m, &ri, 0, &signature);
5215 switch (field_type) {
5217 case _BUS_MESSAGE_HEADER_INVALID:
5220 case BUS_MESSAGE_HEADER_PATH:
5225 if (!streq(signature, "o"))
5228 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5231 case BUS_MESSAGE_HEADER_INTERFACE:
5236 if (!streq(signature, "s"))
5239 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5242 case BUS_MESSAGE_HEADER_MEMBER:
5247 if (!streq(signature, "s"))
5250 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5253 case BUS_MESSAGE_HEADER_ERROR_NAME:
5258 if (!streq(signature, "s"))
5261 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5263 m->error._need_free = -1;
5267 case BUS_MESSAGE_HEADER_DESTINATION:
5272 if (!streq(signature, "s"))
5275 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5278 case BUS_MESSAGE_HEADER_SENDER:
5283 if (!streq(signature, "s"))
5286 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5288 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client) {
5289 m->creds.unique_name = (char*) m->sender;
5290 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5295 case BUS_MESSAGE_HEADER_SIGNATURE: {
5299 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5302 if (m->root_container.signature)
5305 if (!streq(signature, "g"))
5308 r = message_peek_field_signature(m, &ri, item_size, &s);
5316 free(m->root_container.signature);
5317 m->root_container.signature = c;
5321 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5323 if (m->reply_cookie != 0)
5326 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5327 /* 64bit on dbus2 */
5329 if (!streq(signature, "t"))
5332 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5336 /* 32bit on dbus1 */
5339 if (!streq(signature, "u"))
5342 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5346 m->reply_cookie = serial;
5349 if (m->reply_cookie == 0)
5354 case BUS_MESSAGE_HEADER_UNIX_FDS:
5358 if (!streq(signature, "u"))
5361 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5365 unix_fds_set = true;
5369 if (!BUS_MESSAGE_IS_GVARIANT(m))
5370 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5379 if (m->n_fds != unix_fds)
5382 switch (m->header->type) {
5384 case SD_BUS_MESSAGE_SIGNAL:
5385 if (!m->path || !m->interface || !m->member)
5388 if (m->reply_cookie != 0)
5393 case SD_BUS_MESSAGE_METHOD_CALL:
5395 if (!m->path || !m->member)
5398 if (m->reply_cookie != 0)
5403 case SD_BUS_MESSAGE_METHOD_RETURN:
5405 if (m->reply_cookie == 0)
5409 case SD_BUS_MESSAGE_METHOD_ERROR:
5411 if (m->reply_cookie == 0 || !m->error.name)
5416 /* Refuse non-local messages that claim they are local */
5417 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5419 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5421 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5424 m->root_container.end = m->user_body_size;
5426 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5427 r = build_struct_offsets(
5429 m->root_container.signature,
5431 &m->root_container.item_size,
5432 &m->root_container.offsets,
5433 &m->root_container.n_offsets);
5438 /* Try to read the error message, but if we can't it's a non-issue */
5439 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5440 (void) sd_bus_message_read(m, "s", &m->error.message);
5445 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5446 assert_return(m, -EINVAL);
5447 assert_return(destination, -EINVAL);
5448 assert_return(!m->sealed, -EPERM);
5449 assert_return(!m->destination, -EEXIST);
5451 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5454 _public_ int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) {
5455 assert_return(m, -EINVAL);
5456 assert_return(sender, -EINVAL);
5457 assert_return(!m->sealed, -EPERM);
5458 assert_return(!m->sender, -EEXIST);
5460 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5463 #if 0 /// UNNEEDED by elogind
5464 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5468 struct bus_body_part *part;
5474 total = BUS_MESSAGE_SIZE(m);
5480 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5481 MESSAGE_FOREACH_PART(part, i, m)
5482 e = mempcpy(e, part->data, part->size);
5484 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5493 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5500 r = sd_bus_message_enter_container(m, 'a', "s");
5504 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5505 r = strv_extend(l, s);
5512 r = sd_bus_message_exit_container(m);
5519 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5523 assert_return(m, -EINVAL);
5524 assert_return(m->sealed, -EPERM);
5525 assert_return(l, -EINVAL);
5527 r = bus_message_read_strv_extend(m, &strv);
5537 static int bus_message_get_arg_skip(
5541 const char **_contents) {
5546 r = sd_bus_message_rewind(m, true);
5551 const char *contents;
5554 r = sd_bus_message_peek_type(m, &type, &contents);
5560 /* Don't match against arguments after the first one we don't understand */
5561 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5562 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5567 *_contents = contents;
5573 r = sd_bus_message_skip(m, NULL);
5580 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5587 r = bus_message_get_arg_skip(m, i, &type, NULL);
5591 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5594 return sd_bus_message_read_basic(m, type, str);
5597 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5598 const char *contents;
5605 r = bus_message_get_arg_skip(m, i, &type, &contents);
5609 if (type != SD_BUS_TYPE_ARRAY)
5611 if (!STR_IN_SET(contents, "s", "o", "g"))
5614 return sd_bus_message_read_strv(m, strv);
5617 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5618 assert_return(m, EINVAL);
5620 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5623 return sd_bus_error_get_errno(&m->error);
5626 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5627 struct bus_container *c;
5629 assert_return(m, NULL);
5631 c = complete ? &m->root_container : message_get_container(m);
5632 return strempty(c->signature);
5635 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5636 assert_return(m, -EINVAL);
5638 return isempty(m->root_container.signature);
5641 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5642 assert_return(m, -EINVAL);
5644 return streq(strempty(m->root_container.signature), strempty(signature));
5647 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5648 bool done_something = false;
5651 assert_return(m, -EINVAL);
5652 assert_return(source, -EINVAL);
5653 assert_return(!m->sealed, -EPERM);
5654 assert_return(source->sealed, -EPERM);
5657 const char *contents;
5672 r = sd_bus_message_peek_type(source, &type, &contents);
5678 done_something = true;
5680 if (bus_type_is_container(type) > 0) {
5682 r = sd_bus_message_enter_container(source, type, contents);
5686 r = sd_bus_message_open_container(m, type, contents);
5690 r = sd_bus_message_copy(m, source, true);
5694 r = sd_bus_message_close_container(m);
5698 r = sd_bus_message_exit_container(source);
5705 r = sd_bus_message_read_basic(source, type, &basic);
5711 if (IN_SET(type, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_STRING))
5712 r = sd_bus_message_append_basic(m, type, basic.string);
5714 r = sd_bus_message_append_basic(m, type, &basic);
5721 return done_something;
5724 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5729 assert_return(m, -EINVAL);
5730 assert_return(m->sealed, -EPERM);
5731 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5732 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5733 assert_return(type || contents, -EINVAL);
5734 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5736 r = sd_bus_message_peek_type(m, &t, &c);
5740 if (type != 0 && type != t)
5743 if (contents && !streq_ptr(contents, c))
5749 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5750 assert_return(m, NULL);
5755 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5756 _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5764 switch ((*m)->header->type) {
5766 case SD_BUS_MESSAGE_SIGNAL:
5767 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5773 case SD_BUS_MESSAGE_METHOD_CALL:
5774 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5780 case SD_BUS_MESSAGE_METHOD_RETURN:
5781 case SD_BUS_MESSAGE_METHOD_ERROR:
5783 r = sd_bus_message_new(bus, &n, (*m)->header->type);
5789 n->reply_cookie = (*m)->reply_cookie;
5791 r = message_append_reply_cookie(n, n->reply_cookie);
5795 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5796 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5800 n->error._need_free = -1;
5809 if ((*m)->destination && !n->destination) {
5810 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5815 if ((*m)->sender && !n->sender) {
5816 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5821 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5823 r = sd_bus_message_copy(n, *m, true);
5827 timeout = (*m)->timeout;
5828 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5829 timeout = BUS_DEFAULT_TIMEOUT;
5831 r = sd_bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5835 sd_bus_message_unref(*m);
5841 #if 0 /// UNNEEDED by elogind
5842 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5846 assert_return(!m->sealed, -EPERM);
5847 assert_return(!m->sender, -EPERM);
5849 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5853 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5854 assert_return(m, -EINVAL);
5855 assert_return(priority, -EINVAL);
5857 *priority = m->priority;
5861 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5862 assert_return(m, -EINVAL);
5863 assert_return(!m->sealed, -EPERM);
5865 m->priority = priority;