2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "alloc-util.h"
27 #include "bus-gvariant.h"
28 #include "bus-internal.h"
29 #include "bus-message.h"
30 #include "bus-signature.h"
35 #include "memfd-util.h"
36 #include "string-util.h"
38 #include "time-util.h"
42 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
44 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
49 if (old_base == new_base)
52 if ((uint8_t*) p < (uint8_t*) old_base)
55 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
58 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
61 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
65 if (part->memfd >= 0) {
66 /* If we can reuse the memfd, try that. For that it
67 * can't be sealed yet. */
70 assert(part->memfd_offset == 0);
71 assert(part->data == part->mmap_begin);
72 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
75 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
77 safe_close(part->memfd);
80 } else if (part->munmap_this)
81 munmap(part->mmap_begin, part->mapped);
82 else if (part->free_this)
89 static void message_reset_parts(sd_bus_message *m) {
90 struct bus_body_part *part;
95 while (m->n_body_parts > 0) {
96 struct bus_body_part *next = part->next;
97 message_free_part(m, part);
104 m->cached_rindex_part = NULL;
105 m->cached_rindex_part_begin = 0;
108 static void message_reset_containers(sd_bus_message *m) {
113 for (i = 0; i < m->n_containers; i++) {
114 free(m->containers[i].signature);
115 free(m->containers[i].offsets);
118 m->containers = mfree(m->containers);
120 m->n_containers = m->containers_allocated = 0;
121 m->root_container.index = 0;
124 static void message_free(sd_bus_message *m) {
130 message_reset_parts(m);
132 if (m->release_kdbus)
133 bus_kernel_cmd_free(m->bus, (uint8_t *) m->kdbus - (uint8_t *) m->bus->kdbus_buffer);
138 sd_bus_unref(m->bus);
141 close_many(m->fds, m->n_fds);
145 if (m->iovec != m->iovec_fixed)
148 m->destination_ptr = mfree(m->destination_ptr);
149 message_reset_containers(m);
150 free(m->root_container.signature);
151 free(m->root_container.offsets);
153 free(m->root_container.peeked_signature);
155 bus_creds_done(&m->creds);
159 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
161 size_t old_size, new_size, start;
168 old_size = sizeof(struct bus_header) + m->fields_size;
169 start = ALIGN_TO(old_size, align);
170 new_size = start + sz;
172 if (new_size < start ||
173 new_size > (size_t) ((uint32_t) -1))
176 if (old_size == new_size)
177 return (uint8_t*) m->header + old_size;
179 if (m->free_header) {
180 np = realloc(m->header, ALIGN8(new_size));
184 /* Initially, the header is allocated as part of
185 * the sd_bus_message itself, let's replace it by
188 np = malloc(ALIGN8(new_size));
192 memcpy(np, m->header, sizeof(struct bus_header));
195 /* Zero out padding */
196 if (start > old_size)
197 memzero((uint8_t*) np + old_size, start - old_size);
201 m->fields_size = new_size - sizeof(struct bus_header);
203 /* Adjust quick access pointers */
204 m->path = adjust_pointer(m->path, op, old_size, m->header);
205 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
206 m->member = adjust_pointer(m->member, op, old_size, m->header);
207 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
208 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
209 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
211 m->free_header = true;
214 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
217 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
220 return (uint8_t*) np + start;
227 static int message_append_field_string(
239 /* dbus1 only allows 8bit header field ids */
243 /* dbus1 doesn't allow strings over 32bit, let's enforce this
244 * globally, to not risk convertability */
246 if (l > (size_t) (uint32_t) -1)
249 /* Signature "(yv)" where the variant contains "s" */
251 if (BUS_MESSAGE_IS_GVARIANT(m)) {
253 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
254 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
258 *((uint64_t*) p) = h;
265 *ret = (char*) p + 8;
268 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
269 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
278 ((uint32_t*) p)[1] = l;
279 memcpy(p + 8, s, l + 1);
282 *ret = (char*) p + 8;
288 static int message_append_field_signature(
299 /* dbus1 only allows 8bit header field ids */
303 /* dbus1 doesn't allow signatures over 8bit, let's enforce
304 * this globally, to not risk convertability */
309 /* Signature "(yv)" where the variant contains "g" */
311 if (BUS_MESSAGE_IS_GVARIANT(m))
312 /* For gvariant the serialization is the same as for normal strings */
313 return message_append_field_string(m, h, 'g', s, ret);
315 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
316 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
322 p[2] = SD_BUS_TYPE_SIGNATURE;
325 memcpy(p + 5, s, l + 1);
328 *ret = (const char*) p + 5;
334 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
339 /* dbus1 only allows 8bit header field ids */
343 if (BUS_MESSAGE_IS_GVARIANT(m)) {
344 /* (field id 64bit + ((value + NUL + signature string 'u') */
346 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
350 *((uint64_t*) p) = h;
351 *((uint32_t*) (p + 8)) = x;
355 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
356 p = message_extend_fields(m, 8, 4 + 4, false);
365 ((uint32_t*) p)[1] = x;
371 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
376 /* dbus1 only allows 8bit header field ids */
380 if (BUS_MESSAGE_IS_GVARIANT(m)) {
381 /* (field id 64bit + ((value + NUL + signature string 't') */
383 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
387 *((uint64_t*) p) = h;
388 *((uint64_t*) (p + 8)) = x;
392 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
393 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
406 ((uint64_t*) p)[1] = x;
412 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
415 if (BUS_MESSAGE_IS_GVARIANT(m))
416 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
418 /* 64bit cookies are not supported on dbus1 */
419 if (cookie > 0xffffffffUL)
422 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
426 int bus_message_from_header(
429 size_t header_accessible,
431 size_t footer_accessible,
437 sd_bus_message **ret) {
439 _cleanup_free_ sd_bus_message *m = NULL;
440 struct bus_header *h;
444 assert(header || header_accessible <= 0);
445 assert(footer || footer_accessible <= 0);
446 assert(fds || n_fds <= 0);
449 if (header_accessible < sizeof(struct bus_header))
452 if (header_accessible > message_size)
454 if (footer_accessible > message_size)
458 if (!IN_SET(h->version, 1, 2))
461 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
464 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
467 /* Note that we are happy with unknown flags in the flags header! */
469 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
472 label_sz = strlen(label);
483 m->header_accessible = header_accessible;
485 m->footer_accessible = footer_accessible;
487 if (BUS_MESSAGE_IS_GVARIANT(m)) {
490 if (h->dbus2.cookie == 0)
493 /* dbus2 derives the sizes from the message size and
494 the offset table at the end, since it is formatted as
495 gvariant "yyyyuta{tv}v". Since the message itself is a
496 structure with precisely to variable sized entries,
497 there's only one offset in the table, which marks the
498 end of the fields array. */
500 ws = bus_gvariant_determine_word_size(message_size, 0);
501 if (footer_accessible < ws)
504 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
505 if (ALIGN8(m->fields_size) > message_size - ws)
507 if (m->fields_size < sizeof(struct bus_header))
510 m->fields_size -= sizeof(struct bus_header);
511 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
513 if (h->dbus1.serial == 0)
516 /* dbus1 has the sizes in the header */
517 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
518 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
520 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
528 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
529 memcpy(m->creds.label, label, label_sz + 1);
531 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
534 m->bus = sd_bus_ref(bus);
541 int bus_message_from_malloc(
548 sd_bus_message **ret) {
554 r = bus_message_from_header(
556 buffer, length, /* in this case the initial bytes and the final bytes are the same */
565 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
568 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
570 m->body.sealed = true;
575 m->iovec = m->iovec_fixed;
576 m->iovec[0].iov_base = buffer;
577 m->iovec[0].iov_len = length;
579 r = bus_message_parse_fields(m);
583 /* We take possession of the memory and fds now */
584 m->free_header = true;
595 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
600 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
605 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
606 m->header->endian = BUS_NATIVE_ENDIAN;
607 m->header->type = type;
608 m->header->version = bus->message_version;
609 m->allow_fds = bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
610 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
611 m->bus = sd_bus_ref(bus);
613 if (bus->allow_interactive_authorization)
614 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
619 _public_ int sd_bus_message_new_signal(
623 const char *interface,
624 const char *member) {
629 assert_return(bus, -ENOTCONN);
630 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
631 assert_return(object_path_is_valid(path), -EINVAL);
632 assert_return(interface_name_is_valid(interface), -EINVAL);
633 assert_return(member_name_is_valid(member), -EINVAL);
634 assert_return(m, -EINVAL);
636 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
640 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
642 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
645 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
648 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
656 sd_bus_message_unref(t);
660 _public_ int sd_bus_message_new_method_call(
663 const char *destination,
665 const char *interface,
666 const char *member) {
671 assert_return(bus, -ENOTCONN);
672 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
673 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
674 assert_return(object_path_is_valid(path), -EINVAL);
675 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
676 assert_return(member_name_is_valid(member), -EINVAL);
677 assert_return(m, -EINVAL);
679 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
683 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
686 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
691 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
697 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
710 static int message_new_reply(
711 sd_bus_message *call,
713 sd_bus_message **m) {
718 assert_return(call, -EINVAL);
719 assert_return(call->sealed, -EPERM);
720 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
721 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
722 assert_return(m, -EINVAL);
724 t = message_new(call->bus, type);
728 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
729 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
730 if (t->reply_cookie == 0)
733 r = message_append_reply_cookie(t, t->reply_cookie);
738 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
743 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
744 t->enforced_reply_signature = call->enforced_reply_signature;
754 _public_ int sd_bus_message_new_method_return(
755 sd_bus_message *call,
756 sd_bus_message **m) {
758 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
761 _public_ int sd_bus_message_new_method_error(
762 sd_bus_message *call,
764 const sd_bus_error *e) {
769 assert_return(sd_bus_error_is_set(e), -EINVAL);
770 assert_return(m, -EINVAL);
772 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
776 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
781 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
786 t->error._need_free = -1;
796 _public_ int sd_bus_message_new_method_errorf(
797 sd_bus_message *call,
803 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
806 assert_return(name, -EINVAL);
807 assert_return(m, -EINVAL);
809 va_start(ap, format);
810 bus_error_setfv(&error, name, format, ap);
813 return sd_bus_message_new_method_error(call, m, &error);
816 _public_ int sd_bus_message_new_method_errno(
817 sd_bus_message *call,
820 const sd_bus_error *p) {
822 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
824 if (sd_bus_error_is_set(p))
825 return sd_bus_message_new_method_error(call, m, p);
827 sd_bus_error_set_errno(&berror, error);
829 return sd_bus_message_new_method_error(call, m, &berror);
832 #if 0 /// UNNEEDED by elogind
833 _public_ int sd_bus_message_new_method_errnof(
834 sd_bus_message *call,
840 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
843 va_start(ap, format);
844 sd_bus_error_set_errnofv(&berror, error, format, ap);
847 return sd_bus_message_new_method_error(call, m, &berror);
851 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
855 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
856 m->creds.well_known_names_local = true;
857 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
860 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
864 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
865 m->creds.well_known_names_driver = true;
866 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
869 int bus_message_new_synthetic_error(
872 const sd_bus_error *e,
873 sd_bus_message **m) {
879 assert(sd_bus_error_is_set(e));
882 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
886 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
887 t->reply_cookie = cookie;
889 r = message_append_reply_cookie(t, t->reply_cookie);
893 if (bus && bus->unique_name) {
894 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
899 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
904 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
909 t->error._need_free = -1;
911 bus_message_set_sender_driver(bus, t);
921 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
926 assert(m->n_ref > 0);
932 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
937 assert(m->n_ref > 0);
947 #if 0 /// UNNEEDED by elogind
948 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
949 assert_return(m, -EINVAL);
950 assert_return(type, -EINVAL);
952 *type = m->header->type;
956 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
959 assert_return(m, -EINVAL);
960 assert_return(cookie, -EINVAL);
962 c = BUS_MESSAGE_COOKIE(m);
966 *cookie = BUS_MESSAGE_COOKIE(m);
970 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
971 assert_return(m, -EINVAL);
972 assert_return(cookie, -EINVAL);
974 if (m->reply_cookie == 0)
977 *cookie = m->reply_cookie;
981 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
982 assert_return(m, -EINVAL);
984 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
985 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
988 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
989 assert_return(m, -EINVAL);
991 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
995 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
996 assert_return(m, -EINVAL);
998 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
999 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
1002 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1003 assert_return(m, NULL);
1008 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1009 assert_return(m, NULL);
1011 return m->interface;
1014 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1015 assert_return(m, NULL);
1020 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1021 assert_return(m, NULL);
1023 return m->destination;
1026 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1027 assert_return(m, NULL);
1032 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1033 assert_return(m, NULL);
1035 if (!sd_bus_error_is_set(&m->error))
1041 #if 0 /// UNNEEDED by elogind
1042 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1043 assert_return(m, -EINVAL);
1044 assert_return(usec, -EINVAL);
1046 if (m->monotonic <= 0)
1049 *usec = m->monotonic;
1053 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1054 assert_return(m, -EINVAL);
1055 assert_return(usec, -EINVAL);
1057 if (m->realtime <= 0)
1060 *usec = m->realtime;
1064 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1065 assert_return(m, -EINVAL);
1066 assert_return(seqnum, -EINVAL);
1071 *seqnum = m->seqnum;
1076 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1077 assert_return(m, NULL);
1079 if (m->creds.mask == 0)
1085 _public_ int sd_bus_message_is_signal(
1087 const char *interface,
1088 const char *member) {
1090 assert_return(m, -EINVAL);
1092 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1095 if (interface && (!m->interface || !streq(m->interface, interface)))
1098 if (member && (!m->member || !streq(m->member, member)))
1104 _public_ int sd_bus_message_is_method_call(
1106 const char *interface,
1107 const char *member) {
1109 assert_return(m, -EINVAL);
1111 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1114 if (interface && (!m->interface || !streq(m->interface, interface)))
1117 if (member && (!m->member || !streq(m->member, member)))
1123 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1124 assert_return(m, -EINVAL);
1126 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1129 if (name && (!m->error.name || !streq(m->error.name, name)))
1135 #if 0 /// UNNEEDED by elogind
1136 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1137 assert_return(m, -EINVAL);
1138 assert_return(!m->sealed, -EPERM);
1139 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1141 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
1146 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1147 assert_return(m, -EINVAL);
1148 assert_return(!m->sealed, -EPERM);
1150 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
1155 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1156 assert_return(m, -EINVAL);
1157 assert_return(!m->sealed, -EPERM);
1159 SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
1165 static struct bus_container *message_get_container(sd_bus_message *m) {
1168 if (m->n_containers == 0)
1169 return &m->root_container;
1171 assert(m->containers);
1172 return m->containers + m->n_containers - 1;
1175 struct bus_body_part *message_append_part(sd_bus_message *m) {
1176 struct bus_body_part *part;
1183 if (m->n_body_parts <= 0) {
1187 assert(m->body_end);
1189 part = new0(struct bus_body_part, 1);
1195 m->body_end->next = part;
1205 static void part_zero(struct bus_body_part *part, size_t sz) {
1210 /* All other fields can be left in their defaults */
1211 assert(!part->data);
1212 assert(part->memfd < 0);
1215 part->is_zero = true;
1216 part->sealed = true;
1219 static int part_make_space(
1220 struct sd_bus_message *m,
1221 struct bus_body_part *part,
1230 assert(!part->sealed);
1235 if (!part->data && part->memfd < 0) {
1236 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1237 part->mmap_begin = part->data;
1240 if (part->memfd >= 0) {
1242 if (part->allocated == 0 || sz > part->allocated) {
1243 uint64_t new_allocated;
1245 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1246 r = memfd_set_size(part->memfd, new_allocated);
1252 part->allocated = new_allocated;
1255 if (!part->data || sz > part->mapped) {
1258 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1259 if (part->mapped <= 0)
1260 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1262 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1264 if (n == MAP_FAILED) {
1269 part->mmap_begin = part->data = n;
1271 part->memfd_offset = 0;
1274 part->munmap_this = true;
1276 if (part->allocated == 0 || sz > part->allocated) {
1277 size_t new_allocated;
1279 new_allocated = sz > 0 ? 2 * sz : 64;
1280 n = realloc(part->data, new_allocated);
1287 part->allocated = new_allocated;
1288 part->free_this = true;
1293 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1299 static int message_add_offset(sd_bus_message *m, size_t offset) {
1300 struct bus_container *c;
1303 assert(BUS_MESSAGE_IS_GVARIANT(m));
1305 /* Add offset to current container, unless this is the first
1306 * item in it, which will have the 0 offset, which we can
1308 c = message_get_container(m);
1310 if (!c->need_offsets)
1313 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1316 c->offsets[c->n_offsets++] = offset;
1320 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1321 struct bus_container *c;
1328 /* Update counters */
1329 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1332 *c->array_size += expand;
1336 static void *message_extend_body(
1341 bool force_inline) {
1343 size_t start_body, end_body, padding, added;
1354 start_body = ALIGN_TO((size_t) m->body_size, align);
1355 end_body = start_body + sz;
1357 padding = start_body - m->body_size;
1358 added = padding + sz;
1360 /* Check for 32bit overflows */
1361 if (end_body > (size_t) ((uint32_t) -1) ||
1362 end_body < start_body) {
1368 struct bus_body_part *part = NULL;
1372 m->n_body_parts <= 0 ||
1373 m->body_end->sealed ||
1374 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1375 (force_inline && m->body_end->size > MEMFD_MIN_SIZE); /* if this must be an inlined extension, let's create a new part if the previous part is large enough to be inlined */
1379 part = message_append_part(m);
1383 part_zero(part, padding);
1386 part = message_append_part(m);
1390 r = part_make_space(m, part, sz, &p);
1394 struct bus_container *c;
1396 size_t os, start_part, end_part;
1402 start_part = ALIGN_TO(part->size, align);
1403 end_part = start_part + sz;
1405 r = part_make_space(m, part, end_part, &p);
1410 memzero(p, padding);
1411 p = (uint8_t*) p + padding;
1414 /* Readjust pointers */
1415 for (c = m->containers; c < m->containers + m->n_containers; c++)
1416 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1418 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1421 /* Return something that is not NULL and is aligned */
1422 p = (uint8_t *) NULL + align;
1424 m->body_size = end_body;
1425 message_extend_containers(m, added);
1428 r = message_add_offset(m, end_body);
1438 static int message_push_fd(sd_bus_message *m, int fd) {
1449 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1453 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1461 m->fds[m->n_fds] = copy;
1467 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1468 _cleanup_close_ int fd = -1;
1469 struct bus_container *c;
1473 assert_return(m, -EINVAL);
1474 assert_return(!m->sealed, -EPERM);
1475 assert_return(bus_type_is_basic(type), -EINVAL);
1476 assert_return(!m->poisoned, -ESTALE);
1478 c = message_get_container(m);
1480 if (c->signature && c->signature[c->index]) {
1481 /* Container signature is already set */
1483 if (c->signature[c->index] != type)
1488 /* Maybe we can append to the signature? But only if this is the top-level container */
1489 if (c->enclosing != 0)
1492 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1499 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1505 case SD_BUS_TYPE_SIGNATURE:
1506 case SD_BUS_TYPE_STRING:
1509 /* Fall through... */
1510 case SD_BUS_TYPE_OBJECT_PATH:
1518 case SD_BUS_TYPE_BOOLEAN:
1520 u8 = p && *(int*) p;
1526 case SD_BUS_TYPE_UNIX_FD:
1531 fd = message_push_fd(m, *(int*) p);
1542 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1543 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1550 a = message_extend_body(m, align, sz, true, false);
1557 *stored = (const uint8_t*) a;
1564 case SD_BUS_TYPE_STRING:
1565 /* To make things easy we'll serialize a NULL string
1566 * into the empty string */
1569 /* Fall through... */
1570 case SD_BUS_TYPE_OBJECT_PATH:
1576 sz = 4 + strlen(p) + 1;
1579 case SD_BUS_TYPE_SIGNATURE:
1584 sz = 1 + strlen(p) + 1;
1587 case SD_BUS_TYPE_BOOLEAN:
1589 u32 = p && *(int*) p;
1595 case SD_BUS_TYPE_UNIX_FD:
1600 fd = message_push_fd(m, *(int*) p);
1611 align = bus_type_get_alignment(type);
1612 sz = bus_type_get_size(type);
1619 a = message_extend_body(m, align, sz, false, false);
1623 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1624 *(uint32_t*) a = sz - 5;
1625 memcpy((uint8_t*) a + 4, p, sz - 4);
1628 *stored = (const uint8_t*) a + 4;
1630 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1631 *(uint8_t*) a = sz - 2;
1632 memcpy((uint8_t*) a + 1, p, sz - 1);
1635 *stored = (const uint8_t*) a + 1;
1644 if (type == SD_BUS_TYPE_UNIX_FD)
1647 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1654 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1655 return message_append_basic(m, type, p, NULL);
1658 #if 0 /// UNNEEDED by elogind
1659 _public_ int sd_bus_message_append_string_space(
1664 struct bus_container *c;
1667 assert_return(m, -EINVAL);
1668 assert_return(s, -EINVAL);
1669 assert_return(!m->sealed, -EPERM);
1670 assert_return(!m->poisoned, -ESTALE);
1672 c = message_get_container(m);
1674 if (c->signature && c->signature[c->index]) {
1675 /* Container signature is already set */
1677 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1682 /* Maybe we can append to the signature? But only if this is the top-level container */
1683 if (c->enclosing != 0)
1686 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1693 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1694 a = message_extend_body(m, 1, size + 1, true, false);
1700 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1704 *(uint32_t*) a = size;
1710 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1716 _public_ int sd_bus_message_append_string_iovec(
1718 const struct iovec *iov,
1726 assert_return(m, -EINVAL);
1727 assert_return(!m->sealed, -EPERM);
1728 assert_return(iov || n == 0, -EINVAL);
1729 assert_return(!m->poisoned, -ESTALE);
1731 size = IOVEC_TOTAL_SIZE(iov, n);
1733 r = sd_bus_message_append_string_space(m, size, &p);
1737 for (i = 0; i < n; i++) {
1739 if (iov[i].iov_base)
1740 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1742 memset(p, ' ', iov[i].iov_len);
1744 p += iov[i].iov_len;
1751 static int bus_message_open_array(
1753 struct bus_container *c,
1754 const char *contents,
1755 uint32_t **array_size,
1757 bool *need_offsets) {
1767 assert(need_offsets);
1769 if (!signature_is_single(contents, true))
1772 if (c->signature && c->signature[c->index]) {
1774 /* Verify the existing signature */
1776 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1779 if (!startswith(c->signature + c->index + 1, contents))
1782 nindex = c->index + 1 + strlen(contents);
1786 if (c->enclosing != 0)
1789 /* Extend the existing signature */
1791 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1797 nindex = e - c->signature;
1800 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1801 alignment = bus_gvariant_get_alignment(contents);
1805 /* Add alignment padding and add to offset list */
1806 if (!message_extend_body(m, alignment, 0, false, false))
1809 r = bus_gvariant_is_fixed_size(contents);
1813 *begin = m->body_size;
1814 *need_offsets = r == 0;
1818 struct bus_body_part *o;
1820 alignment = bus_type_get_alignment(contents[0]);
1824 a = message_extend_body(m, 4, 4, false, false);
1829 op = m->body_end->data;
1830 os = m->body_end->size;
1832 /* Add alignment between size and first element */
1833 if (!message_extend_body(m, alignment, 0, false, false))
1836 /* location of array size might have changed so let's readjust a */
1837 if (o == m->body_end)
1838 a = adjust_pointer(a, op, os, m->body_end->data);
1844 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1850 static int bus_message_open_variant(
1852 struct bus_container *c,
1853 const char *contents) {
1859 if (!signature_is_single(contents, false))
1862 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1865 if (c->signature && c->signature[c->index]) {
1867 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1873 if (c->enclosing != 0)
1876 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1883 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1884 /* Variants are always aligned to 8 */
1886 if (!message_extend_body(m, 8, 0, false, false))
1893 l = strlen(contents);
1894 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1899 memcpy((uint8_t*) a + 1, contents, l + 1);
1902 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1908 static int bus_message_open_struct(
1910 struct bus_container *c,
1911 const char *contents,
1913 bool *need_offsets) {
1922 assert(need_offsets);
1924 if (!signature_is_valid(contents, false))
1927 if (c->signature && c->signature[c->index]) {
1930 l = strlen(contents);
1932 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1933 !startswith(c->signature + c->index + 1, contents) ||
1934 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1937 nindex = c->index + 1 + l + 1;
1941 if (c->enclosing != 0)
1944 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1950 nindex = e - c->signature;
1953 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1956 alignment = bus_gvariant_get_alignment(contents);
1960 if (!message_extend_body(m, alignment, 0, false, false))
1963 r = bus_gvariant_is_fixed_size(contents);
1967 *begin = m->body_size;
1968 *need_offsets = r == 0;
1970 /* Align contents to 8 byte boundary */
1971 if (!message_extend_body(m, 8, 0, false, false))
1975 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1981 static int bus_message_open_dict_entry(
1983 struct bus_container *c,
1984 const char *contents,
1986 bool *need_offsets) {
1994 assert(need_offsets);
1996 if (!signature_is_pair(contents))
1999 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2002 if (c->signature && c->signature[c->index]) {
2005 l = strlen(contents);
2007 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2008 !startswith(c->signature + c->index + 1, contents) ||
2009 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2014 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2017 alignment = bus_gvariant_get_alignment(contents);
2021 if (!message_extend_body(m, alignment, 0, false, false))
2024 r = bus_gvariant_is_fixed_size(contents);
2028 *begin = m->body_size;
2029 *need_offsets = r == 0;
2031 /* Align contents to 8 byte boundary */
2032 if (!message_extend_body(m, 8, 0, false, false))
2039 _public_ int sd_bus_message_open_container(
2042 const char *contents) {
2044 struct bus_container *c, *w;
2045 uint32_t *array_size = NULL;
2047 size_t before, begin = 0;
2048 bool need_offsets = false;
2051 assert_return(m, -EINVAL);
2052 assert_return(!m->sealed, -EPERM);
2053 assert_return(contents, -EINVAL);
2054 assert_return(!m->poisoned, -ESTALE);
2056 /* Make sure we have space for one more container */
2057 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2062 c = message_get_container(m);
2064 signature = strdup(contents);
2070 /* Save old index in the parent container, in case we have to
2071 * abort this container */
2072 c->saved_index = c->index;
2073 before = m->body_size;
2075 if (type == SD_BUS_TYPE_ARRAY)
2076 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2077 else if (type == SD_BUS_TYPE_VARIANT)
2078 r = bus_message_open_variant(m, c, contents);
2079 else if (type == SD_BUS_TYPE_STRUCT)
2080 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2081 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2082 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2091 /* OK, let's fill it in */
2092 w = m->containers + m->n_containers++;
2093 w->enclosing = type;
2094 w->signature = signature;
2096 w->array_size = array_size;
2099 w->n_offsets = w->offsets_allocated = 0;
2101 w->need_offsets = need_offsets;
2106 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2111 if (!BUS_MESSAGE_IS_GVARIANT(m))
2114 if (c->need_offsets) {
2115 size_t payload, sz, i;
2118 /* Variable-width arrays */
2120 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2121 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2123 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2127 for (i = 0; i < c->n_offsets; i++)
2128 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2132 /* Fixed-width or empty arrays */
2134 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2142 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2148 assert(c->signature);
2150 if (!BUS_MESSAGE_IS_GVARIANT(m))
2153 l = strlen(c->signature);
2155 a = message_extend_body(m, 1, 1 + l, true, false);
2160 memcpy(a+1, c->signature, l);
2165 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2166 bool fixed_size = true;
2167 size_t n_variable = 0;
2176 if (!BUS_MESSAGE_IS_GVARIANT(m))
2179 p = strempty(c->signature);
2183 r = signature_element_length(p, &n);
2192 r = bus_gvariant_is_fixed_size(t);
2197 assert(!c->need_offsets || i <= c->n_offsets);
2199 /* We need to add an offset for each item that has a
2200 * variable size and that is not the last one in the
2204 if (r == 0 && p[n] != 0)
2211 assert(!c->need_offsets || i == c->n_offsets);
2212 assert(c->need_offsets || n_variable == 0);
2214 if (isempty(c->signature)) {
2215 /* The unary type is encoded as fixed 1 byte padding */
2216 a = message_extend_body(m, 1, 1, add_offset, false);
2221 } else if (n_variable <= 0) {
2224 /* Structures with fixed-size members only have to be
2225 * fixed-size themselves. But gvariant requires all fixed-size
2226 * elements to be sized a multiple of their alignment. Hence,
2227 * we must *always* add final padding after the last member so
2228 * the overall size of the structure is properly aligned. */
2230 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2232 assert(alignment > 0);
2234 a = message_extend_body(m, alignment, 0, add_offset, false);
2241 assert(c->offsets[c->n_offsets-1] == m->body_size);
2243 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2245 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2249 p = strempty(c->signature);
2250 for (i = 0, j = 0; i < c->n_offsets; i++) {
2254 r = signature_element_length(p, &n);
2265 r = bus_gvariant_is_fixed_size(t);
2268 if (r > 0 || p[0] == 0)
2272 k = n_variable - 1 - j;
2274 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2283 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2284 struct bus_container *c;
2287 assert_return(m, -EINVAL);
2288 assert_return(!m->sealed, -EPERM);
2289 assert_return(m->n_containers > 0, -EINVAL);
2290 assert_return(!m->poisoned, -ESTALE);
2292 c = message_get_container(m);
2294 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2295 if (c->signature && c->signature[c->index] != 0)
2300 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2301 r = bus_message_close_array(m, c);
2302 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2303 r = bus_message_close_variant(m, c);
2304 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2305 r = bus_message_close_struct(m, c, true);
2307 assert_not_reached("Unknown container type");
2321 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2328 stack[*i].types = types;
2329 stack[*i].n_struct = n_struct;
2330 stack[*i].n_array = n_array;
2336 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2347 *types = stack[*i].types;
2348 *n_struct = stack[*i].n_struct;
2349 *n_array = stack[*i].n_array;
2354 _public_ int sd_bus_message_appendv(
2359 unsigned n_array, n_struct;
2360 TypeStack stack[BUS_CONTAINER_DEPTH];
2361 unsigned stack_ptr = 0;
2364 assert_return(m, -EINVAL);
2365 assert_return(types, -EINVAL);
2366 assert_return(!m->sealed, -EPERM);
2367 assert_return(!m->poisoned, -ESTALE);
2369 n_array = (unsigned) -1;
2370 n_struct = strlen(types);
2375 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2376 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2382 r = sd_bus_message_close_container(m);
2390 if (n_array != (unsigned) -1)
2399 case SD_BUS_TYPE_BYTE: {
2402 x = (uint8_t) va_arg(ap, int);
2403 r = sd_bus_message_append_basic(m, *t, &x);
2407 case SD_BUS_TYPE_BOOLEAN:
2408 case SD_BUS_TYPE_INT32:
2409 case SD_BUS_TYPE_UINT32:
2410 case SD_BUS_TYPE_UNIX_FD: {
2413 /* We assume a boolean is the same as int32_t */
2414 assert_cc(sizeof(int32_t) == sizeof(int));
2416 x = va_arg(ap, uint32_t);
2417 r = sd_bus_message_append_basic(m, *t, &x);
2421 case SD_BUS_TYPE_INT16:
2422 case SD_BUS_TYPE_UINT16: {
2425 x = (uint16_t) va_arg(ap, int);
2426 r = sd_bus_message_append_basic(m, *t, &x);
2430 case SD_BUS_TYPE_INT64:
2431 case SD_BUS_TYPE_UINT64: {
2434 x = va_arg(ap, uint64_t);
2435 r = sd_bus_message_append_basic(m, *t, &x);
2439 case SD_BUS_TYPE_DOUBLE: {
2442 x = va_arg(ap, double);
2443 r = sd_bus_message_append_basic(m, *t, &x);
2447 case SD_BUS_TYPE_STRING:
2448 case SD_BUS_TYPE_OBJECT_PATH:
2449 case SD_BUS_TYPE_SIGNATURE: {
2452 x = va_arg(ap, const char*);
2453 r = sd_bus_message_append_basic(m, *t, x);
2457 case SD_BUS_TYPE_ARRAY: {
2460 r = signature_element_length(t + 1, &k);
2466 memcpy(s, t + 1, k);
2469 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2474 if (n_array == (unsigned) -1) {
2479 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2485 n_array = va_arg(ap, unsigned);
2490 case SD_BUS_TYPE_VARIANT: {
2493 s = va_arg(ap, const char*);
2497 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2501 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2506 n_struct = strlen(s);
2507 n_array = (unsigned) -1;
2512 case SD_BUS_TYPE_STRUCT_BEGIN:
2513 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2516 r = signature_element_length(t, &k);
2523 memcpy(s, t + 1, k - 2);
2526 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2531 if (n_array == (unsigned) -1) {
2536 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2542 n_array = (unsigned) -1;
2558 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2562 assert_return(m, -EINVAL);
2563 assert_return(types, -EINVAL);
2564 assert_return(!m->sealed, -EPERM);
2565 assert_return(!m->poisoned, -ESTALE);
2567 va_start(ap, types);
2568 r = sd_bus_message_appendv(m, types, ap);
2574 _public_ int sd_bus_message_append_array_space(
2584 assert_return(m, -EINVAL);
2585 assert_return(!m->sealed, -EPERM);
2586 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2587 assert_return(ptr || size == 0, -EINVAL);
2588 assert_return(!m->poisoned, -ESTALE);
2590 /* alignment and size of the trivial types (except bool) is
2591 * identical for gvariant and dbus1 marshalling */
2592 align = bus_type_get_alignment(type);
2593 sz = bus_type_get_size(type);
2595 assert_se(align > 0);
2601 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2605 a = message_extend_body(m, align, size, false, false);
2609 r = sd_bus_message_close_container(m);
2617 #if 0 /// UNNEEDED by elogind
2618 _public_ int sd_bus_message_append_array(
2626 assert_return(m, -EINVAL);
2627 assert_return(!m->sealed, -EPERM);
2628 assert_return(bus_type_is_trivial(type), -EINVAL);
2629 assert_return(ptr || size == 0, -EINVAL);
2630 assert_return(!m->poisoned, -ESTALE);
2632 r = sd_bus_message_append_array_space(m, type, size, &p);
2636 memcpy_safe(p, ptr, size);
2641 _public_ int sd_bus_message_append_array_iovec(
2644 const struct iovec *iov,
2652 assert_return(m, -EINVAL);
2653 assert_return(!m->sealed, -EPERM);
2654 assert_return(bus_type_is_trivial(type), -EINVAL);
2655 assert_return(iov || n == 0, -EINVAL);
2656 assert_return(!m->poisoned, -ESTALE);
2658 size = IOVEC_TOTAL_SIZE(iov, n);
2660 r = sd_bus_message_append_array_space(m, type, size, &p);
2664 for (i = 0; i < n; i++) {
2666 if (iov[i].iov_base)
2667 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2669 memzero(p, iov[i].iov_len);
2671 p = (uint8_t*) p + iov[i].iov_len;
2677 _public_ int sd_bus_message_append_array_memfd(
2684 _cleanup_close_ int copy_fd = -1;
2685 struct bus_body_part *part;
2691 assert_return(m, -EINVAL);
2692 assert_return(memfd >= 0, -EBADF);
2693 assert_return(bus_type_is_trivial(type), -EINVAL);
2694 assert_return(size > 0, -EINVAL);
2695 assert_return(!m->sealed, -EPERM);
2696 assert_return(!m->poisoned, -ESTALE);
2698 r = memfd_set_sealed(memfd);
2702 copy_fd = dup(memfd);
2706 r = memfd_get_size(memfd, &real_size);
2710 if (offset == 0 && size == (uint64_t) -1)
2712 else if (offset + size > real_size)
2715 align = bus_type_get_alignment(type);
2716 sz = bus_type_get_size(type);
2718 assert_se(align > 0);
2721 if (offset % align != 0)
2727 if (size > (uint64_t) (uint32_t) -1)
2730 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2734 a = message_extend_body(m, align, 0, false, false);
2738 part = message_append_part(m);
2742 part->memfd = copy_fd;
2743 part->memfd_offset = offset;
2744 part->sealed = true;
2748 m->body_size += size;
2749 message_extend_containers(m, size);
2751 return sd_bus_message_close_container(m);
2754 _public_ int sd_bus_message_append_string_memfd(
2760 _cleanup_close_ int copy_fd = -1;
2761 struct bus_body_part *part;
2762 struct bus_container *c;
2767 assert_return(m, -EINVAL);
2768 assert_return(memfd >= 0, -EBADF);
2769 assert_return(size > 0, -EINVAL);
2770 assert_return(!m->sealed, -EPERM);
2771 assert_return(!m->poisoned, -ESTALE);
2773 r = memfd_set_sealed(memfd);
2777 copy_fd = dup(memfd);
2781 r = memfd_get_size(memfd, &real_size);
2785 if (offset == 0 && size == (uint64_t) -1)
2787 else if (offset + size > real_size)
2790 /* We require this to be NUL terminated */
2794 if (size > (uint64_t) (uint32_t) -1)
2797 c = message_get_container(m);
2798 if (c->signature && c->signature[c->index]) {
2799 /* Container signature is already set */
2801 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2806 /* Maybe we can append to the signature? But only if this is the top-level container */
2807 if (c->enclosing != 0)
2810 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2817 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2818 a = message_extend_body(m, 4, 4, false, false);
2822 *(uint32_t*) a = size - 1;
2825 part = message_append_part(m);
2829 part->memfd = copy_fd;
2830 part->memfd_offset = offset;
2831 part->sealed = true;
2835 m->body_size += size;
2836 message_extend_containers(m, size);
2838 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2839 r = message_add_offset(m, m->body_size);
2846 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2853 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2857 assert_return(m, -EINVAL);
2858 assert_return(!m->sealed, -EPERM);
2859 assert_return(!m->poisoned, -ESTALE);
2861 r = sd_bus_message_open_container(m, 'a', "s");
2865 STRV_FOREACH(i, l) {
2866 r = sd_bus_message_append_basic(m, 's', *i);
2871 return sd_bus_message_close_container(m);
2874 static int bus_message_close_header(sd_bus_message *m) {
2878 /* The actual user data is finished now, we just complete the
2879 variant and struct now (at least on gvariant). Remember
2880 this position, so that during parsing we know where to
2881 put the outer container end. */
2882 m->user_body_size = m->body_size;
2884 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2885 const char *signature;
2889 /* Add offset table to end of fields array */
2890 if (m->n_header_offsets >= 1) {
2894 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2896 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2897 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2901 for (i = 0; i < m->n_header_offsets; i++)
2902 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2905 /* Add gvariant NUL byte plus signature to the end of
2906 * the body, followed by the final offset pointing to
2907 * the end of the fields array */
2909 signature = strempty(m->root_container.signature);
2910 l = strlen(signature);
2912 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2913 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2918 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2919 memcpy((uint8_t*) d + 2, signature, l);
2920 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2922 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2925 m->footer_accessible = 1 + l + 2 + sz;
2927 m->header->dbus1.fields_size = m->fields_size;
2928 m->header->dbus1.body_size = m->body_size;
2934 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2935 struct bus_body_part *part;
2945 if (m->n_containers > 0)
2951 if (cookie > 0xffffffffULL &&
2952 !BUS_MESSAGE_IS_GVARIANT(m))
2955 /* In vtables the return signature of method calls is listed,
2956 * let's check if they match if this is a response */
2957 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2958 m->enforced_reply_signature &&
2959 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2962 /* If gvariant marshalling is used we need to close the body structure */
2963 r = bus_message_close_struct(m, &m->root_container, false);
2967 /* If there's a non-trivial signature set, then add it in
2968 * here, but only on dbus1 */
2969 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2970 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2976 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2981 r = bus_message_close_header(m);
2985 if (BUS_MESSAGE_IS_GVARIANT(m))
2986 m->header->dbus2.cookie = cookie;
2988 m->header->dbus1.serial = (uint32_t) cookie;
2990 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2992 /* Add padding at the end of the fields part, since we know
2993 * the body needs to start at an 8 byte alignment. We made
2994 * sure we allocated enough space for this, so all we need to
2995 * do here is to zero it out. */
2996 a = ALIGN8(m->fields_size) - m->fields_size;
2998 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
3000 /* If this is something we can send as memfd, then let's seal
3001 the memfd now. Note that we can send memfds as payload only
3002 for directed messages, and not for broadcasts. */
3003 if (m->destination && m->bus->use_memfd) {
3004 MESSAGE_FOREACH_PART(part, i, m)
3005 if (part->memfd >= 0 &&
3007 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3008 part != m->body_end) { /* The last part may never be sent as memfd */
3011 /* Try to seal it if that makes
3012 * sense. First, unmap our own map to
3013 * make sure we don't keep it busy. */
3014 bus_body_part_unmap(part);
3016 /* Then, sync up real memfd size */
3018 r = memfd_set_size(part->memfd, sz);
3022 /* Finally, try to seal */
3023 if (memfd_set_sealed(part->memfd) >= 0)
3024 part->sealed = true;
3028 m->root_container.end = m->user_body_size;
3029 m->root_container.index = 0;
3030 m->root_container.offset_index = 0;
3031 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3038 int bus_body_part_map(struct bus_body_part *part) {
3047 if (part->size <= 0)
3050 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3051 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3052 static const uint8_t zeroes[7] = { };
3053 part->data = (void*) zeroes;
3057 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3058 psz = PAGE_ALIGN(part->size + shift);
3060 if (part->memfd >= 0)
3061 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3062 else if (part->is_zero)
3063 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3067 if (p == MAP_FAILED)
3071 part->mmap_begin = p;
3072 part->data = (uint8_t*) p + shift;
3073 part->munmap_this = true;
3078 void bus_body_part_unmap(struct bus_body_part *part) {
3082 if (part->memfd < 0)
3085 if (!part->mmap_begin)
3088 if (!part->munmap_this)
3091 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3093 part->mmap_begin = NULL;
3096 part->munmap_this = false;
3101 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3102 size_t k, start, end;
3107 start = ALIGN_TO((size_t) *rindex, align);
3108 end = start + nbytes;
3113 /* Verify that padding is 0 */
3114 for (k = *rindex; k < start; k++)
3115 if (((const uint8_t*) p)[k] != 0)
3119 *r = (uint8_t*) p + start;
3126 static bool message_end_of_signature(sd_bus_message *m) {
3127 struct bus_container *c;
3131 c = message_get_container(m);
3132 return !c->signature || c->signature[c->index] == 0;
3135 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3136 struct bus_container *c;
3140 c = message_get_container(m);
3141 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3144 if (BUS_MESSAGE_IS_GVARIANT(m))
3145 return index >= c->end;
3147 assert(c->array_size);
3148 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3152 #if 0 /// UNNEEDED by elogind
3153 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3154 assert_return(m, -EINVAL);
3155 assert_return(m->sealed, -EPERM);
3157 if (complete && m->n_containers > 0)
3160 if (message_end_of_signature(m))
3163 if (message_end_of_array(m, m->rindex))
3170 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3171 struct bus_body_part *part;
3177 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3178 part = m->cached_rindex_part;
3179 begin = m->cached_rindex_part_begin;
3189 if (index + sz <= begin + part->size) {
3191 r = bus_body_part_map(part);
3196 *p = (uint8_t*) part->data + index - begin;
3198 m->cached_rindex_part = part;
3199 m->cached_rindex_part_begin = begin;
3204 begin += part->size;
3211 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3218 if (!BUS_MESSAGE_IS_GVARIANT(m))
3221 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3224 sz = bus_gvariant_get_size(c->signature);
3228 if (c->offset_index+1 >= c->n_offsets)
3231 /* Variable-size array */
3233 alignment = bus_gvariant_get_alignment(c->signature);
3234 assert(alignment > 0);
3236 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3237 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3240 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3243 /* Fixed-size array */
3244 *rindex = c->begin + (c->offset_index+1) * sz;
3250 } else if (c->enclosing == 0 ||
3251 c->enclosing == SD_BUS_TYPE_STRUCT ||
3252 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3257 if (c->offset_index+1 >= c->n_offsets)
3260 r = signature_element_length(c->signature + c->index, &n);
3264 r = signature_element_length(c->signature + c->index + n, &j);
3269 memcpy(t, c->signature + c->index + n, j);
3272 alignment = bus_gvariant_get_alignment(t);
3275 assert(alignment > 0);
3277 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3278 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3282 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3285 assert_not_reached("Unknown container type");
3290 /* Reached the end */
3297 static int message_peek_body(
3304 size_t k, start, end, padding;
3305 struct bus_body_part *part;
3312 start = ALIGN_TO((size_t) *rindex, align);
3313 padding = start - *rindex;
3314 end = start + nbytes;
3316 if (end > m->user_body_size)
3319 part = find_part(m, *rindex, padding, (void**) &q);
3324 /* Verify padding */
3325 for (k = 0; k < padding; k++)
3330 part = find_part(m, start, nbytes, (void**) &q);
3331 if (!part || (nbytes > 0 && !q))
3342 static bool validate_nul(const char *s, size_t l) {
3344 /* Check for NUL chars in the string */
3345 if (memchr(s, 0, l))
3348 /* Check for NUL termination */
3355 static bool validate_string(const char *s, size_t l) {
3357 if (!validate_nul(s, l))
3360 /* Check if valid UTF8 */
3361 if (!utf8_is_valid(s))
3367 static bool validate_signature(const char *s, size_t l) {
3369 if (!validate_nul(s, l))
3372 /* Check if valid signature */
3373 if (!signature_is_valid(s, true))
3379 static bool validate_object_path(const char *s, size_t l) {
3381 if (!validate_nul(s, l))
3384 if (!object_path_is_valid(s))
3390 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3391 struct bus_container *c;
3396 assert_return(m, -EINVAL);
3397 assert_return(m->sealed, -EPERM);
3398 assert_return(bus_type_is_basic(type), -EINVAL);
3400 if (message_end_of_signature(m))
3403 if (message_end_of_array(m, m->rindex))
3406 c = message_get_container(m);
3407 if (c->signature[c->index] != type)
3412 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3414 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3417 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3421 if (type == SD_BUS_TYPE_STRING)
3422 ok = validate_string(q, c->item_size-1);
3423 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3424 ok = validate_object_path(q, c->item_size-1);
3426 ok = validate_signature(q, c->item_size-1);
3432 *(const char**) p = q;
3436 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3438 if ((size_t) sz != c->item_size)
3441 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3444 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3450 case SD_BUS_TYPE_BYTE:
3452 *(uint8_t*) p = *(uint8_t*) q;
3455 case SD_BUS_TYPE_BOOLEAN:
3457 *(int*) p = !!*(uint8_t*) q;
3460 case SD_BUS_TYPE_INT16:
3461 case SD_BUS_TYPE_UINT16:
3463 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3466 case SD_BUS_TYPE_INT32:
3467 case SD_BUS_TYPE_UINT32:
3469 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3472 case SD_BUS_TYPE_INT64:
3473 case SD_BUS_TYPE_UINT64:
3474 case SD_BUS_TYPE_DOUBLE:
3476 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3479 case SD_BUS_TYPE_UNIX_FD: {
3482 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3487 *(int*) p = m->fds[j];
3493 assert_not_reached("unexpected type");
3497 r = container_next_item(m, c, &rindex);
3502 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3506 r = message_peek_body(m, &rindex, 4, 4, &q);
3510 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3511 r = message_peek_body(m, &rindex, 1, l+1, &q);
3515 if (type == SD_BUS_TYPE_OBJECT_PATH)
3516 ok = validate_object_path(q, l);
3518 ok = validate_string(q, l);
3523 *(const char**) p = q;
3525 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3528 r = message_peek_body(m, &rindex, 1, 1, &q);
3533 r = message_peek_body(m, &rindex, 1, l+1, &q);
3537 if (!validate_signature(q, l))
3541 *(const char**) p = q;
3546 align = bus_type_get_alignment(type);
3549 sz = bus_type_get_size(type);
3552 r = message_peek_body(m, &rindex, align, sz, &q);
3558 case SD_BUS_TYPE_BYTE:
3560 *(uint8_t*) p = *(uint8_t*) q;
3563 case SD_BUS_TYPE_BOOLEAN:
3565 *(int*) p = !!*(uint32_t*) q;
3568 case SD_BUS_TYPE_INT16:
3569 case SD_BUS_TYPE_UINT16:
3571 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3574 case SD_BUS_TYPE_INT32:
3575 case SD_BUS_TYPE_UINT32:
3577 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3580 case SD_BUS_TYPE_INT64:
3581 case SD_BUS_TYPE_UINT64:
3582 case SD_BUS_TYPE_DOUBLE:
3584 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3587 case SD_BUS_TYPE_UNIX_FD: {
3590 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3595 *(int*) p = m->fds[j];
3600 assert_not_reached("Unknown basic type...");
3607 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3613 static int bus_message_enter_array(
3615 struct bus_container *c,
3616 const char *contents,
3617 uint32_t **array_size,
3620 size_t *n_offsets) {
3634 if (!signature_is_single(contents, true))
3637 if (!c->signature || c->signature[c->index] == 0)
3640 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3643 if (!startswith(c->signature + c->index + 1, contents))
3648 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3651 r = message_peek_body(m, &rindex, 4, 4, &q);
3655 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3658 alignment = bus_type_get_alignment(contents[0]);
3662 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3666 *array_size = (uint32_t*) q;
3668 } else if (c->item_size <= 0) {
3670 /* gvariant: empty array */
3675 } else if (bus_gvariant_is_fixed_size(contents)) {
3677 /* gvariant: fixed length array */
3678 *item_size = bus_gvariant_get_size(contents);
3683 size_t where, p = 0, framing, sz;
3686 /* gvariant: variable length array */
3687 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3689 where = rindex + c->item_size - sz;
3690 r = message_peek_body(m, &where, 1, sz, &q);
3694 framing = bus_gvariant_read_word_le(q, sz);
3695 if (framing > c->item_size - sz)
3697 if ((c->item_size - framing) % sz != 0)
3700 *n_offsets = (c->item_size - framing) / sz;
3702 where = rindex + framing;
3703 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3707 *offsets = new(size_t, *n_offsets);
3711 for (i = 0; i < *n_offsets; i++) {
3714 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3715 if (x > c->item_size - sz)
3720 (*offsets)[i] = rindex + x;
3724 *item_size = (*offsets)[0] - rindex;
3729 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3730 c->index += 1 + strlen(contents);
3735 static int bus_message_enter_variant(
3737 struct bus_container *c,
3738 const char *contents,
3739 size_t *item_size) {
3751 if (!signature_is_single(contents, false))
3754 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3757 if (!c->signature || c->signature[c->index] == 0)
3760 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3765 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3768 k = strlen(contents);
3769 if (1+k > c->item_size)
3772 where = rindex + c->item_size - (1+k);
3773 r = message_peek_body(m, &where, 1, 1+k, &q);
3777 if (*(char*) q != 0)
3780 if (memcmp((uint8_t*) q+1, contents, k))
3783 *item_size = c->item_size - (1+k);
3786 r = message_peek_body(m, &rindex, 1, 1, &q);
3791 r = message_peek_body(m, &rindex, 1, l+1, &q);
3795 if (!validate_signature(q, l))
3798 if (!streq(q, contents))
3804 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3810 static int build_struct_offsets(
3812 const char *signature,
3816 size_t *n_offsets) {
3818 unsigned n_variable = 0, n_total = 0, v;
3819 size_t previous = 0, where;
3830 if (isempty(signature)) {
3831 /* Unary type is encoded as *fixed* 1 byte padding */
3832 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3836 if (*(uint8_t *) q != 0)
3845 sz = bus_gvariant_determine_word_size(size, 0);
3849 /* First, loop over signature and count variable elements and
3850 * elements in general. We use this to know how large the
3851 * offset array is at the end of the structure. Note that
3852 * GVariant only stores offsets for all variable size elements
3853 * that are not the last item. */
3859 r = signature_element_length(p, &n);
3868 r = bus_gvariant_is_fixed_size(t);
3873 if (r == 0 && p[n] != 0) /* except the last item */
3880 if (size < n_variable * sz)
3883 where = m->rindex + size - (n_variable * sz);
3884 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3890 *offsets = new(size_t, n_total);
3896 /* Second, loop again and build an offset table */
3902 r = signature_element_length(p, &n);
3911 k = bus_gvariant_get_size(t);
3919 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3922 if (m->rindex + x < previous)
3925 /* The last item's end
3926 * is determined from
3929 x = size - (n_variable * sz);
3931 offset = m->rindex + x;
3937 align = bus_gvariant_get_alignment(t);
3940 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3944 previous = (*offsets)[(*n_offsets)++] = offset;
3949 assert(*n_offsets == n_total);
3951 *item_size = (*offsets)[0] - m->rindex;
3955 static int enter_struct_or_dict_entry(
3957 struct bus_container *c,
3958 const char *contents,
3961 size_t *n_offsets) {
3972 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3975 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3980 /* gvariant with contents */
3981 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3986 static int bus_message_enter_struct(
3988 struct bus_container *c,
3989 const char *contents,
3992 size_t *n_offsets) {
4004 if (!signature_is_valid(contents, false))
4007 if (!c->signature || c->signature[c->index] == 0)
4010 l = strlen(contents);
4012 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4013 !startswith(c->signature + c->index + 1, contents) ||
4014 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4017 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4021 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4022 c->index += 1 + l + 1;
4027 static int bus_message_enter_dict_entry(
4029 struct bus_container *c,
4030 const char *contents,
4033 size_t *n_offsets) {
4042 if (!signature_is_pair(contents))
4045 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4048 if (!c->signature || c->signature[c->index] == 0)
4051 l = strlen(contents);
4053 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4054 !startswith(c->signature + c->index + 1, contents) ||
4055 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4058 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4062 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4063 c->index += 1 + l + 1;
4068 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4070 const char *contents) {
4071 struct bus_container *c, *w;
4072 uint32_t *array_size = NULL;
4075 size_t *offsets = NULL;
4076 size_t n_offsets = 0, item_size = 0;
4079 assert_return(m, -EINVAL);
4080 assert_return(m->sealed, -EPERM);
4081 assert_return(type != 0 || !contents, -EINVAL);
4083 if (type == 0 || !contents) {
4087 /* Allow entering into anonymous containers */
4088 r = sd_bus_message_peek_type(m, &tt, &cc);
4092 if (type != 0 && type != tt)
4095 if (contents && !streq(contents, cc))
4103 * We enforce a global limit on container depth, that is much
4104 * higher than the 32 structs and 32 arrays the specification
4105 * mandates. This is simpler to implement for us, and we need
4106 * this only to ensure our container array doesn't grow
4107 * without bounds. We are happy to return any data from a
4108 * message as long as the data itself is valid, even if the
4109 * overall message might be not.
4111 * Note that the message signature is validated when
4112 * parsing the headers, and that validation does check the
4115 * Note that the specification defines no limits on the depth
4116 * of stacked variants, but we do.
4118 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4121 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4124 if (message_end_of_signature(m))
4127 if (message_end_of_array(m, m->rindex))
4130 c = message_get_container(m);
4132 signature = strdup(contents);
4136 c->saved_index = c->index;
4139 if (type == SD_BUS_TYPE_ARRAY)
4140 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4141 else if (type == SD_BUS_TYPE_VARIANT)
4142 r = bus_message_enter_variant(m, c, contents, &item_size);
4143 else if (type == SD_BUS_TYPE_STRUCT)
4144 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4145 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4146 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4156 /* OK, let's fill it in */
4157 w = m->containers + m->n_containers++;
4158 w->enclosing = type;
4159 w->signature = signature;
4160 w->peeked_signature = NULL;
4164 w->begin = m->rindex;
4166 /* Unary type has fixed size of 1, but virtual size of 0 */
4167 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4168 type == SD_BUS_TYPE_STRUCT &&
4170 w->end = m->rindex + 0;
4172 w->end = m->rindex + c->item_size;
4174 w->array_size = array_size;
4175 w->item_size = item_size;
4176 w->offsets = offsets;
4177 w->n_offsets = n_offsets;
4178 w->offset_index = 0;
4183 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4184 struct bus_container *c;
4188 assert_return(m, -EINVAL);
4189 assert_return(m->sealed, -EPERM);
4190 assert_return(m->n_containers > 0, -ENXIO);
4192 c = message_get_container(m);
4194 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4195 if (c->signature && c->signature[c->index] != 0)
4199 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4200 if (m->rindex < c->end)
4203 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4206 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4207 if (c->begin + l != m->rindex)
4212 free(c->peeked_signature);
4216 c = message_get_container(m);
4219 c->index = c->saved_index;
4220 r = container_next_item(m, c, &m->rindex);
4228 static void message_quit_container(sd_bus_message *m) {
4229 struct bus_container *c;
4233 assert(m->n_containers > 0);
4235 c = message_get_container(m);
4238 assert(m->rindex >= c->before);
4239 m->rindex = c->before;
4241 /* Free container */
4246 /* Correct index of new top-level container */
4247 c = message_get_container(m);
4248 c->index = c->saved_index;
4251 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4252 struct bus_container *c;
4255 assert_return(m, -EINVAL);
4256 assert_return(m->sealed, -EPERM);
4258 if (message_end_of_signature(m))
4261 if (message_end_of_array(m, m->rindex))
4264 c = message_get_container(m);
4266 if (bus_type_is_basic(c->signature[c->index])) {
4270 *type = c->signature[c->index];
4274 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4280 r = signature_element_length(c->signature+c->index+1, &l);
4286 sig = strndup(c->signature + c->index + 1, l);
4290 free(c->peeked_signature);
4291 *contents = c->peeked_signature = sig;
4295 *type = SD_BUS_TYPE_ARRAY;
4300 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4301 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4307 r = signature_element_length(c->signature+c->index, &l);
4312 sig = strndup(c->signature + c->index + 1, l - 2);
4316 free(c->peeked_signature);
4317 *contents = c->peeked_signature = sig;
4321 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4326 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4330 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4333 if (c->item_size < 2)
4336 /* Look for the NUL delimiter that
4337 separates the payload from the
4338 signature. Since the body might be
4339 in a different part that then the
4340 signature we map byte by byte. */
4342 for (k = 2; k <= c->item_size; k++) {
4345 where = m->rindex + c->item_size - k;
4346 r = message_peek_body(m, &where, 1, k, &q);
4350 if (*(char*) q == 0)
4354 if (k > c->item_size)
4357 free(c->peeked_signature);
4358 c->peeked_signature = strndup((char*) q + 1, k - 1);
4359 if (!c->peeked_signature)
4362 if (!signature_is_valid(c->peeked_signature, true))
4365 *contents = c->peeked_signature;
4370 r = message_peek_body(m, &rindex, 1, 1, &q);
4375 r = message_peek_body(m, &rindex, 1, l+1, &q);
4379 if (!validate_signature(q, l))
4387 *type = SD_BUS_TYPE_VARIANT;
4402 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4403 struct bus_container *c;
4405 assert_return(m, -EINVAL);
4406 assert_return(m->sealed, -EPERM);
4409 message_reset_containers(m);
4412 c = message_get_container(m);
4414 c = message_get_container(m);
4416 c->offset_index = 0;
4418 m->rindex = c->begin;
4421 c->offset_index = 0;
4422 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4424 return !isempty(c->signature);
4427 static int message_read_ap(
4432 unsigned n_array, n_struct;
4433 TypeStack stack[BUS_CONTAINER_DEPTH];
4434 unsigned stack_ptr = 0;
4435 unsigned n_loop = 0;
4443 /* Ideally, we'd just call ourselves recursively on every
4444 * complex type. However, the state of a va_list that is
4445 * passed to a function is undefined after that function
4446 * returns. This means we need to docode the va_list linearly
4447 * in a single stackframe. We hence implement our own
4448 * home-grown stack in an array. */
4450 n_array = (unsigned) -1; /* length of current array entries */
4451 n_struct = strlen(types); /* length of current struct contents signature */
4458 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4459 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4465 r = sd_bus_message_exit_container(m);
4473 if (n_array != (unsigned) -1)
4482 case SD_BUS_TYPE_BYTE:
4483 case SD_BUS_TYPE_BOOLEAN:
4484 case SD_BUS_TYPE_INT16:
4485 case SD_BUS_TYPE_UINT16:
4486 case SD_BUS_TYPE_INT32:
4487 case SD_BUS_TYPE_UINT32:
4488 case SD_BUS_TYPE_INT64:
4489 case SD_BUS_TYPE_UINT64:
4490 case SD_BUS_TYPE_DOUBLE:
4491 case SD_BUS_TYPE_STRING:
4492 case SD_BUS_TYPE_OBJECT_PATH:
4493 case SD_BUS_TYPE_SIGNATURE:
4494 case SD_BUS_TYPE_UNIX_FD: {
4497 p = va_arg(ap, void*);
4498 r = sd_bus_message_read_basic(m, *t, p);
4511 case SD_BUS_TYPE_ARRAY: {
4514 r = signature_element_length(t + 1, &k);
4520 memcpy(s, t + 1, k);
4523 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4534 if (n_array == (unsigned) -1) {
4539 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4545 n_array = va_arg(ap, unsigned);
4550 case SD_BUS_TYPE_VARIANT: {
4553 s = va_arg(ap, const char *);
4557 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4567 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4572 n_struct = strlen(s);
4573 n_array = (unsigned) -1;
4578 case SD_BUS_TYPE_STRUCT_BEGIN:
4579 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4582 r = signature_element_length(t, &k);
4588 memcpy(s, t + 1, k - 2);
4591 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4601 if (n_array == (unsigned) -1) {
4606 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4612 n_array = (unsigned) -1;
4625 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4629 assert_return(m, -EINVAL);
4630 assert_return(m->sealed, -EPERM);
4631 assert_return(types, -EINVAL);
4633 va_start(ap, types);
4634 r = message_read_ap(m, types, ap);
4640 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4643 assert_return(m, -EINVAL);
4644 assert_return(m->sealed, -EPERM);
4646 /* If types is NULL, read exactly one element */
4648 struct bus_container *c;
4651 if (message_end_of_signature(m))
4654 if (message_end_of_array(m, m->rindex))
4657 c = message_get_container(m);
4659 r = signature_element_length(c->signature + c->index, &l);
4663 types = strndupa(c->signature + c->index, l);
4668 case 0: /* Nothing to drop */
4671 case SD_BUS_TYPE_BYTE:
4672 case SD_BUS_TYPE_BOOLEAN:
4673 case SD_BUS_TYPE_INT16:
4674 case SD_BUS_TYPE_UINT16:
4675 case SD_BUS_TYPE_INT32:
4676 case SD_BUS_TYPE_UINT32:
4677 case SD_BUS_TYPE_INT64:
4678 case SD_BUS_TYPE_UINT64:
4679 case SD_BUS_TYPE_DOUBLE:
4680 case SD_BUS_TYPE_STRING:
4681 case SD_BUS_TYPE_OBJECT_PATH:
4682 case SD_BUS_TYPE_SIGNATURE:
4683 case SD_BUS_TYPE_UNIX_FD:
4685 r = sd_bus_message_read_basic(m, *types, NULL);
4689 r = sd_bus_message_skip(m, types + 1);
4695 case SD_BUS_TYPE_ARRAY: {
4698 r = signature_element_length(types + 1, &k);
4704 memcpy(s, types+1, k);
4707 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4712 r = sd_bus_message_skip(m, s);
4719 r = sd_bus_message_exit_container(m);
4724 r = sd_bus_message_skip(m, types + 1 + k);
4731 case SD_BUS_TYPE_VARIANT: {
4732 const char *contents;
4735 r = sd_bus_message_peek_type(m, &x, &contents);
4739 if (x != SD_BUS_TYPE_VARIANT)
4742 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4746 r = sd_bus_message_skip(m, contents);
4751 r = sd_bus_message_exit_container(m);
4755 r = sd_bus_message_skip(m, types + 1);
4762 case SD_BUS_TYPE_STRUCT_BEGIN:
4763 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4766 r = signature_element_length(types, &k);
4772 memcpy(s, types+1, k-2);
4775 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4779 r = sd_bus_message_skip(m, s);
4783 r = sd_bus_message_exit_container(m);
4788 r = sd_bus_message_skip(m, types + k);
4800 _public_ int sd_bus_message_read_array(
4806 struct bus_container *c;
4812 assert_return(m, -EINVAL);
4813 assert_return(m->sealed, -EPERM);
4814 assert_return(bus_type_is_trivial(type), -EINVAL);
4815 assert_return(ptr, -EINVAL);
4816 assert_return(size, -EINVAL);
4817 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4819 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4823 c = message_get_container(m);
4825 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4826 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4830 sz = c->end - c->begin;
4832 align = bus_type_get_alignment(type);
4836 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4840 /* Zero length array, let's return some aligned
4841 * pointer that is not NULL */
4842 p = (uint8_t*) NULL + align;
4844 r = message_peek_body(m, &m->rindex, align, sz, &p);
4849 r = sd_bus_message_exit_container(m);
4853 *ptr = (const void*) p;
4859 message_quit_container(m);
4863 static int message_peek_fields(
4874 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4877 static int message_peek_field_uint32(
4889 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4892 /* identical for gvariant and dbus1 */
4894 r = message_peek_fields(m, ri, 4, 4, &q);
4899 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4904 static int message_peek_field_uint64(
4916 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4919 /* identical for gvariant and dbus1 */
4921 r = message_peek_fields(m, ri, 8, 8, &q);
4926 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4931 static int message_peek_field_string(
4933 bool (*validate)(const char *p),
4945 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4950 r = message_peek_fields(m, ri, 1, item_size, &q);
4956 r = message_peek_field_uint32(m, ri, 4, &l);
4960 r = message_peek_fields(m, ri, 1, l+1, &q);
4966 if (!validate_nul(q, l))
4972 if (!validate_string(q, l))
4982 static int message_peek_field_signature(
4995 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5000 r = message_peek_fields(m, ri, 1, item_size, &q);
5006 r = message_peek_fields(m, ri, 1, 1, &q);
5011 r = message_peek_fields(m, ri, 1, l+1, &q);
5016 if (!validate_signature(q, l))
5025 static int message_skip_fields(
5028 uint32_t array_size,
5029 const char **signature) {
5031 size_t original_index;
5037 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5039 original_index = *ri;
5045 if (array_size != (uint32_t) -1 &&
5046 array_size <= *ri - original_index)
5053 if (t == SD_BUS_TYPE_STRING) {
5055 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5061 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5063 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5069 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5071 r = message_peek_field_signature(m, ri, 0, NULL);
5077 } else if (bus_type_is_basic(t)) {
5080 align = bus_type_get_alignment(t);
5081 k = bus_type_get_size(t);
5082 assert(align > 0 && k > 0);
5084 r = message_peek_fields(m, ri, align, k, NULL);
5090 } else if (t == SD_BUS_TYPE_ARRAY) {
5092 r = signature_element_length(*signature+1, &l);
5102 strncpy(sig, *signature + 1, l-1);
5105 alignment = bus_type_get_alignment(sig[0]);
5109 r = message_peek_field_uint32(m, ri, 0, &nas);
5112 if (nas > BUS_ARRAY_MAX_SIZE)
5115 r = message_peek_fields(m, ri, alignment, 0, NULL);
5119 r = message_skip_fields(m, ri, nas, (const char**) &s);
5124 (*signature) += 1 + l;
5126 } else if (t == SD_BUS_TYPE_VARIANT) {
5129 r = message_peek_field_signature(m, ri, 0, &s);
5133 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5139 } else if (t == SD_BUS_TYPE_STRUCT ||
5140 t == SD_BUS_TYPE_DICT_ENTRY) {
5142 r = signature_element_length(*signature, &l);
5149 strncpy(sig, *signature + 1, l-1);
5152 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5163 int bus_message_parse_fields(sd_bus_message *m) {
5166 uint32_t unix_fds = 0;
5167 bool unix_fds_set = false;
5168 void *offsets = NULL;
5169 unsigned n_offsets = 0;
5175 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5178 /* Read the signature from the end of the body variant first */
5179 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5180 if (m->footer_accessible < 1 + sz)
5183 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5185 if (p < (char*) m->footer)
5192 /* We found the beginning of the signature
5193 * string, yay! We require the body to be a
5194 * structure, so verify it and then strip the
5195 * opening/closing brackets. */
5197 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5199 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5200 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5203 c = strndup(p + 1 + 1, l - 2);
5207 free(m->root_container.signature);
5208 m->root_container.signature = c;
5215 /* Calculate the actual user body size, by removing
5216 * the trailing variant signature and struct offset
5218 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5220 /* Pull out the offset table for the fields array */
5221 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5226 ri = m->fields_size - sz;
5227 r = message_peek_fields(m, &ri, 1, sz, &q);
5231 framing = bus_gvariant_read_word_le(q, sz);
5232 if (framing >= m->fields_size - sz)
5234 if ((m->fields_size - framing) % sz != 0)
5238 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5242 n_offsets = (m->fields_size - framing) / sz;
5245 m->user_body_size = m->body_size;
5248 while (ri < m->fields_size) {
5249 _cleanup_free_ char *sig = NULL;
5250 const char *signature;
5251 uint64_t field_type;
5252 size_t item_size = (size_t) -1;
5254 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5263 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5265 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5269 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5273 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5280 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5285 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5290 where = ri = ALIGN_TO(ri, 8);
5291 item_size = end - ri;
5292 r = message_peek_fields(m, &where, 1, item_size, &q);
5296 b = memrchr(q, 0, item_size);
5300 sig = strndup(b+1, item_size - (b+1-(char*) q));
5305 item_size = b - (char*) q;
5307 r = message_peek_field_signature(m, &ri, 0, &signature);
5312 switch (field_type) {
5314 case _BUS_MESSAGE_HEADER_INVALID:
5317 case BUS_MESSAGE_HEADER_PATH:
5322 if (!streq(signature, "o"))
5325 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5328 case BUS_MESSAGE_HEADER_INTERFACE:
5333 if (!streq(signature, "s"))
5336 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5339 case BUS_MESSAGE_HEADER_MEMBER:
5344 if (!streq(signature, "s"))
5347 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5350 case BUS_MESSAGE_HEADER_ERROR_NAME:
5355 if (!streq(signature, "s"))
5358 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5360 m->error._need_free = -1;
5364 case BUS_MESSAGE_HEADER_DESTINATION:
5369 if (!streq(signature, "s"))
5372 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5375 case BUS_MESSAGE_HEADER_SENDER:
5380 if (!streq(signature, "s"))
5383 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5385 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5386 m->creds.unique_name = (char*) m->sender;
5387 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5393 case BUS_MESSAGE_HEADER_SIGNATURE: {
5397 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5400 if (m->root_container.signature)
5403 if (!streq(signature, "g"))
5406 r = message_peek_field_signature(m, &ri, item_size, &s);
5414 free(m->root_container.signature);
5415 m->root_container.signature = c;
5419 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5421 if (m->reply_cookie != 0)
5424 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5425 /* 64bit on dbus2 */
5427 if (!streq(signature, "t"))
5430 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5434 /* 32bit on dbus1 */
5437 if (!streq(signature, "u"))
5440 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5444 m->reply_cookie = serial;
5447 if (m->reply_cookie == 0)
5452 case BUS_MESSAGE_HEADER_UNIX_FDS:
5456 if (!streq(signature, "u"))
5459 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5463 unix_fds_set = true;
5467 if (!BUS_MESSAGE_IS_GVARIANT(m))
5468 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5477 if (m->n_fds != unix_fds)
5480 switch (m->header->type) {
5482 case SD_BUS_MESSAGE_SIGNAL:
5483 if (!m->path || !m->interface || !m->member)
5486 if (m->reply_cookie != 0)
5491 case SD_BUS_MESSAGE_METHOD_CALL:
5493 if (!m->path || !m->member)
5496 if (m->reply_cookie != 0)
5501 case SD_BUS_MESSAGE_METHOD_RETURN:
5503 if (m->reply_cookie == 0)
5507 case SD_BUS_MESSAGE_METHOD_ERROR:
5509 if (m->reply_cookie == 0 || !m->error.name)
5514 /* Refuse non-local messages that claim they are local */
5515 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5517 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5519 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5522 m->root_container.end = m->user_body_size;
5524 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5525 r = build_struct_offsets(
5527 m->root_container.signature,
5529 &m->root_container.item_size,
5530 &m->root_container.offsets,
5531 &m->root_container.n_offsets);
5536 /* Try to read the error message, but if we can't it's a non-issue */
5537 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5538 (void) sd_bus_message_read(m, "s", &m->error.message);
5543 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5544 assert_return(m, -EINVAL);
5545 assert_return(destination, -EINVAL);
5546 assert_return(!m->sealed, -EPERM);
5547 assert_return(!m->destination, -EEXIST);
5549 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5552 #if 0 /// UNNEEDED by elogind
5553 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5557 struct bus_body_part *part;
5563 total = BUS_MESSAGE_SIZE(m);
5569 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5570 MESSAGE_FOREACH_PART(part, i, m)
5571 e = mempcpy(e, part->data, part->size);
5573 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5582 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5589 r = sd_bus_message_enter_container(m, 'a', "s");
5593 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5594 r = strv_extend(l, s);
5601 r = sd_bus_message_exit_container(m);
5608 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5612 assert_return(m, -EINVAL);
5613 assert_return(m->sealed, -EPERM);
5614 assert_return(l, -EINVAL);
5616 r = bus_message_read_strv_extend(m, &strv);
5626 static int bus_message_get_arg_skip(
5630 const char **_contents) {
5635 r = sd_bus_message_rewind(m, true);
5640 const char *contents;
5643 r = sd_bus_message_peek_type(m, &type, &contents);
5649 /* Don't match against arguments after the first one we don't understand */
5650 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5651 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5656 *_contents = contents;
5662 r = sd_bus_message_skip(m, NULL);
5669 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5676 r = bus_message_get_arg_skip(m, i, &type, NULL);
5680 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5683 return sd_bus_message_read_basic(m, type, str);
5686 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5687 const char *contents;
5694 r = bus_message_get_arg_skip(m, i, &type, &contents);
5698 if (type != SD_BUS_TYPE_ARRAY)
5700 if (!STR_IN_SET(contents, "s", "o", "g"))
5703 return sd_bus_message_read_strv(m, strv);
5706 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5707 assert_return(m, EINVAL);
5709 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5712 return sd_bus_error_get_errno(&m->error);
5715 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5716 struct bus_container *c;
5718 assert_return(m, NULL);
5720 c = complete ? &m->root_container : message_get_container(m);
5721 return strempty(c->signature);
5724 #if 0 /// UNNEEDED by elogind
5725 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5726 assert_return(m, -EINVAL);
5728 return isempty(m->root_container.signature);
5731 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5732 assert_return(m, -EINVAL);
5734 return streq(strempty(m->root_container.signature), strempty(signature));
5738 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5739 bool done_something = false;
5742 assert_return(m, -EINVAL);
5743 assert_return(source, -EINVAL);
5744 assert_return(!m->sealed, -EPERM);
5745 assert_return(source->sealed, -EPERM);
5748 const char *contents;
5763 r = sd_bus_message_peek_type(source, &type, &contents);
5769 done_something = true;
5771 if (bus_type_is_container(type) > 0) {
5773 r = sd_bus_message_enter_container(source, type, contents);
5777 r = sd_bus_message_open_container(m, type, contents);
5781 r = sd_bus_message_copy(m, source, true);
5785 r = sd_bus_message_close_container(m);
5789 r = sd_bus_message_exit_container(source);
5796 r = sd_bus_message_read_basic(source, type, &basic);
5802 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5803 type == SD_BUS_TYPE_SIGNATURE ||
5804 type == SD_BUS_TYPE_STRING)
5805 r = sd_bus_message_append_basic(m, type, basic.string);
5807 r = sd_bus_message_append_basic(m, type, &basic);
5814 return done_something;
5817 #if 0 /// UNNEEDED by elogind
5818 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5823 assert_return(m, -EINVAL);
5824 assert_return(m->sealed, -EPERM);
5825 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5826 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5827 assert_return(type || contents, -EINVAL);
5828 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5830 r = sd_bus_message_peek_type(m, &t, &c);
5834 if (type != 0 && type != t)
5837 if (contents && !streq_ptr(contents, c))
5844 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5845 assert_return(m, NULL);
5850 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5851 _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5859 switch ((*m)->header->type) {
5861 case SD_BUS_MESSAGE_SIGNAL:
5862 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5868 case SD_BUS_MESSAGE_METHOD_CALL:
5869 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5875 case SD_BUS_MESSAGE_METHOD_RETURN:
5876 case SD_BUS_MESSAGE_METHOD_ERROR:
5878 n = message_new(bus, (*m)->header->type);
5882 n->reply_cookie = (*m)->reply_cookie;
5884 r = message_append_reply_cookie(n, n->reply_cookie);
5888 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5889 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5893 n->error._need_free = -1;
5902 if ((*m)->destination && !n->destination) {
5903 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5908 if ((*m)->sender && !n->sender) {
5909 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5914 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5916 r = sd_bus_message_copy(n, *m, true);
5920 timeout = (*m)->timeout;
5921 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5922 timeout = BUS_DEFAULT_TIMEOUT;
5924 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5928 sd_bus_message_unref(*m);
5935 #if 0 /// UNNEEDED by elogind
5936 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5940 assert_return(!m->sealed, -EPERM);
5941 assert_return(!m->sender, -EPERM);
5943 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5946 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5947 assert_return(m, -EINVAL);
5948 assert_return(priority, -EINVAL);
5950 *priority = m->priority;
5954 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5955 assert_return(m, -EINVAL);
5956 assert_return(!m->sealed, -EPERM);
5958 m->priority = priority;