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 #if 0 /// UNNEEDED by elogind
1086 _public_ int sd_bus_message_is_signal(
1088 const char *interface,
1089 const char *member) {
1091 assert_return(m, -EINVAL);
1093 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1096 if (interface && (!m->interface || !streq(m->interface, interface)))
1099 if (member && (!m->member || !streq(m->member, member)))
1106 _public_ int sd_bus_message_is_method_call(
1108 const char *interface,
1109 const char *member) {
1111 assert_return(m, -EINVAL);
1113 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1116 if (interface && (!m->interface || !streq(m->interface, interface)))
1119 if (member && (!m->member || !streq(m->member, member)))
1125 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1126 assert_return(m, -EINVAL);
1128 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1131 if (name && (!m->error.name || !streq(m->error.name, name)))
1137 #if 0 /// UNNEEDED by elogind
1138 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1139 assert_return(m, -EINVAL);
1140 assert_return(!m->sealed, -EPERM);
1141 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1143 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
1148 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1149 assert_return(m, -EINVAL);
1150 assert_return(!m->sealed, -EPERM);
1152 SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
1157 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1158 assert_return(m, -EINVAL);
1159 assert_return(!m->sealed, -EPERM);
1161 SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
1167 static struct bus_container *message_get_container(sd_bus_message *m) {
1170 if (m->n_containers == 0)
1171 return &m->root_container;
1173 assert(m->containers);
1174 return m->containers + m->n_containers - 1;
1177 struct bus_body_part *message_append_part(sd_bus_message *m) {
1178 struct bus_body_part *part;
1185 if (m->n_body_parts <= 0) {
1189 assert(m->body_end);
1191 part = new0(struct bus_body_part, 1);
1197 m->body_end->next = part;
1207 static void part_zero(struct bus_body_part *part, size_t sz) {
1212 /* All other fields can be left in their defaults */
1213 assert(!part->data);
1214 assert(part->memfd < 0);
1217 part->is_zero = true;
1218 part->sealed = true;
1221 static int part_make_space(
1222 struct sd_bus_message *m,
1223 struct bus_body_part *part,
1232 assert(!part->sealed);
1237 if (!part->data && part->memfd < 0) {
1238 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1239 part->mmap_begin = part->data;
1242 if (part->memfd >= 0) {
1244 if (part->allocated == 0 || sz > part->allocated) {
1245 uint64_t new_allocated;
1247 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1248 r = memfd_set_size(part->memfd, new_allocated);
1254 part->allocated = new_allocated;
1257 if (!part->data || sz > part->mapped) {
1260 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1261 if (part->mapped <= 0)
1262 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1264 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1266 if (n == MAP_FAILED) {
1271 part->mmap_begin = part->data = n;
1273 part->memfd_offset = 0;
1276 part->munmap_this = true;
1278 if (part->allocated == 0 || sz > part->allocated) {
1279 size_t new_allocated;
1281 new_allocated = sz > 0 ? 2 * sz : 64;
1282 n = realloc(part->data, new_allocated);
1289 part->allocated = new_allocated;
1290 part->free_this = true;
1295 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1301 static int message_add_offset(sd_bus_message *m, size_t offset) {
1302 struct bus_container *c;
1305 assert(BUS_MESSAGE_IS_GVARIANT(m));
1307 /* Add offset to current container, unless this is the first
1308 * item in it, which will have the 0 offset, which we can
1310 c = message_get_container(m);
1312 if (!c->need_offsets)
1315 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1318 c->offsets[c->n_offsets++] = offset;
1322 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1323 struct bus_container *c;
1330 /* Update counters */
1331 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1334 *c->array_size += expand;
1338 static void *message_extend_body(
1343 bool force_inline) {
1345 size_t start_body, end_body, padding, added;
1356 start_body = ALIGN_TO((size_t) m->body_size, align);
1357 end_body = start_body + sz;
1359 padding = start_body - m->body_size;
1360 added = padding + sz;
1362 /* Check for 32bit overflows */
1363 if (end_body > (size_t) ((uint32_t) -1) ||
1364 end_body < start_body) {
1370 struct bus_body_part *part = NULL;
1374 m->n_body_parts <= 0 ||
1375 m->body_end->sealed ||
1376 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1377 (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 */
1381 part = message_append_part(m);
1385 part_zero(part, padding);
1388 part = message_append_part(m);
1392 r = part_make_space(m, part, sz, &p);
1396 struct bus_container *c;
1398 size_t os, start_part, end_part;
1404 start_part = ALIGN_TO(part->size, align);
1405 end_part = start_part + sz;
1407 r = part_make_space(m, part, end_part, &p);
1412 memzero(p, padding);
1413 p = (uint8_t*) p + padding;
1416 /* Readjust pointers */
1417 for (c = m->containers; c < m->containers + m->n_containers; c++)
1418 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1420 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1423 /* Return something that is not NULL and is aligned */
1424 p = (uint8_t *) NULL + align;
1426 m->body_size = end_body;
1427 message_extend_containers(m, added);
1430 r = message_add_offset(m, end_body);
1440 static int message_push_fd(sd_bus_message *m, int fd) {
1451 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1455 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1463 m->fds[m->n_fds] = copy;
1469 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1470 _cleanup_close_ int fd = -1;
1471 struct bus_container *c;
1475 assert_return(m, -EINVAL);
1476 assert_return(!m->sealed, -EPERM);
1477 assert_return(bus_type_is_basic(type), -EINVAL);
1478 assert_return(!m->poisoned, -ESTALE);
1480 c = message_get_container(m);
1482 if (c->signature && c->signature[c->index]) {
1483 /* Container signature is already set */
1485 if (c->signature[c->index] != type)
1490 /* Maybe we can append to the signature? But only if this is the top-level container */
1491 if (c->enclosing != 0)
1494 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1501 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1507 case SD_BUS_TYPE_SIGNATURE:
1508 case SD_BUS_TYPE_STRING:
1511 /* Fall through... */
1512 case SD_BUS_TYPE_OBJECT_PATH:
1520 case SD_BUS_TYPE_BOOLEAN:
1522 u8 = p && *(int*) p;
1528 case SD_BUS_TYPE_UNIX_FD:
1533 fd = message_push_fd(m, *(int*) p);
1544 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1545 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1552 a = message_extend_body(m, align, sz, true, false);
1559 *stored = (const uint8_t*) a;
1566 case SD_BUS_TYPE_STRING:
1567 /* To make things easy we'll serialize a NULL string
1568 * into the empty string */
1571 /* Fall through... */
1572 case SD_BUS_TYPE_OBJECT_PATH:
1578 sz = 4 + strlen(p) + 1;
1581 case SD_BUS_TYPE_SIGNATURE:
1586 sz = 1 + strlen(p) + 1;
1589 case SD_BUS_TYPE_BOOLEAN:
1591 u32 = p && *(int*) p;
1597 case SD_BUS_TYPE_UNIX_FD:
1602 fd = message_push_fd(m, *(int*) p);
1613 align = bus_type_get_alignment(type);
1614 sz = bus_type_get_size(type);
1621 a = message_extend_body(m, align, sz, false, false);
1625 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1626 *(uint32_t*) a = sz - 5;
1627 memcpy((uint8_t*) a + 4, p, sz - 4);
1630 *stored = (const uint8_t*) a + 4;
1632 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1633 *(uint8_t*) a = sz - 2;
1634 memcpy((uint8_t*) a + 1, p, sz - 1);
1637 *stored = (const uint8_t*) a + 1;
1646 if (type == SD_BUS_TYPE_UNIX_FD)
1649 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1656 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1657 return message_append_basic(m, type, p, NULL);
1660 #if 0 /// UNNEEDED by elogind
1661 _public_ int sd_bus_message_append_string_space(
1666 struct bus_container *c;
1669 assert_return(m, -EINVAL);
1670 assert_return(s, -EINVAL);
1671 assert_return(!m->sealed, -EPERM);
1672 assert_return(!m->poisoned, -ESTALE);
1674 c = message_get_container(m);
1676 if (c->signature && c->signature[c->index]) {
1677 /* Container signature is already set */
1679 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1684 /* Maybe we can append to the signature? But only if this is the top-level container */
1685 if (c->enclosing != 0)
1688 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1695 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1696 a = message_extend_body(m, 1, size + 1, true, false);
1702 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1706 *(uint32_t*) a = size;
1712 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1718 _public_ int sd_bus_message_append_string_iovec(
1720 const struct iovec *iov,
1728 assert_return(m, -EINVAL);
1729 assert_return(!m->sealed, -EPERM);
1730 assert_return(iov || n == 0, -EINVAL);
1731 assert_return(!m->poisoned, -ESTALE);
1733 size = IOVEC_TOTAL_SIZE(iov, n);
1735 r = sd_bus_message_append_string_space(m, size, &p);
1739 for (i = 0; i < n; i++) {
1741 if (iov[i].iov_base)
1742 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1744 memset(p, ' ', iov[i].iov_len);
1746 p += iov[i].iov_len;
1753 static int bus_message_open_array(
1755 struct bus_container *c,
1756 const char *contents,
1757 uint32_t **array_size,
1759 bool *need_offsets) {
1769 assert(need_offsets);
1771 if (!signature_is_single(contents, true))
1774 if (c->signature && c->signature[c->index]) {
1776 /* Verify the existing signature */
1778 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1781 if (!startswith(c->signature + c->index + 1, contents))
1784 nindex = c->index + 1 + strlen(contents);
1788 if (c->enclosing != 0)
1791 /* Extend the existing signature */
1793 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1799 nindex = e - c->signature;
1802 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1803 alignment = bus_gvariant_get_alignment(contents);
1807 /* Add alignment padding and add to offset list */
1808 if (!message_extend_body(m, alignment, 0, false, false))
1811 r = bus_gvariant_is_fixed_size(contents);
1815 *begin = m->body_size;
1816 *need_offsets = r == 0;
1820 struct bus_body_part *o;
1822 alignment = bus_type_get_alignment(contents[0]);
1826 a = message_extend_body(m, 4, 4, false, false);
1831 op = m->body_end->data;
1832 os = m->body_end->size;
1834 /* Add alignment between size and first element */
1835 if (!message_extend_body(m, alignment, 0, false, false))
1838 /* location of array size might have changed so let's readjust a */
1839 if (o == m->body_end)
1840 a = adjust_pointer(a, op, os, m->body_end->data);
1846 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1852 static int bus_message_open_variant(
1854 struct bus_container *c,
1855 const char *contents) {
1861 if (!signature_is_single(contents, false))
1864 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1867 if (c->signature && c->signature[c->index]) {
1869 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1875 if (c->enclosing != 0)
1878 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1885 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1886 /* Variants are always aligned to 8 */
1888 if (!message_extend_body(m, 8, 0, false, false))
1895 l = strlen(contents);
1896 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1901 memcpy((uint8_t*) a + 1, contents, l + 1);
1904 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1910 static int bus_message_open_struct(
1912 struct bus_container *c,
1913 const char *contents,
1915 bool *need_offsets) {
1924 assert(need_offsets);
1926 if (!signature_is_valid(contents, false))
1929 if (c->signature && c->signature[c->index]) {
1932 l = strlen(contents);
1934 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1935 !startswith(c->signature + c->index + 1, contents) ||
1936 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1939 nindex = c->index + 1 + l + 1;
1943 if (c->enclosing != 0)
1946 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1952 nindex = e - c->signature;
1955 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1958 alignment = bus_gvariant_get_alignment(contents);
1962 if (!message_extend_body(m, alignment, 0, false, false))
1965 r = bus_gvariant_is_fixed_size(contents);
1969 *begin = m->body_size;
1970 *need_offsets = r == 0;
1972 /* Align contents to 8 byte boundary */
1973 if (!message_extend_body(m, 8, 0, false, false))
1977 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1983 static int bus_message_open_dict_entry(
1985 struct bus_container *c,
1986 const char *contents,
1988 bool *need_offsets) {
1996 assert(need_offsets);
1998 if (!signature_is_pair(contents))
2001 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2004 if (c->signature && c->signature[c->index]) {
2007 l = strlen(contents);
2009 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2010 !startswith(c->signature + c->index + 1, contents) ||
2011 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2016 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2019 alignment = bus_gvariant_get_alignment(contents);
2023 if (!message_extend_body(m, alignment, 0, false, false))
2026 r = bus_gvariant_is_fixed_size(contents);
2030 *begin = m->body_size;
2031 *need_offsets = r == 0;
2033 /* Align contents to 8 byte boundary */
2034 if (!message_extend_body(m, 8, 0, false, false))
2041 _public_ int sd_bus_message_open_container(
2044 const char *contents) {
2046 struct bus_container *c, *w;
2047 uint32_t *array_size = NULL;
2049 size_t before, begin = 0;
2050 bool need_offsets = false;
2053 assert_return(m, -EINVAL);
2054 assert_return(!m->sealed, -EPERM);
2055 assert_return(contents, -EINVAL);
2056 assert_return(!m->poisoned, -ESTALE);
2058 /* Make sure we have space for one more container */
2059 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2064 c = message_get_container(m);
2066 signature = strdup(contents);
2072 /* Save old index in the parent container, in case we have to
2073 * abort this container */
2074 c->saved_index = c->index;
2075 before = m->body_size;
2077 if (type == SD_BUS_TYPE_ARRAY)
2078 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2079 else if (type == SD_BUS_TYPE_VARIANT)
2080 r = bus_message_open_variant(m, c, contents);
2081 else if (type == SD_BUS_TYPE_STRUCT)
2082 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2083 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2084 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2093 /* OK, let's fill it in */
2094 w = m->containers + m->n_containers++;
2095 w->enclosing = type;
2096 w->signature = signature;
2098 w->array_size = array_size;
2101 w->n_offsets = w->offsets_allocated = 0;
2103 w->need_offsets = need_offsets;
2108 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2113 if (!BUS_MESSAGE_IS_GVARIANT(m))
2116 if (c->need_offsets) {
2117 size_t payload, sz, i;
2120 /* Variable-width arrays */
2122 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2123 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2125 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2129 for (i = 0; i < c->n_offsets; i++)
2130 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2134 /* Fixed-width or empty arrays */
2136 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2144 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2150 assert(c->signature);
2152 if (!BUS_MESSAGE_IS_GVARIANT(m))
2155 l = strlen(c->signature);
2157 a = message_extend_body(m, 1, 1 + l, true, false);
2162 memcpy(a+1, c->signature, l);
2167 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2168 bool fixed_size = true;
2169 size_t n_variable = 0;
2178 if (!BUS_MESSAGE_IS_GVARIANT(m))
2181 p = strempty(c->signature);
2185 r = signature_element_length(p, &n);
2194 r = bus_gvariant_is_fixed_size(t);
2199 assert(!c->need_offsets || i <= c->n_offsets);
2201 /* We need to add an offset for each item that has a
2202 * variable size and that is not the last one in the
2206 if (r == 0 && p[n] != 0)
2213 assert(!c->need_offsets || i == c->n_offsets);
2214 assert(c->need_offsets || n_variable == 0);
2216 if (isempty(c->signature)) {
2217 /* The unary type is encoded as fixed 1 byte padding */
2218 a = message_extend_body(m, 1, 1, add_offset, false);
2223 } else if (n_variable <= 0) {
2226 /* Structures with fixed-size members only have to be
2227 * fixed-size themselves. But gvariant requires all fixed-size
2228 * elements to be sized a multiple of their alignment. Hence,
2229 * we must *always* add final padding after the last member so
2230 * the overall size of the structure is properly aligned. */
2232 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2234 assert(alignment > 0);
2236 a = message_extend_body(m, alignment, 0, add_offset, false);
2243 assert(c->offsets[c->n_offsets-1] == m->body_size);
2245 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2247 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2251 p = strempty(c->signature);
2252 for (i = 0, j = 0; i < c->n_offsets; i++) {
2256 r = signature_element_length(p, &n);
2267 r = bus_gvariant_is_fixed_size(t);
2270 if (r > 0 || p[0] == 0)
2274 k = n_variable - 1 - j;
2276 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2285 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2286 struct bus_container *c;
2289 assert_return(m, -EINVAL);
2290 assert_return(!m->sealed, -EPERM);
2291 assert_return(m->n_containers > 0, -EINVAL);
2292 assert_return(!m->poisoned, -ESTALE);
2294 c = message_get_container(m);
2296 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2297 if (c->signature && c->signature[c->index] != 0)
2302 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2303 r = bus_message_close_array(m, c);
2304 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2305 r = bus_message_close_variant(m, c);
2306 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2307 r = bus_message_close_struct(m, c, true);
2309 assert_not_reached("Unknown container type");
2323 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2330 stack[*i].types = types;
2331 stack[*i].n_struct = n_struct;
2332 stack[*i].n_array = n_array;
2338 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2349 *types = stack[*i].types;
2350 *n_struct = stack[*i].n_struct;
2351 *n_array = stack[*i].n_array;
2356 int bus_message_append_ap(
2361 unsigned n_array, n_struct;
2362 TypeStack stack[BUS_CONTAINER_DEPTH];
2363 unsigned stack_ptr = 0;
2371 n_array = (unsigned) -1;
2372 n_struct = strlen(types);
2377 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2378 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2384 r = sd_bus_message_close_container(m);
2392 if (n_array != (unsigned) -1)
2401 case SD_BUS_TYPE_BYTE: {
2404 x = (uint8_t) va_arg(ap, int);
2405 r = sd_bus_message_append_basic(m, *t, &x);
2409 case SD_BUS_TYPE_BOOLEAN:
2410 case SD_BUS_TYPE_INT32:
2411 case SD_BUS_TYPE_UINT32:
2412 case SD_BUS_TYPE_UNIX_FD: {
2415 /* We assume a boolean is the same as int32_t */
2416 assert_cc(sizeof(int32_t) == sizeof(int));
2418 x = va_arg(ap, uint32_t);
2419 r = sd_bus_message_append_basic(m, *t, &x);
2423 case SD_BUS_TYPE_INT16:
2424 case SD_BUS_TYPE_UINT16: {
2427 x = (uint16_t) va_arg(ap, int);
2428 r = sd_bus_message_append_basic(m, *t, &x);
2432 case SD_BUS_TYPE_INT64:
2433 case SD_BUS_TYPE_UINT64: {
2436 x = va_arg(ap, uint64_t);
2437 r = sd_bus_message_append_basic(m, *t, &x);
2441 case SD_BUS_TYPE_DOUBLE: {
2444 x = va_arg(ap, double);
2445 r = sd_bus_message_append_basic(m, *t, &x);
2449 case SD_BUS_TYPE_STRING:
2450 case SD_BUS_TYPE_OBJECT_PATH:
2451 case SD_BUS_TYPE_SIGNATURE: {
2454 x = va_arg(ap, const char*);
2455 r = sd_bus_message_append_basic(m, *t, x);
2459 case SD_BUS_TYPE_ARRAY: {
2462 r = signature_element_length(t + 1, &k);
2468 memcpy(s, t + 1, k);
2471 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2476 if (n_array == (unsigned) -1) {
2481 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2487 n_array = va_arg(ap, unsigned);
2492 case SD_BUS_TYPE_VARIANT: {
2495 s = va_arg(ap, const char*);
2499 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2503 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2508 n_struct = strlen(s);
2509 n_array = (unsigned) -1;
2514 case SD_BUS_TYPE_STRUCT_BEGIN:
2515 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2518 r = signature_element_length(t, &k);
2525 memcpy(s, t + 1, k - 2);
2528 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2533 if (n_array == (unsigned) -1) {
2538 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2544 n_array = (unsigned) -1;
2560 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2564 assert_return(m, -EINVAL);
2565 assert_return(types, -EINVAL);
2566 assert_return(!m->sealed, -EPERM);
2567 assert_return(!m->poisoned, -ESTALE);
2569 va_start(ap, types);
2570 r = bus_message_append_ap(m, types, ap);
2576 #if 0 /// UNNEEDED by elogind
2577 _public_ int sd_bus_message_append_array_space(
2587 assert_return(m, -EINVAL);
2588 assert_return(!m->sealed, -EPERM);
2589 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2590 assert_return(ptr || size == 0, -EINVAL);
2591 assert_return(!m->poisoned, -ESTALE);
2593 /* alignment and size of the trivial types (except bool) is
2594 * identical for gvariant and dbus1 marshalling */
2595 align = bus_type_get_alignment(type);
2596 sz = bus_type_get_size(type);
2598 assert_se(align > 0);
2604 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2608 a = message_extend_body(m, align, size, false, false);
2612 r = sd_bus_message_close_container(m);
2620 _public_ int sd_bus_message_append_array(
2628 assert_return(m, -EINVAL);
2629 assert_return(!m->sealed, -EPERM);
2630 assert_return(bus_type_is_trivial(type), -EINVAL);
2631 assert_return(ptr || size == 0, -EINVAL);
2632 assert_return(!m->poisoned, -ESTALE);
2634 r = sd_bus_message_append_array_space(m, type, size, &p);
2638 memcpy_safe(p, ptr, size);
2643 _public_ int sd_bus_message_append_array_iovec(
2646 const struct iovec *iov,
2654 assert_return(m, -EINVAL);
2655 assert_return(!m->sealed, -EPERM);
2656 assert_return(bus_type_is_trivial(type), -EINVAL);
2657 assert_return(iov || n == 0, -EINVAL);
2658 assert_return(!m->poisoned, -ESTALE);
2660 size = IOVEC_TOTAL_SIZE(iov, n);
2662 r = sd_bus_message_append_array_space(m, type, size, &p);
2666 for (i = 0; i < n; i++) {
2668 if (iov[i].iov_base)
2669 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2671 memzero(p, iov[i].iov_len);
2673 p = (uint8_t*) p + iov[i].iov_len;
2679 _public_ int sd_bus_message_append_array_memfd(
2686 _cleanup_close_ int copy_fd = -1;
2687 struct bus_body_part *part;
2693 assert_return(m, -EINVAL);
2694 assert_return(memfd >= 0, -EBADF);
2695 assert_return(bus_type_is_trivial(type), -EINVAL);
2696 assert_return(size > 0, -EINVAL);
2697 assert_return(!m->sealed, -EPERM);
2698 assert_return(!m->poisoned, -ESTALE);
2700 r = memfd_set_sealed(memfd);
2704 copy_fd = dup(memfd);
2708 r = memfd_get_size(memfd, &real_size);
2712 if (offset == 0 && size == (uint64_t) -1)
2714 else if (offset + size > real_size)
2717 align = bus_type_get_alignment(type);
2718 sz = bus_type_get_size(type);
2720 assert_se(align > 0);
2723 if (offset % align != 0)
2729 if (size > (uint64_t) (uint32_t) -1)
2732 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2736 a = message_extend_body(m, align, 0, false, false);
2740 part = message_append_part(m);
2744 part->memfd = copy_fd;
2745 part->memfd_offset = offset;
2746 part->sealed = true;
2750 m->body_size += size;
2751 message_extend_containers(m, size);
2753 return sd_bus_message_close_container(m);
2756 _public_ int sd_bus_message_append_string_memfd(
2762 _cleanup_close_ int copy_fd = -1;
2763 struct bus_body_part *part;
2764 struct bus_container *c;
2769 assert_return(m, -EINVAL);
2770 assert_return(memfd >= 0, -EBADF);
2771 assert_return(size > 0, -EINVAL);
2772 assert_return(!m->sealed, -EPERM);
2773 assert_return(!m->poisoned, -ESTALE);
2775 r = memfd_set_sealed(memfd);
2779 copy_fd = dup(memfd);
2783 r = memfd_get_size(memfd, &real_size);
2787 if (offset == 0 && size == (uint64_t) -1)
2789 else if (offset + size > real_size)
2792 /* We require this to be NUL terminated */
2796 if (size > (uint64_t) (uint32_t) -1)
2799 c = message_get_container(m);
2800 if (c->signature && c->signature[c->index]) {
2801 /* Container signature is already set */
2803 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2808 /* Maybe we can append to the signature? But only if this is the top-level container */
2809 if (c->enclosing != 0)
2812 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2819 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2820 a = message_extend_body(m, 4, 4, false, false);
2824 *(uint32_t*) a = size - 1;
2827 part = message_append_part(m);
2831 part->memfd = copy_fd;
2832 part->memfd_offset = offset;
2833 part->sealed = true;
2837 m->body_size += size;
2838 message_extend_containers(m, size);
2840 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2841 r = message_add_offset(m, m->body_size);
2848 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2855 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2859 assert_return(m, -EINVAL);
2860 assert_return(!m->sealed, -EPERM);
2861 assert_return(!m->poisoned, -ESTALE);
2863 r = sd_bus_message_open_container(m, 'a', "s");
2867 STRV_FOREACH(i, l) {
2868 r = sd_bus_message_append_basic(m, 's', *i);
2873 return sd_bus_message_close_container(m);
2876 static int bus_message_close_header(sd_bus_message *m) {
2880 /* The actual user data is finished now, we just complete the
2881 variant and struct now (at least on gvariant). Remember
2882 this position, so that during parsing we know where to
2883 put the outer container end. */
2884 m->user_body_size = m->body_size;
2886 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2887 const char *signature;
2891 /* Add offset table to end of fields array */
2892 if (m->n_header_offsets >= 1) {
2896 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2898 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2899 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2903 for (i = 0; i < m->n_header_offsets; i++)
2904 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2907 /* Add gvariant NUL byte plus signature to the end of
2908 * the body, followed by the final offset pointing to
2909 * the end of the fields array */
2911 signature = strempty(m->root_container.signature);
2912 l = strlen(signature);
2914 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2915 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2920 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2921 memcpy((uint8_t*) d + 2, signature, l);
2922 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2924 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2927 m->footer_accessible = 1 + l + 2 + sz;
2929 m->header->dbus1.fields_size = m->fields_size;
2930 m->header->dbus1.body_size = m->body_size;
2936 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2937 struct bus_body_part *part;
2947 if (m->n_containers > 0)
2953 if (cookie > 0xffffffffULL &&
2954 !BUS_MESSAGE_IS_GVARIANT(m))
2957 /* In vtables the return signature of method calls is listed,
2958 * let's check if they match if this is a response */
2959 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2960 m->enforced_reply_signature &&
2961 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2964 /* If gvariant marshalling is used we need to close the body structure */
2965 r = bus_message_close_struct(m, &m->root_container, false);
2969 /* If there's a non-trivial signature set, then add it in
2970 * here, but only on dbus1 */
2971 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2972 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2978 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2983 r = bus_message_close_header(m);
2987 if (BUS_MESSAGE_IS_GVARIANT(m))
2988 m->header->dbus2.cookie = cookie;
2990 m->header->dbus1.serial = (uint32_t) cookie;
2992 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2994 /* Add padding at the end of the fields part, since we know
2995 * the body needs to start at an 8 byte alignment. We made
2996 * sure we allocated enough space for this, so all we need to
2997 * do here is to zero it out. */
2998 a = ALIGN8(m->fields_size) - m->fields_size;
3000 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
3002 /* If this is something we can send as memfd, then let's seal
3003 the memfd now. Note that we can send memfds as payload only
3004 for directed messages, and not for broadcasts. */
3005 if (m->destination && m->bus->use_memfd) {
3006 MESSAGE_FOREACH_PART(part, i, m)
3007 if (part->memfd >= 0 &&
3009 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3010 part != m->body_end) { /* The last part may never be sent as memfd */
3013 /* Try to seal it if that makes
3014 * sense. First, unmap our own map to
3015 * make sure we don't keep it busy. */
3016 bus_body_part_unmap(part);
3018 /* Then, sync up real memfd size */
3020 r = memfd_set_size(part->memfd, sz);
3024 /* Finally, try to seal */
3025 if (memfd_set_sealed(part->memfd) >= 0)
3026 part->sealed = true;
3030 m->root_container.end = m->user_body_size;
3031 m->root_container.index = 0;
3032 m->root_container.offset_index = 0;
3033 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3040 int bus_body_part_map(struct bus_body_part *part) {
3049 if (part->size <= 0)
3052 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3053 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3054 static const uint8_t zeroes[7] = { };
3055 part->data = (void*) zeroes;
3059 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3060 psz = PAGE_ALIGN(part->size + shift);
3062 if (part->memfd >= 0)
3063 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3064 else if (part->is_zero)
3065 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3069 if (p == MAP_FAILED)
3073 part->mmap_begin = p;
3074 part->data = (uint8_t*) p + shift;
3075 part->munmap_this = true;
3080 void bus_body_part_unmap(struct bus_body_part *part) {
3084 if (part->memfd < 0)
3087 if (!part->mmap_begin)
3090 if (!part->munmap_this)
3093 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3095 part->mmap_begin = NULL;
3098 part->munmap_this = false;
3103 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3104 size_t k, start, end;
3109 start = ALIGN_TO((size_t) *rindex, align);
3110 end = start + nbytes;
3115 /* Verify that padding is 0 */
3116 for (k = *rindex; k < start; k++)
3117 if (((const uint8_t*) p)[k] != 0)
3121 *r = (uint8_t*) p + start;
3128 static bool message_end_of_signature(sd_bus_message *m) {
3129 struct bus_container *c;
3133 c = message_get_container(m);
3134 return !c->signature || c->signature[c->index] == 0;
3137 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3138 struct bus_container *c;
3142 c = message_get_container(m);
3143 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3146 if (BUS_MESSAGE_IS_GVARIANT(m))
3147 return index >= c->end;
3149 assert(c->array_size);
3150 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3154 #if 0 /// UNNEEDED by elogind
3155 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3156 assert_return(m, -EINVAL);
3157 assert_return(m->sealed, -EPERM);
3159 if (complete && m->n_containers > 0)
3162 if (message_end_of_signature(m))
3165 if (message_end_of_array(m, m->rindex))
3172 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3173 struct bus_body_part *part;
3179 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3180 part = m->cached_rindex_part;
3181 begin = m->cached_rindex_part_begin;
3191 if (index + sz <= begin + part->size) {
3193 r = bus_body_part_map(part);
3198 *p = (uint8_t*) part->data + index - begin;
3200 m->cached_rindex_part = part;
3201 m->cached_rindex_part_begin = begin;
3206 begin += part->size;
3213 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3220 if (!BUS_MESSAGE_IS_GVARIANT(m))
3223 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3226 sz = bus_gvariant_get_size(c->signature);
3230 if (c->offset_index+1 >= c->n_offsets)
3233 /* Variable-size array */
3235 alignment = bus_gvariant_get_alignment(c->signature);
3236 assert(alignment > 0);
3238 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3239 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3242 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3245 /* Fixed-size array */
3246 *rindex = c->begin + (c->offset_index+1) * sz;
3252 } else if (c->enclosing == 0 ||
3253 c->enclosing == SD_BUS_TYPE_STRUCT ||
3254 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3259 if (c->offset_index+1 >= c->n_offsets)
3262 r = signature_element_length(c->signature + c->index, &n);
3266 r = signature_element_length(c->signature + c->index + n, &j);
3271 memcpy(t, c->signature + c->index + n, j);
3274 alignment = bus_gvariant_get_alignment(t);
3277 assert(alignment > 0);
3279 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3280 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3284 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3287 assert_not_reached("Unknown container type");
3292 /* Reached the end */
3299 static int message_peek_body(
3306 size_t k, start, end, padding;
3307 struct bus_body_part *part;
3314 start = ALIGN_TO((size_t) *rindex, align);
3315 padding = start - *rindex;
3316 end = start + nbytes;
3318 if (end > m->user_body_size)
3321 part = find_part(m, *rindex, padding, (void**) &q);
3326 /* Verify padding */
3327 for (k = 0; k < padding; k++)
3332 part = find_part(m, start, nbytes, (void**) &q);
3333 if (!part || (nbytes > 0 && !q))
3344 static bool validate_nul(const char *s, size_t l) {
3346 /* Check for NUL chars in the string */
3347 if (memchr(s, 0, l))
3350 /* Check for NUL termination */
3357 static bool validate_string(const char *s, size_t l) {
3359 if (!validate_nul(s, l))
3362 /* Check if valid UTF8 */
3363 if (!utf8_is_valid(s))
3369 static bool validate_signature(const char *s, size_t l) {
3371 if (!validate_nul(s, l))
3374 /* Check if valid signature */
3375 if (!signature_is_valid(s, true))
3381 static bool validate_object_path(const char *s, size_t l) {
3383 if (!validate_nul(s, l))
3386 if (!object_path_is_valid(s))
3392 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3393 struct bus_container *c;
3398 assert_return(m, -EINVAL);
3399 assert_return(m->sealed, -EPERM);
3400 assert_return(bus_type_is_basic(type), -EINVAL);
3402 if (message_end_of_signature(m))
3405 if (message_end_of_array(m, m->rindex))
3408 c = message_get_container(m);
3409 if (c->signature[c->index] != type)
3414 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3416 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3419 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3423 if (type == SD_BUS_TYPE_STRING)
3424 ok = validate_string(q, c->item_size-1);
3425 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3426 ok = validate_object_path(q, c->item_size-1);
3428 ok = validate_signature(q, c->item_size-1);
3434 *(const char**) p = q;
3438 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3440 if ((size_t) sz != c->item_size)
3443 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3446 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3452 case SD_BUS_TYPE_BYTE:
3454 *(uint8_t*) p = *(uint8_t*) q;
3457 case SD_BUS_TYPE_BOOLEAN:
3459 *(int*) p = !!*(uint8_t*) q;
3462 case SD_BUS_TYPE_INT16:
3463 case SD_BUS_TYPE_UINT16:
3465 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3468 case SD_BUS_TYPE_INT32:
3469 case SD_BUS_TYPE_UINT32:
3471 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3474 case SD_BUS_TYPE_INT64:
3475 case SD_BUS_TYPE_UINT64:
3476 case SD_BUS_TYPE_DOUBLE:
3478 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3481 case SD_BUS_TYPE_UNIX_FD: {
3484 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3489 *(int*) p = m->fds[j];
3495 assert_not_reached("unexpected type");
3499 r = container_next_item(m, c, &rindex);
3504 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3508 r = message_peek_body(m, &rindex, 4, 4, &q);
3512 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3513 r = message_peek_body(m, &rindex, 1, l+1, &q);
3517 if (type == SD_BUS_TYPE_OBJECT_PATH)
3518 ok = validate_object_path(q, l);
3520 ok = validate_string(q, l);
3525 *(const char**) p = q;
3527 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3530 r = message_peek_body(m, &rindex, 1, 1, &q);
3535 r = message_peek_body(m, &rindex, 1, l+1, &q);
3539 if (!validate_signature(q, l))
3543 *(const char**) p = q;
3548 align = bus_type_get_alignment(type);
3551 sz = bus_type_get_size(type);
3554 r = message_peek_body(m, &rindex, align, sz, &q);
3560 case SD_BUS_TYPE_BYTE:
3562 *(uint8_t*) p = *(uint8_t*) q;
3565 case SD_BUS_TYPE_BOOLEAN:
3567 *(int*) p = !!*(uint32_t*) q;
3570 case SD_BUS_TYPE_INT16:
3571 case SD_BUS_TYPE_UINT16:
3573 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3576 case SD_BUS_TYPE_INT32:
3577 case SD_BUS_TYPE_UINT32:
3579 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3582 case SD_BUS_TYPE_INT64:
3583 case SD_BUS_TYPE_UINT64:
3584 case SD_BUS_TYPE_DOUBLE:
3586 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3589 case SD_BUS_TYPE_UNIX_FD: {
3592 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3597 *(int*) p = m->fds[j];
3602 assert_not_reached("Unknown basic type...");
3609 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3615 static int bus_message_enter_array(
3617 struct bus_container *c,
3618 const char *contents,
3619 uint32_t **array_size,
3622 size_t *n_offsets) {
3636 if (!signature_is_single(contents, true))
3639 if (!c->signature || c->signature[c->index] == 0)
3642 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3645 if (!startswith(c->signature + c->index + 1, contents))
3650 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3653 r = message_peek_body(m, &rindex, 4, 4, &q);
3657 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3660 alignment = bus_type_get_alignment(contents[0]);
3664 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3668 *array_size = (uint32_t*) q;
3670 } else if (c->item_size <= 0) {
3672 /* gvariant: empty array */
3677 } else if (bus_gvariant_is_fixed_size(contents)) {
3679 /* gvariant: fixed length array */
3680 *item_size = bus_gvariant_get_size(contents);
3685 size_t where, p = 0, framing, sz;
3688 /* gvariant: variable length array */
3689 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3691 where = rindex + c->item_size - sz;
3692 r = message_peek_body(m, &where, 1, sz, &q);
3696 framing = bus_gvariant_read_word_le(q, sz);
3697 if (framing > c->item_size - sz)
3699 if ((c->item_size - framing) % sz != 0)
3702 *n_offsets = (c->item_size - framing) / sz;
3704 where = rindex + framing;
3705 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3709 *offsets = new(size_t, *n_offsets);
3713 for (i = 0; i < *n_offsets; i++) {
3716 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3717 if (x > c->item_size - sz)
3722 (*offsets)[i] = rindex + x;
3726 *item_size = (*offsets)[0] - rindex;
3731 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3732 c->index += 1 + strlen(contents);
3737 static int bus_message_enter_variant(
3739 struct bus_container *c,
3740 const char *contents,
3741 size_t *item_size) {
3753 if (!signature_is_single(contents, false))
3756 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3759 if (!c->signature || c->signature[c->index] == 0)
3762 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3767 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3770 k = strlen(contents);
3771 if (1+k > c->item_size)
3774 where = rindex + c->item_size - (1+k);
3775 r = message_peek_body(m, &where, 1, 1+k, &q);
3779 if (*(char*) q != 0)
3782 if (memcmp((uint8_t*) q+1, contents, k))
3785 *item_size = c->item_size - (1+k);
3788 r = message_peek_body(m, &rindex, 1, 1, &q);
3793 r = message_peek_body(m, &rindex, 1, l+1, &q);
3797 if (!validate_signature(q, l))
3800 if (!streq(q, contents))
3806 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3812 static int build_struct_offsets(
3814 const char *signature,
3818 size_t *n_offsets) {
3820 unsigned n_variable = 0, n_total = 0, v;
3821 size_t previous = 0, where;
3832 if (isempty(signature)) {
3833 /* Unary type is encoded as *fixed* 1 byte padding */
3834 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3838 if (*(uint8_t *) q != 0)
3847 sz = bus_gvariant_determine_word_size(size, 0);
3851 /* First, loop over signature and count variable elements and
3852 * elements in general. We use this to know how large the
3853 * offset array is at the end of the structure. Note that
3854 * GVariant only stores offsets for all variable size elements
3855 * that are not the last item. */
3861 r = signature_element_length(p, &n);
3870 r = bus_gvariant_is_fixed_size(t);
3875 if (r == 0 && p[n] != 0) /* except the last item */
3882 if (size < n_variable * sz)
3885 where = m->rindex + size - (n_variable * sz);
3886 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3892 *offsets = new(size_t, n_total);
3898 /* Second, loop again and build an offset table */
3904 r = signature_element_length(p, &n);
3913 k = bus_gvariant_get_size(t);
3921 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3924 if (m->rindex + x < previous)
3927 /* The last item's end
3928 * is determined from
3931 x = size - (n_variable * sz);
3933 offset = m->rindex + x;
3939 align = bus_gvariant_get_alignment(t);
3942 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3946 previous = (*offsets)[(*n_offsets)++] = offset;
3951 assert(*n_offsets == n_total);
3953 *item_size = (*offsets)[0] - m->rindex;
3957 static int enter_struct_or_dict_entry(
3959 struct bus_container *c,
3960 const char *contents,
3963 size_t *n_offsets) {
3974 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3977 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3982 /* gvariant with contents */
3983 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3988 static int bus_message_enter_struct(
3990 struct bus_container *c,
3991 const char *contents,
3994 size_t *n_offsets) {
4006 if (!signature_is_valid(contents, false))
4009 if (!c->signature || c->signature[c->index] == 0)
4012 l = strlen(contents);
4014 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4015 !startswith(c->signature + c->index + 1, contents) ||
4016 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4019 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4023 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4024 c->index += 1 + l + 1;
4029 static int bus_message_enter_dict_entry(
4031 struct bus_container *c,
4032 const char *contents,
4035 size_t *n_offsets) {
4044 if (!signature_is_pair(contents))
4047 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4050 if (!c->signature || c->signature[c->index] == 0)
4053 l = strlen(contents);
4055 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4056 !startswith(c->signature + c->index + 1, contents) ||
4057 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4060 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4064 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4065 c->index += 1 + l + 1;
4070 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4072 const char *contents) {
4073 struct bus_container *c, *w;
4074 uint32_t *array_size = NULL;
4077 size_t *offsets = NULL;
4078 size_t n_offsets = 0, item_size = 0;
4081 assert_return(m, -EINVAL);
4082 assert_return(m->sealed, -EPERM);
4083 assert_return(type != 0 || !contents, -EINVAL);
4085 if (type == 0 || !contents) {
4089 /* Allow entering into anonymous containers */
4090 r = sd_bus_message_peek_type(m, &tt, &cc);
4094 if (type != 0 && type != tt)
4097 if (contents && !streq(contents, cc))
4105 * We enforce a global limit on container depth, that is much
4106 * higher than the 32 structs and 32 arrays the specification
4107 * mandates. This is simpler to implement for us, and we need
4108 * this only to ensure our container array doesn't grow
4109 * without bounds. We are happy to return any data from a
4110 * message as long as the data itself is valid, even if the
4111 * overall message might be not.
4113 * Note that the message signature is validated when
4114 * parsing the headers, and that validation does check the
4117 * Note that the specification defines no limits on the depth
4118 * of stacked variants, but we do.
4120 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4123 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4126 if (message_end_of_signature(m))
4129 if (message_end_of_array(m, m->rindex))
4132 c = message_get_container(m);
4134 signature = strdup(contents);
4138 c->saved_index = c->index;
4141 if (type == SD_BUS_TYPE_ARRAY)
4142 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4143 else if (type == SD_BUS_TYPE_VARIANT)
4144 r = bus_message_enter_variant(m, c, contents, &item_size);
4145 else if (type == SD_BUS_TYPE_STRUCT)
4146 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4147 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4148 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4158 /* OK, let's fill it in */
4159 w = m->containers + m->n_containers++;
4160 w->enclosing = type;
4161 w->signature = signature;
4162 w->peeked_signature = NULL;
4166 w->begin = m->rindex;
4168 /* Unary type has fixed size of 1, but virtual size of 0 */
4169 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4170 type == SD_BUS_TYPE_STRUCT &&
4172 w->end = m->rindex + 0;
4174 w->end = m->rindex + c->item_size;
4176 w->array_size = array_size;
4177 w->item_size = item_size;
4178 w->offsets = offsets;
4179 w->n_offsets = n_offsets;
4180 w->offset_index = 0;
4185 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4186 struct bus_container *c;
4190 assert_return(m, -EINVAL);
4191 assert_return(m->sealed, -EPERM);
4192 assert_return(m->n_containers > 0, -ENXIO);
4194 c = message_get_container(m);
4196 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4197 if (c->signature && c->signature[c->index] != 0)
4201 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4202 if (m->rindex < c->end)
4205 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4208 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4209 if (c->begin + l != m->rindex)
4214 free(c->peeked_signature);
4218 c = message_get_container(m);
4221 c->index = c->saved_index;
4222 r = container_next_item(m, c, &m->rindex);
4230 static void message_quit_container(sd_bus_message *m) {
4231 struct bus_container *c;
4235 assert(m->n_containers > 0);
4237 c = message_get_container(m);
4240 assert(m->rindex >= c->before);
4241 m->rindex = c->before;
4243 /* Free container */
4248 /* Correct index of new top-level container */
4249 c = message_get_container(m);
4250 c->index = c->saved_index;
4253 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4254 struct bus_container *c;
4257 assert_return(m, -EINVAL);
4258 assert_return(m->sealed, -EPERM);
4260 if (message_end_of_signature(m))
4263 if (message_end_of_array(m, m->rindex))
4266 c = message_get_container(m);
4268 if (bus_type_is_basic(c->signature[c->index])) {
4272 *type = c->signature[c->index];
4276 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4282 r = signature_element_length(c->signature+c->index+1, &l);
4288 sig = strndup(c->signature + c->index + 1, l);
4292 free(c->peeked_signature);
4293 *contents = c->peeked_signature = sig;
4297 *type = SD_BUS_TYPE_ARRAY;
4302 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4303 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4309 r = signature_element_length(c->signature+c->index, &l);
4314 sig = strndup(c->signature + c->index + 1, l - 2);
4318 free(c->peeked_signature);
4319 *contents = c->peeked_signature = sig;
4323 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4328 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4332 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4335 if (c->item_size < 2)
4338 /* Look for the NUL delimiter that
4339 separates the payload from the
4340 signature. Since the body might be
4341 in a different part that then the
4342 signature we map byte by byte. */
4344 for (k = 2; k <= c->item_size; k++) {
4347 where = m->rindex + c->item_size - k;
4348 r = message_peek_body(m, &where, 1, k, &q);
4352 if (*(char*) q == 0)
4356 if (k > c->item_size)
4359 free(c->peeked_signature);
4360 c->peeked_signature = strndup((char*) q + 1, k - 1);
4361 if (!c->peeked_signature)
4364 if (!signature_is_valid(c->peeked_signature, true))
4367 *contents = c->peeked_signature;
4372 r = message_peek_body(m, &rindex, 1, 1, &q);
4377 r = message_peek_body(m, &rindex, 1, l+1, &q);
4381 if (!validate_signature(q, l))
4389 *type = SD_BUS_TYPE_VARIANT;
4404 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4405 struct bus_container *c;
4407 assert_return(m, -EINVAL);
4408 assert_return(m->sealed, -EPERM);
4411 message_reset_containers(m);
4414 c = message_get_container(m);
4416 c = message_get_container(m);
4418 c->offset_index = 0;
4420 m->rindex = c->begin;
4423 c->offset_index = 0;
4424 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4426 return !isempty(c->signature);
4429 static int message_read_ap(
4434 unsigned n_array, n_struct;
4435 TypeStack stack[BUS_CONTAINER_DEPTH];
4436 unsigned stack_ptr = 0;
4437 unsigned n_loop = 0;
4445 /* Ideally, we'd just call ourselves recursively on every
4446 * complex type. However, the state of a va_list that is
4447 * passed to a function is undefined after that function
4448 * returns. This means we need to docode the va_list linearly
4449 * in a single stackframe. We hence implement our own
4450 * home-grown stack in an array. */
4452 n_array = (unsigned) -1; /* length of current array entries */
4453 n_struct = strlen(types); /* length of current struct contents signature */
4460 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4461 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4467 r = sd_bus_message_exit_container(m);
4475 if (n_array != (unsigned) -1)
4484 case SD_BUS_TYPE_BYTE:
4485 case SD_BUS_TYPE_BOOLEAN:
4486 case SD_BUS_TYPE_INT16:
4487 case SD_BUS_TYPE_UINT16:
4488 case SD_BUS_TYPE_INT32:
4489 case SD_BUS_TYPE_UINT32:
4490 case SD_BUS_TYPE_INT64:
4491 case SD_BUS_TYPE_UINT64:
4492 case SD_BUS_TYPE_DOUBLE:
4493 case SD_BUS_TYPE_STRING:
4494 case SD_BUS_TYPE_OBJECT_PATH:
4495 case SD_BUS_TYPE_SIGNATURE:
4496 case SD_BUS_TYPE_UNIX_FD: {
4499 p = va_arg(ap, void*);
4500 r = sd_bus_message_read_basic(m, *t, p);
4513 case SD_BUS_TYPE_ARRAY: {
4516 r = signature_element_length(t + 1, &k);
4522 memcpy(s, t + 1, k);
4525 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4536 if (n_array == (unsigned) -1) {
4541 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4547 n_array = va_arg(ap, unsigned);
4552 case SD_BUS_TYPE_VARIANT: {
4555 s = va_arg(ap, const char *);
4559 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4569 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4574 n_struct = strlen(s);
4575 n_array = (unsigned) -1;
4580 case SD_BUS_TYPE_STRUCT_BEGIN:
4581 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4584 r = signature_element_length(t, &k);
4590 memcpy(s, t + 1, k - 2);
4593 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4603 if (n_array == (unsigned) -1) {
4608 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4614 n_array = (unsigned) -1;
4627 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4631 assert_return(m, -EINVAL);
4632 assert_return(m->sealed, -EPERM);
4633 assert_return(types, -EINVAL);
4635 va_start(ap, types);
4636 r = message_read_ap(m, types, ap);
4642 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4645 assert_return(m, -EINVAL);
4646 assert_return(m->sealed, -EPERM);
4648 /* If types is NULL, read exactly one element */
4650 struct bus_container *c;
4653 if (message_end_of_signature(m))
4656 if (message_end_of_array(m, m->rindex))
4659 c = message_get_container(m);
4661 r = signature_element_length(c->signature + c->index, &l);
4665 types = strndupa(c->signature + c->index, l);
4670 case 0: /* Nothing to drop */
4673 case SD_BUS_TYPE_BYTE:
4674 case SD_BUS_TYPE_BOOLEAN:
4675 case SD_BUS_TYPE_INT16:
4676 case SD_BUS_TYPE_UINT16:
4677 case SD_BUS_TYPE_INT32:
4678 case SD_BUS_TYPE_UINT32:
4679 case SD_BUS_TYPE_INT64:
4680 case SD_BUS_TYPE_UINT64:
4681 case SD_BUS_TYPE_DOUBLE:
4682 case SD_BUS_TYPE_STRING:
4683 case SD_BUS_TYPE_OBJECT_PATH:
4684 case SD_BUS_TYPE_SIGNATURE:
4685 case SD_BUS_TYPE_UNIX_FD:
4687 r = sd_bus_message_read_basic(m, *types, NULL);
4691 r = sd_bus_message_skip(m, types + 1);
4697 case SD_BUS_TYPE_ARRAY: {
4700 r = signature_element_length(types + 1, &k);
4706 memcpy(s, types+1, k);
4709 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4714 r = sd_bus_message_skip(m, s);
4721 r = sd_bus_message_exit_container(m);
4726 r = sd_bus_message_skip(m, types + 1 + k);
4733 case SD_BUS_TYPE_VARIANT: {
4734 const char *contents;
4737 r = sd_bus_message_peek_type(m, &x, &contents);
4741 if (x != SD_BUS_TYPE_VARIANT)
4744 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4748 r = sd_bus_message_skip(m, contents);
4753 r = sd_bus_message_exit_container(m);
4757 r = sd_bus_message_skip(m, types + 1);
4764 case SD_BUS_TYPE_STRUCT_BEGIN:
4765 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4768 r = signature_element_length(types, &k);
4774 memcpy(s, types+1, k-2);
4777 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4781 r = sd_bus_message_skip(m, s);
4785 r = sd_bus_message_exit_container(m);
4790 r = sd_bus_message_skip(m, types + k);
4802 _public_ int sd_bus_message_read_array(
4808 struct bus_container *c;
4814 assert_return(m, -EINVAL);
4815 assert_return(m->sealed, -EPERM);
4816 assert_return(bus_type_is_trivial(type), -EINVAL);
4817 assert_return(ptr, -EINVAL);
4818 assert_return(size, -EINVAL);
4819 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4821 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4825 c = message_get_container(m);
4827 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4828 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4832 sz = c->end - c->begin;
4834 align = bus_type_get_alignment(type);
4838 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4842 /* Zero length array, let's return some aligned
4843 * pointer that is not NULL */
4844 p = (uint8_t*) NULL + align;
4846 r = message_peek_body(m, &m->rindex, align, sz, &p);
4851 r = sd_bus_message_exit_container(m);
4855 *ptr = (const void*) p;
4861 message_quit_container(m);
4865 static int message_peek_fields(
4876 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4879 static int message_peek_field_uint32(
4891 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4894 /* identical for gvariant and dbus1 */
4896 r = message_peek_fields(m, ri, 4, 4, &q);
4901 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4906 static int message_peek_field_uint64(
4918 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4921 /* identical for gvariant and dbus1 */
4923 r = message_peek_fields(m, ri, 8, 8, &q);
4928 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4933 static int message_peek_field_string(
4935 bool (*validate)(const char *p),
4947 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4952 r = message_peek_fields(m, ri, 1, item_size, &q);
4958 r = message_peek_field_uint32(m, ri, 4, &l);
4962 r = message_peek_fields(m, ri, 1, l+1, &q);
4968 if (!validate_nul(q, l))
4974 if (!validate_string(q, l))
4984 static int message_peek_field_signature(
4997 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5002 r = message_peek_fields(m, ri, 1, item_size, &q);
5008 r = message_peek_fields(m, ri, 1, 1, &q);
5013 r = message_peek_fields(m, ri, 1, l+1, &q);
5018 if (!validate_signature(q, l))
5027 static int message_skip_fields(
5030 uint32_t array_size,
5031 const char **signature) {
5033 size_t original_index;
5039 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5041 original_index = *ri;
5047 if (array_size != (uint32_t) -1 &&
5048 array_size <= *ri - original_index)
5055 if (t == SD_BUS_TYPE_STRING) {
5057 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5063 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5065 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5071 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5073 r = message_peek_field_signature(m, ri, 0, NULL);
5079 } else if (bus_type_is_basic(t)) {
5082 align = bus_type_get_alignment(t);
5083 k = bus_type_get_size(t);
5084 assert(align > 0 && k > 0);
5086 r = message_peek_fields(m, ri, align, k, NULL);
5092 } else if (t == SD_BUS_TYPE_ARRAY) {
5094 r = signature_element_length(*signature+1, &l);
5104 strncpy(sig, *signature + 1, l-1);
5107 alignment = bus_type_get_alignment(sig[0]);
5111 r = message_peek_field_uint32(m, ri, 0, &nas);
5114 if (nas > BUS_ARRAY_MAX_SIZE)
5117 r = message_peek_fields(m, ri, alignment, 0, NULL);
5121 r = message_skip_fields(m, ri, nas, (const char**) &s);
5126 (*signature) += 1 + l;
5128 } else if (t == SD_BUS_TYPE_VARIANT) {
5131 r = message_peek_field_signature(m, ri, 0, &s);
5135 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5141 } else if (t == SD_BUS_TYPE_STRUCT ||
5142 t == SD_BUS_TYPE_DICT_ENTRY) {
5144 r = signature_element_length(*signature, &l);
5151 strncpy(sig, *signature + 1, l-1);
5154 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5165 int bus_message_parse_fields(sd_bus_message *m) {
5168 uint32_t unix_fds = 0;
5169 bool unix_fds_set = false;
5170 void *offsets = NULL;
5171 unsigned n_offsets = 0;
5177 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5180 /* Read the signature from the end of the body variant first */
5181 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5182 if (m->footer_accessible < 1 + sz)
5185 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5187 if (p < (char*) m->footer)
5194 /* We found the beginning of the signature
5195 * string, yay! We require the body to be a
5196 * structure, so verify it and then strip the
5197 * opening/closing brackets. */
5199 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5201 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5202 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5205 c = strndup(p + 1 + 1, l - 2);
5209 free(m->root_container.signature);
5210 m->root_container.signature = c;
5217 /* Calculate the actual user body size, by removing
5218 * the trailing variant signature and struct offset
5220 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5222 /* Pull out the offset table for the fields array */
5223 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5228 ri = m->fields_size - sz;
5229 r = message_peek_fields(m, &ri, 1, sz, &q);
5233 framing = bus_gvariant_read_word_le(q, sz);
5234 if (framing >= m->fields_size - sz)
5236 if ((m->fields_size - framing) % sz != 0)
5240 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5244 n_offsets = (m->fields_size - framing) / sz;
5247 m->user_body_size = m->body_size;
5250 while (ri < m->fields_size) {
5251 _cleanup_free_ char *sig = NULL;
5252 const char *signature;
5253 uint64_t field_type;
5254 size_t item_size = (size_t) -1;
5256 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5265 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5267 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5271 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5275 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5282 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5287 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5292 where = ri = ALIGN_TO(ri, 8);
5293 item_size = end - ri;
5294 r = message_peek_fields(m, &where, 1, item_size, &q);
5298 b = memrchr(q, 0, item_size);
5302 sig = strndup(b+1, item_size - (b+1-(char*) q));
5307 item_size = b - (char*) q;
5309 r = message_peek_field_signature(m, &ri, 0, &signature);
5314 switch (field_type) {
5316 case _BUS_MESSAGE_HEADER_INVALID:
5319 case BUS_MESSAGE_HEADER_PATH:
5324 if (!streq(signature, "o"))
5327 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5330 case BUS_MESSAGE_HEADER_INTERFACE:
5335 if (!streq(signature, "s"))
5338 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5341 case BUS_MESSAGE_HEADER_MEMBER:
5346 if (!streq(signature, "s"))
5349 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5352 case BUS_MESSAGE_HEADER_ERROR_NAME:
5357 if (!streq(signature, "s"))
5360 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5362 m->error._need_free = -1;
5366 case BUS_MESSAGE_HEADER_DESTINATION:
5371 if (!streq(signature, "s"))
5374 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5377 case BUS_MESSAGE_HEADER_SENDER:
5382 if (!streq(signature, "s"))
5385 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5387 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5388 m->creds.unique_name = (char*) m->sender;
5389 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5395 case BUS_MESSAGE_HEADER_SIGNATURE: {
5399 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5402 if (m->root_container.signature)
5405 if (!streq(signature, "g"))
5408 r = message_peek_field_signature(m, &ri, item_size, &s);
5416 free(m->root_container.signature);
5417 m->root_container.signature = c;
5421 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5423 if (m->reply_cookie != 0)
5426 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5427 /* 64bit on dbus2 */
5429 if (!streq(signature, "t"))
5432 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5436 /* 32bit on dbus1 */
5439 if (!streq(signature, "u"))
5442 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5446 m->reply_cookie = serial;
5449 if (m->reply_cookie == 0)
5454 case BUS_MESSAGE_HEADER_UNIX_FDS:
5458 if (!streq(signature, "u"))
5461 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5465 unix_fds_set = true;
5469 if (!BUS_MESSAGE_IS_GVARIANT(m))
5470 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5479 if (m->n_fds != unix_fds)
5482 switch (m->header->type) {
5484 case SD_BUS_MESSAGE_SIGNAL:
5485 if (!m->path || !m->interface || !m->member)
5488 if (m->reply_cookie != 0)
5493 case SD_BUS_MESSAGE_METHOD_CALL:
5495 if (!m->path || !m->member)
5498 if (m->reply_cookie != 0)
5503 case SD_BUS_MESSAGE_METHOD_RETURN:
5505 if (m->reply_cookie == 0)
5509 case SD_BUS_MESSAGE_METHOD_ERROR:
5511 if (m->reply_cookie == 0 || !m->error.name)
5516 /* Refuse non-local messages that claim they are local */
5517 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5519 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5521 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5524 m->root_container.end = m->user_body_size;
5526 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5527 r = build_struct_offsets(
5529 m->root_container.signature,
5531 &m->root_container.item_size,
5532 &m->root_container.offsets,
5533 &m->root_container.n_offsets);
5538 /* Try to read the error message, but if we can't it's a non-issue */
5539 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5540 (void) sd_bus_message_read(m, "s", &m->error.message);
5545 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5546 assert_return(m, -EINVAL);
5547 assert_return(destination, -EINVAL);
5548 assert_return(!m->sealed, -EPERM);
5549 assert_return(!m->destination, -EEXIST);
5551 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5554 #if 0 /// UNNEEDED by elogind
5555 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5559 struct bus_body_part *part;
5565 total = BUS_MESSAGE_SIZE(m);
5571 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5572 MESSAGE_FOREACH_PART(part, i, m)
5573 e = mempcpy(e, part->data, part->size);
5575 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5584 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5591 r = sd_bus_message_enter_container(m, 'a', "s");
5595 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5596 r = strv_extend(l, s);
5603 r = sd_bus_message_exit_container(m);
5610 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5614 assert_return(m, -EINVAL);
5615 assert_return(m->sealed, -EPERM);
5616 assert_return(l, -EINVAL);
5618 r = bus_message_read_strv_extend(m, &strv);
5628 static int bus_message_get_arg_skip(
5632 const char **_contents) {
5637 r = sd_bus_message_rewind(m, true);
5642 const char *contents;
5645 r = sd_bus_message_peek_type(m, &type, &contents);
5651 /* Don't match against arguments after the first one we don't understand */
5652 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5653 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5658 *_contents = contents;
5664 r = sd_bus_message_skip(m, NULL);
5671 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5678 r = bus_message_get_arg_skip(m, i, &type, NULL);
5682 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5685 return sd_bus_message_read_basic(m, type, str);
5688 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5689 const char *contents;
5696 r = bus_message_get_arg_skip(m, i, &type, &contents);
5700 if (type != SD_BUS_TYPE_ARRAY)
5702 if (!STR_IN_SET(contents, "s", "o", "g"))
5705 return sd_bus_message_read_strv(m, strv);
5708 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5709 assert_return(m, EINVAL);
5711 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5714 return sd_bus_error_get_errno(&m->error);
5717 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5718 struct bus_container *c;
5720 assert_return(m, NULL);
5722 c = complete ? &m->root_container : message_get_container(m);
5723 return strempty(c->signature);
5726 #if 0 /// UNNEEDED by elogind
5727 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5728 assert_return(m, -EINVAL);
5730 return isempty(m->root_container.signature);
5733 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5734 assert_return(m, -EINVAL);
5736 return streq(strempty(m->root_container.signature), strempty(signature));
5740 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5741 bool done_something = false;
5744 assert_return(m, -EINVAL);
5745 assert_return(source, -EINVAL);
5746 assert_return(!m->sealed, -EPERM);
5747 assert_return(source->sealed, -EPERM);
5750 const char *contents;
5765 r = sd_bus_message_peek_type(source, &type, &contents);
5771 done_something = true;
5773 if (bus_type_is_container(type) > 0) {
5775 r = sd_bus_message_enter_container(source, type, contents);
5779 r = sd_bus_message_open_container(m, type, contents);
5783 r = sd_bus_message_copy(m, source, true);
5787 r = sd_bus_message_close_container(m);
5791 r = sd_bus_message_exit_container(source);
5798 r = sd_bus_message_read_basic(source, type, &basic);
5804 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5805 type == SD_BUS_TYPE_SIGNATURE ||
5806 type == SD_BUS_TYPE_STRING)
5807 r = sd_bus_message_append_basic(m, type, basic.string);
5809 r = sd_bus_message_append_basic(m, type, &basic);
5816 return done_something;
5819 #if 0 /// UNNEEDED by elogind
5820 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5825 assert_return(m, -EINVAL);
5826 assert_return(m->sealed, -EPERM);
5827 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5828 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5829 assert_return(type || contents, -EINVAL);
5830 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5832 r = sd_bus_message_peek_type(m, &t, &c);
5836 if (type != 0 && type != t)
5839 if (contents && !streq_ptr(contents, c))
5846 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5847 assert_return(m, NULL);
5852 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5853 _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5861 switch ((*m)->header->type) {
5863 case SD_BUS_MESSAGE_SIGNAL:
5864 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5870 case SD_BUS_MESSAGE_METHOD_CALL:
5871 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5877 case SD_BUS_MESSAGE_METHOD_RETURN:
5878 case SD_BUS_MESSAGE_METHOD_ERROR:
5880 n = message_new(bus, (*m)->header->type);
5884 n->reply_cookie = (*m)->reply_cookie;
5886 r = message_append_reply_cookie(n, n->reply_cookie);
5890 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5891 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5895 n->error._need_free = -1;
5904 if ((*m)->destination && !n->destination) {
5905 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5910 if ((*m)->sender && !n->sender) {
5911 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5916 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5918 r = sd_bus_message_copy(n, *m, true);
5922 timeout = (*m)->timeout;
5923 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5924 timeout = BUS_DEFAULT_TIMEOUT;
5926 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5930 sd_bus_message_unref(*m);
5937 #if 0 /// UNNEEDED by elogind
5938 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5942 assert_return(!m->sealed, -EPERM);
5943 assert_return(!m->sender, -EPERM);
5945 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5948 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5949 assert_return(m, -EINVAL);
5950 assert_return(priority, -EINVAL);
5952 *priority = m->priority;
5956 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5957 assert_return(m, -EINVAL);
5958 assert_return(!m->sealed, -EPERM);
5960 m->priority = priority;