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 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);
1144 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1146 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1151 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1152 assert_return(m, -EINVAL);
1153 assert_return(!m->sealed, -EPERM);
1156 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1158 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1163 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1164 assert_return(m, -EINVAL);
1165 assert_return(!m->sealed, -EPERM);
1168 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1170 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1176 static struct bus_container *message_get_container(sd_bus_message *m) {
1179 if (m->n_containers == 0)
1180 return &m->root_container;
1182 assert(m->containers);
1183 return m->containers + m->n_containers - 1;
1186 struct bus_body_part *message_append_part(sd_bus_message *m) {
1187 struct bus_body_part *part;
1194 if (m->n_body_parts <= 0) {
1198 assert(m->body_end);
1200 part = new0(struct bus_body_part, 1);
1206 m->body_end->next = part;
1216 static void part_zero(struct bus_body_part *part, size_t sz) {
1221 /* All other fields can be left in their defaults */
1222 assert(!part->data);
1223 assert(part->memfd < 0);
1226 part->is_zero = true;
1227 part->sealed = true;
1230 static int part_make_space(
1231 struct sd_bus_message *m,
1232 struct bus_body_part *part,
1241 assert(!part->sealed);
1246 if (!part->data && part->memfd < 0) {
1247 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1248 part->mmap_begin = part->data;
1251 if (part->memfd >= 0) {
1253 if (part->allocated == 0 || sz > part->allocated) {
1254 uint64_t new_allocated;
1256 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1257 r = memfd_set_size(part->memfd, new_allocated);
1263 part->allocated = new_allocated;
1266 if (!part->data || sz > part->mapped) {
1269 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1270 if (part->mapped <= 0)
1271 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1273 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1275 if (n == MAP_FAILED) {
1280 part->mmap_begin = part->data = n;
1282 part->memfd_offset = 0;
1285 part->munmap_this = true;
1287 if (part->allocated == 0 || sz > part->allocated) {
1288 size_t new_allocated;
1290 new_allocated = sz > 0 ? 2 * sz : 64;
1291 n = realloc(part->data, new_allocated);
1298 part->allocated = new_allocated;
1299 part->free_this = true;
1304 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1310 static int message_add_offset(sd_bus_message *m, size_t offset) {
1311 struct bus_container *c;
1314 assert(BUS_MESSAGE_IS_GVARIANT(m));
1316 /* Add offset to current container, unless this is the first
1317 * item in it, which will have the 0 offset, which we can
1319 c = message_get_container(m);
1321 if (!c->need_offsets)
1324 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1327 c->offsets[c->n_offsets++] = offset;
1331 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1332 struct bus_container *c;
1339 /* Update counters */
1340 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1343 *c->array_size += expand;
1347 static void *message_extend_body(
1352 bool force_inline) {
1354 size_t start_body, end_body, padding, added;
1365 start_body = ALIGN_TO((size_t) m->body_size, align);
1366 end_body = start_body + sz;
1368 padding = start_body - m->body_size;
1369 added = padding + sz;
1371 /* Check for 32bit overflows */
1372 if (end_body > (size_t) ((uint32_t) -1) ||
1373 end_body < start_body) {
1379 struct bus_body_part *part = NULL;
1383 m->n_body_parts <= 0 ||
1384 m->body_end->sealed ||
1385 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1386 (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 */
1390 part = message_append_part(m);
1394 part_zero(part, padding);
1397 part = message_append_part(m);
1401 r = part_make_space(m, part, sz, &p);
1405 struct bus_container *c;
1407 size_t os, start_part, end_part;
1413 start_part = ALIGN_TO(part->size, align);
1414 end_part = start_part + sz;
1416 r = part_make_space(m, part, end_part, &p);
1421 memzero(p, padding);
1422 p = (uint8_t*) p + padding;
1425 /* Readjust pointers */
1426 for (c = m->containers; c < m->containers + m->n_containers; c++)
1427 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1429 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1432 /* Return something that is not NULL and is aligned */
1433 p = (uint8_t *) NULL + align;
1435 m->body_size = end_body;
1436 message_extend_containers(m, added);
1439 r = message_add_offset(m, end_body);
1449 static int message_push_fd(sd_bus_message *m, int fd) {
1460 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1464 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1472 m->fds[m->n_fds] = copy;
1478 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1479 _cleanup_close_ int fd = -1;
1480 struct bus_container *c;
1484 assert_return(m, -EINVAL);
1485 assert_return(!m->sealed, -EPERM);
1486 assert_return(bus_type_is_basic(type), -EINVAL);
1487 assert_return(!m->poisoned, -ESTALE);
1489 c = message_get_container(m);
1491 if (c->signature && c->signature[c->index]) {
1492 /* Container signature is already set */
1494 if (c->signature[c->index] != type)
1499 /* Maybe we can append to the signature? But only if this is the top-level container */
1500 if (c->enclosing != 0)
1503 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1510 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1516 case SD_BUS_TYPE_SIGNATURE:
1517 case SD_BUS_TYPE_STRING:
1520 /* Fall through... */
1521 case SD_BUS_TYPE_OBJECT_PATH:
1529 case SD_BUS_TYPE_BOOLEAN:
1531 u8 = p && *(int*) p;
1537 case SD_BUS_TYPE_UNIX_FD:
1542 fd = message_push_fd(m, *(int*) p);
1553 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1554 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1561 a = message_extend_body(m, align, sz, true, false);
1568 *stored = (const uint8_t*) a;
1575 case SD_BUS_TYPE_STRING:
1576 /* To make things easy we'll serialize a NULL string
1577 * into the empty string */
1580 /* Fall through... */
1581 case SD_BUS_TYPE_OBJECT_PATH:
1587 sz = 4 + strlen(p) + 1;
1590 case SD_BUS_TYPE_SIGNATURE:
1595 sz = 1 + strlen(p) + 1;
1598 case SD_BUS_TYPE_BOOLEAN:
1600 u32 = p && *(int*) p;
1606 case SD_BUS_TYPE_UNIX_FD:
1611 fd = message_push_fd(m, *(int*) p);
1622 align = bus_type_get_alignment(type);
1623 sz = bus_type_get_size(type);
1630 a = message_extend_body(m, align, sz, false, false);
1634 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1635 *(uint32_t*) a = sz - 5;
1636 memcpy((uint8_t*) a + 4, p, sz - 4);
1639 *stored = (const uint8_t*) a + 4;
1641 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1642 *(uint8_t*) a = sz - 2;
1643 memcpy((uint8_t*) a + 1, p, sz - 1);
1646 *stored = (const uint8_t*) a + 1;
1655 if (type == SD_BUS_TYPE_UNIX_FD)
1658 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1665 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1666 return message_append_basic(m, type, p, NULL);
1669 #if 0 /// UNNEEDED by elogind
1670 _public_ int sd_bus_message_append_string_space(
1675 struct bus_container *c;
1678 assert_return(m, -EINVAL);
1679 assert_return(s, -EINVAL);
1680 assert_return(!m->sealed, -EPERM);
1681 assert_return(!m->poisoned, -ESTALE);
1683 c = message_get_container(m);
1685 if (c->signature && c->signature[c->index]) {
1686 /* Container signature is already set */
1688 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1693 /* Maybe we can append to the signature? But only if this is the top-level container */
1694 if (c->enclosing != 0)
1697 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1704 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1705 a = message_extend_body(m, 1, size + 1, true, false);
1711 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1715 *(uint32_t*) a = size;
1721 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1727 _public_ int sd_bus_message_append_string_iovec(
1729 const struct iovec *iov,
1737 assert_return(m, -EINVAL);
1738 assert_return(!m->sealed, -EPERM);
1739 assert_return(iov || n == 0, -EINVAL);
1740 assert_return(!m->poisoned, -ESTALE);
1742 size = IOVEC_TOTAL_SIZE(iov, n);
1744 r = sd_bus_message_append_string_space(m, size, &p);
1748 for (i = 0; i < n; i++) {
1750 if (iov[i].iov_base)
1751 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1753 memset(p, ' ', iov[i].iov_len);
1755 p += iov[i].iov_len;
1762 static int bus_message_open_array(
1764 struct bus_container *c,
1765 const char *contents,
1766 uint32_t **array_size,
1768 bool *need_offsets) {
1778 assert(need_offsets);
1780 if (!signature_is_single(contents, true))
1783 if (c->signature && c->signature[c->index]) {
1785 /* Verify the existing signature */
1787 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1790 if (!startswith(c->signature + c->index + 1, contents))
1793 nindex = c->index + 1 + strlen(contents);
1797 if (c->enclosing != 0)
1800 /* Extend the existing signature */
1802 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1808 nindex = e - c->signature;
1811 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1812 alignment = bus_gvariant_get_alignment(contents);
1816 /* Add alignment padding and add to offset list */
1817 if (!message_extend_body(m, alignment, 0, false, false))
1820 r = bus_gvariant_is_fixed_size(contents);
1824 *begin = m->body_size;
1825 *need_offsets = r == 0;
1829 struct bus_body_part *o;
1831 alignment = bus_type_get_alignment(contents[0]);
1835 a = message_extend_body(m, 4, 4, false, false);
1840 op = m->body_end->data;
1841 os = m->body_end->size;
1843 /* Add alignment between size and first element */
1844 if (!message_extend_body(m, alignment, 0, false, false))
1847 /* location of array size might have changed so let's readjust a */
1848 if (o == m->body_end)
1849 a = adjust_pointer(a, op, os, m->body_end->data);
1855 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1861 static int bus_message_open_variant(
1863 struct bus_container *c,
1864 const char *contents) {
1870 if (!signature_is_single(contents, false))
1873 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1876 if (c->signature && c->signature[c->index]) {
1878 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1884 if (c->enclosing != 0)
1887 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1894 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1895 /* Variants are always aligned to 8 */
1897 if (!message_extend_body(m, 8, 0, false, false))
1904 l = strlen(contents);
1905 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1910 memcpy((uint8_t*) a + 1, contents, l + 1);
1913 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1919 static int bus_message_open_struct(
1921 struct bus_container *c,
1922 const char *contents,
1924 bool *need_offsets) {
1933 assert(need_offsets);
1935 if (!signature_is_valid(contents, false))
1938 if (c->signature && c->signature[c->index]) {
1941 l = strlen(contents);
1943 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1944 !startswith(c->signature + c->index + 1, contents) ||
1945 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1948 nindex = c->index + 1 + l + 1;
1952 if (c->enclosing != 0)
1955 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1961 nindex = e - c->signature;
1964 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1967 alignment = bus_gvariant_get_alignment(contents);
1971 if (!message_extend_body(m, alignment, 0, false, false))
1974 r = bus_gvariant_is_fixed_size(contents);
1978 *begin = m->body_size;
1979 *need_offsets = r == 0;
1981 /* Align contents to 8 byte boundary */
1982 if (!message_extend_body(m, 8, 0, false, false))
1986 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1992 static int bus_message_open_dict_entry(
1994 struct bus_container *c,
1995 const char *contents,
1997 bool *need_offsets) {
2005 assert(need_offsets);
2007 if (!signature_is_pair(contents))
2010 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2013 if (c->signature && c->signature[c->index]) {
2016 l = strlen(contents);
2018 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2019 !startswith(c->signature + c->index + 1, contents) ||
2020 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2025 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2028 alignment = bus_gvariant_get_alignment(contents);
2032 if (!message_extend_body(m, alignment, 0, false, false))
2035 r = bus_gvariant_is_fixed_size(contents);
2039 *begin = m->body_size;
2040 *need_offsets = r == 0;
2042 /* Align contents to 8 byte boundary */
2043 if (!message_extend_body(m, 8, 0, false, false))
2050 _public_ int sd_bus_message_open_container(
2053 const char *contents) {
2055 struct bus_container *c, *w;
2056 uint32_t *array_size = NULL;
2058 size_t before, begin = 0;
2059 bool need_offsets = false;
2062 assert_return(m, -EINVAL);
2063 assert_return(!m->sealed, -EPERM);
2064 assert_return(contents, -EINVAL);
2065 assert_return(!m->poisoned, -ESTALE);
2067 /* Make sure we have space for one more container */
2068 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2073 c = message_get_container(m);
2075 signature = strdup(contents);
2081 /* Save old index in the parent container, in case we have to
2082 * abort this container */
2083 c->saved_index = c->index;
2084 before = m->body_size;
2086 if (type == SD_BUS_TYPE_ARRAY)
2087 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2088 else if (type == SD_BUS_TYPE_VARIANT)
2089 r = bus_message_open_variant(m, c, contents);
2090 else if (type == SD_BUS_TYPE_STRUCT)
2091 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2092 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2093 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2102 /* OK, let's fill it in */
2103 w = m->containers + m->n_containers++;
2104 w->enclosing = type;
2105 w->signature = signature;
2107 w->array_size = array_size;
2110 w->n_offsets = w->offsets_allocated = 0;
2112 w->need_offsets = need_offsets;
2117 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2122 if (!BUS_MESSAGE_IS_GVARIANT(m))
2125 if (c->need_offsets) {
2126 size_t payload, sz, i;
2129 /* Variable-width arrays */
2131 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2132 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2134 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2138 for (i = 0; i < c->n_offsets; i++)
2139 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2143 /* Fixed-width or empty arrays */
2145 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2153 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2159 assert(c->signature);
2161 if (!BUS_MESSAGE_IS_GVARIANT(m))
2164 l = strlen(c->signature);
2166 a = message_extend_body(m, 1, 1 + l, true, false);
2171 memcpy(a+1, c->signature, l);
2176 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2177 bool fixed_size = true;
2178 size_t n_variable = 0;
2187 if (!BUS_MESSAGE_IS_GVARIANT(m))
2190 p = strempty(c->signature);
2194 r = signature_element_length(p, &n);
2203 r = bus_gvariant_is_fixed_size(t);
2208 assert(!c->need_offsets || i <= c->n_offsets);
2210 /* We need to add an offset for each item that has a
2211 * variable size and that is not the last one in the
2215 if (r == 0 && p[n] != 0)
2222 assert(!c->need_offsets || i == c->n_offsets);
2223 assert(c->need_offsets || n_variable == 0);
2225 if (isempty(c->signature)) {
2226 /* The unary type is encoded as fixed 1 byte padding */
2227 a = message_extend_body(m, 1, 1, add_offset, false);
2232 } else if (n_variable <= 0) {
2235 /* Structures with fixed-size members only have to be
2236 * fixed-size themselves. But gvariant requires all fixed-size
2237 * elements to be sized a multiple of their alignment. Hence,
2238 * we must *always* add final padding after the last member so
2239 * the overall size of the structure is properly aligned. */
2241 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2243 assert(alignment > 0);
2245 a = message_extend_body(m, alignment, 0, add_offset, false);
2252 assert(c->offsets[c->n_offsets-1] == m->body_size);
2254 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2256 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2260 p = strempty(c->signature);
2261 for (i = 0, j = 0; i < c->n_offsets; i++) {
2265 r = signature_element_length(p, &n);
2276 r = bus_gvariant_is_fixed_size(t);
2279 if (r > 0 || p[0] == 0)
2283 k = n_variable - 1 - j;
2285 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2294 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2295 struct bus_container *c;
2298 assert_return(m, -EINVAL);
2299 assert_return(!m->sealed, -EPERM);
2300 assert_return(m->n_containers > 0, -EINVAL);
2301 assert_return(!m->poisoned, -ESTALE);
2303 c = message_get_container(m);
2305 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2306 if (c->signature && c->signature[c->index] != 0)
2311 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2312 r = bus_message_close_array(m, c);
2313 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2314 r = bus_message_close_variant(m, c);
2315 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2316 r = bus_message_close_struct(m, c, true);
2318 assert_not_reached("Unknown container type");
2332 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2339 stack[*i].types = types;
2340 stack[*i].n_struct = n_struct;
2341 stack[*i].n_array = n_array;
2347 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2358 *types = stack[*i].types;
2359 *n_struct = stack[*i].n_struct;
2360 *n_array = stack[*i].n_array;
2365 int bus_message_append_ap(
2370 unsigned n_array, n_struct;
2371 TypeStack stack[BUS_CONTAINER_DEPTH];
2372 unsigned stack_ptr = 0;
2380 n_array = (unsigned) -1;
2381 n_struct = strlen(types);
2386 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2387 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2393 r = sd_bus_message_close_container(m);
2401 if (n_array != (unsigned) -1)
2410 case SD_BUS_TYPE_BYTE: {
2413 x = (uint8_t) va_arg(ap, int);
2414 r = sd_bus_message_append_basic(m, *t, &x);
2418 case SD_BUS_TYPE_BOOLEAN:
2419 case SD_BUS_TYPE_INT32:
2420 case SD_BUS_TYPE_UINT32:
2421 case SD_BUS_TYPE_UNIX_FD: {
2424 /* We assume a boolean is the same as int32_t */
2425 assert_cc(sizeof(int32_t) == sizeof(int));
2427 x = va_arg(ap, uint32_t);
2428 r = sd_bus_message_append_basic(m, *t, &x);
2432 case SD_BUS_TYPE_INT16:
2433 case SD_BUS_TYPE_UINT16: {
2436 x = (uint16_t) va_arg(ap, int);
2437 r = sd_bus_message_append_basic(m, *t, &x);
2441 case SD_BUS_TYPE_INT64:
2442 case SD_BUS_TYPE_UINT64: {
2445 x = va_arg(ap, uint64_t);
2446 r = sd_bus_message_append_basic(m, *t, &x);
2450 case SD_BUS_TYPE_DOUBLE: {
2453 x = va_arg(ap, double);
2454 r = sd_bus_message_append_basic(m, *t, &x);
2458 case SD_BUS_TYPE_STRING:
2459 case SD_BUS_TYPE_OBJECT_PATH:
2460 case SD_BUS_TYPE_SIGNATURE: {
2463 x = va_arg(ap, const char*);
2464 r = sd_bus_message_append_basic(m, *t, x);
2468 case SD_BUS_TYPE_ARRAY: {
2471 r = signature_element_length(t + 1, &k);
2477 memcpy(s, t + 1, k);
2480 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2485 if (n_array == (unsigned) -1) {
2490 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2496 n_array = va_arg(ap, unsigned);
2501 case SD_BUS_TYPE_VARIANT: {
2504 s = va_arg(ap, const char*);
2508 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2512 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2517 n_struct = strlen(s);
2518 n_array = (unsigned) -1;
2523 case SD_BUS_TYPE_STRUCT_BEGIN:
2524 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2527 r = signature_element_length(t, &k);
2534 memcpy(s, t + 1, k - 2);
2537 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2542 if (n_array == (unsigned) -1) {
2547 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2553 n_array = (unsigned) -1;
2569 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2573 assert_return(m, -EINVAL);
2574 assert_return(types, -EINVAL);
2575 assert_return(!m->sealed, -EPERM);
2576 assert_return(!m->poisoned, -ESTALE);
2578 va_start(ap, types);
2579 r = bus_message_append_ap(m, types, ap);
2585 #if 0 /// UNNEEDED by elogind
2586 _public_ int sd_bus_message_append_array_space(
2596 assert_return(m, -EINVAL);
2597 assert_return(!m->sealed, -EPERM);
2598 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2599 assert_return(ptr || size == 0, -EINVAL);
2600 assert_return(!m->poisoned, -ESTALE);
2602 /* alignment and size of the trivial types (except bool) is
2603 * identical for gvariant and dbus1 marshalling */
2604 align = bus_type_get_alignment(type);
2605 sz = bus_type_get_size(type);
2607 assert_se(align > 0);
2613 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2617 a = message_extend_body(m, align, size, false, false);
2621 r = sd_bus_message_close_container(m);
2629 _public_ int sd_bus_message_append_array(
2637 assert_return(m, -EINVAL);
2638 assert_return(!m->sealed, -EPERM);
2639 assert_return(bus_type_is_trivial(type), -EINVAL);
2640 assert_return(ptr || size == 0, -EINVAL);
2641 assert_return(!m->poisoned, -ESTALE);
2643 r = sd_bus_message_append_array_space(m, type, size, &p);
2647 memcpy_safe(p, ptr, size);
2652 _public_ int sd_bus_message_append_array_iovec(
2655 const struct iovec *iov,
2663 assert_return(m, -EINVAL);
2664 assert_return(!m->sealed, -EPERM);
2665 assert_return(bus_type_is_trivial(type), -EINVAL);
2666 assert_return(iov || n == 0, -EINVAL);
2667 assert_return(!m->poisoned, -ESTALE);
2669 size = IOVEC_TOTAL_SIZE(iov, n);
2671 r = sd_bus_message_append_array_space(m, type, size, &p);
2675 for (i = 0; i < n; i++) {
2677 if (iov[i].iov_base)
2678 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2680 memzero(p, iov[i].iov_len);
2682 p = (uint8_t*) p + iov[i].iov_len;
2688 _public_ int sd_bus_message_append_array_memfd(
2695 _cleanup_close_ int copy_fd = -1;
2696 struct bus_body_part *part;
2702 assert_return(m, -EINVAL);
2703 assert_return(memfd >= 0, -EBADF);
2704 assert_return(bus_type_is_trivial(type), -EINVAL);
2705 assert_return(size > 0, -EINVAL);
2706 assert_return(!m->sealed, -EPERM);
2707 assert_return(!m->poisoned, -ESTALE);
2709 r = memfd_set_sealed(memfd);
2713 copy_fd = dup(memfd);
2717 r = memfd_get_size(memfd, &real_size);
2721 if (offset == 0 && size == (uint64_t) -1)
2723 else if (offset + size > real_size)
2726 align = bus_type_get_alignment(type);
2727 sz = bus_type_get_size(type);
2729 assert_se(align > 0);
2732 if (offset % align != 0)
2738 if (size > (uint64_t) (uint32_t) -1)
2741 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2745 a = message_extend_body(m, align, 0, false, false);
2749 part = message_append_part(m);
2753 part->memfd = copy_fd;
2754 part->memfd_offset = offset;
2755 part->sealed = true;
2759 m->body_size += size;
2760 message_extend_containers(m, size);
2762 return sd_bus_message_close_container(m);
2765 _public_ int sd_bus_message_append_string_memfd(
2771 _cleanup_close_ int copy_fd = -1;
2772 struct bus_body_part *part;
2773 struct bus_container *c;
2778 assert_return(m, -EINVAL);
2779 assert_return(memfd >= 0, -EBADF);
2780 assert_return(size > 0, -EINVAL);
2781 assert_return(!m->sealed, -EPERM);
2782 assert_return(!m->poisoned, -ESTALE);
2784 r = memfd_set_sealed(memfd);
2788 copy_fd = dup(memfd);
2792 r = memfd_get_size(memfd, &real_size);
2796 if (offset == 0 && size == (uint64_t) -1)
2798 else if (offset + size > real_size)
2801 /* We require this to be NUL terminated */
2805 if (size > (uint64_t) (uint32_t) -1)
2808 c = message_get_container(m);
2809 if (c->signature && c->signature[c->index]) {
2810 /* Container signature is already set */
2812 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2817 /* Maybe we can append to the signature? But only if this is the top-level container */
2818 if (c->enclosing != 0)
2821 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2828 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2829 a = message_extend_body(m, 4, 4, false, false);
2833 *(uint32_t*) a = size - 1;
2836 part = message_append_part(m);
2840 part->memfd = copy_fd;
2841 part->memfd_offset = offset;
2842 part->sealed = true;
2846 m->body_size += size;
2847 message_extend_containers(m, size);
2849 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2850 r = message_add_offset(m, m->body_size);
2857 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2864 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2868 assert_return(m, -EINVAL);
2869 assert_return(!m->sealed, -EPERM);
2870 assert_return(!m->poisoned, -ESTALE);
2872 r = sd_bus_message_open_container(m, 'a', "s");
2876 STRV_FOREACH(i, l) {
2877 r = sd_bus_message_append_basic(m, 's', *i);
2882 return sd_bus_message_close_container(m);
2885 static int bus_message_close_header(sd_bus_message *m) {
2889 /* The actual user data is finished now, we just complete the
2890 variant and struct now (at least on gvariant). Remember
2891 this position, so that during parsing we know where to to
2892 put the outer container end. */
2893 m->user_body_size = m->body_size;
2895 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2896 const char *signature;
2900 /* Add offset table to end of fields array */
2901 if (m->n_header_offsets >= 1) {
2905 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2907 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2908 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2912 for (i = 0; i < m->n_header_offsets; i++)
2913 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2916 /* Add gvariant NUL byte plus signature to the end of
2917 * the body, followed by the final offset pointing to
2918 * the end of the fields array */
2920 signature = strempty(m->root_container.signature);
2921 l = strlen(signature);
2923 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2924 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2929 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2930 memcpy((uint8_t*) d + 2, signature, l);
2931 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2933 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2936 m->footer_accessible = 1 + l + 2 + sz;
2938 m->header->dbus1.fields_size = m->fields_size;
2939 m->header->dbus1.body_size = m->body_size;
2945 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2946 struct bus_body_part *part;
2956 if (m->n_containers > 0)
2962 if (cookie > 0xffffffffULL &&
2963 !BUS_MESSAGE_IS_GVARIANT(m))
2966 /* In vtables the return signature of method calls is listed,
2967 * let's check if they match if this is a response */
2968 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2969 m->enforced_reply_signature &&
2970 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2973 /* If gvariant marshalling is used we need to close the body structure */
2974 r = bus_message_close_struct(m, &m->root_container, false);
2978 /* If there's a non-trivial signature set, then add it in
2979 * here, but only on dbus1 */
2980 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2981 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2987 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2992 r = bus_message_close_header(m);
2996 if (BUS_MESSAGE_IS_GVARIANT(m))
2997 m->header->dbus2.cookie = cookie;
2999 m->header->dbus1.serial = (uint32_t) cookie;
3001 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
3003 /* Add padding at the end of the fields part, since we know
3004 * the body needs to start at an 8 byte alignment. We made
3005 * sure we allocated enough space for this, so all we need to
3006 * do here is to zero it out. */
3007 a = ALIGN8(m->fields_size) - m->fields_size;
3009 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
3011 /* If this is something we can send as memfd, then let's seal
3012 the memfd now. Note that we can send memfds as payload only
3013 for directed messages, and not for broadcasts. */
3014 if (m->destination && m->bus->use_memfd) {
3015 MESSAGE_FOREACH_PART(part, i, m)
3016 if (part->memfd >= 0 &&
3018 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3019 part != m->body_end) { /* The last part may never be sent as memfd */
3022 /* Try to seal it if that makes
3023 * sense. First, unmap our own map to
3024 * make sure we don't keep it busy. */
3025 bus_body_part_unmap(part);
3027 /* Then, sync up real memfd size */
3029 r = memfd_set_size(part->memfd, sz);
3033 /* Finally, try to seal */
3034 if (memfd_set_sealed(part->memfd) >= 0)
3035 part->sealed = true;
3039 m->root_container.end = m->user_body_size;
3040 m->root_container.index = 0;
3041 m->root_container.offset_index = 0;
3042 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3049 int bus_body_part_map(struct bus_body_part *part) {
3058 if (part->size <= 0)
3061 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3062 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3063 static const uint8_t zeroes[7] = { };
3064 part->data = (void*) zeroes;
3068 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3069 psz = PAGE_ALIGN(part->size + shift);
3071 if (part->memfd >= 0)
3072 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3073 else if (part->is_zero)
3074 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3078 if (p == MAP_FAILED)
3082 part->mmap_begin = p;
3083 part->data = (uint8_t*) p + shift;
3084 part->munmap_this = true;
3089 void bus_body_part_unmap(struct bus_body_part *part) {
3093 if (part->memfd < 0)
3096 if (!part->mmap_begin)
3099 if (!part->munmap_this)
3102 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3104 part->mmap_begin = NULL;
3107 part->munmap_this = false;
3112 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3113 size_t k, start, end;
3118 start = ALIGN_TO((size_t) *rindex, align);
3119 end = start + nbytes;
3124 /* Verify that padding is 0 */
3125 for (k = *rindex; k < start; k++)
3126 if (((const uint8_t*) p)[k] != 0)
3130 *r = (uint8_t*) p + start;
3137 static bool message_end_of_signature(sd_bus_message *m) {
3138 struct bus_container *c;
3142 c = message_get_container(m);
3143 return !c->signature || c->signature[c->index] == 0;
3146 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3147 struct bus_container *c;
3151 c = message_get_container(m);
3152 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3155 if (BUS_MESSAGE_IS_GVARIANT(m))
3156 return index >= c->end;
3158 assert(c->array_size);
3159 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3163 #if 0 /// UNNEEDED by elogind
3164 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3165 assert_return(m, -EINVAL);
3166 assert_return(m->sealed, -EPERM);
3168 if (complete && m->n_containers > 0)
3171 if (message_end_of_signature(m))
3174 if (message_end_of_array(m, m->rindex))
3181 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3182 struct bus_body_part *part;
3188 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3189 part = m->cached_rindex_part;
3190 begin = m->cached_rindex_part_begin;
3200 if (index + sz <= begin + part->size) {
3202 r = bus_body_part_map(part);
3207 *p = (uint8_t*) part->data + index - begin;
3209 m->cached_rindex_part = part;
3210 m->cached_rindex_part_begin = begin;
3215 begin += part->size;
3222 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3229 if (!BUS_MESSAGE_IS_GVARIANT(m))
3232 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3235 sz = bus_gvariant_get_size(c->signature);
3239 if (c->offset_index+1 >= c->n_offsets)
3242 /* Variable-size array */
3244 alignment = bus_gvariant_get_alignment(c->signature);
3245 assert(alignment > 0);
3247 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3248 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3251 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3254 /* Fixed-size array */
3255 *rindex = c->begin + (c->offset_index+1) * sz;
3261 } else if (c->enclosing == 0 ||
3262 c->enclosing == SD_BUS_TYPE_STRUCT ||
3263 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3268 if (c->offset_index+1 >= c->n_offsets)
3271 r = signature_element_length(c->signature + c->index, &n);
3275 r = signature_element_length(c->signature + c->index + n, &j);
3280 memcpy(t, c->signature + c->index + n, j);
3283 alignment = bus_gvariant_get_alignment(t);
3286 assert(alignment > 0);
3288 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3289 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3293 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3296 assert_not_reached("Unknown container type");
3301 /* Reached the end */
3308 static int message_peek_body(
3315 size_t k, start, end, padding;
3316 struct bus_body_part *part;
3323 start = ALIGN_TO((size_t) *rindex, align);
3324 padding = start - *rindex;
3325 end = start + nbytes;
3327 if (end > m->user_body_size)
3330 part = find_part(m, *rindex, padding, (void**) &q);
3335 /* Verify padding */
3336 for (k = 0; k < padding; k++)
3341 part = find_part(m, start, nbytes, (void**) &q);
3342 if (!part || (nbytes > 0 && !q))
3353 static bool validate_nul(const char *s, size_t l) {
3355 /* Check for NUL chars in the string */
3356 if (memchr(s, 0, l))
3359 /* Check for NUL termination */
3366 static bool validate_string(const char *s, size_t l) {
3368 if (!validate_nul(s, l))
3371 /* Check if valid UTF8 */
3372 if (!utf8_is_valid(s))
3378 static bool validate_signature(const char *s, size_t l) {
3380 if (!validate_nul(s, l))
3383 /* Check if valid signature */
3384 if (!signature_is_valid(s, true))
3390 static bool validate_object_path(const char *s, size_t l) {
3392 if (!validate_nul(s, l))
3395 if (!object_path_is_valid(s))
3401 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3402 struct bus_container *c;
3407 assert_return(m, -EINVAL);
3408 assert_return(m->sealed, -EPERM);
3409 assert_return(bus_type_is_basic(type), -EINVAL);
3411 if (message_end_of_signature(m))
3414 if (message_end_of_array(m, m->rindex))
3417 c = message_get_container(m);
3418 if (c->signature[c->index] != type)
3423 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3425 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3428 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3432 if (type == SD_BUS_TYPE_STRING)
3433 ok = validate_string(q, c->item_size-1);
3434 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3435 ok = validate_object_path(q, c->item_size-1);
3437 ok = validate_signature(q, c->item_size-1);
3443 *(const char**) p = q;
3447 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3449 if ((size_t) sz != c->item_size)
3452 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3455 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3461 case SD_BUS_TYPE_BYTE:
3463 *(uint8_t*) p = *(uint8_t*) q;
3466 case SD_BUS_TYPE_BOOLEAN:
3468 *(int*) p = !!*(uint8_t*) q;
3471 case SD_BUS_TYPE_INT16:
3472 case SD_BUS_TYPE_UINT16:
3474 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3477 case SD_BUS_TYPE_INT32:
3478 case SD_BUS_TYPE_UINT32:
3480 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3483 case SD_BUS_TYPE_INT64:
3484 case SD_BUS_TYPE_UINT64:
3485 case SD_BUS_TYPE_DOUBLE:
3487 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3490 case SD_BUS_TYPE_UNIX_FD: {
3493 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3498 *(int*) p = m->fds[j];
3504 assert_not_reached("unexpected type");
3508 r = container_next_item(m, c, &rindex);
3513 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3517 r = message_peek_body(m, &rindex, 4, 4, &q);
3521 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3522 r = message_peek_body(m, &rindex, 1, l+1, &q);
3526 if (type == SD_BUS_TYPE_OBJECT_PATH)
3527 ok = validate_object_path(q, l);
3529 ok = validate_string(q, l);
3534 *(const char**) p = q;
3536 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3539 r = message_peek_body(m, &rindex, 1, 1, &q);
3544 r = message_peek_body(m, &rindex, 1, l+1, &q);
3548 if (!validate_signature(q, l))
3552 *(const char**) p = q;
3557 align = bus_type_get_alignment(type);
3560 sz = bus_type_get_size(type);
3563 r = message_peek_body(m, &rindex, align, sz, &q);
3569 case SD_BUS_TYPE_BYTE:
3571 *(uint8_t*) p = *(uint8_t*) q;
3574 case SD_BUS_TYPE_BOOLEAN:
3576 *(int*) p = !!*(uint32_t*) q;
3579 case SD_BUS_TYPE_INT16:
3580 case SD_BUS_TYPE_UINT16:
3582 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3585 case SD_BUS_TYPE_INT32:
3586 case SD_BUS_TYPE_UINT32:
3588 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3591 case SD_BUS_TYPE_INT64:
3592 case SD_BUS_TYPE_UINT64:
3593 case SD_BUS_TYPE_DOUBLE:
3595 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3598 case SD_BUS_TYPE_UNIX_FD: {
3601 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3606 *(int*) p = m->fds[j];
3611 assert_not_reached("Unknown basic type...");
3618 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3624 static int bus_message_enter_array(
3626 struct bus_container *c,
3627 const char *contents,
3628 uint32_t **array_size,
3631 size_t *n_offsets) {
3645 if (!signature_is_single(contents, true))
3648 if (!c->signature || c->signature[c->index] == 0)
3651 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3654 if (!startswith(c->signature + c->index + 1, contents))
3659 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3662 r = message_peek_body(m, &rindex, 4, 4, &q);
3666 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3669 alignment = bus_type_get_alignment(contents[0]);
3673 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3677 *array_size = (uint32_t*) q;
3679 } else if (c->item_size <= 0) {
3681 /* gvariant: empty array */
3686 } else if (bus_gvariant_is_fixed_size(contents)) {
3688 /* gvariant: fixed length array */
3689 *item_size = bus_gvariant_get_size(contents);
3694 size_t where, p = 0, framing, sz;
3697 /* gvariant: variable length array */
3698 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3700 where = rindex + c->item_size - sz;
3701 r = message_peek_body(m, &where, 1, sz, &q);
3705 framing = bus_gvariant_read_word_le(q, sz);
3706 if (framing > c->item_size - sz)
3708 if ((c->item_size - framing) % sz != 0)
3711 *n_offsets = (c->item_size - framing) / sz;
3713 where = rindex + framing;
3714 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3718 *offsets = new(size_t, *n_offsets);
3722 for (i = 0; i < *n_offsets; i++) {
3725 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3726 if (x > c->item_size - sz)
3731 (*offsets)[i] = rindex + x;
3735 *item_size = (*offsets)[0] - rindex;
3740 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3741 c->index += 1 + strlen(contents);
3746 static int bus_message_enter_variant(
3748 struct bus_container *c,
3749 const char *contents,
3750 size_t *item_size) {
3762 if (!signature_is_single(contents, false))
3765 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3768 if (!c->signature || c->signature[c->index] == 0)
3771 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3776 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3779 k = strlen(contents);
3780 if (1+k > c->item_size)
3783 where = rindex + c->item_size - (1+k);
3784 r = message_peek_body(m, &where, 1, 1+k, &q);
3788 if (*(char*) q != 0)
3791 if (memcmp((uint8_t*) q+1, contents, k))
3794 *item_size = c->item_size - (1+k);
3797 r = message_peek_body(m, &rindex, 1, 1, &q);
3802 r = message_peek_body(m, &rindex, 1, l+1, &q);
3806 if (!validate_signature(q, l))
3809 if (!streq(q, contents))
3815 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3821 static int build_struct_offsets(
3823 const char *signature,
3827 size_t *n_offsets) {
3829 unsigned n_variable = 0, n_total = 0, v;
3830 size_t previous = 0, where;
3841 if (isempty(signature)) {
3842 /* Unary type is encoded as *fixed* 1 byte padding */
3843 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3847 if (*(uint8_t *) q != 0)
3856 sz = bus_gvariant_determine_word_size(size, 0);
3860 /* First, loop over signature and count variable elements and
3861 * elements in general. We use this to know how large the
3862 * offset array is at the end of the structure. Note that
3863 * GVariant only stores offsets for all variable size elements
3864 * that are not the last item. */
3870 r = signature_element_length(p, &n);
3879 r = bus_gvariant_is_fixed_size(t);
3884 if (r == 0 && p[n] != 0) /* except the last item */
3891 if (size < n_variable * sz)
3894 where = m->rindex + size - (n_variable * sz);
3895 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3901 *offsets = new(size_t, n_total);
3907 /* Second, loop again and build an offset table */
3913 r = signature_element_length(p, &n);
3922 k = bus_gvariant_get_size(t);
3930 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3933 if (m->rindex + x < previous)
3936 /* The last item's end
3937 * is determined from
3940 x = size - (n_variable * sz);
3942 offset = m->rindex + x;
3948 align = bus_gvariant_get_alignment(t);
3951 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3955 previous = (*offsets)[(*n_offsets)++] = offset;
3960 assert(*n_offsets == n_total);
3962 *item_size = (*offsets)[0] - m->rindex;
3966 static int enter_struct_or_dict_entry(
3968 struct bus_container *c,
3969 const char *contents,
3972 size_t *n_offsets) {
3983 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3986 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3991 /* gvariant with contents */
3992 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3997 static int bus_message_enter_struct(
3999 struct bus_container *c,
4000 const char *contents,
4003 size_t *n_offsets) {
4015 if (!signature_is_valid(contents, false))
4018 if (!c->signature || c->signature[c->index] == 0)
4021 l = strlen(contents);
4023 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4024 !startswith(c->signature + c->index + 1, contents) ||
4025 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4028 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4032 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4033 c->index += 1 + l + 1;
4038 static int bus_message_enter_dict_entry(
4040 struct bus_container *c,
4041 const char *contents,
4044 size_t *n_offsets) {
4053 if (!signature_is_pair(contents))
4056 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4059 if (!c->signature || c->signature[c->index] == 0)
4062 l = strlen(contents);
4064 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4065 !startswith(c->signature + c->index + 1, contents) ||
4066 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4069 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4073 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4074 c->index += 1 + l + 1;
4079 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4081 const char *contents) {
4082 struct bus_container *c, *w;
4083 uint32_t *array_size = NULL;
4086 size_t *offsets = NULL;
4087 size_t n_offsets = 0, item_size = 0;
4090 assert_return(m, -EINVAL);
4091 assert_return(m->sealed, -EPERM);
4092 assert_return(type != 0 || !contents, -EINVAL);
4094 if (type == 0 || !contents) {
4098 /* Allow entering into anonymous containers */
4099 r = sd_bus_message_peek_type(m, &tt, &cc);
4103 if (type != 0 && type != tt)
4106 if (contents && !streq(contents, cc))
4114 * We enforce a global limit on container depth, that is much
4115 * higher than the 32 structs and 32 arrays the specification
4116 * mandates. This is simpler to implement for us, and we need
4117 * this only to ensure our container array doesn't grow
4118 * without bounds. We are happy to return any data from a
4119 * message as long as the data itself is valid, even if the
4120 * overall message might be not.
4122 * Note that the message signature is validated when
4123 * parsing the headers, and that validation does check the
4126 * Note that the specification defines no limits on the depth
4127 * of stacked variants, but we do.
4129 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4132 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4135 if (message_end_of_signature(m))
4138 if (message_end_of_array(m, m->rindex))
4141 c = message_get_container(m);
4143 signature = strdup(contents);
4147 c->saved_index = c->index;
4150 if (type == SD_BUS_TYPE_ARRAY)
4151 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4152 else if (type == SD_BUS_TYPE_VARIANT)
4153 r = bus_message_enter_variant(m, c, contents, &item_size);
4154 else if (type == SD_BUS_TYPE_STRUCT)
4155 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4156 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4157 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4167 /* OK, let's fill it in */
4168 w = m->containers + m->n_containers++;
4169 w->enclosing = type;
4170 w->signature = signature;
4171 w->peeked_signature = NULL;
4175 w->begin = m->rindex;
4177 /* Unary type has fixed size of 1, but virtual size of 0 */
4178 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4179 type == SD_BUS_TYPE_STRUCT &&
4181 w->end = m->rindex + 0;
4183 w->end = m->rindex + c->item_size;
4185 w->array_size = array_size;
4186 w->item_size = item_size;
4187 w->offsets = offsets;
4188 w->n_offsets = n_offsets;
4189 w->offset_index = 0;
4194 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4195 struct bus_container *c;
4199 assert_return(m, -EINVAL);
4200 assert_return(m->sealed, -EPERM);
4201 assert_return(m->n_containers > 0, -ENXIO);
4203 c = message_get_container(m);
4205 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4206 if (c->signature && c->signature[c->index] != 0)
4210 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4211 if (m->rindex < c->end)
4214 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4217 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4218 if (c->begin + l != m->rindex)
4223 free(c->peeked_signature);
4227 c = message_get_container(m);
4230 c->index = c->saved_index;
4231 r = container_next_item(m, c, &m->rindex);
4239 static void message_quit_container(sd_bus_message *m) {
4240 struct bus_container *c;
4244 assert(m->n_containers > 0);
4246 c = message_get_container(m);
4249 assert(m->rindex >= c->before);
4250 m->rindex = c->before;
4252 /* Free container */
4257 /* Correct index of new top-level container */
4258 c = message_get_container(m);
4259 c->index = c->saved_index;
4262 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4263 struct bus_container *c;
4266 assert_return(m, -EINVAL);
4267 assert_return(m->sealed, -EPERM);
4269 if (message_end_of_signature(m))
4272 if (message_end_of_array(m, m->rindex))
4275 c = message_get_container(m);
4277 if (bus_type_is_basic(c->signature[c->index])) {
4281 *type = c->signature[c->index];
4285 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4291 r = signature_element_length(c->signature+c->index+1, &l);
4297 sig = strndup(c->signature + c->index + 1, l);
4301 free(c->peeked_signature);
4302 *contents = c->peeked_signature = sig;
4306 *type = SD_BUS_TYPE_ARRAY;
4311 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4312 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4318 r = signature_element_length(c->signature+c->index, &l);
4323 sig = strndup(c->signature + c->index + 1, l - 2);
4327 free(c->peeked_signature);
4328 *contents = c->peeked_signature = sig;
4332 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4337 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4341 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4344 if (c->item_size < 2)
4347 /* Look for the NUL delimiter that
4348 separates the payload from the
4349 signature. Since the body might be
4350 in a different part that then the
4351 signature we map byte by byte. */
4353 for (k = 2; k <= c->item_size; k++) {
4356 where = m->rindex + c->item_size - k;
4357 r = message_peek_body(m, &where, 1, k, &q);
4361 if (*(char*) q == 0)
4365 if (k > c->item_size)
4368 free(c->peeked_signature);
4369 c->peeked_signature = strndup((char*) q + 1, k - 1);
4370 if (!c->peeked_signature)
4373 if (!signature_is_valid(c->peeked_signature, true))
4376 *contents = c->peeked_signature;
4381 r = message_peek_body(m, &rindex, 1, 1, &q);
4386 r = message_peek_body(m, &rindex, 1, l+1, &q);
4390 if (!validate_signature(q, l))
4398 *type = SD_BUS_TYPE_VARIANT;
4413 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4414 struct bus_container *c;
4416 assert_return(m, -EINVAL);
4417 assert_return(m->sealed, -EPERM);
4420 message_reset_containers(m);
4423 c = message_get_container(m);
4425 c = message_get_container(m);
4427 c->offset_index = 0;
4429 m->rindex = c->begin;
4432 c->offset_index = 0;
4433 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4435 return !isempty(c->signature);
4438 static int message_read_ap(
4443 unsigned n_array, n_struct;
4444 TypeStack stack[BUS_CONTAINER_DEPTH];
4445 unsigned stack_ptr = 0;
4446 unsigned n_loop = 0;
4454 /* Ideally, we'd just call ourselves recursively on every
4455 * complex type. However, the state of a va_list that is
4456 * passed to a function is undefined after that function
4457 * returns. This means we need to docode the va_list linearly
4458 * in a single stackframe. We hence implement our own
4459 * home-grown stack in an array. */
4461 n_array = (unsigned) -1; /* length of current array entries */
4462 n_struct = strlen(types); /* length of current struct contents signature */
4469 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4470 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4476 r = sd_bus_message_exit_container(m);
4484 if (n_array != (unsigned) -1)
4493 case SD_BUS_TYPE_BYTE:
4494 case SD_BUS_TYPE_BOOLEAN:
4495 case SD_BUS_TYPE_INT16:
4496 case SD_BUS_TYPE_UINT16:
4497 case SD_BUS_TYPE_INT32:
4498 case SD_BUS_TYPE_UINT32:
4499 case SD_BUS_TYPE_INT64:
4500 case SD_BUS_TYPE_UINT64:
4501 case SD_BUS_TYPE_DOUBLE:
4502 case SD_BUS_TYPE_STRING:
4503 case SD_BUS_TYPE_OBJECT_PATH:
4504 case SD_BUS_TYPE_SIGNATURE:
4505 case SD_BUS_TYPE_UNIX_FD: {
4508 p = va_arg(ap, void*);
4509 r = sd_bus_message_read_basic(m, *t, p);
4522 case SD_BUS_TYPE_ARRAY: {
4525 r = signature_element_length(t + 1, &k);
4531 memcpy(s, t + 1, k);
4534 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4545 if (n_array == (unsigned) -1) {
4550 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4556 n_array = va_arg(ap, unsigned);
4561 case SD_BUS_TYPE_VARIANT: {
4564 s = va_arg(ap, const char *);
4568 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4578 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4583 n_struct = strlen(s);
4584 n_array = (unsigned) -1;
4589 case SD_BUS_TYPE_STRUCT_BEGIN:
4590 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4593 r = signature_element_length(t, &k);
4599 memcpy(s, t + 1, k - 2);
4602 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4612 if (n_array == (unsigned) -1) {
4617 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4623 n_array = (unsigned) -1;
4636 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4640 assert_return(m, -EINVAL);
4641 assert_return(m->sealed, -EPERM);
4642 assert_return(types, -EINVAL);
4644 va_start(ap, types);
4645 r = message_read_ap(m, types, ap);
4651 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4654 assert_return(m, -EINVAL);
4655 assert_return(m->sealed, -EPERM);
4657 /* If types is NULL, read exactly one element */
4659 struct bus_container *c;
4662 if (message_end_of_signature(m))
4665 if (message_end_of_array(m, m->rindex))
4668 c = message_get_container(m);
4670 r = signature_element_length(c->signature + c->index, &l);
4674 types = strndupa(c->signature + c->index, l);
4679 case 0: /* Nothing to drop */
4682 case SD_BUS_TYPE_BYTE:
4683 case SD_BUS_TYPE_BOOLEAN:
4684 case SD_BUS_TYPE_INT16:
4685 case SD_BUS_TYPE_UINT16:
4686 case SD_BUS_TYPE_INT32:
4687 case SD_BUS_TYPE_UINT32:
4688 case SD_BUS_TYPE_INT64:
4689 case SD_BUS_TYPE_UINT64:
4690 case SD_BUS_TYPE_DOUBLE:
4691 case SD_BUS_TYPE_STRING:
4692 case SD_BUS_TYPE_OBJECT_PATH:
4693 case SD_BUS_TYPE_SIGNATURE:
4694 case SD_BUS_TYPE_UNIX_FD:
4696 r = sd_bus_message_read_basic(m, *types, NULL);
4700 r = sd_bus_message_skip(m, types + 1);
4706 case SD_BUS_TYPE_ARRAY: {
4709 r = signature_element_length(types + 1, &k);
4715 memcpy(s, types+1, k);
4718 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4723 r = sd_bus_message_skip(m, s);
4730 r = sd_bus_message_exit_container(m);
4735 r = sd_bus_message_skip(m, types + 1 + k);
4742 case SD_BUS_TYPE_VARIANT: {
4743 const char *contents;
4746 r = sd_bus_message_peek_type(m, &x, &contents);
4750 if (x != SD_BUS_TYPE_VARIANT)
4753 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4757 r = sd_bus_message_skip(m, contents);
4762 r = sd_bus_message_exit_container(m);
4766 r = sd_bus_message_skip(m, types + 1);
4773 case SD_BUS_TYPE_STRUCT_BEGIN:
4774 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4777 r = signature_element_length(types, &k);
4783 memcpy(s, types+1, k-2);
4786 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4790 r = sd_bus_message_skip(m, s);
4794 r = sd_bus_message_exit_container(m);
4799 r = sd_bus_message_skip(m, types + k);
4811 _public_ int sd_bus_message_read_array(
4817 struct bus_container *c;
4823 assert_return(m, -EINVAL);
4824 assert_return(m->sealed, -EPERM);
4825 assert_return(bus_type_is_trivial(type), -EINVAL);
4826 assert_return(ptr, -EINVAL);
4827 assert_return(size, -EINVAL);
4828 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4830 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4834 c = message_get_container(m);
4836 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4837 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4841 sz = c->end - c->begin;
4843 align = bus_type_get_alignment(type);
4847 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4851 /* Zero length array, let's return some aligned
4852 * pointer that is not NULL */
4853 p = (uint8_t*) NULL + align;
4855 r = message_peek_body(m, &m->rindex, align, sz, &p);
4860 r = sd_bus_message_exit_container(m);
4864 *ptr = (const void*) p;
4870 message_quit_container(m);
4874 static int message_peek_fields(
4885 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4888 static int message_peek_field_uint32(
4900 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4903 /* identical for gvariant and dbus1 */
4905 r = message_peek_fields(m, ri, 4, 4, &q);
4910 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4915 static int message_peek_field_uint64(
4927 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4930 /* identical for gvariant and dbus1 */
4932 r = message_peek_fields(m, ri, 8, 8, &q);
4937 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4942 static int message_peek_field_string(
4944 bool (*validate)(const char *p),
4956 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4961 r = message_peek_fields(m, ri, 1, item_size, &q);
4967 r = message_peek_field_uint32(m, ri, 4, &l);
4971 r = message_peek_fields(m, ri, 1, l+1, &q);
4977 if (!validate_nul(q, l))
4983 if (!validate_string(q, l))
4993 static int message_peek_field_signature(
5006 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5011 r = message_peek_fields(m, ri, 1, item_size, &q);
5017 r = message_peek_fields(m, ri, 1, 1, &q);
5022 r = message_peek_fields(m, ri, 1, l+1, &q);
5027 if (!validate_signature(q, l))
5036 static int message_skip_fields(
5039 uint32_t array_size,
5040 const char **signature) {
5042 size_t original_index;
5048 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5050 original_index = *ri;
5056 if (array_size != (uint32_t) -1 &&
5057 array_size <= *ri - original_index)
5064 if (t == SD_BUS_TYPE_STRING) {
5066 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5072 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5074 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5080 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5082 r = message_peek_field_signature(m, ri, 0, NULL);
5088 } else if (bus_type_is_basic(t)) {
5091 align = bus_type_get_alignment(t);
5092 k = bus_type_get_size(t);
5093 assert(align > 0 && k > 0);
5095 r = message_peek_fields(m, ri, align, k, NULL);
5101 } else if (t == SD_BUS_TYPE_ARRAY) {
5103 r = signature_element_length(*signature+1, &l);
5113 strncpy(sig, *signature + 1, l-1);
5116 alignment = bus_type_get_alignment(sig[0]);
5120 r = message_peek_field_uint32(m, ri, 0, &nas);
5123 if (nas > BUS_ARRAY_MAX_SIZE)
5126 r = message_peek_fields(m, ri, alignment, 0, NULL);
5130 r = message_skip_fields(m, ri, nas, (const char**) &s);
5135 (*signature) += 1 + l;
5137 } else if (t == SD_BUS_TYPE_VARIANT) {
5140 r = message_peek_field_signature(m, ri, 0, &s);
5144 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5150 } else if (t == SD_BUS_TYPE_STRUCT ||
5151 t == SD_BUS_TYPE_DICT_ENTRY) {
5153 r = signature_element_length(*signature, &l);
5160 strncpy(sig, *signature + 1, l-1);
5163 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5174 int bus_message_parse_fields(sd_bus_message *m) {
5177 uint32_t unix_fds = 0;
5178 bool unix_fds_set = false;
5179 void *offsets = NULL;
5180 unsigned n_offsets = 0;
5186 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5189 /* Read the signature from the end of the body variant first */
5190 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5191 if (m->footer_accessible < 1 + sz)
5194 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5196 if (p < (char*) m->footer)
5203 /* We found the beginning of the signature
5204 * string, yay! We require the body to be a
5205 * structure, so verify it and then strip the
5206 * opening/closing brackets. */
5208 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5210 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5211 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5214 c = strndup(p + 1 + 1, l - 2);
5218 free(m->root_container.signature);
5219 m->root_container.signature = c;
5226 /* Calculate the actual user body size, by removing
5227 * the trailing variant signature and struct offset
5229 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5231 /* Pull out the offset table for the fields array */
5232 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5237 ri = m->fields_size - sz;
5238 r = message_peek_fields(m, &ri, 1, sz, &q);
5242 framing = bus_gvariant_read_word_le(q, sz);
5243 if (framing >= m->fields_size - sz)
5245 if ((m->fields_size - framing) % sz != 0)
5249 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5253 n_offsets = (m->fields_size - framing) / sz;
5256 m->user_body_size = m->body_size;
5259 while (ri < m->fields_size) {
5260 _cleanup_free_ char *sig = NULL;
5261 const char *signature;
5262 uint64_t field_type;
5263 size_t item_size = (size_t) -1;
5265 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5274 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5276 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5280 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5284 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5291 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5296 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5301 where = ri = ALIGN_TO(ri, 8);
5302 item_size = end - ri;
5303 r = message_peek_fields(m, &where, 1, item_size, &q);
5307 b = memrchr(q, 0, item_size);
5311 sig = strndup(b+1, item_size - (b+1-(char*) q));
5316 item_size = b - (char*) q;
5318 r = message_peek_field_signature(m, &ri, 0, &signature);
5323 switch (field_type) {
5325 case _BUS_MESSAGE_HEADER_INVALID:
5328 case BUS_MESSAGE_HEADER_PATH:
5333 if (!streq(signature, "o"))
5336 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5339 case BUS_MESSAGE_HEADER_INTERFACE:
5344 if (!streq(signature, "s"))
5347 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5350 case BUS_MESSAGE_HEADER_MEMBER:
5355 if (!streq(signature, "s"))
5358 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5361 case BUS_MESSAGE_HEADER_ERROR_NAME:
5366 if (!streq(signature, "s"))
5369 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5371 m->error._need_free = -1;
5375 case BUS_MESSAGE_HEADER_DESTINATION:
5380 if (!streq(signature, "s"))
5383 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5386 case BUS_MESSAGE_HEADER_SENDER:
5391 if (!streq(signature, "s"))
5394 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5396 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5397 m->creds.unique_name = (char*) m->sender;
5398 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5404 case BUS_MESSAGE_HEADER_SIGNATURE: {
5408 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5411 if (m->root_container.signature)
5414 if (!streq(signature, "g"))
5417 r = message_peek_field_signature(m, &ri, item_size, &s);
5425 free(m->root_container.signature);
5426 m->root_container.signature = c;
5430 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5432 if (m->reply_cookie != 0)
5435 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5436 /* 64bit on dbus2 */
5438 if (!streq(signature, "t"))
5441 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5445 /* 32bit on dbus1 */
5448 if (!streq(signature, "u"))
5451 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5455 m->reply_cookie = serial;
5458 if (m->reply_cookie == 0)
5463 case BUS_MESSAGE_HEADER_UNIX_FDS:
5467 if (!streq(signature, "u"))
5470 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5474 unix_fds_set = true;
5478 if (!BUS_MESSAGE_IS_GVARIANT(m))
5479 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5488 if (m->n_fds != unix_fds)
5491 switch (m->header->type) {
5493 case SD_BUS_MESSAGE_SIGNAL:
5494 if (!m->path || !m->interface || !m->member)
5497 if (m->reply_cookie != 0)
5502 case SD_BUS_MESSAGE_METHOD_CALL:
5504 if (!m->path || !m->member)
5507 if (m->reply_cookie != 0)
5512 case SD_BUS_MESSAGE_METHOD_RETURN:
5514 if (m->reply_cookie == 0)
5518 case SD_BUS_MESSAGE_METHOD_ERROR:
5520 if (m->reply_cookie == 0 || !m->error.name)
5525 /* Refuse non-local messages that claim they are local */
5526 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5528 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5530 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5533 m->root_container.end = m->user_body_size;
5535 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5536 r = build_struct_offsets(
5538 m->root_container.signature,
5540 &m->root_container.item_size,
5541 &m->root_container.offsets,
5542 &m->root_container.n_offsets);
5547 /* Try to read the error message, but if we can't it's a non-issue */
5548 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5549 (void) sd_bus_message_read(m, "s", &m->error.message);
5554 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5555 assert_return(m, -EINVAL);
5556 assert_return(destination, -EINVAL);
5557 assert_return(!m->sealed, -EPERM);
5558 assert_return(!m->destination, -EEXIST);
5560 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5563 #if 0 /// UNNEEDED by elogind
5564 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5568 struct bus_body_part *part;
5574 total = BUS_MESSAGE_SIZE(m);
5580 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5581 MESSAGE_FOREACH_PART(part, i, m)
5582 e = mempcpy(e, part->data, part->size);
5584 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5593 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5600 r = sd_bus_message_enter_container(m, 'a', "s");
5604 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5605 r = strv_extend(l, s);
5612 r = sd_bus_message_exit_container(m);
5619 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5623 assert_return(m, -EINVAL);
5624 assert_return(m->sealed, -EPERM);
5625 assert_return(l, -EINVAL);
5627 r = bus_message_read_strv_extend(m, &strv);
5637 static int bus_message_get_arg_skip(
5641 const char **_contents) {
5646 r = sd_bus_message_rewind(m, true);
5651 const char *contents;
5654 r = sd_bus_message_peek_type(m, &type, &contents);
5660 /* Don't match against arguments after the first one we don't understand */
5661 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5662 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5667 *_contents = contents;
5673 r = sd_bus_message_skip(m, NULL);
5680 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5687 r = bus_message_get_arg_skip(m, i, &type, NULL);
5691 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5694 return sd_bus_message_read_basic(m, type, str);
5697 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5698 const char *contents;
5705 r = bus_message_get_arg_skip(m, i, &type, &contents);
5709 if (type != SD_BUS_TYPE_ARRAY)
5711 if (!STR_IN_SET(contents, "s", "o", "g"))
5714 return sd_bus_message_read_strv(m, strv);
5717 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5718 assert_return(m, EINVAL);
5720 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5723 return sd_bus_error_get_errno(&m->error);
5726 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5727 struct bus_container *c;
5729 assert_return(m, NULL);
5731 c = complete ? &m->root_container : message_get_container(m);
5732 return strempty(c->signature);
5735 #if 0 /// UNNEEDED by elogind
5736 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5737 assert_return(m, -EINVAL);
5739 return isempty(m->root_container.signature);
5742 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5743 assert_return(m, -EINVAL);
5745 return streq(strempty(m->root_container.signature), strempty(signature));
5749 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5750 bool done_something = false;
5753 assert_return(m, -EINVAL);
5754 assert_return(source, -EINVAL);
5755 assert_return(!m->sealed, -EPERM);
5756 assert_return(source->sealed, -EPERM);
5759 const char *contents;
5774 r = sd_bus_message_peek_type(source, &type, &contents);
5780 done_something = true;
5782 if (bus_type_is_container(type) > 0) {
5784 r = sd_bus_message_enter_container(source, type, contents);
5788 r = sd_bus_message_open_container(m, type, contents);
5792 r = sd_bus_message_copy(m, source, true);
5796 r = sd_bus_message_close_container(m);
5800 r = sd_bus_message_exit_container(source);
5807 r = sd_bus_message_read_basic(source, type, &basic);
5813 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5814 type == SD_BUS_TYPE_SIGNATURE ||
5815 type == SD_BUS_TYPE_STRING)
5816 r = sd_bus_message_append_basic(m, type, basic.string);
5818 r = sd_bus_message_append_basic(m, type, &basic);
5825 return done_something;
5828 #if 0 /// UNNEEDED by elogind
5829 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5834 assert_return(m, -EINVAL);
5835 assert_return(m->sealed, -EPERM);
5836 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5837 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5838 assert_return(type || contents, -EINVAL);
5839 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5841 r = sd_bus_message_peek_type(m, &t, &c);
5845 if (type != 0 && type != t)
5848 if (contents && !streq_ptr(contents, c))
5855 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5856 assert_return(m, NULL);
5861 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5862 _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5870 switch ((*m)->header->type) {
5872 case SD_BUS_MESSAGE_SIGNAL:
5873 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5879 case SD_BUS_MESSAGE_METHOD_CALL:
5880 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5886 case SD_BUS_MESSAGE_METHOD_RETURN:
5887 case SD_BUS_MESSAGE_METHOD_ERROR:
5889 n = message_new(bus, (*m)->header->type);
5893 n->reply_cookie = (*m)->reply_cookie;
5895 r = message_append_reply_cookie(n, n->reply_cookie);
5899 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5900 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5904 n->error._need_free = -1;
5913 if ((*m)->destination && !n->destination) {
5914 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5919 if ((*m)->sender && !n->sender) {
5920 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5925 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5927 r = sd_bus_message_copy(n, *m, true);
5931 timeout = (*m)->timeout;
5932 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5933 timeout = BUS_DEFAULT_TIMEOUT;
5935 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5939 sd_bus_message_unref(*m);
5946 #if 0 /// UNNEEDED by elogind
5947 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5951 assert_return(!m->sealed, -EPERM);
5952 assert_return(!m->sender, -EPERM);
5954 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5957 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5958 assert_return(m, -EINVAL);
5959 assert_return(priority, -EINVAL);
5961 *priority = m->priority;
5965 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5966 assert_return(m, -EINVAL);
5967 assert_return(!m->sealed, -EPERM);
5969 m->priority = priority;