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"
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 = ftruncate(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 if (ftruncate(part->memfd, sz) < 0)
2826 /* Finally, try to seal */
2827 if (fcntl(part->memfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE) >= 0)
2828 part->sealed = true;
2832 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2833 m->root_container.index = 0;
2834 m->root_container.offset_index = 0;
2835 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2842 int bus_body_part_map(struct bus_body_part *part) {
2851 if (part->size <= 0)
2854 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2855 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2856 static const uint8_t zeroes[7] = { };
2857 part->data = (void*) zeroes;
2861 psz = PAGE_ALIGN(part->size);
2863 if (part->memfd >= 0)
2864 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, 0);
2865 else if (part->is_zero)
2866 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2870 if (p == MAP_FAILED)
2875 part->munmap_this = true;
2880 void bus_body_part_unmap(struct bus_body_part *part) {
2884 if (part->memfd < 0)
2890 if (!part->munmap_this)
2893 assert_se(munmap(part->data, part->mapped) == 0);
2897 part->munmap_this = false;
2902 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2903 size_t k, start, end;
2908 start = ALIGN_TO((size_t) *rindex, align);
2909 end = start + nbytes;
2914 /* Verify that padding is 0 */
2915 for (k = *rindex; k < start; k++)
2916 if (((const uint8_t*) p)[k] != 0)
2920 *r = (uint8_t*) p + start;
2927 static bool message_end_of_signature(sd_bus_message *m) {
2928 struct bus_container *c;
2932 c = message_get_container(m);
2933 return !c->signature || c->signature[c->index] == 0;
2936 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2937 struct bus_container *c;
2941 c = message_get_container(m);
2942 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2945 if (BUS_MESSAGE_IS_GVARIANT(m))
2946 return index >= c->end;
2948 assert(c->array_size);
2949 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2953 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2954 assert_return(m, -EINVAL);
2955 assert_return(m->sealed, -EPERM);
2957 if (complete && m->n_containers > 0)
2960 if (message_end_of_signature(m))
2963 if (message_end_of_array(m, m->rindex))
2969 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2970 struct bus_body_part *part;
2976 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2977 part = m->cached_rindex_part;
2978 begin = m->cached_rindex_part_begin;
2988 if (index + sz <= begin + part->size) {
2990 r = bus_body_part_map(part);
2995 *p = (uint8_t*) part->data + index - begin;
2997 m->cached_rindex_part = part;
2998 m->cached_rindex_part_begin = begin;
3003 begin += part->size;
3010 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3017 if (!BUS_MESSAGE_IS_GVARIANT(m))
3020 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3023 sz = bus_gvariant_get_size(c->signature);
3027 if (c->offset_index+1 >= c->n_offsets)
3030 /* Variable-size array */
3032 alignment = bus_gvariant_get_alignment(c->signature);
3033 assert(alignment > 0);
3035 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3036 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3039 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3042 /* Fixed-size array */
3043 *rindex = c->begin + (c->offset_index+1) * sz;
3049 } else if (c->enclosing == 0 ||
3050 c->enclosing == SD_BUS_TYPE_STRUCT ||
3051 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3056 if (c->offset_index+1 >= c->n_offsets)
3059 r = signature_element_length(c->signature + c->index, &n);
3063 r = signature_element_length(c->signature + c->index + n, &j);
3068 memcpy(t, c->signature + c->index + n, j);
3071 alignment = bus_gvariant_get_alignment(t);
3074 assert(alignment > 0);
3076 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3077 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3081 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3084 assert_not_reached("Unknown container type");
3089 /* Reached the end */
3096 static int message_peek_body(
3103 size_t k, start, end, padding;
3104 struct bus_body_part *part;
3111 start = ALIGN_TO((size_t) *rindex, align);
3112 padding = start - *rindex;
3113 end = start + nbytes;
3115 if (end > BUS_MESSAGE_BODY_SIZE(m))
3118 part = find_part(m, *rindex, padding, (void**) &q);
3123 /* Verify padding */
3124 for (k = 0; k < padding; k++)
3129 part = find_part(m, start, nbytes, (void**) &q);
3130 if (!part || (nbytes > 0 && !q))
3141 static bool validate_nul(const char *s, size_t l) {
3143 /* Check for NUL chars in the string */
3144 if (memchr(s, 0, l))
3147 /* Check for NUL termination */
3154 static bool validate_string(const char *s, size_t l) {
3156 if (!validate_nul(s, l))
3159 /* Check if valid UTF8 */
3160 if (!utf8_is_valid(s))
3166 static bool validate_signature(const char *s, size_t l) {
3168 if (!validate_nul(s, l))
3171 /* Check if valid signature */
3172 if (!signature_is_valid(s, true))
3178 static bool validate_object_path(const char *s, size_t l) {
3180 if (!validate_nul(s, l))
3183 if (!object_path_is_valid(s))
3189 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3190 struct bus_container *c;
3195 assert_return(m, -EINVAL);
3196 assert_return(m->sealed, -EPERM);
3197 assert_return(bus_type_is_basic(type), -EINVAL);
3199 if (message_end_of_signature(m))
3202 if (message_end_of_array(m, m->rindex))
3205 c = message_get_container(m);
3206 if (c->signature[c->index] != type)
3211 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3213 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3216 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3220 if (type == SD_BUS_TYPE_STRING)
3221 ok = validate_string(q, c->item_size-1);
3222 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3223 ok = validate_object_path(q, c->item_size-1);
3225 ok = validate_signature(q, c->item_size-1);
3231 *(const char**) p = q;
3235 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3237 if ((size_t) sz != c->item_size)
3240 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3243 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3249 case SD_BUS_TYPE_BYTE:
3251 *(uint8_t*) p = *(uint8_t*) q;
3254 case SD_BUS_TYPE_BOOLEAN:
3256 *(int*) p = !!*(uint8_t*) q;
3259 case SD_BUS_TYPE_INT16:
3260 case SD_BUS_TYPE_UINT16:
3262 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3265 case SD_BUS_TYPE_INT32:
3266 case SD_BUS_TYPE_UINT32:
3268 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3271 case SD_BUS_TYPE_INT64:
3272 case SD_BUS_TYPE_UINT64:
3273 case SD_BUS_TYPE_DOUBLE:
3275 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3278 case SD_BUS_TYPE_UNIX_FD: {
3281 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3286 *(int*) p = m->fds[j];
3292 assert_not_reached("unexpected type");
3296 r = container_next_item(m, c, &rindex);
3303 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3307 r = message_peek_body(m, &rindex, 4, 4, &q);
3311 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3312 r = message_peek_body(m, &rindex, 1, l+1, &q);
3316 if (type == SD_BUS_TYPE_OBJECT_PATH)
3317 ok = validate_object_path(q, l);
3319 ok = validate_string(q, l);
3324 *(const char**) p = q;
3326 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3329 r = message_peek_body(m, &rindex, 1, 1, &q);
3334 r = message_peek_body(m, &rindex, 1, l+1, &q);
3338 if (!validate_signature(q, l))
3342 *(const char**) p = q;
3347 align = bus_type_get_alignment(type);
3350 sz = bus_type_get_size(type);
3353 r = message_peek_body(m, &rindex, align, sz, &q);
3359 case SD_BUS_TYPE_BYTE:
3361 *(uint8_t*) p = *(uint8_t*) q;
3364 case SD_BUS_TYPE_BOOLEAN:
3366 *(int*) p = !!*(uint32_t*) q;
3369 case SD_BUS_TYPE_INT16:
3370 case SD_BUS_TYPE_UINT16:
3372 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3375 case SD_BUS_TYPE_INT32:
3376 case SD_BUS_TYPE_UINT32:
3378 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3381 case SD_BUS_TYPE_INT64:
3382 case SD_BUS_TYPE_UINT64:
3383 case SD_BUS_TYPE_DOUBLE:
3385 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3388 case SD_BUS_TYPE_UNIX_FD: {
3391 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3396 *(int*) p = m->fds[j];
3401 assert_not_reached("Unknown basic type...");
3408 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3414 static int bus_message_enter_array(
3416 struct bus_container *c,
3417 const char *contents,
3418 uint32_t **array_size,
3421 size_t *n_offsets) {
3435 if (!signature_is_single(contents, true))
3438 if (!c->signature || c->signature[c->index] == 0)
3441 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3444 if (!startswith(c->signature + c->index + 1, contents))
3449 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3452 r = message_peek_body(m, &rindex, 4, 4, &q);
3456 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3459 alignment = bus_type_get_alignment(contents[0]);
3463 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3467 *array_size = (uint32_t*) q;
3469 } else if (c->item_size <= 0) {
3471 /* gvariant: empty array */
3476 } else if (bus_gvariant_is_fixed_size(contents)) {
3478 /* gvariant: fixed length array */
3479 *item_size = bus_gvariant_get_size(contents);
3484 size_t where, p = 0, framing, sz;
3487 /* gvariant: variable length array */
3488 sz = determine_word_size(c->item_size, 0);
3490 where = rindex + c->item_size - sz;
3491 r = message_peek_body(m, &where, 1, sz, &q);
3495 framing = read_word_le(q, sz);
3496 if (framing > c->item_size - sz)
3498 if ((c->item_size - framing) % sz != 0)
3501 *n_offsets = (c->item_size - framing) / sz;
3503 where = rindex + framing;
3504 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3508 *offsets = new(size_t, *n_offsets);
3512 for (i = 0; i < *n_offsets; i++) {
3515 x = read_word_le((uint8_t*) q + i * sz, sz);
3516 if (x > c->item_size - sz)
3521 (*offsets)[i] = rindex + x;
3525 *item_size = (*offsets)[0] - rindex;
3530 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3531 c->index += 1 + strlen(contents);
3536 static int bus_message_enter_variant(
3538 struct bus_container *c,
3539 const char *contents,
3540 size_t *item_size) {
3552 if (!signature_is_single(contents, false))
3555 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3558 if (!c->signature || c->signature[c->index] == 0)
3561 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3566 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3569 k = strlen(contents);
3570 if (1+k > c->item_size)
3573 where = rindex + c->item_size - (1+k);
3574 r = message_peek_body(m, &where, 1, 1+k, &q);
3578 if (*(char*) q != 0)
3581 if (memcmp((uint8_t*) q+1, contents, k))
3584 *item_size = c->item_size - (1+k);
3587 r = message_peek_body(m, &rindex, 1, 1, &q);
3592 r = message_peek_body(m, &rindex, 1, l+1, &q);
3596 if (!validate_signature(q, l))
3599 if (!streq(q, contents))
3605 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3611 static int build_struct_offsets(
3613 const char *signature,
3617 size_t *n_offsets) {
3619 unsigned n_variable = 0, n_total = 0, v;
3620 size_t previous = 0, where;
3631 if (isempty(signature)) {
3638 sz = determine_word_size(size, 0);
3642 /* First, loop over signature and count variable elements and
3643 * elements in general. We use this to know how large the
3644 * offset array is at the end of the structure. Note that
3645 * GVariant only stores offsets for all variable size elements
3646 * that are not the last item. */
3652 r = signature_element_length(p, &n);
3661 r = bus_gvariant_is_fixed_size(t);
3666 if (r == 0 && p[n] != 0) /* except the last item */
3673 if (size < n_variable * sz)
3676 where = m->rindex + size - (n_variable * sz);
3677 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3683 *offsets = new(size_t, n_total);
3689 /* Second, loop again and build an offset table */
3695 r = signature_element_length(p, &n);
3704 k = bus_gvariant_get_size(t);
3712 x = read_word_le((uint8_t*) q + v*sz, sz);
3715 if (m->rindex + x < previous)
3718 /* The last item's end
3719 * is determined from
3722 x = size - (n_variable * sz);
3724 offset = m->rindex + x;
3730 align = bus_gvariant_get_alignment(t);
3733 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3737 previous = (*offsets)[(*n_offsets)++] = offset;
3742 assert(*n_offsets == n_total);
3744 *item_size = (*offsets)[0] - m->rindex;
3748 static int enter_struct_or_dict_entry(
3750 struct bus_container *c,
3751 const char *contents,
3754 size_t *n_offsets) {
3765 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3768 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3772 } else if (c->item_size <= 0) {
3774 /* gvariant empty struct */
3779 /* gvariant with contents */
3780 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3785 static int bus_message_enter_struct(
3787 struct bus_container *c,
3788 const char *contents,
3791 size_t *n_offsets) {
3803 if (!signature_is_valid(contents, false))
3806 if (!c->signature || c->signature[c->index] == 0)
3809 l = strlen(contents);
3811 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3812 !startswith(c->signature + c->index + 1, contents) ||
3813 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3816 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3820 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3821 c->index += 1 + l + 1;
3826 static int bus_message_enter_dict_entry(
3828 struct bus_container *c,
3829 const char *contents,
3832 size_t *n_offsets) {
3841 if (!signature_is_pair(contents))
3844 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3847 if (!c->signature || c->signature[c->index] == 0)
3850 l = strlen(contents);
3852 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3853 !startswith(c->signature + c->index + 1, contents) ||
3854 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3857 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3861 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3862 c->index += 1 + l + 1;
3867 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3869 const char *contents) {
3870 struct bus_container *c, *w;
3871 uint32_t *array_size = NULL;
3874 size_t *offsets = NULL;
3875 size_t n_offsets = 0, item_size = 0;
3878 assert_return(m, -EINVAL);
3879 assert_return(m->sealed, -EPERM);
3880 assert_return(type != 0 || !contents, -EINVAL);
3882 if (type == 0 || !contents) {
3886 /* Allow entering into anonymous containers */
3887 r = sd_bus_message_peek_type(m, &tt, &cc);
3891 if (type != 0 && type != tt)
3894 if (contents && !streq(contents, cc))
3902 * We enforce a global limit on container depth, that is much
3903 * higher than the 32 structs and 32 arrays the specification
3904 * mandates. This is simpler to implement for us, and we need
3905 * this only to ensure our container array doesn't grow
3906 * without bounds. We are happy to return any data from a
3907 * message as long as the data itself is valid, even if the
3908 * overall message might be not.
3910 * Note that the message signature is validated when
3911 * parsing the headers, and that validation does check the
3914 * Note that the specification defines no limits on the depth
3915 * of stacked variants, but we do.
3917 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3920 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3923 if (message_end_of_signature(m))
3926 if (message_end_of_array(m, m->rindex))
3929 c = message_get_container(m);
3931 signature = strdup(contents);
3935 c->saved_index = c->index;
3938 if (type == SD_BUS_TYPE_ARRAY)
3939 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3940 else if (type == SD_BUS_TYPE_VARIANT)
3941 r = bus_message_enter_variant(m, c, contents, &item_size);
3942 else if (type == SD_BUS_TYPE_STRUCT)
3943 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3944 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3945 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3955 /* OK, let's fill it in */
3956 w = m->containers + m->n_containers++;
3957 w->enclosing = type;
3958 w->signature = signature;
3959 w->peeked_signature = NULL;
3963 w->begin = m->rindex;
3964 w->end = m->rindex + c->item_size;
3966 w->array_size = array_size;
3967 w->item_size = item_size;
3968 w->offsets = offsets;
3969 w->n_offsets = n_offsets;
3970 w->offset_index = 0;
3975 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3976 struct bus_container *c;
3980 assert_return(m, -EINVAL);
3981 assert_return(m->sealed, -EPERM);
3982 assert_return(m->n_containers > 0, -ENXIO);
3984 c = message_get_container(m);
3986 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3987 if (c->signature && c->signature[c->index] != 0)
3991 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3992 if (m->rindex < c->end)
3995 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3998 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3999 if (c->begin + l != m->rindex)
4004 free(c->peeked_signature);
4008 c = message_get_container(m);
4011 c->index = c->saved_index;
4012 r = container_next_item(m, c, &m->rindex);
4020 static void message_quit_container(sd_bus_message *m) {
4021 struct bus_container *c;
4025 assert(m->n_containers > 0);
4027 c = message_get_container(m);
4030 assert(m->rindex >= c->before);
4031 m->rindex = c->before;
4033 /* Free container */
4038 /* Correct index of new top-level container */
4039 c = message_get_container(m);
4040 c->index = c->saved_index;
4043 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4044 struct bus_container *c;
4047 assert_return(m, -EINVAL);
4048 assert_return(m->sealed, -EPERM);
4050 if (message_end_of_signature(m))
4053 if (message_end_of_array(m, m->rindex))
4056 c = message_get_container(m);
4058 if (bus_type_is_basic(c->signature[c->index])) {
4062 *type = c->signature[c->index];
4066 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4072 r = signature_element_length(c->signature+c->index+1, &l);
4078 sig = strndup(c->signature + c->index + 1, l);
4082 free(c->peeked_signature);
4083 *contents = c->peeked_signature = sig;
4087 *type = SD_BUS_TYPE_ARRAY;
4092 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4093 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4099 r = signature_element_length(c->signature+c->index, &l);
4104 sig = strndup(c->signature + c->index + 1, l - 2);
4108 free(c->peeked_signature);
4109 *contents = c->peeked_signature = sig;
4113 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4118 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4122 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4125 if (c->item_size < 2)
4128 /* Look for the NUL delimiter that
4129 separates the payload from the
4130 signature. Since the body might be
4131 in a different part that then the
4132 signature we map byte by byte. */
4134 for (k = 2; k <= c->item_size; k++) {
4137 where = m->rindex + c->item_size - k;
4138 r = message_peek_body(m, &where, 1, k, &q);
4142 if (*(char*) q == 0)
4146 if (k > c->item_size)
4149 free(c->peeked_signature);
4150 c->peeked_signature = strndup((char*) q + 1, k - 1);
4151 if (!c->peeked_signature)
4154 if (!signature_is_valid(c->peeked_signature, true))
4157 *contents = c->peeked_signature;
4162 r = message_peek_body(m, &rindex, 1, 1, &q);
4167 r = message_peek_body(m, &rindex, 1, l+1, &q);
4171 if (!validate_signature(q, l))
4179 *type = SD_BUS_TYPE_VARIANT;
4194 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4195 struct bus_container *c;
4197 assert_return(m, -EINVAL);
4198 assert_return(m->sealed, -EPERM);
4201 message_reset_containers(m);
4204 c = message_get_container(m);
4206 c = message_get_container(m);
4208 c->offset_index = 0;
4210 m->rindex = c->begin;
4213 c->offset_index = 0;
4214 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4216 return !isempty(c->signature);
4219 static int message_read_ap(
4224 unsigned n_array, n_struct;
4225 TypeStack stack[BUS_CONTAINER_DEPTH];
4226 unsigned stack_ptr = 0;
4227 unsigned n_loop = 0;
4235 /* Ideally, we'd just call ourselves recursively on every
4236 * complex type. However, the state of a va_list that is
4237 * passed to a function is undefined after that function
4238 * returns. This means we need to docode the va_list linearly
4239 * in a single stackframe. We hence implement our own
4240 * home-grown stack in an array. */
4242 n_array = (unsigned) -1; /* length of current array entries */
4243 n_struct = strlen(types); /* length of current struct contents signature */
4250 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4251 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4257 r = sd_bus_message_exit_container(m);
4265 if (n_array != (unsigned) -1)
4274 case SD_BUS_TYPE_BYTE:
4275 case SD_BUS_TYPE_BOOLEAN:
4276 case SD_BUS_TYPE_INT16:
4277 case SD_BUS_TYPE_UINT16:
4278 case SD_BUS_TYPE_INT32:
4279 case SD_BUS_TYPE_UINT32:
4280 case SD_BUS_TYPE_INT64:
4281 case SD_BUS_TYPE_UINT64:
4282 case SD_BUS_TYPE_DOUBLE:
4283 case SD_BUS_TYPE_STRING:
4284 case SD_BUS_TYPE_OBJECT_PATH:
4285 case SD_BUS_TYPE_SIGNATURE:
4286 case SD_BUS_TYPE_UNIX_FD: {
4289 p = va_arg(ap, void*);
4290 r = sd_bus_message_read_basic(m, *t, p);
4303 case SD_BUS_TYPE_ARRAY: {
4306 r = signature_element_length(t + 1, &k);
4312 memcpy(s, t + 1, k);
4315 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4326 if (n_array == (unsigned) -1) {
4331 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4337 n_array = va_arg(ap, unsigned);
4342 case SD_BUS_TYPE_VARIANT: {
4345 s = va_arg(ap, const char *);
4349 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4359 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4364 n_struct = strlen(s);
4365 n_array = (unsigned) -1;
4370 case SD_BUS_TYPE_STRUCT_BEGIN:
4371 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4374 r = signature_element_length(t, &k);
4380 memcpy(s, t + 1, k - 2);
4383 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4393 if (n_array == (unsigned) -1) {
4398 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4404 n_array = (unsigned) -1;
4417 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4421 assert_return(m, -EINVAL);
4422 assert_return(m->sealed, -EPERM);
4423 assert_return(types, -EINVAL);
4425 va_start(ap, types);
4426 r = message_read_ap(m, types, ap);
4432 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4435 assert_return(m, -EINVAL);
4436 assert_return(m->sealed, -EPERM);
4437 assert_return(types, -EINVAL);
4444 case SD_BUS_TYPE_BYTE:
4445 case SD_BUS_TYPE_BOOLEAN:
4446 case SD_BUS_TYPE_INT16:
4447 case SD_BUS_TYPE_UINT16:
4448 case SD_BUS_TYPE_INT32:
4449 case SD_BUS_TYPE_UINT32:
4450 case SD_BUS_TYPE_INT64:
4451 case SD_BUS_TYPE_UINT64:
4452 case SD_BUS_TYPE_DOUBLE:
4453 case SD_BUS_TYPE_STRING:
4454 case SD_BUS_TYPE_OBJECT_PATH:
4455 case SD_BUS_TYPE_SIGNATURE:
4456 case SD_BUS_TYPE_UNIX_FD:
4458 r = sd_bus_message_read_basic(m, *types, NULL);
4462 r = sd_bus_message_skip(m, types + 1);
4468 case SD_BUS_TYPE_ARRAY: {
4471 r = signature_element_length(types + 1, &k);
4477 memcpy(s, types+1, k);
4480 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4485 r = sd_bus_message_skip(m, s);
4492 r = sd_bus_message_exit_container(m);
4497 r = sd_bus_message_skip(m, types + 1 + k);
4504 case SD_BUS_TYPE_VARIANT: {
4505 const char *contents;
4508 r = sd_bus_message_peek_type(m, &x, &contents);
4512 if (x != SD_BUS_TYPE_VARIANT)
4515 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4519 r = sd_bus_message_skip(m, contents);
4524 r = sd_bus_message_exit_container(m);
4528 r = sd_bus_message_skip(m, types + 1);
4535 case SD_BUS_TYPE_STRUCT_BEGIN:
4536 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4539 r = signature_element_length(types, &k);
4545 memcpy(s, types+1, k-2);
4548 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4552 r = sd_bus_message_skip(m, s);
4557 r = sd_bus_message_exit_container(m);
4562 r = sd_bus_message_skip(m, types + k);
4574 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4578 struct bus_container *c;
4584 assert_return(m, -EINVAL);
4585 assert_return(m->sealed, -EPERM);
4586 assert_return(bus_type_is_trivial(type), -EINVAL);
4587 assert_return(ptr, -EINVAL);
4588 assert_return(size, -EINVAL);
4589 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4591 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4595 c = message_get_container(m);
4597 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4598 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4602 sz = c->end - c->begin;
4604 align = bus_type_get_alignment(type);
4608 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4612 /* Zero length array, let's return some aligned
4613 * pointer that is not NULL */
4614 p = (uint8_t*) NULL + align;
4616 r = message_peek_body(m, &m->rindex, align, sz, &p);
4621 r = sd_bus_message_exit_container(m);
4625 *ptr = (const void*) p;
4631 message_quit_container(m);
4635 static int message_peek_fields(
4646 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4649 static int message_peek_field_uint32(
4661 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4664 /* identical for gvariant and dbus1 */
4666 r = message_peek_fields(m, ri, 4, 4, &q);
4671 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4676 static int message_peek_field_string(
4678 bool (*validate)(const char *p),
4690 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4695 r = message_peek_fields(m, ri, 1, item_size, &q);
4701 r = message_peek_field_uint32(m, ri, 4, &l);
4705 r = message_peek_fields(m, ri, 1, l+1, &q);
4711 if (!validate_nul(q, l))
4717 if (!validate_string(q, l))
4727 static int message_peek_field_signature(
4740 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4745 r = message_peek_fields(m, ri, 1, item_size, &q);
4751 r = message_peek_fields(m, ri, 1, 1, &q);
4756 r = message_peek_fields(m, ri, 1, l+1, &q);
4761 if (!validate_signature(q, l))
4770 static int message_skip_fields(
4773 uint32_t array_size,
4774 const char **signature) {
4776 size_t original_index;
4782 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4784 original_index = *ri;
4790 if (array_size != (uint32_t) -1 &&
4791 array_size <= *ri - original_index)
4798 if (t == SD_BUS_TYPE_STRING) {
4800 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4806 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4808 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4814 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4816 r = message_peek_field_signature(m, ri, 0, NULL);
4822 } else if (bus_type_is_basic(t)) {
4825 align = bus_type_get_alignment(t);
4826 k = bus_type_get_size(t);
4827 assert(align > 0 && k > 0);
4829 r = message_peek_fields(m, ri, align, k, NULL);
4835 } else if (t == SD_BUS_TYPE_ARRAY) {
4837 r = signature_element_length(*signature+1, &l);
4847 strncpy(sig, *signature + 1, l-1);
4850 alignment = bus_type_get_alignment(sig[0]);
4854 r = message_peek_field_uint32(m, ri, 0, &nas);
4857 if (nas > BUS_ARRAY_MAX_SIZE)
4860 r = message_peek_fields(m, ri, alignment, 0, NULL);
4864 r = message_skip_fields(m, ri, nas, (const char**) &s);
4869 (*signature) += 1 + l;
4871 } else if (t == SD_BUS_TYPE_VARIANT) {
4874 r = message_peek_field_signature(m, ri, 0, &s);
4878 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4884 } else if (t == SD_BUS_TYPE_STRUCT ||
4885 t == SD_BUS_TYPE_DICT_ENTRY) {
4887 r = signature_element_length(*signature, &l);
4894 strncpy(sig, *signature + 1, l-1);
4897 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4908 int bus_message_parse_fields(sd_bus_message *m) {
4911 uint32_t unix_fds = 0;
4912 bool unix_fds_set = false;
4913 void *offsets = NULL;
4914 unsigned n_offsets = 0;
4920 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4923 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4927 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4928 r = message_peek_fields(m, &ri, 1, sz, &q);
4932 framing = read_word_le(q, sz);
4933 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4935 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4939 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4943 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4948 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4949 _cleanup_free_ char *sig = NULL;
4950 const char *signature;
4952 size_t item_size = (size_t) -1;
4954 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4961 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4964 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4968 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4973 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4978 where = ri = ALIGN_TO(ri, 8);
4979 item_size = end - ri;
4980 r = message_peek_fields(m, &where, 1, item_size, &q);
4984 b = memrchr(q, 0, item_size);
4988 sig = strndup(b+1, item_size - (b+1-(char*) q));
4993 item_size = b - (char*) q;
4995 r = message_peek_field_signature(m, &ri, 0, &signature);
5001 case _BUS_MESSAGE_HEADER_INVALID:
5004 case BUS_MESSAGE_HEADER_PATH:
5009 if (!streq(signature, "o"))
5012 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5015 case BUS_MESSAGE_HEADER_INTERFACE:
5020 if (!streq(signature, "s"))
5023 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5026 case BUS_MESSAGE_HEADER_MEMBER:
5031 if (!streq(signature, "s"))
5034 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5037 case BUS_MESSAGE_HEADER_ERROR_NAME:
5042 if (!streq(signature, "s"))
5045 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5047 m->error._need_free = -1;
5051 case BUS_MESSAGE_HEADER_DESTINATION:
5056 if (!streq(signature, "s"))
5059 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5062 case BUS_MESSAGE_HEADER_SENDER:
5067 if (!streq(signature, "s"))
5070 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5072 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5073 m->creds.unique_name = (char*) m->sender;
5074 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5080 case BUS_MESSAGE_HEADER_SIGNATURE: {
5084 if (m->root_container.signature)
5087 if (!streq(signature, "g"))
5090 r = message_peek_field_signature(m, &ri, item_size, &s);
5098 free(m->root_container.signature);
5099 m->root_container.signature = c;
5103 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5106 if (m->reply_cookie != 0)
5109 if (!streq(signature, "u"))
5112 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5116 m->reply_cookie = serial;
5118 if (m->reply_cookie == 0)
5124 case BUS_MESSAGE_HEADER_UNIX_FDS:
5128 if (!streq(signature, "u"))
5131 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5135 unix_fds_set = true;
5139 if (!BUS_MESSAGE_IS_GVARIANT(m))
5140 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5149 if (m->n_fds != unix_fds)
5152 switch (m->header->type) {
5154 case SD_BUS_MESSAGE_SIGNAL:
5155 if (!m->path || !m->interface || !m->member)
5159 case SD_BUS_MESSAGE_METHOD_CALL:
5161 if (!m->path || !m->member)
5166 case SD_BUS_MESSAGE_METHOD_RETURN:
5168 if (m->reply_cookie == 0)
5172 case SD_BUS_MESSAGE_METHOD_ERROR:
5174 if (m->reply_cookie == 0 || !m->error.name)
5179 /* Refuse non-local messages that claim they are local */
5180 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5182 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5184 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5187 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5189 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5190 r = build_struct_offsets(
5192 m->root_container.signature,
5193 BUS_MESSAGE_BODY_SIZE(m),
5194 &m->root_container.item_size,
5195 &m->root_container.offsets,
5196 &m->root_container.n_offsets);
5201 /* Try to read the error message, but if we can't it's a non-issue */
5202 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5203 sd_bus_message_read(m, "s", &m->error.message);
5208 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5209 assert_return(m, -EINVAL);
5210 assert_return(destination, -EINVAL);
5211 assert_return(!m->sealed, -EPERM);
5212 assert_return(!m->destination, -EEXIST);
5214 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5217 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5221 struct bus_body_part *part;
5227 total = BUS_MESSAGE_SIZE(m);
5233 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5234 MESSAGE_FOREACH_PART(part, i, m)
5235 e = mempcpy(e, part->data, part->size);
5237 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5245 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5251 r = sd_bus_message_enter_container(m, 'a', "s");
5258 r = sd_bus_message_read_basic(m, 's', &s);
5264 r = strv_extend(l, s);
5269 r = sd_bus_message_exit_container(m);
5276 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5280 assert_return(m, -EINVAL);
5281 assert_return(m->sealed, -EPERM);
5282 assert_return(l, -EINVAL);
5284 r = bus_message_read_strv_extend(m, &strv);
5294 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5296 const char *t = NULL;
5301 r = sd_bus_message_rewind(m, true);
5305 for (j = 0; j <= i; j++) {
5308 r = sd_bus_message_peek_type(m, &type, NULL);
5312 if (type != SD_BUS_TYPE_STRING &&
5313 type != SD_BUS_TYPE_OBJECT_PATH &&
5314 type != SD_BUS_TYPE_SIGNATURE)
5317 r = sd_bus_message_read_basic(m, type, &t);
5325 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5331 if (size < sizeof(struct bus_header))
5334 full = sizeof(struct bus_header) +
5335 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5337 return size >= full;
5340 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5346 if (h->endian == BUS_NATIVE_ENDIAN) {
5347 fs = h->fields_size;
5349 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5350 fs = bswap_32(h->fields_size);
5351 bs = bswap_32(h->body_size);
5355 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5359 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5360 assert_return(m, EINVAL);
5362 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5365 return sd_bus_error_get_errno(&m->error);
5368 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5369 struct bus_container *c;
5371 assert_return(m, NULL);
5373 c = complete ? &m->root_container : message_get_container(m);
5374 return strempty(c->signature);
5377 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5378 bool done_something = false;
5381 assert_return(m, -EINVAL);
5382 assert_return(source, -EINVAL);
5383 assert_return(!m->sealed, -EPERM);
5384 assert_return(source->sealed, -EPERM);
5387 const char *contents;
5402 r = sd_bus_message_peek_type(source, &type, &contents);
5408 done_something = true;
5410 if (bus_type_is_container(type) > 0) {
5412 r = sd_bus_message_enter_container(source, type, contents);
5416 r = sd_bus_message_open_container(m, type, contents);
5420 r = sd_bus_message_copy(m, source, true);
5424 r = sd_bus_message_close_container(m);
5428 r = sd_bus_message_exit_container(source);
5435 r = sd_bus_message_read_basic(source, type, &basic);
5441 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5442 type == SD_BUS_TYPE_SIGNATURE ||
5443 type == SD_BUS_TYPE_STRING)
5444 r = sd_bus_message_append_basic(m, type, basic.string);
5446 r = sd_bus_message_append_basic(m, type, &basic);
5453 return done_something;
5456 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5461 assert_return(m, -EINVAL);
5462 assert_return(m->sealed, -EPERM);
5463 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5464 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5465 assert_return(type || contents, -EINVAL);
5466 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5468 r = sd_bus_message_peek_type(m, &t, &c);
5472 if (type != 0 && type != t)
5475 if (contents && !streq_ptr(contents, c))
5481 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5482 assert_return(m, NULL);
5487 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5488 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5496 switch ((*m)->header->type) {
5498 case SD_BUS_MESSAGE_SIGNAL:
5499 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5505 case SD_BUS_MESSAGE_METHOD_CALL:
5506 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5512 case SD_BUS_MESSAGE_METHOD_RETURN:
5513 case SD_BUS_MESSAGE_METHOD_ERROR:
5515 n = message_new(bus, (*m)->header->type);
5519 n->reply_cookie = (*m)->reply_cookie;
5520 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5524 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5525 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5529 n->error._need_free = -1;
5538 if ((*m)->destination && !n->destination) {
5539 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5544 if ((*m)->sender && !n->sender) {
5545 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5550 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5552 r = sd_bus_message_copy(n, *m, true);
5556 timeout = (*m)->timeout;
5557 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5558 timeout = BUS_DEFAULT_TIMEOUT;
5560 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5564 sd_bus_message_unref(*m);
5571 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5575 assert_return(!m->sealed, -EPERM);
5576 assert_return(!m->sender, -EPERM);
5578 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5581 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5582 assert_return(m, -EINVAL);
5583 assert_return(priority, -EINVAL);
5585 *priority = m->priority;
5589 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5590 assert_return(m, -EINVAL);
5591 assert_return(!m->sealed, -EPERM);
5593 m->priority = priority;