1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include "time-util.h"
30 #include "cgroup-util.h"
31 #include "memfd-util.h"
34 #include "bus-message.h"
35 #include "bus-internal.h"
37 #include "bus-signature.h"
38 #include "bus-gvariant.h"
41 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
43 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
48 if (old_base == new_base)
51 if ((uint8_t*) p < (uint8_t*) old_base)
54 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
57 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
60 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
64 if (part->memfd >= 0) {
65 /* If we can reuse the memfd, try that. For that it
66 * can't be sealed yet. */
69 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
72 assert_se(munmap(part->data, part->mapped) == 0);
74 safe_close(part->memfd);
77 } else if (part->munmap_this)
78 munmap(part->data, part->mapped);
79 else if (part->free_this)
86 static void message_reset_parts(sd_bus_message *m) {
87 struct bus_body_part *part;
92 while (m->n_body_parts > 0) {
93 struct bus_body_part *next = part->next;
94 message_free_part(m, part);
101 m->cached_rindex_part = NULL;
102 m->cached_rindex_part_begin = 0;
105 static void message_reset_containers(sd_bus_message *m) {
110 for (i = 0; i < m->n_containers; i++) {
111 free(m->containers[i].signature);
112 free(m->containers[i].offsets);
116 m->containers = NULL;
118 m->n_containers = m->containers_allocated = 0;
119 m->root_container.index = 0;
122 static void message_free(sd_bus_message *m) {
128 message_reset_parts(m);
130 if (m->release_kdbus) {
131 struct kdbus_cmd_free cmd_free;
134 cmd_free.offset = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
135 (void) ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &cmd_free);
141 sd_bus_unref(m->bus);
144 close_many(m->fds, m->n_fds);
148 if (m->iovec != m->iovec_fixed)
151 message_reset_containers(m);
152 free(m->root_container.signature);
153 free(m->root_container.offsets);
155 free(m->root_container.peeked_signature);
157 bus_creds_done(&m->creds);
161 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
163 size_t old_size, new_size, start;
170 old_size = sizeof(struct bus_header) + m->header->fields_size;
171 start = ALIGN_TO(old_size, align);
172 new_size = start + sz;
174 if (old_size == new_size)
175 return (uint8_t*) m->header + old_size;
177 if (new_size > (size_t) ((uint32_t) -1))
180 if (m->free_header) {
181 np = realloc(m->header, ALIGN8(new_size));
185 /* Initially, the header is allocated as part of of
186 * the sd_bus_message itself, let's replace it by
189 np = malloc(ALIGN8(new_size));
193 memcpy(np, m->header, sizeof(struct bus_header));
196 /* Zero out padding */
197 if (start > old_size)
198 memzero((uint8_t*) np + old_size, start - old_size);
202 m->header->fields_size = new_size - sizeof(struct bus_header);
204 /* Adjust quick access pointers */
205 m->path = adjust_pointer(m->path, op, old_size, m->header);
206 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
207 m->member = adjust_pointer(m->member, op, old_size, m->header);
208 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
209 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
210 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
212 m->free_header = true;
215 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
218 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
221 return (uint8_t*) np + start;
228 static int message_append_field_string(
240 /* dbus1 doesn't allow strings over 32bit, let's enforce this
241 * globally, to not risk convertability */
243 if (l > (size_t) (uint32_t) -1)
246 /* Signature "(yv)" where the variant contains "s" */
248 if (BUS_MESSAGE_IS_GVARIANT(m)) {
250 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
251 p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
263 *ret = (char*) p + 8;
266 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
267 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
276 ((uint32_t*) p)[1] = l;
277 memcpy(p + 8, s, l + 1);
280 *ret = (char*) p + 8;
286 static int message_append_field_signature(
297 /* dbus1 doesn't allow signatures over 32bit, let's enforce
298 * this globally, to not risk convertability */
303 /* Signature "(yv)" where the variant contains "g" */
305 if (BUS_MESSAGE_IS_GVARIANT(m))
306 /* For gvariant the serialization is the same as for normal strings */
307 return message_append_field_string(m, h, 'g', s, ret);
309 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
310 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
316 p[2] = SD_BUS_TYPE_SIGNATURE;
319 memcpy(p + 5, s, l + 1);
322 *ret = (const char*) p + 5;
328 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
333 if (BUS_MESSAGE_IS_GVARIANT(m)) {
334 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
336 p = message_extend_fields(m, 8, 1 + 7 + 4 + 1 + 1, true);
342 *((uint32_t*) (p + 8)) = x;
346 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
347 p = message_extend_fields(m, 8, 4 + 4, false);
353 p[2] = SD_BUS_TYPE_UINT32;
356 ((uint32_t*) p)[1] = x;
362 int bus_message_from_header(
368 const struct ucred *ucred,
371 sd_bus_message **ret) {
374 struct bus_header *h;
378 assert(buffer || length <= 0);
379 assert(fds || n_fds <= 0);
382 if (length < sizeof(struct bus_header))
386 if (h->version != 1 &&
393 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
396 if (h->endian != BUS_LITTLE_ENDIAN &&
397 h->endian != BUS_BIG_ENDIAN)
400 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
403 label_sz = strlen(label);
418 m->creds.uid = ucred->uid;
419 m->creds.pid = ucred->pid;
420 m->creds.gid = ucred->gid;
421 m->creds.mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID;
425 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
426 memcpy(m->creds.label, label, label_sz + 1);
428 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
431 m->bus = sd_bus_ref(bus);
437 int bus_message_from_malloc(
443 const struct ucred *ucred,
445 sd_bus_message **ret) {
451 r = bus_message_from_header(bus, buffer, length, fds, n_fds, ucred, label, 0, &m);
455 if (length != BUS_MESSAGE_SIZE(m)) {
460 sz = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
463 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
465 m->body.sealed = true;
470 m->iovec = m->iovec_fixed;
471 m->iovec[0].iov_base = buffer;
472 m->iovec[0].iov_len = length;
474 r = bus_message_parse_fields(m);
478 /* We take possession of the memory and fds now */
479 m->free_header = true;
490 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
495 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
500 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
501 m->header->endian = BUS_NATIVE_ENDIAN;
502 m->header->type = type;
503 m->header->version = bus ? bus->message_version : 1;
504 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
505 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
506 m->bus = sd_bus_ref(bus);
511 _public_ int sd_bus_message_new_signal(
515 const char *interface,
516 const char *member) {
521 assert_return(bus, -ENOTCONN);
522 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
523 assert_return(object_path_is_valid(path), -EINVAL);
524 assert_return(interface_name_is_valid(interface), -EINVAL);
525 assert_return(member_name_is_valid(member), -EINVAL);
526 assert_return(m, -EINVAL);
528 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
532 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
534 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
537 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
540 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
548 sd_bus_message_unref(t);
552 _public_ int sd_bus_message_new_method_call(
555 const char *destination,
557 const char *interface,
558 const char *member) {
563 assert_return(bus, -ENOTCONN);
564 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
565 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
566 assert_return(object_path_is_valid(path), -EINVAL);
567 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
568 assert_return(member_name_is_valid(member), -EINVAL);
569 assert_return(m, -EINVAL);
571 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
575 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
578 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
583 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
589 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
602 static int message_new_reply(
603 sd_bus_message *call,
605 sd_bus_message **m) {
610 assert_return(call, -EINVAL);
611 assert_return(call->sealed, -EPERM);
612 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
613 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
614 assert_return(m, -EINVAL);
616 t = message_new(call->bus, type);
620 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
621 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
623 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
628 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
633 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
634 t->enforced_reply_signature = call->enforced_reply_signature;
644 _public_ int sd_bus_message_new_method_return(
645 sd_bus_message *call,
646 sd_bus_message **m) {
648 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
651 _public_ int sd_bus_message_new_method_error(
652 sd_bus_message *call,
654 const sd_bus_error *e) {
659 assert_return(sd_bus_error_is_set(e), -EINVAL);
660 assert_return(m, -EINVAL);
662 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
666 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
671 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
676 t->error._need_free = -1;
686 _public_ int sd_bus_message_new_method_errorf(
687 sd_bus_message *call,
693 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
696 assert_return(name, -EINVAL);
697 assert_return(m, -EINVAL);
699 va_start(ap, format);
700 bus_error_setfv(&error, name, format, ap);
703 return sd_bus_message_new_method_error(call, m, &error);
706 _public_ int sd_bus_message_new_method_errno(
707 sd_bus_message *call,
710 const sd_bus_error *p) {
712 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
714 if (sd_bus_error_is_set(p))
715 return sd_bus_message_new_method_error(call, m, p);
717 sd_bus_error_set_errno(&berror, error);
719 return sd_bus_message_new_method_error(call, m, &berror);
722 _public_ int sd_bus_message_new_method_errnof(
723 sd_bus_message *call,
729 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
732 va_start(ap, format);
733 bus_error_set_errnofv(&berror, error, format, ap);
736 return sd_bus_message_new_method_error(call, m, &berror);
739 int bus_message_new_synthetic_error(
742 const sd_bus_error *e,
743 sd_bus_message **m) {
749 assert(sd_bus_error_is_set(e));
752 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
756 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
757 t->reply_cookie = cookie;
759 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
763 if (bus && bus->unique_name) {
764 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
769 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
774 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
779 t->error._need_free = -1;
789 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
790 assert_return(m, NULL);
792 assert(m->n_ref > 0);
798 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
803 assert(m->n_ref > 0);
813 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
814 assert_return(m, -EINVAL);
815 assert_return(type, -EINVAL);
817 *type = m->header->type;
821 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
822 assert_return(m, -EINVAL);
823 assert_return(cookie, -EINVAL);
824 assert_return(m->header->serial != 0, -ENODATA);
826 *cookie = BUS_MESSAGE_COOKIE(m);
830 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
831 assert_return(m, -EINVAL);
832 assert_return(cookie, -EINVAL);
833 assert_return(m->reply_cookie != 0, -ENODATA);
835 *cookie = m->reply_cookie;
839 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
840 assert_return(m, -EINVAL);
842 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
843 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
846 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
847 assert_return(m, -EINVAL);
849 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
852 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
853 assert_return(m, -EINVAL);
855 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
856 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
859 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
860 assert_return(m, NULL);
865 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
866 assert_return(m, NULL);
871 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
872 assert_return(m, NULL);
877 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
878 assert_return(m, NULL);
880 return m->destination;
883 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
884 assert_return(m, NULL);
889 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
890 assert_return(m, NULL);
891 assert_return(sd_bus_error_is_set(&m->error), NULL);
896 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
897 assert_return(m, -EINVAL);
898 assert_return(usec, -EINVAL);
900 if (m->monotonic <= 0)
903 *usec = m->monotonic;
907 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
908 assert_return(m, -EINVAL);
909 assert_return(usec, -EINVAL);
911 if (m->realtime <= 0)
918 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
919 assert_return(m, -EINVAL);
920 assert_return(seqnum, -EINVAL);
929 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
930 assert_return(m, NULL);
932 if (m->creds.mask == 0)
938 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
939 const char *interface,
940 const char *member) {
941 assert_return(m, -EINVAL);
943 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
946 if (interface && (!m->interface || !streq(m->interface, interface)))
949 if (member && (!m->member || !streq(m->member, member)))
955 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
956 const char *interface,
957 const char *member) {
958 assert_return(m, -EINVAL);
960 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
963 if (interface && (!m->interface || !streq(m->interface, interface)))
966 if (member && (!m->member || !streq(m->member, member)))
972 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
973 assert_return(m, -EINVAL);
975 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
978 if (name && (!m->error.name || !streq(m->error.name, name)))
984 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
985 assert_return(m, -EINVAL);
986 assert_return(!m->sealed, -EPERM);
987 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
990 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
992 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
997 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
998 assert_return(m, -EINVAL);
999 assert_return(!m->sealed, -EPERM);
1002 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1004 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1009 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1010 assert_return(m, -EINVAL);
1011 assert_return(!m->sealed, -EPERM);
1014 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1016 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1021 static struct bus_container *message_get_container(sd_bus_message *m) {
1024 if (m->n_containers == 0)
1025 return &m->root_container;
1027 assert(m->containers);
1028 return m->containers + m->n_containers - 1;
1031 struct bus_body_part *message_append_part(sd_bus_message *m) {
1032 struct bus_body_part *part;
1039 if (m->n_body_parts <= 0) {
1043 assert(m->body_end);
1045 part = new0(struct bus_body_part, 1);
1051 m->body_end->next = part;
1061 static void part_zero(struct bus_body_part *part, size_t sz) {
1066 /* All other fields can be left in their defaults */
1067 assert(!part->data);
1068 assert(part->memfd < 0);
1071 part->is_zero = true;
1072 part->sealed = true;
1075 static int part_make_space(
1076 struct sd_bus_message *m,
1077 struct bus_body_part *part,
1086 assert(!part->sealed);
1091 if (!part->data && part->memfd < 0)
1092 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1094 if (part->memfd >= 0) {
1096 if (part->allocated == 0 || sz > part->allocated) {
1097 uint64_t new_allocated;
1099 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1100 r = memfd_set_size(part->memfd, new_allocated);
1106 part->allocated = new_allocated;
1109 if (!part->data || sz > part->mapped) {
1112 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1113 if (part->mapped <= 0)
1114 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1116 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1118 if (n == MAP_FAILED) {
1127 part->munmap_this = true;
1129 if (part->allocated == 0 || sz > part->allocated) {
1130 size_t new_allocated;
1132 new_allocated = sz > 0 ? 2 * sz : 64;
1133 n = realloc(part->data, new_allocated);
1140 part->allocated = new_allocated;
1141 part->free_this = true;
1146 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1152 static int message_add_offset(sd_bus_message *m, size_t offset) {
1153 struct bus_container *c;
1156 assert(BUS_MESSAGE_IS_GVARIANT(m));
1158 /* Add offset to current container, unless this is the first
1159 * item in it, which will have the 0 offset, which we can
1161 c = message_get_container(m);
1163 if (!c->need_offsets)
1166 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1169 c->offsets[c->n_offsets++] = offset;
1173 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1174 struct bus_container *c;
1181 /* Update counters */
1182 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1185 *c->array_size += expand;
1189 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1190 size_t start_body, end_body, padding, added;
1201 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1202 end_body = start_body + sz;
1204 padding = start_body - m->header->body_size;
1205 added = padding + sz;
1207 /* Check for 32bit overflows */
1208 if (end_body > (size_t) ((uint32_t) -1)) {
1214 struct bus_body_part *part = NULL;
1218 m->n_body_parts <= 0 ||
1219 m->body_end->sealed ||
1220 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1224 part = message_append_part(m);
1228 part_zero(part, padding);
1231 part = message_append_part(m);
1235 r = part_make_space(m, part, sz, &p);
1239 struct bus_container *c;
1241 size_t os, start_part, end_part;
1247 start_part = ALIGN_TO(part->size, align);
1248 end_part = start_part + sz;
1250 r = part_make_space(m, part, end_part, &p);
1255 memzero(p, padding);
1256 p = (uint8_t*) p + padding;
1259 /* Readjust pointers */
1260 for (c = m->containers; c < m->containers + m->n_containers; c++)
1261 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1263 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1266 /* Return something that is not NULL and is aligned */
1267 p = (uint8_t *) NULL + align;
1269 m->header->body_size = end_body;
1270 message_extend_containers(m, added);
1273 r = message_add_offset(m, end_body);
1283 static int message_push_fd(sd_bus_message *m, int fd) {
1294 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1298 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1306 m->fds[m->n_fds] = copy;
1312 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1313 _cleanup_close_ int fd = -1;
1314 struct bus_container *c;
1318 assert_return(m, -EINVAL);
1319 assert_return(!m->sealed, -EPERM);
1320 assert_return(bus_type_is_basic(type), -EINVAL);
1321 assert_return(!m->poisoned, -ESTALE);
1323 c = message_get_container(m);
1325 if (c->signature && c->signature[c->index]) {
1326 /* Container signature is already set */
1328 if (c->signature[c->index] != type)
1333 /* Maybe we can append to the signature? But only if this is the top-level container*/
1334 if (c->enclosing != 0)
1337 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1344 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1350 case SD_BUS_TYPE_SIGNATURE:
1351 case SD_BUS_TYPE_STRING:
1354 /* Fall through... */
1355 case SD_BUS_TYPE_OBJECT_PATH:
1363 case SD_BUS_TYPE_BOOLEAN:
1365 u8 = p && *(int*) p;
1371 case SD_BUS_TYPE_UNIX_FD:
1376 fd = message_push_fd(m, *(int*) p);
1387 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1388 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1395 a = message_extend_body(m, align, sz, true);
1402 *stored = (const uint8_t*) a;
1409 case SD_BUS_TYPE_STRING:
1410 /* To make things easy we'll serialize a NULL string
1411 * into the empty string */
1414 /* Fall through... */
1415 case SD_BUS_TYPE_OBJECT_PATH:
1421 sz = 4 + strlen(p) + 1;
1424 case SD_BUS_TYPE_SIGNATURE:
1429 sz = 1 + strlen(p) + 1;
1432 case SD_BUS_TYPE_BOOLEAN:
1434 u32 = p && *(int*) p;
1440 case SD_BUS_TYPE_UNIX_FD:
1445 fd = message_push_fd(m, *(int*) p);
1456 align = bus_type_get_alignment(type);
1457 sz = bus_type_get_size(type);
1464 a = message_extend_body(m, align, sz, false);
1468 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1469 *(uint32_t*) a = sz - 5;
1470 memcpy((uint8_t*) a + 4, p, sz - 4);
1473 *stored = (const uint8_t*) a + 4;
1475 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1476 *(uint8_t*) a = sz - 2;
1477 memcpy((uint8_t*) a + 1, p, sz - 1);
1480 *stored = (const uint8_t*) a + 1;
1489 if (type == SD_BUS_TYPE_UNIX_FD)
1492 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1499 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1500 return message_append_basic(m, type, p, NULL);
1503 _public_ int sd_bus_message_append_string_space(
1508 struct bus_container *c;
1511 assert_return(m, -EINVAL);
1512 assert_return(s, -EINVAL);
1513 assert_return(!m->sealed, -EPERM);
1514 assert_return(!m->poisoned, -ESTALE);
1516 c = message_get_container(m);
1518 if (c->signature && c->signature[c->index]) {
1519 /* Container signature is already set */
1521 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1526 /* Maybe we can append to the signature? But only if this is the top-level container*/
1527 if (c->enclosing != 0)
1530 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1537 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1538 a = message_extend_body(m, 1, size + 1, true);
1544 a = message_extend_body(m, 4, 4 + size + 1, false);
1548 *(uint32_t*) a = size;
1554 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1560 _public_ int sd_bus_message_append_string_iovec(
1562 const struct iovec *iov,
1570 assert_return(m, -EINVAL);
1571 assert_return(!m->sealed, -EPERM);
1572 assert_return(iov || n == 0, -EINVAL);
1573 assert_return(!m->poisoned, -ESTALE);
1575 size = IOVEC_TOTAL_SIZE(iov, n);
1577 r = sd_bus_message_append_string_space(m, size, &p);
1581 for (i = 0; i < n; i++) {
1583 if (iov[i].iov_base)
1584 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1586 memset(p, ' ', iov[i].iov_len);
1588 p += iov[i].iov_len;
1594 static int bus_message_open_array(
1596 struct bus_container *c,
1597 const char *contents,
1598 uint32_t **array_size,
1600 bool *need_offsets) {
1610 assert(need_offsets);
1612 if (!signature_is_single(contents, true))
1615 if (c->signature && c->signature[c->index]) {
1617 /* Verify the existing signature */
1619 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1622 if (!startswith(c->signature + c->index + 1, contents))
1625 nindex = c->index + 1 + strlen(contents);
1629 if (c->enclosing != 0)
1632 /* Extend the existing signature */
1634 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1640 nindex = e - c->signature;
1643 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1644 alignment = bus_gvariant_get_alignment(contents);
1648 /* Add alignment padding and add to offset list */
1649 if (!message_extend_body(m, alignment, 0, false))
1652 r = bus_gvariant_is_fixed_size(contents);
1656 *begin = m->header->body_size;
1657 *need_offsets = r == 0;
1661 struct bus_body_part *o;
1663 alignment = bus_type_get_alignment(contents[0]);
1667 a = message_extend_body(m, 4, 4, false);
1672 op = m->body_end->data;
1673 os = m->body_end->size;
1675 /* Add alignment between size and first element */
1676 if (!message_extend_body(m, alignment, 0, false))
1679 /* location of array size might have changed so let's readjust a */
1680 if (o == m->body_end)
1681 a = adjust_pointer(a, op, os, m->body_end->data);
1687 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1693 static int bus_message_open_variant(
1695 struct bus_container *c,
1696 const char *contents) {
1702 if (!signature_is_single(contents, false))
1705 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1708 if (c->signature && c->signature[c->index]) {
1710 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1716 if (c->enclosing != 0)
1719 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1726 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1727 /* Variants are always aligned to 8 */
1729 if (!message_extend_body(m, 8, 0, false))
1736 l = strlen(contents);
1737 a = message_extend_body(m, 1, 1 + l + 1, false);
1742 memcpy((uint8_t*) a + 1, contents, l + 1);
1745 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1751 static int bus_message_open_struct(
1753 struct bus_container *c,
1754 const char *contents,
1756 bool *need_offsets) {
1765 assert(need_offsets);
1767 if (!signature_is_valid(contents, false))
1770 if (c->signature && c->signature[c->index]) {
1773 l = strlen(contents);
1775 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1776 !startswith(c->signature + c->index + 1, contents) ||
1777 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1780 nindex = c->index + 1 + l + 1;
1784 if (c->enclosing != 0)
1787 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1793 nindex = e - c->signature;
1796 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1799 alignment = bus_gvariant_get_alignment(contents);
1803 if (!message_extend_body(m, alignment, 0, false))
1806 r = bus_gvariant_is_fixed_size(contents);
1810 *begin = m->header->body_size;
1811 *need_offsets = r == 0;
1813 /* Align contents to 8 byte boundary */
1814 if (!message_extend_body(m, 8, 0, false))
1818 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1824 static int bus_message_open_dict_entry(
1826 struct bus_container *c,
1827 const char *contents,
1829 bool *need_offsets) {
1837 assert(need_offsets);
1839 if (!signature_is_pair(contents))
1842 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1845 if (c->signature && c->signature[c->index]) {
1848 l = strlen(contents);
1850 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1851 !startswith(c->signature + c->index + 1, contents) ||
1852 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1857 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1860 alignment = bus_gvariant_get_alignment(contents);
1864 if (!message_extend_body(m, alignment, 0, false))
1867 r = bus_gvariant_is_fixed_size(contents);
1871 *begin = m->header->body_size;
1872 *need_offsets = r == 0;
1874 /* Align contents to 8 byte boundary */
1875 if (!message_extend_body(m, 8, 0, false))
1882 _public_ int sd_bus_message_open_container(
1885 const char *contents) {
1887 struct bus_container *c, *w;
1888 uint32_t *array_size = NULL;
1890 size_t before, begin = 0;
1891 bool need_offsets = false;
1894 assert_return(m, -EINVAL);
1895 assert_return(!m->sealed, -EPERM);
1896 assert_return(contents, -EINVAL);
1897 assert_return(!m->poisoned, -ESTALE);
1899 /* Make sure we have space for one more container */
1900 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1905 c = message_get_container(m);
1907 signature = strdup(contents);
1913 /* Save old index in the parent container, in case we have to
1914 * abort this container */
1915 c->saved_index = c->index;
1916 before = m->header->body_size;
1918 if (type == SD_BUS_TYPE_ARRAY)
1919 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1920 else if (type == SD_BUS_TYPE_VARIANT)
1921 r = bus_message_open_variant(m, c, contents);
1922 else if (type == SD_BUS_TYPE_STRUCT)
1923 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1924 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1925 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1934 /* OK, let's fill it in */
1935 w = m->containers + m->n_containers++;
1936 w->enclosing = type;
1937 w->signature = signature;
1939 w->array_size = array_size;
1942 w->n_offsets = w->offsets_allocated = 0;
1944 w->need_offsets = need_offsets;
1949 static size_t determine_word_size(size_t sz, size_t extra) {
1950 if (sz + extra <= 0xFF)
1952 else if (sz + extra*2 <= 0xFFFF)
1954 else if (sz + extra*4 <= 0xFFFFFFFF)
1960 static size_t read_word_le(void *p, size_t sz) {
1970 return *(uint8_t*) p;
1975 return le16toh(x.u16);
1977 return le32toh(x.u32);
1979 return le64toh(x.u64);
1981 assert_not_reached("unknown word width");
1984 static void write_word_le(void *p, size_t sz, size_t value) {
1992 assert(sz == 8 || (value < (1ULL << (sz*8))));
1995 *(uint8_t*) p = value;
1998 x.u16 = htole16((uint16_t) value);
2000 x.u32 = htole32((uint32_t) value);
2002 x.u64 = htole64((uint64_t) value);
2004 assert_not_reached("unknown word width");
2009 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2014 if (!BUS_MESSAGE_IS_GVARIANT(m))
2017 if (c->need_offsets) {
2018 size_t payload, sz, i;
2021 /* Variable-width arrays */
2023 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2024 sz = determine_word_size(payload, c->n_offsets);
2026 a = message_extend_body(m, 1, sz * c->n_offsets, true);
2030 for (i = 0; i < c->n_offsets; i++)
2031 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2035 /* Fixed-width or empty arrays */
2037 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
2045 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2052 if (!BUS_MESSAGE_IS_GVARIANT(m))
2055 l = strlen(c->signature);
2057 a = message_extend_body(m, 1, 1 + l, true);
2062 memcpy(a+1, c->signature, l);
2067 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2068 size_t n_variable = 0;
2077 if (!BUS_MESSAGE_IS_GVARIANT(m))
2080 p = strempty(c->signature);
2084 r = signature_element_length(p, &n);
2093 r = bus_gvariant_is_fixed_size(t);
2098 assert(!c->need_offsets || i <= c->n_offsets);
2100 /* We need to add an offset for each item that has a
2101 * variable size and that is not the last one in the
2103 if (r == 0 && p[n] != 0)
2110 assert(!c->need_offsets || i == c->n_offsets);
2111 assert(c->need_offsets || n_variable == 0);
2113 if (n_variable <= 0) {
2114 a = message_extend_body(m, 1, 0, add_offset);
2121 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2123 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2125 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2129 p = strempty(c->signature);
2130 for (i = 0, j = 0; i < c->n_offsets; i++) {
2134 r = signature_element_length(p, &n);
2145 r = bus_gvariant_is_fixed_size(t);
2148 if (r > 0 || p[0] == 0)
2152 k = n_variable - 1 - j;
2154 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2163 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2164 struct bus_container *c;
2167 assert_return(m, -EINVAL);
2168 assert_return(!m->sealed, -EPERM);
2169 assert_return(m->n_containers > 0, -EINVAL);
2170 assert_return(!m->poisoned, -ESTALE);
2172 c = message_get_container(m);
2174 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2175 if (c->signature && c->signature[c->index] != 0)
2180 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2181 r = bus_message_close_array(m, c);
2182 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2183 r = bus_message_close_variant(m, c);
2184 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2185 r = bus_message_close_struct(m, c, true);
2187 assert_not_reached("Unknown container type");
2201 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2208 stack[*i].types = types;
2209 stack[*i].n_struct = n_struct;
2210 stack[*i].n_array = n_array;
2216 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2227 *types = stack[*i].types;
2228 *n_struct = stack[*i].n_struct;
2229 *n_array = stack[*i].n_array;
2234 int bus_message_append_ap(
2239 unsigned n_array, n_struct;
2240 TypeStack stack[BUS_CONTAINER_DEPTH];
2241 unsigned stack_ptr = 0;
2249 n_array = (unsigned) -1;
2250 n_struct = strlen(types);
2255 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2256 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2262 r = sd_bus_message_close_container(m);
2270 if (n_array != (unsigned) -1)
2279 case SD_BUS_TYPE_BYTE: {
2282 x = (uint8_t) va_arg(ap, int);
2283 r = sd_bus_message_append_basic(m, *t, &x);
2287 case SD_BUS_TYPE_BOOLEAN:
2288 case SD_BUS_TYPE_INT32:
2289 case SD_BUS_TYPE_UINT32:
2290 case SD_BUS_TYPE_UNIX_FD: {
2293 /* We assume a boolean is the same as int32_t */
2294 assert_cc(sizeof(int32_t) == sizeof(int));
2296 x = va_arg(ap, uint32_t);
2297 r = sd_bus_message_append_basic(m, *t, &x);
2301 case SD_BUS_TYPE_INT16:
2302 case SD_BUS_TYPE_UINT16: {
2305 x = (uint16_t) va_arg(ap, int);
2306 r = sd_bus_message_append_basic(m, *t, &x);
2310 case SD_BUS_TYPE_INT64:
2311 case SD_BUS_TYPE_UINT64:
2312 case SD_BUS_TYPE_DOUBLE: {
2315 x = va_arg(ap, uint64_t);
2316 r = sd_bus_message_append_basic(m, *t, &x);
2320 case SD_BUS_TYPE_STRING:
2321 case SD_BUS_TYPE_OBJECT_PATH:
2322 case SD_BUS_TYPE_SIGNATURE: {
2325 x = va_arg(ap, const char*);
2326 r = sd_bus_message_append_basic(m, *t, x);
2330 case SD_BUS_TYPE_ARRAY: {
2333 r = signature_element_length(t + 1, &k);
2339 memcpy(s, t + 1, k);
2342 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2347 if (n_array == (unsigned) -1) {
2352 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2358 n_array = va_arg(ap, unsigned);
2363 case SD_BUS_TYPE_VARIANT: {
2366 s = va_arg(ap, const char*);
2370 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2374 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2379 n_struct = strlen(s);
2380 n_array = (unsigned) -1;
2385 case SD_BUS_TYPE_STRUCT_BEGIN:
2386 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2389 r = signature_element_length(t, &k);
2396 memcpy(s, t + 1, k - 2);
2399 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2404 if (n_array == (unsigned) -1) {
2409 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2415 n_array = (unsigned) -1;
2431 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2435 assert_return(m, -EINVAL);
2436 assert_return(types, -EINVAL);
2437 assert_return(!m->sealed, -EPERM);
2438 assert_return(!m->poisoned, -ESTALE);
2440 va_start(ap, types);
2441 r = bus_message_append_ap(m, types, ap);
2447 _public_ int sd_bus_message_append_array_space(
2457 assert_return(m, -EINVAL);
2458 assert_return(!m->sealed, -EPERM);
2459 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2460 assert_return(ptr || size == 0, -EINVAL);
2461 assert_return(!m->poisoned, -ESTALE);
2463 /* alignment and size of the trivial types (except bool) is
2464 * identical for gvariant and dbus1 marshalling */
2465 align = bus_type_get_alignment(type);
2466 sz = bus_type_get_size(type);
2468 assert_se(align > 0);
2474 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2478 a = message_extend_body(m, align, size, false);
2482 r = sd_bus_message_close_container(m);
2490 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2497 assert_return(m, -EINVAL);
2498 assert_return(!m->sealed, -EPERM);
2499 assert_return(bus_type_is_trivial(type), -EINVAL);
2500 assert_return(ptr || size == 0, -EINVAL);
2501 assert_return(!m->poisoned, -ESTALE);
2503 r = sd_bus_message_append_array_space(m, type, size, &p);
2508 memcpy(p, ptr, size);
2513 _public_ int sd_bus_message_append_array_iovec(
2516 const struct iovec *iov,
2524 assert_return(m, -EINVAL);
2525 assert_return(!m->sealed, -EPERM);
2526 assert_return(bus_type_is_trivial(type), -EINVAL);
2527 assert_return(iov || n == 0, -EINVAL);
2528 assert_return(!m->poisoned, -ESTALE);
2530 size = IOVEC_TOTAL_SIZE(iov, n);
2532 r = sd_bus_message_append_array_space(m, type, size, &p);
2536 for (i = 0; i < n; i++) {
2538 if (iov[i].iov_base)
2539 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2541 memzero(p, iov[i].iov_len);
2543 p = (uint8_t*) p + iov[i].iov_len;
2549 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2552 _cleanup_close_ int copy_fd = -1;
2553 struct bus_body_part *part;
2565 if (!bus_type_is_trivial(type))
2570 r = memfd_set_sealed(memfd);
2574 copy_fd = dup(memfd);
2578 r = memfd_get_size(memfd, &size);
2582 align = bus_type_get_alignment(type);
2583 sz = bus_type_get_size(type);
2585 assert_se(align > 0);
2591 if (size > (uint64_t) (uint32_t) -1)
2594 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2598 a = message_extend_body(m, align, 0, false);
2602 part = message_append_part(m);
2606 part->memfd = copy_fd;
2607 part->sealed = true;
2611 m->header->body_size += size;
2612 message_extend_containers(m, size);
2614 return sd_bus_message_close_container(m);
2617 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) {
2618 _cleanup_close_ int copy_fd = -1;
2619 struct bus_body_part *part;
2620 struct bus_container *c;
2625 assert_return(m, -EINVAL);
2626 assert_return(memfd >= 0, -EINVAL);
2627 assert_return(!m->sealed, -EPERM);
2628 assert_return(!m->poisoned, -ESTALE);
2630 r = memfd_set_sealed(memfd);
2634 copy_fd = dup(memfd);
2638 r = memfd_get_size(memfd, &size);
2642 /* We require this to be NUL terminated */
2646 if (size > (uint64_t) (uint32_t) -1)
2649 c = message_get_container(m);
2650 if (c->signature && c->signature[c->index]) {
2651 /* Container signature is already set */
2653 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2658 /* Maybe we can append to the signature? But only if this is the top-level container*/
2659 if (c->enclosing != 0)
2662 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2669 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2670 a = message_extend_body(m, 4, 4, false);
2674 *(uint32_t*) a = size - 1;
2677 part = message_append_part(m);
2681 part->memfd = copy_fd;
2682 part->sealed = true;
2686 m->header->body_size += size;
2687 message_extend_containers(m, size);
2689 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2690 r = message_add_offset(m, m->header->body_size);
2697 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2703 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2707 assert_return(m, -EINVAL);
2708 assert_return(!m->sealed, -EPERM);
2709 assert_return(!m->poisoned, -ESTALE);
2711 r = sd_bus_message_open_container(m, 'a', "s");
2715 STRV_FOREACH(i, l) {
2716 r = sd_bus_message_append_basic(m, 's', *i);
2721 return sd_bus_message_close_container(m);
2724 static int bus_message_close_header(sd_bus_message *m) {
2730 if (!BUS_MESSAGE_IS_GVARIANT(m))
2733 if (m->n_header_offsets < 1)
2736 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2738 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2740 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2744 for (i = 0; i < m->n_header_offsets; i++)
2745 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2750 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2751 struct bus_body_part *part;
2761 if (m->n_containers > 0)
2767 /* In vtables the return signature of method calls is listed,
2768 * let's check if they match if this is a response */
2769 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2770 m->enforced_reply_signature &&
2771 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2774 /* If gvariant marshalling is used we need to close the body structure */
2775 r = bus_message_close_struct(m, &m->root_container, false);
2779 /* If there's a non-trivial signature set, then add it in here */
2780 if (!isempty(m->root_container.signature)) {
2781 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2787 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2792 r = bus_message_close_header(m);
2796 m->header->serial = (uint32_t) cookie;
2797 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2799 /* Add padding at the end of the fields part, since we know
2800 * the body needs to start at an 8 byte alignment. We made
2801 * sure we allocated enough space for this, so all we need to
2802 * do here is to zero it out. */
2803 l = BUS_MESSAGE_FIELDS_SIZE(m);
2806 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, a);
2808 /* If this is something we can send as memfd, then let's seal
2809 the memfd now. Note that we can send memfds as payload only
2810 for directed messages, and not for broadcasts. */
2811 if (m->destination && m->bus->use_memfd) {
2812 MESSAGE_FOREACH_PART(part, i, m)
2813 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2816 /* Try to seal it if that makes
2817 * sense. First, unmap our own map to
2818 * make sure we don't keep it busy. */
2819 bus_body_part_unmap(part);
2821 /* Then, sync up real memfd size */
2823 r = memfd_set_size(part->memfd, sz);
2827 /* Finally, try to seal */
2828 if (memfd_set_sealed(part->memfd) >= 0)
2829 part->sealed = true;
2833 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2834 m->root_container.index = 0;
2835 m->root_container.offset_index = 0;
2836 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2843 int bus_body_part_map(struct bus_body_part *part) {
2852 if (part->size <= 0)
2855 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2856 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2857 static const uint8_t zeroes[7] = { };
2858 part->data = (void*) zeroes;
2862 psz = PAGE_ALIGN(part->size);
2864 if (part->memfd >= 0)
2865 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, 0);
2866 else if (part->is_zero)
2867 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2871 if (p == MAP_FAILED)
2876 part->munmap_this = true;
2881 void bus_body_part_unmap(struct bus_body_part *part) {
2885 if (part->memfd < 0)
2891 if (!part->munmap_this)
2894 assert_se(munmap(part->data, part->mapped) == 0);
2898 part->munmap_this = false;
2903 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2904 size_t k, start, end;
2909 start = ALIGN_TO((size_t) *rindex, align);
2910 end = start + nbytes;
2915 /* Verify that padding is 0 */
2916 for (k = *rindex; k < start; k++)
2917 if (((const uint8_t*) p)[k] != 0)
2921 *r = (uint8_t*) p + start;
2928 static bool message_end_of_signature(sd_bus_message *m) {
2929 struct bus_container *c;
2933 c = message_get_container(m);
2934 return !c->signature || c->signature[c->index] == 0;
2937 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2938 struct bus_container *c;
2942 c = message_get_container(m);
2943 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2946 if (BUS_MESSAGE_IS_GVARIANT(m))
2947 return index >= c->end;
2949 assert(c->array_size);
2950 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2954 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2955 assert_return(m, -EINVAL);
2956 assert_return(m->sealed, -EPERM);
2958 if (complete && m->n_containers > 0)
2961 if (message_end_of_signature(m))
2964 if (message_end_of_array(m, m->rindex))
2970 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2971 struct bus_body_part *part;
2977 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2978 part = m->cached_rindex_part;
2979 begin = m->cached_rindex_part_begin;
2989 if (index + sz <= begin + part->size) {
2991 r = bus_body_part_map(part);
2996 *p = (uint8_t*) part->data + index - begin;
2998 m->cached_rindex_part = part;
2999 m->cached_rindex_part_begin = begin;
3004 begin += part->size;
3011 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3018 if (!BUS_MESSAGE_IS_GVARIANT(m))
3021 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3024 sz = bus_gvariant_get_size(c->signature);
3028 if (c->offset_index+1 >= c->n_offsets)
3031 /* Variable-size array */
3033 alignment = bus_gvariant_get_alignment(c->signature);
3034 assert(alignment > 0);
3036 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3037 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3040 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3043 /* Fixed-size array */
3044 *rindex = c->begin + (c->offset_index+1) * sz;
3050 } else if (c->enclosing == 0 ||
3051 c->enclosing == SD_BUS_TYPE_STRUCT ||
3052 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3057 if (c->offset_index+1 >= c->n_offsets)
3060 r = signature_element_length(c->signature + c->index, &n);
3064 r = signature_element_length(c->signature + c->index + n, &j);
3069 memcpy(t, c->signature + c->index + n, j);
3072 alignment = bus_gvariant_get_alignment(t);
3075 assert(alignment > 0);
3077 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3078 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3082 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3085 assert_not_reached("Unknown container type");
3090 /* Reached the end */
3097 static int message_peek_body(
3104 size_t k, start, end, padding;
3105 struct bus_body_part *part;
3112 start = ALIGN_TO((size_t) *rindex, align);
3113 padding = start - *rindex;
3114 end = start + nbytes;
3116 if (end > BUS_MESSAGE_BODY_SIZE(m))
3119 part = find_part(m, *rindex, padding, (void**) &q);
3124 /* Verify padding */
3125 for (k = 0; k < padding; k++)
3130 part = find_part(m, start, nbytes, (void**) &q);
3131 if (!part || (nbytes > 0 && !q))
3142 static bool validate_nul(const char *s, size_t l) {
3144 /* Check for NUL chars in the string */
3145 if (memchr(s, 0, l))
3148 /* Check for NUL termination */
3155 static bool validate_string(const char *s, size_t l) {
3157 if (!validate_nul(s, l))
3160 /* Check if valid UTF8 */
3161 if (!utf8_is_valid(s))
3167 static bool validate_signature(const char *s, size_t l) {
3169 if (!validate_nul(s, l))
3172 /* Check if valid signature */
3173 if (!signature_is_valid(s, true))
3179 static bool validate_object_path(const char *s, size_t l) {
3181 if (!validate_nul(s, l))
3184 if (!object_path_is_valid(s))
3190 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3191 struct bus_container *c;
3196 assert_return(m, -EINVAL);
3197 assert_return(m->sealed, -EPERM);
3198 assert_return(bus_type_is_basic(type), -EINVAL);
3200 if (message_end_of_signature(m))
3203 if (message_end_of_array(m, m->rindex))
3206 c = message_get_container(m);
3207 if (c->signature[c->index] != type)
3212 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3214 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3217 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3221 if (type == SD_BUS_TYPE_STRING)
3222 ok = validate_string(q, c->item_size-1);
3223 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3224 ok = validate_object_path(q, c->item_size-1);
3226 ok = validate_signature(q, c->item_size-1);
3232 *(const char**) p = q;
3236 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3238 if ((size_t) sz != c->item_size)
3241 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3244 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3250 case SD_BUS_TYPE_BYTE:
3252 *(uint8_t*) p = *(uint8_t*) q;
3255 case SD_BUS_TYPE_BOOLEAN:
3257 *(int*) p = !!*(uint8_t*) q;
3260 case SD_BUS_TYPE_INT16:
3261 case SD_BUS_TYPE_UINT16:
3263 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3266 case SD_BUS_TYPE_INT32:
3267 case SD_BUS_TYPE_UINT32:
3269 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3272 case SD_BUS_TYPE_INT64:
3273 case SD_BUS_TYPE_UINT64:
3274 case SD_BUS_TYPE_DOUBLE:
3276 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3279 case SD_BUS_TYPE_UNIX_FD: {
3282 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3287 *(int*) p = m->fds[j];
3293 assert_not_reached("unexpected type");
3297 r = container_next_item(m, c, &rindex);
3304 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3308 r = message_peek_body(m, &rindex, 4, 4, &q);
3312 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3313 r = message_peek_body(m, &rindex, 1, l+1, &q);
3317 if (type == SD_BUS_TYPE_OBJECT_PATH)
3318 ok = validate_object_path(q, l);
3320 ok = validate_string(q, l);
3325 *(const char**) p = q;
3327 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3330 r = message_peek_body(m, &rindex, 1, 1, &q);
3335 r = message_peek_body(m, &rindex, 1, l+1, &q);
3339 if (!validate_signature(q, l))
3343 *(const char**) p = q;
3348 align = bus_type_get_alignment(type);
3351 sz = bus_type_get_size(type);
3354 r = message_peek_body(m, &rindex, align, sz, &q);
3360 case SD_BUS_TYPE_BYTE:
3362 *(uint8_t*) p = *(uint8_t*) q;
3365 case SD_BUS_TYPE_BOOLEAN:
3367 *(int*) p = !!*(uint32_t*) q;
3370 case SD_BUS_TYPE_INT16:
3371 case SD_BUS_TYPE_UINT16:
3373 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3376 case SD_BUS_TYPE_INT32:
3377 case SD_BUS_TYPE_UINT32:
3379 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3382 case SD_BUS_TYPE_INT64:
3383 case SD_BUS_TYPE_UINT64:
3384 case SD_BUS_TYPE_DOUBLE:
3386 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3389 case SD_BUS_TYPE_UNIX_FD: {
3392 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3397 *(int*) p = m->fds[j];
3402 assert_not_reached("Unknown basic type...");
3409 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3415 static int bus_message_enter_array(
3417 struct bus_container *c,
3418 const char *contents,
3419 uint32_t **array_size,
3422 size_t *n_offsets) {
3436 if (!signature_is_single(contents, true))
3439 if (!c->signature || c->signature[c->index] == 0)
3442 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3445 if (!startswith(c->signature + c->index + 1, contents))
3450 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3453 r = message_peek_body(m, &rindex, 4, 4, &q);
3457 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3460 alignment = bus_type_get_alignment(contents[0]);
3464 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3468 *array_size = (uint32_t*) q;
3470 } else if (c->item_size <= 0) {
3472 /* gvariant: empty array */
3477 } else if (bus_gvariant_is_fixed_size(contents)) {
3479 /* gvariant: fixed length array */
3480 *item_size = bus_gvariant_get_size(contents);
3485 size_t where, p = 0, framing, sz;
3488 /* gvariant: variable length array */
3489 sz = determine_word_size(c->item_size, 0);
3491 where = rindex + c->item_size - sz;
3492 r = message_peek_body(m, &where, 1, sz, &q);
3496 framing = read_word_le(q, sz);
3497 if (framing > c->item_size - sz)
3499 if ((c->item_size - framing) % sz != 0)
3502 *n_offsets = (c->item_size - framing) / sz;
3504 where = rindex + framing;
3505 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3509 *offsets = new(size_t, *n_offsets);
3513 for (i = 0; i < *n_offsets; i++) {
3516 x = read_word_le((uint8_t*) q + i * sz, sz);
3517 if (x > c->item_size - sz)
3522 (*offsets)[i] = rindex + x;
3526 *item_size = (*offsets)[0] - rindex;
3531 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3532 c->index += 1 + strlen(contents);
3537 static int bus_message_enter_variant(
3539 struct bus_container *c,
3540 const char *contents,
3541 size_t *item_size) {
3553 if (!signature_is_single(contents, false))
3556 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3559 if (!c->signature || c->signature[c->index] == 0)
3562 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3567 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3570 k = strlen(contents);
3571 if (1+k > c->item_size)
3574 where = rindex + c->item_size - (1+k);
3575 r = message_peek_body(m, &where, 1, 1+k, &q);
3579 if (*(char*) q != 0)
3582 if (memcmp((uint8_t*) q+1, contents, k))
3585 *item_size = c->item_size - (1+k);
3588 r = message_peek_body(m, &rindex, 1, 1, &q);
3593 r = message_peek_body(m, &rindex, 1, l+1, &q);
3597 if (!validate_signature(q, l))
3600 if (!streq(q, contents))
3606 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3612 static int build_struct_offsets(
3614 const char *signature,
3618 size_t *n_offsets) {
3620 unsigned n_variable = 0, n_total = 0, v;
3621 size_t previous = 0, where;
3632 if (isempty(signature)) {
3639 sz = determine_word_size(size, 0);
3643 /* First, loop over signature and count variable elements and
3644 * elements in general. We use this to know how large the
3645 * offset array is at the end of the structure. Note that
3646 * GVariant only stores offsets for all variable size elements
3647 * that are not the last item. */
3653 r = signature_element_length(p, &n);
3662 r = bus_gvariant_is_fixed_size(t);
3667 if (r == 0 && p[n] != 0) /* except the last item */
3674 if (size < n_variable * sz)
3677 where = m->rindex + size - (n_variable * sz);
3678 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3684 *offsets = new(size_t, n_total);
3690 /* Second, loop again and build an offset table */
3696 r = signature_element_length(p, &n);
3705 k = bus_gvariant_get_size(t);
3713 x = read_word_le((uint8_t*) q + v*sz, sz);
3716 if (m->rindex + x < previous)
3719 /* The last item's end
3720 * is determined from
3723 x = size - (n_variable * sz);
3725 offset = m->rindex + x;
3731 align = bus_gvariant_get_alignment(t);
3734 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3738 previous = (*offsets)[(*n_offsets)++] = offset;
3743 assert(*n_offsets == n_total);
3745 *item_size = (*offsets)[0] - m->rindex;
3749 static int enter_struct_or_dict_entry(
3751 struct bus_container *c,
3752 const char *contents,
3755 size_t *n_offsets) {
3766 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3769 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3773 } else if (c->item_size <= 0) {
3775 /* gvariant empty struct */
3780 /* gvariant with contents */
3781 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3786 static int bus_message_enter_struct(
3788 struct bus_container *c,
3789 const char *contents,
3792 size_t *n_offsets) {
3804 if (!signature_is_valid(contents, false))
3807 if (!c->signature || c->signature[c->index] == 0)
3810 l = strlen(contents);
3812 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3813 !startswith(c->signature + c->index + 1, contents) ||
3814 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3817 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3821 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3822 c->index += 1 + l + 1;
3827 static int bus_message_enter_dict_entry(
3829 struct bus_container *c,
3830 const char *contents,
3833 size_t *n_offsets) {
3842 if (!signature_is_pair(contents))
3845 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3848 if (!c->signature || c->signature[c->index] == 0)
3851 l = strlen(contents);
3853 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3854 !startswith(c->signature + c->index + 1, contents) ||
3855 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3858 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3862 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3863 c->index += 1 + l + 1;
3868 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3870 const char *contents) {
3871 struct bus_container *c, *w;
3872 uint32_t *array_size = NULL;
3875 size_t *offsets = NULL;
3876 size_t n_offsets = 0, item_size = 0;
3879 assert_return(m, -EINVAL);
3880 assert_return(m->sealed, -EPERM);
3881 assert_return(type != 0 || !contents, -EINVAL);
3883 if (type == 0 || !contents) {
3887 /* Allow entering into anonymous containers */
3888 r = sd_bus_message_peek_type(m, &tt, &cc);
3892 if (type != 0 && type != tt)
3895 if (contents && !streq(contents, cc))
3903 * We enforce a global limit on container depth, that is much
3904 * higher than the 32 structs and 32 arrays the specification
3905 * mandates. This is simpler to implement for us, and we need
3906 * this only to ensure our container array doesn't grow
3907 * without bounds. We are happy to return any data from a
3908 * message as long as the data itself is valid, even if the
3909 * overall message might be not.
3911 * Note that the message signature is validated when
3912 * parsing the headers, and that validation does check the
3915 * Note that the specification defines no limits on the depth
3916 * of stacked variants, but we do.
3918 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3921 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3924 if (message_end_of_signature(m))
3927 if (message_end_of_array(m, m->rindex))
3930 c = message_get_container(m);
3932 signature = strdup(contents);
3936 c->saved_index = c->index;
3939 if (type == SD_BUS_TYPE_ARRAY)
3940 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3941 else if (type == SD_BUS_TYPE_VARIANT)
3942 r = bus_message_enter_variant(m, c, contents, &item_size);
3943 else if (type == SD_BUS_TYPE_STRUCT)
3944 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3945 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3946 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3956 /* OK, let's fill it in */
3957 w = m->containers + m->n_containers++;
3958 w->enclosing = type;
3959 w->signature = signature;
3960 w->peeked_signature = NULL;
3964 w->begin = m->rindex;
3965 w->end = m->rindex + c->item_size;
3967 w->array_size = array_size;
3968 w->item_size = item_size;
3969 w->offsets = offsets;
3970 w->n_offsets = n_offsets;
3971 w->offset_index = 0;
3976 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3977 struct bus_container *c;
3981 assert_return(m, -EINVAL);
3982 assert_return(m->sealed, -EPERM);
3983 assert_return(m->n_containers > 0, -ENXIO);
3985 c = message_get_container(m);
3987 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3988 if (c->signature && c->signature[c->index] != 0)
3992 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3993 if (m->rindex < c->end)
3996 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3999 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4000 if (c->begin + l != m->rindex)
4005 free(c->peeked_signature);
4009 c = message_get_container(m);
4012 c->index = c->saved_index;
4013 r = container_next_item(m, c, &m->rindex);
4021 static void message_quit_container(sd_bus_message *m) {
4022 struct bus_container *c;
4026 assert(m->n_containers > 0);
4028 c = message_get_container(m);
4031 assert(m->rindex >= c->before);
4032 m->rindex = c->before;
4034 /* Free container */
4039 /* Correct index of new top-level container */
4040 c = message_get_container(m);
4041 c->index = c->saved_index;
4044 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4045 struct bus_container *c;
4048 assert_return(m, -EINVAL);
4049 assert_return(m->sealed, -EPERM);
4051 if (message_end_of_signature(m))
4054 if (message_end_of_array(m, m->rindex))
4057 c = message_get_container(m);
4059 if (bus_type_is_basic(c->signature[c->index])) {
4063 *type = c->signature[c->index];
4067 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4073 r = signature_element_length(c->signature+c->index+1, &l);
4079 sig = strndup(c->signature + c->index + 1, l);
4083 free(c->peeked_signature);
4084 *contents = c->peeked_signature = sig;
4088 *type = SD_BUS_TYPE_ARRAY;
4093 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4094 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4100 r = signature_element_length(c->signature+c->index, &l);
4105 sig = strndup(c->signature + c->index + 1, l - 2);
4109 free(c->peeked_signature);
4110 *contents = c->peeked_signature = sig;
4114 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4119 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4123 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4126 if (c->item_size < 2)
4129 /* Look for the NUL delimiter that
4130 separates the payload from the
4131 signature. Since the body might be
4132 in a different part that then the
4133 signature we map byte by byte. */
4135 for (k = 2; k <= c->item_size; k++) {
4138 where = m->rindex + c->item_size - k;
4139 r = message_peek_body(m, &where, 1, k, &q);
4143 if (*(char*) q == 0)
4147 if (k > c->item_size)
4150 free(c->peeked_signature);
4151 c->peeked_signature = strndup((char*) q + 1, k - 1);
4152 if (!c->peeked_signature)
4155 if (!signature_is_valid(c->peeked_signature, true))
4158 *contents = c->peeked_signature;
4163 r = message_peek_body(m, &rindex, 1, 1, &q);
4168 r = message_peek_body(m, &rindex, 1, l+1, &q);
4172 if (!validate_signature(q, l))
4180 *type = SD_BUS_TYPE_VARIANT;
4195 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4196 struct bus_container *c;
4198 assert_return(m, -EINVAL);
4199 assert_return(m->sealed, -EPERM);
4202 message_reset_containers(m);
4205 c = message_get_container(m);
4207 c = message_get_container(m);
4209 c->offset_index = 0;
4211 m->rindex = c->begin;
4214 c->offset_index = 0;
4215 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4217 return !isempty(c->signature);
4220 static int message_read_ap(
4225 unsigned n_array, n_struct;
4226 TypeStack stack[BUS_CONTAINER_DEPTH];
4227 unsigned stack_ptr = 0;
4228 unsigned n_loop = 0;
4236 /* Ideally, we'd just call ourselves recursively on every
4237 * complex type. However, the state of a va_list that is
4238 * passed to a function is undefined after that function
4239 * returns. This means we need to docode the va_list linearly
4240 * in a single stackframe. We hence implement our own
4241 * home-grown stack in an array. */
4243 n_array = (unsigned) -1; /* length of current array entries */
4244 n_struct = strlen(types); /* length of current struct contents signature */
4251 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4252 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4258 r = sd_bus_message_exit_container(m);
4266 if (n_array != (unsigned) -1)
4275 case SD_BUS_TYPE_BYTE:
4276 case SD_BUS_TYPE_BOOLEAN:
4277 case SD_BUS_TYPE_INT16:
4278 case SD_BUS_TYPE_UINT16:
4279 case SD_BUS_TYPE_INT32:
4280 case SD_BUS_TYPE_UINT32:
4281 case SD_BUS_TYPE_INT64:
4282 case SD_BUS_TYPE_UINT64:
4283 case SD_BUS_TYPE_DOUBLE:
4284 case SD_BUS_TYPE_STRING:
4285 case SD_BUS_TYPE_OBJECT_PATH:
4286 case SD_BUS_TYPE_SIGNATURE:
4287 case SD_BUS_TYPE_UNIX_FD: {
4290 p = va_arg(ap, void*);
4291 r = sd_bus_message_read_basic(m, *t, p);
4304 case SD_BUS_TYPE_ARRAY: {
4307 r = signature_element_length(t + 1, &k);
4313 memcpy(s, t + 1, k);
4316 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4327 if (n_array == (unsigned) -1) {
4332 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4338 n_array = va_arg(ap, unsigned);
4343 case SD_BUS_TYPE_VARIANT: {
4346 s = va_arg(ap, const char *);
4350 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4360 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4365 n_struct = strlen(s);
4366 n_array = (unsigned) -1;
4371 case SD_BUS_TYPE_STRUCT_BEGIN:
4372 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4375 r = signature_element_length(t, &k);
4381 memcpy(s, t + 1, k - 2);
4384 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4394 if (n_array == (unsigned) -1) {
4399 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4405 n_array = (unsigned) -1;
4418 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4422 assert_return(m, -EINVAL);
4423 assert_return(m->sealed, -EPERM);
4424 assert_return(types, -EINVAL);
4426 va_start(ap, types);
4427 r = message_read_ap(m, types, ap);
4433 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4436 assert_return(m, -EINVAL);
4437 assert_return(m->sealed, -EPERM);
4438 assert_return(types, -EINVAL);
4445 case SD_BUS_TYPE_BYTE:
4446 case SD_BUS_TYPE_BOOLEAN:
4447 case SD_BUS_TYPE_INT16:
4448 case SD_BUS_TYPE_UINT16:
4449 case SD_BUS_TYPE_INT32:
4450 case SD_BUS_TYPE_UINT32:
4451 case SD_BUS_TYPE_INT64:
4452 case SD_BUS_TYPE_UINT64:
4453 case SD_BUS_TYPE_DOUBLE:
4454 case SD_BUS_TYPE_STRING:
4455 case SD_BUS_TYPE_OBJECT_PATH:
4456 case SD_BUS_TYPE_SIGNATURE:
4457 case SD_BUS_TYPE_UNIX_FD:
4459 r = sd_bus_message_read_basic(m, *types, NULL);
4463 r = sd_bus_message_skip(m, types + 1);
4469 case SD_BUS_TYPE_ARRAY: {
4472 r = signature_element_length(types + 1, &k);
4478 memcpy(s, types+1, k);
4481 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4486 r = sd_bus_message_skip(m, s);
4493 r = sd_bus_message_exit_container(m);
4498 r = sd_bus_message_skip(m, types + 1 + k);
4505 case SD_BUS_TYPE_VARIANT: {
4506 const char *contents;
4509 r = sd_bus_message_peek_type(m, &x, &contents);
4513 if (x != SD_BUS_TYPE_VARIANT)
4516 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4520 r = sd_bus_message_skip(m, contents);
4525 r = sd_bus_message_exit_container(m);
4529 r = sd_bus_message_skip(m, types + 1);
4536 case SD_BUS_TYPE_STRUCT_BEGIN:
4537 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4540 r = signature_element_length(types, &k);
4546 memcpy(s, types+1, k-2);
4549 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4553 r = sd_bus_message_skip(m, s);
4558 r = sd_bus_message_exit_container(m);
4563 r = sd_bus_message_skip(m, types + k);
4575 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4579 struct bus_container *c;
4585 assert_return(m, -EINVAL);
4586 assert_return(m->sealed, -EPERM);
4587 assert_return(bus_type_is_trivial(type), -EINVAL);
4588 assert_return(ptr, -EINVAL);
4589 assert_return(size, -EINVAL);
4590 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4592 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4596 c = message_get_container(m);
4598 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4599 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4603 sz = c->end - c->begin;
4605 align = bus_type_get_alignment(type);
4609 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4613 /* Zero length array, let's return some aligned
4614 * pointer that is not NULL */
4615 p = (uint8_t*) NULL + align;
4617 r = message_peek_body(m, &m->rindex, align, sz, &p);
4622 r = sd_bus_message_exit_container(m);
4626 *ptr = (const void*) p;
4632 message_quit_container(m);
4636 static int message_peek_fields(
4647 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4650 static int message_peek_field_uint32(
4662 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4665 /* identical for gvariant and dbus1 */
4667 r = message_peek_fields(m, ri, 4, 4, &q);
4672 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4677 static int message_peek_field_string(
4679 bool (*validate)(const char *p),
4691 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4696 r = message_peek_fields(m, ri, 1, item_size, &q);
4702 r = message_peek_field_uint32(m, ri, 4, &l);
4706 r = message_peek_fields(m, ri, 1, l+1, &q);
4712 if (!validate_nul(q, l))
4718 if (!validate_string(q, l))
4728 static int message_peek_field_signature(
4741 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4746 r = message_peek_fields(m, ri, 1, item_size, &q);
4752 r = message_peek_fields(m, ri, 1, 1, &q);
4757 r = message_peek_fields(m, ri, 1, l+1, &q);
4762 if (!validate_signature(q, l))
4771 static int message_skip_fields(
4774 uint32_t array_size,
4775 const char **signature) {
4777 size_t original_index;
4783 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4785 original_index = *ri;
4791 if (array_size != (uint32_t) -1 &&
4792 array_size <= *ri - original_index)
4799 if (t == SD_BUS_TYPE_STRING) {
4801 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4807 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4809 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4815 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4817 r = message_peek_field_signature(m, ri, 0, NULL);
4823 } else if (bus_type_is_basic(t)) {
4826 align = bus_type_get_alignment(t);
4827 k = bus_type_get_size(t);
4828 assert(align > 0 && k > 0);
4830 r = message_peek_fields(m, ri, align, k, NULL);
4836 } else if (t == SD_BUS_TYPE_ARRAY) {
4838 r = signature_element_length(*signature+1, &l);
4848 strncpy(sig, *signature + 1, l-1);
4851 alignment = bus_type_get_alignment(sig[0]);
4855 r = message_peek_field_uint32(m, ri, 0, &nas);
4858 if (nas > BUS_ARRAY_MAX_SIZE)
4861 r = message_peek_fields(m, ri, alignment, 0, NULL);
4865 r = message_skip_fields(m, ri, nas, (const char**) &s);
4870 (*signature) += 1 + l;
4872 } else if (t == SD_BUS_TYPE_VARIANT) {
4875 r = message_peek_field_signature(m, ri, 0, &s);
4879 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4885 } else if (t == SD_BUS_TYPE_STRUCT ||
4886 t == SD_BUS_TYPE_DICT_ENTRY) {
4888 r = signature_element_length(*signature, &l);
4895 strncpy(sig, *signature + 1, l-1);
4898 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4909 int bus_message_parse_fields(sd_bus_message *m) {
4912 uint32_t unix_fds = 0;
4913 bool unix_fds_set = false;
4914 void *offsets = NULL;
4915 unsigned n_offsets = 0;
4921 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4924 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4928 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4929 r = message_peek_fields(m, &ri, 1, sz, &q);
4933 framing = read_word_le(q, sz);
4934 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4936 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4940 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4944 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4949 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4950 _cleanup_free_ char *sig = NULL;
4951 const char *signature;
4953 size_t item_size = (size_t) -1;
4955 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4962 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4965 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4969 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4974 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4979 where = ri = ALIGN_TO(ri, 8);
4980 item_size = end - ri;
4981 r = message_peek_fields(m, &where, 1, item_size, &q);
4985 b = memrchr(q, 0, item_size);
4989 sig = strndup(b+1, item_size - (b+1-(char*) q));
4994 item_size = b - (char*) q;
4996 r = message_peek_field_signature(m, &ri, 0, &signature);
5002 case _BUS_MESSAGE_HEADER_INVALID:
5005 case BUS_MESSAGE_HEADER_PATH:
5010 if (!streq(signature, "o"))
5013 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5016 case BUS_MESSAGE_HEADER_INTERFACE:
5021 if (!streq(signature, "s"))
5024 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5027 case BUS_MESSAGE_HEADER_MEMBER:
5032 if (!streq(signature, "s"))
5035 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5038 case BUS_MESSAGE_HEADER_ERROR_NAME:
5043 if (!streq(signature, "s"))
5046 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5048 m->error._need_free = -1;
5052 case BUS_MESSAGE_HEADER_DESTINATION:
5057 if (!streq(signature, "s"))
5060 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5063 case BUS_MESSAGE_HEADER_SENDER:
5068 if (!streq(signature, "s"))
5071 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5073 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5074 m->creds.unique_name = (char*) m->sender;
5075 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5081 case BUS_MESSAGE_HEADER_SIGNATURE: {
5085 if (m->root_container.signature)
5088 if (!streq(signature, "g"))
5091 r = message_peek_field_signature(m, &ri, item_size, &s);
5099 free(m->root_container.signature);
5100 m->root_container.signature = c;
5104 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5107 if (m->reply_cookie != 0)
5110 if (!streq(signature, "u"))
5113 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5117 m->reply_cookie = serial;
5119 if (m->reply_cookie == 0)
5125 case BUS_MESSAGE_HEADER_UNIX_FDS:
5129 if (!streq(signature, "u"))
5132 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5136 unix_fds_set = true;
5140 if (!BUS_MESSAGE_IS_GVARIANT(m))
5141 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5150 if (m->n_fds != unix_fds)
5153 switch (m->header->type) {
5155 case SD_BUS_MESSAGE_SIGNAL:
5156 if (!m->path || !m->interface || !m->member)
5160 case SD_BUS_MESSAGE_METHOD_CALL:
5162 if (!m->path || !m->member)
5167 case SD_BUS_MESSAGE_METHOD_RETURN:
5169 if (m->reply_cookie == 0)
5173 case SD_BUS_MESSAGE_METHOD_ERROR:
5175 if (m->reply_cookie == 0 || !m->error.name)
5180 /* Refuse non-local messages that claim they are local */
5181 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5183 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5185 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5188 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5190 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5191 r = build_struct_offsets(
5193 m->root_container.signature,
5194 BUS_MESSAGE_BODY_SIZE(m),
5195 &m->root_container.item_size,
5196 &m->root_container.offsets,
5197 &m->root_container.n_offsets);
5202 /* Try to read the error message, but if we can't it's a non-issue */
5203 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5204 sd_bus_message_read(m, "s", &m->error.message);
5209 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5210 assert_return(m, -EINVAL);
5211 assert_return(destination, -EINVAL);
5212 assert_return(!m->sealed, -EPERM);
5213 assert_return(!m->destination, -EEXIST);
5215 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5218 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5222 struct bus_body_part *part;
5228 total = BUS_MESSAGE_SIZE(m);
5234 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5235 MESSAGE_FOREACH_PART(part, i, m)
5236 e = mempcpy(e, part->data, part->size);
5238 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5246 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5252 r = sd_bus_message_enter_container(m, 'a', "s");
5259 r = sd_bus_message_read_basic(m, 's', &s);
5265 r = strv_extend(l, s);
5270 r = sd_bus_message_exit_container(m);
5277 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5281 assert_return(m, -EINVAL);
5282 assert_return(m->sealed, -EPERM);
5283 assert_return(l, -EINVAL);
5285 r = bus_message_read_strv_extend(m, &strv);
5295 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5297 const char *t = NULL;
5302 r = sd_bus_message_rewind(m, true);
5306 for (j = 0; j <= i; j++) {
5309 r = sd_bus_message_peek_type(m, &type, NULL);
5313 if (type != SD_BUS_TYPE_STRING &&
5314 type != SD_BUS_TYPE_OBJECT_PATH &&
5315 type != SD_BUS_TYPE_SIGNATURE)
5318 r = sd_bus_message_read_basic(m, type, &t);
5326 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5332 if (size < sizeof(struct bus_header))
5335 full = sizeof(struct bus_header) +
5336 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5338 return size >= full;
5341 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5347 if (h->endian == BUS_NATIVE_ENDIAN) {
5348 fs = h->fields_size;
5350 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5351 fs = bswap_32(h->fields_size);
5352 bs = bswap_32(h->body_size);
5356 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5360 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5361 assert_return(m, EINVAL);
5363 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5366 return sd_bus_error_get_errno(&m->error);
5369 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5370 struct bus_container *c;
5372 assert_return(m, NULL);
5374 c = complete ? &m->root_container : message_get_container(m);
5375 return strempty(c->signature);
5378 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5379 bool done_something = false;
5382 assert_return(m, -EINVAL);
5383 assert_return(source, -EINVAL);
5384 assert_return(!m->sealed, -EPERM);
5385 assert_return(source->sealed, -EPERM);
5388 const char *contents;
5403 r = sd_bus_message_peek_type(source, &type, &contents);
5409 done_something = true;
5411 if (bus_type_is_container(type) > 0) {
5413 r = sd_bus_message_enter_container(source, type, contents);
5417 r = sd_bus_message_open_container(m, type, contents);
5421 r = sd_bus_message_copy(m, source, true);
5425 r = sd_bus_message_close_container(m);
5429 r = sd_bus_message_exit_container(source);
5436 r = sd_bus_message_read_basic(source, type, &basic);
5442 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5443 type == SD_BUS_TYPE_SIGNATURE ||
5444 type == SD_BUS_TYPE_STRING)
5445 r = sd_bus_message_append_basic(m, type, basic.string);
5447 r = sd_bus_message_append_basic(m, type, &basic);
5454 return done_something;
5457 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5462 assert_return(m, -EINVAL);
5463 assert_return(m->sealed, -EPERM);
5464 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5465 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5466 assert_return(type || contents, -EINVAL);
5467 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5469 r = sd_bus_message_peek_type(m, &t, &c);
5473 if (type != 0 && type != t)
5476 if (contents && !streq_ptr(contents, c))
5482 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5483 assert_return(m, NULL);
5488 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5489 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5497 switch ((*m)->header->type) {
5499 case SD_BUS_MESSAGE_SIGNAL:
5500 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5506 case SD_BUS_MESSAGE_METHOD_CALL:
5507 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5513 case SD_BUS_MESSAGE_METHOD_RETURN:
5514 case SD_BUS_MESSAGE_METHOD_ERROR:
5516 n = message_new(bus, (*m)->header->type);
5520 n->reply_cookie = (*m)->reply_cookie;
5521 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5525 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5526 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5530 n->error._need_free = -1;
5539 if ((*m)->destination && !n->destination) {
5540 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5545 if ((*m)->sender && !n->sender) {
5546 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5551 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5553 r = sd_bus_message_copy(n, *m, true);
5557 timeout = (*m)->timeout;
5558 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5559 timeout = BUS_DEFAULT_TIMEOUT;
5561 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5565 sd_bus_message_unref(*m);
5572 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5576 assert_return(!m->sealed, -EPERM);
5577 assert_return(!m->sender, -EPERM);
5579 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5582 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5583 assert_return(m, -EINVAL);
5584 assert_return(priority, -EINVAL);
5586 *priority = m->priority;
5590 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5591 assert_return(m, -EINVAL);
5592 assert_return(!m->sealed, -EPERM);
5594 m->priority = priority;