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_ const char *sd_bus_message_get_path(sd_bus_message *m) {
853 assert_return(m, NULL);
858 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
859 assert_return(m, NULL);
864 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
865 assert_return(m, NULL);
870 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
871 assert_return(m, NULL);
873 return m->destination;
876 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
877 assert_return(m, NULL);
882 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
883 assert_return(m, NULL);
884 assert_return(sd_bus_error_is_set(&m->error), NULL);
889 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
890 assert_return(m, -EINVAL);
891 assert_return(usec, -EINVAL);
893 if (m->monotonic <= 0)
896 *usec = m->monotonic;
900 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
901 assert_return(m, -EINVAL);
902 assert_return(usec, -EINVAL);
904 if (m->realtime <= 0)
911 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
912 assert_return(m, -EINVAL);
913 assert_return(seqnum, -EINVAL);
922 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
923 assert_return(m, NULL);
925 if (m->creds.mask == 0)
931 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
932 const char *interface,
933 const char *member) {
934 assert_return(m, -EINVAL);
936 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
939 if (interface && (!m->interface || !streq(m->interface, interface)))
942 if (member && (!m->member || !streq(m->member, member)))
948 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
949 const char *interface,
950 const char *member) {
951 assert_return(m, -EINVAL);
953 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
956 if (interface && (!m->interface || !streq(m->interface, interface)))
959 if (member && (!m->member || !streq(m->member, member)))
965 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
966 assert_return(m, -EINVAL);
968 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
971 if (name && (!m->error.name || !streq(m->error.name, name)))
977 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
978 assert_return(m, -EINVAL);
979 assert_return(!m->sealed, -EPERM);
980 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
983 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
985 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
990 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
991 assert_return(m, -EINVAL);
992 assert_return(!m->sealed, -EPERM);
995 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
997 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1002 static struct bus_container *message_get_container(sd_bus_message *m) {
1005 if (m->n_containers == 0)
1006 return &m->root_container;
1008 assert(m->containers);
1009 return m->containers + m->n_containers - 1;
1012 struct bus_body_part *message_append_part(sd_bus_message *m) {
1013 struct bus_body_part *part;
1020 if (m->n_body_parts <= 0) {
1024 assert(m->body_end);
1026 part = new0(struct bus_body_part, 1);
1032 m->body_end->next = part;
1042 static void part_zero(struct bus_body_part *part, size_t sz) {
1047 /* All other fields can be left in their defaults */
1048 assert(!part->data);
1049 assert(part->memfd < 0);
1052 part->is_zero = true;
1053 part->sealed = true;
1056 static int part_make_space(
1057 struct sd_bus_message *m,
1058 struct bus_body_part *part,
1067 assert(!part->sealed);
1072 if (!part->data && part->memfd < 0)
1073 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1075 if (part->memfd >= 0) {
1077 if (part->allocated == 0 || sz > part->allocated) {
1078 uint64_t new_allocated;
1080 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1081 r = ftruncate(part->memfd, new_allocated);
1087 part->allocated = new_allocated;
1090 if (!part->data || sz > part->mapped) {
1093 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1094 if (part->mapped <= 0)
1095 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1097 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1099 if (n == MAP_FAILED) {
1108 part->munmap_this = true;
1110 if (part->allocated == 0 || sz > part->allocated) {
1111 size_t new_allocated;
1113 new_allocated = sz > 0 ? 2 * sz : 64;
1114 n = realloc(part->data, new_allocated);
1121 part->allocated = new_allocated;
1122 part->free_this = true;
1127 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1133 static int message_add_offset(sd_bus_message *m, size_t offset) {
1134 struct bus_container *c;
1137 assert(BUS_MESSAGE_IS_GVARIANT(m));
1139 /* Add offset to current container, unless this is the first
1140 * item in it, which will have the 0 offset, which we can
1142 c = message_get_container(m);
1144 if (!c->need_offsets)
1147 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1150 c->offsets[c->n_offsets++] = offset;
1154 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1155 struct bus_container *c;
1162 /* Update counters */
1163 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1166 *c->array_size += expand;
1170 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1171 size_t start_body, end_body, padding, added;
1182 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1183 end_body = start_body + sz;
1185 padding = start_body - m->header->body_size;
1186 added = padding + sz;
1188 /* Check for 32bit overflows */
1189 if (end_body > (size_t) ((uint32_t) -1)) {
1195 struct bus_body_part *part = NULL;
1199 m->n_body_parts <= 0 ||
1200 m->body_end->sealed ||
1201 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1205 part = message_append_part(m);
1209 part_zero(part, padding);
1212 part = message_append_part(m);
1216 r = part_make_space(m, part, sz, &p);
1220 struct bus_container *c;
1222 size_t os, start_part, end_part;
1228 start_part = ALIGN_TO(part->size, align);
1229 end_part = start_part + sz;
1231 r = part_make_space(m, part, end_part, &p);
1236 memzero(p, padding);
1237 p = (uint8_t*) p + padding;
1240 /* Readjust pointers */
1241 for (c = m->containers; c < m->containers + m->n_containers; c++)
1242 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1244 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1247 /* Return something that is not NULL and is aligned */
1248 p = (uint8_t *) NULL + align;
1250 m->header->body_size = end_body;
1251 message_extend_containers(m, added);
1254 r = message_add_offset(m, end_body);
1264 static int message_push_fd(sd_bus_message *m, int fd) {
1275 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1279 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1287 m->fds[m->n_fds] = copy;
1293 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1294 _cleanup_close_ int fd = -1;
1295 struct bus_container *c;
1299 assert_return(m, -EINVAL);
1300 assert_return(!m->sealed, -EPERM);
1301 assert_return(bus_type_is_basic(type), -EINVAL);
1302 assert_return(!m->poisoned, -ESTALE);
1304 c = message_get_container(m);
1306 if (c->signature && c->signature[c->index]) {
1307 /* Container signature is already set */
1309 if (c->signature[c->index] != type)
1314 /* Maybe we can append to the signature? But only if this is the top-level container*/
1315 if (c->enclosing != 0)
1318 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1325 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1331 case SD_BUS_TYPE_SIGNATURE:
1332 case SD_BUS_TYPE_STRING:
1335 /* Fall through... */
1336 case SD_BUS_TYPE_OBJECT_PATH:
1344 case SD_BUS_TYPE_BOOLEAN:
1346 u8 = p && *(int*) p;
1352 case SD_BUS_TYPE_UNIX_FD:
1357 fd = message_push_fd(m, *(int*) p);
1368 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1369 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1376 a = message_extend_body(m, align, sz, true);
1383 *stored = (const uint8_t*) a;
1390 case SD_BUS_TYPE_STRING:
1391 /* To make things easy we'll serialize a NULL string
1392 * into the empty string */
1395 /* Fall through... */
1396 case SD_BUS_TYPE_OBJECT_PATH:
1402 sz = 4 + strlen(p) + 1;
1405 case SD_BUS_TYPE_SIGNATURE:
1410 sz = 1 + strlen(p) + 1;
1413 case SD_BUS_TYPE_BOOLEAN:
1415 u32 = p && *(int*) p;
1421 case SD_BUS_TYPE_UNIX_FD:
1426 fd = message_push_fd(m, *(int*) p);
1437 align = bus_type_get_alignment(type);
1438 sz = bus_type_get_size(type);
1445 a = message_extend_body(m, align, sz, false);
1449 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1450 *(uint32_t*) a = sz - 5;
1451 memcpy((uint8_t*) a + 4, p, sz - 4);
1454 *stored = (const uint8_t*) a + 4;
1456 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1457 *(uint8_t*) a = sz - 2;
1458 memcpy((uint8_t*) a + 1, p, sz - 1);
1461 *stored = (const uint8_t*) a + 1;
1470 if (type == SD_BUS_TYPE_UNIX_FD)
1473 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1480 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1481 return message_append_basic(m, type, p, NULL);
1484 _public_ int sd_bus_message_append_string_space(
1489 struct bus_container *c;
1492 assert_return(m, -EINVAL);
1493 assert_return(s, -EINVAL);
1494 assert_return(!m->sealed, -EPERM);
1495 assert_return(!m->poisoned, -ESTALE);
1497 c = message_get_container(m);
1499 if (c->signature && c->signature[c->index]) {
1500 /* Container signature is already set */
1502 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1507 /* Maybe we can append to the signature? But only if this is the top-level container*/
1508 if (c->enclosing != 0)
1511 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1518 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1519 a = message_extend_body(m, 1, size + 1, true);
1525 a = message_extend_body(m, 4, 4 + size + 1, false);
1529 *(uint32_t*) a = size;
1535 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1541 _public_ int sd_bus_message_append_string_iovec(
1543 const struct iovec *iov,
1551 assert_return(m, -EINVAL);
1552 assert_return(!m->sealed, -EPERM);
1553 assert_return(iov || n == 0, -EINVAL);
1554 assert_return(!m->poisoned, -ESTALE);
1556 size = IOVEC_TOTAL_SIZE(iov, n);
1558 r = sd_bus_message_append_string_space(m, size, &p);
1562 for (i = 0; i < n; i++) {
1564 if (iov[i].iov_base)
1565 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1567 memset(p, ' ', iov[i].iov_len);
1569 p += iov[i].iov_len;
1575 static int bus_message_open_array(
1577 struct bus_container *c,
1578 const char *contents,
1579 uint32_t **array_size,
1581 bool *need_offsets) {
1591 assert(need_offsets);
1593 if (!signature_is_single(contents, true))
1596 if (c->signature && c->signature[c->index]) {
1598 /* Verify the existing signature */
1600 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1603 if (!startswith(c->signature + c->index + 1, contents))
1606 nindex = c->index + 1 + strlen(contents);
1610 if (c->enclosing != 0)
1613 /* Extend the existing signature */
1615 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1621 nindex = e - c->signature;
1624 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1625 alignment = bus_gvariant_get_alignment(contents);
1629 /* Add alignment padding and add to offset list */
1630 if (!message_extend_body(m, alignment, 0, false))
1633 r = bus_gvariant_is_fixed_size(contents);
1637 *begin = m->header->body_size;
1638 *need_offsets = r == 0;
1642 struct bus_body_part *o;
1644 alignment = bus_type_get_alignment(contents[0]);
1648 a = message_extend_body(m, 4, 4, false);
1653 op = m->body_end->data;
1654 os = m->body_end->size;
1656 /* Add alignment between size and first element */
1657 if (!message_extend_body(m, alignment, 0, false))
1660 /* location of array size might have changed so let's readjust a */
1661 if (o == m->body_end)
1662 a = adjust_pointer(a, op, os, m->body_end->data);
1668 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1674 static int bus_message_open_variant(
1676 struct bus_container *c,
1677 const char *contents) {
1683 if (!signature_is_single(contents, false))
1686 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1689 if (c->signature && c->signature[c->index]) {
1691 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1697 if (c->enclosing != 0)
1700 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1707 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1708 /* Variants are always aligned to 8 */
1710 if (!message_extend_body(m, 8, 0, false))
1717 l = strlen(contents);
1718 a = message_extend_body(m, 1, 1 + l + 1, false);
1723 memcpy((uint8_t*) a + 1, contents, l + 1);
1726 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1732 static int bus_message_open_struct(
1734 struct bus_container *c,
1735 const char *contents,
1737 bool *need_offsets) {
1746 assert(need_offsets);
1748 if (!signature_is_valid(contents, false))
1751 if (c->signature && c->signature[c->index]) {
1754 l = strlen(contents);
1756 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1757 !startswith(c->signature + c->index + 1, contents) ||
1758 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1761 nindex = c->index + 1 + l + 1;
1765 if (c->enclosing != 0)
1768 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1774 nindex = e - c->signature;
1777 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1780 alignment = bus_gvariant_get_alignment(contents);
1784 if (!message_extend_body(m, alignment, 0, false))
1787 r = bus_gvariant_is_fixed_size(contents);
1791 *begin = m->header->body_size;
1792 *need_offsets = r == 0;
1794 /* Align contents to 8 byte boundary */
1795 if (!message_extend_body(m, 8, 0, false))
1799 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1805 static int bus_message_open_dict_entry(
1807 struct bus_container *c,
1808 const char *contents,
1810 bool *need_offsets) {
1818 assert(need_offsets);
1820 if (!signature_is_pair(contents))
1823 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1826 if (c->signature && c->signature[c->index]) {
1829 l = strlen(contents);
1831 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1832 !startswith(c->signature + c->index + 1, contents) ||
1833 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1838 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1841 alignment = bus_gvariant_get_alignment(contents);
1845 if (!message_extend_body(m, alignment, 0, false))
1848 r = bus_gvariant_is_fixed_size(contents);
1852 *begin = m->header->body_size;
1853 *need_offsets = r == 0;
1855 /* Align contents to 8 byte boundary */
1856 if (!message_extend_body(m, 8, 0, false))
1863 _public_ int sd_bus_message_open_container(
1866 const char *contents) {
1868 struct bus_container *c, *w;
1869 uint32_t *array_size = NULL;
1871 size_t before, begin = 0;
1872 bool need_offsets = false;
1875 assert_return(m, -EINVAL);
1876 assert_return(!m->sealed, -EPERM);
1877 assert_return(contents, -EINVAL);
1878 assert_return(!m->poisoned, -ESTALE);
1880 /* Make sure we have space for one more container */
1881 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1886 c = message_get_container(m);
1888 signature = strdup(contents);
1894 /* Save old index in the parent container, in case we have to
1895 * abort this container */
1896 c->saved_index = c->index;
1897 before = m->header->body_size;
1899 if (type == SD_BUS_TYPE_ARRAY)
1900 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1901 else if (type == SD_BUS_TYPE_VARIANT)
1902 r = bus_message_open_variant(m, c, contents);
1903 else if (type == SD_BUS_TYPE_STRUCT)
1904 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1905 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1906 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1915 /* OK, let's fill it in */
1916 w = m->containers + m->n_containers++;
1917 w->enclosing = type;
1918 w->signature = signature;
1920 w->array_size = array_size;
1923 w->n_offsets = w->offsets_allocated = 0;
1925 w->need_offsets = need_offsets;
1930 static size_t determine_word_size(size_t sz, size_t extra) {
1931 if (sz + extra <= 0xFF)
1933 else if (sz + extra*2 <= 0xFFFF)
1935 else if (sz + extra*4 <= 0xFFFFFFFF)
1941 static size_t read_word_le(void *p, size_t sz) {
1951 return *(uint8_t*) p;
1956 return le16toh(x.u16);
1958 return le32toh(x.u32);
1960 return le64toh(x.u64);
1962 assert_not_reached("unknown word width");
1965 static void write_word_le(void *p, size_t sz, size_t value) {
1973 assert(sz == 8 || (value < (1ULL << (sz*8))));
1976 *(uint8_t*) p = value;
1979 x.u16 = htole16((uint16_t) value);
1981 x.u32 = htole32((uint32_t) value);
1983 x.u64 = htole64((uint64_t) value);
1985 assert_not_reached("unknown word width");
1990 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1995 if (!BUS_MESSAGE_IS_GVARIANT(m))
1998 if (c->need_offsets) {
1999 size_t payload, sz, i;
2002 /* Variable-width arrays */
2004 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2005 sz = determine_word_size(payload, c->n_offsets);
2007 a = message_extend_body(m, 1, sz * c->n_offsets, true);
2011 for (i = 0; i < c->n_offsets; i++)
2012 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2016 /* Fixed-width or empty arrays */
2018 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
2026 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2033 if (!BUS_MESSAGE_IS_GVARIANT(m))
2036 l = strlen(c->signature);
2038 a = message_extend_body(m, 1, 1 + l, true);
2043 memcpy(a+1, c->signature, l);
2048 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2049 size_t n_variable = 0;
2058 if (!BUS_MESSAGE_IS_GVARIANT(m))
2061 p = strempty(c->signature);
2065 r = signature_element_length(p, &n);
2074 r = bus_gvariant_is_fixed_size(t);
2079 assert(!c->need_offsets || i <= c->n_offsets);
2081 /* We need to add an offset for each item that has a
2082 * variable size and that is not the last one in the
2084 if (r == 0 && p[n] != 0)
2091 assert(!c->need_offsets || i == c->n_offsets);
2092 assert(c->need_offsets || n_variable == 0);
2094 if (n_variable <= 0) {
2095 a = message_extend_body(m, 1, 0, add_offset);
2102 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2104 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2106 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2110 p = strempty(c->signature);
2111 for (i = 0, j = 0; i < c->n_offsets; i++) {
2115 r = signature_element_length(p, &n);
2126 r = bus_gvariant_is_fixed_size(t);
2129 if (r > 0 || p[0] == 0)
2133 k = n_variable - 1 - j;
2135 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2144 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2145 struct bus_container *c;
2148 assert_return(m, -EINVAL);
2149 assert_return(!m->sealed, -EPERM);
2150 assert_return(m->n_containers > 0, -EINVAL);
2151 assert_return(!m->poisoned, -ESTALE);
2153 c = message_get_container(m);
2155 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2156 if (c->signature && c->signature[c->index] != 0)
2161 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2162 r = bus_message_close_array(m, c);
2163 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2164 r = bus_message_close_variant(m, c);
2165 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2166 r = bus_message_close_struct(m, c, true);
2168 assert_not_reached("Unknown container type");
2182 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2189 stack[*i].types = types;
2190 stack[*i].n_struct = n_struct;
2191 stack[*i].n_array = n_array;
2197 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2208 *types = stack[*i].types;
2209 *n_struct = stack[*i].n_struct;
2210 *n_array = stack[*i].n_array;
2215 int bus_message_append_ap(
2220 unsigned n_array, n_struct;
2221 TypeStack stack[BUS_CONTAINER_DEPTH];
2222 unsigned stack_ptr = 0;
2230 n_array = (unsigned) -1;
2231 n_struct = strlen(types);
2236 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2237 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2243 r = sd_bus_message_close_container(m);
2251 if (n_array != (unsigned) -1)
2260 case SD_BUS_TYPE_BYTE: {
2263 x = (uint8_t) va_arg(ap, int);
2264 r = sd_bus_message_append_basic(m, *t, &x);
2268 case SD_BUS_TYPE_BOOLEAN:
2269 case SD_BUS_TYPE_INT32:
2270 case SD_BUS_TYPE_UINT32:
2271 case SD_BUS_TYPE_UNIX_FD: {
2274 /* We assume a boolean is the same as int32_t */
2275 assert_cc(sizeof(int32_t) == sizeof(int));
2277 x = va_arg(ap, uint32_t);
2278 r = sd_bus_message_append_basic(m, *t, &x);
2282 case SD_BUS_TYPE_INT16:
2283 case SD_BUS_TYPE_UINT16: {
2286 x = (uint16_t) va_arg(ap, int);
2287 r = sd_bus_message_append_basic(m, *t, &x);
2291 case SD_BUS_TYPE_INT64:
2292 case SD_BUS_TYPE_UINT64:
2293 case SD_BUS_TYPE_DOUBLE: {
2296 x = va_arg(ap, uint64_t);
2297 r = sd_bus_message_append_basic(m, *t, &x);
2301 case SD_BUS_TYPE_STRING:
2302 case SD_BUS_TYPE_OBJECT_PATH:
2303 case SD_BUS_TYPE_SIGNATURE: {
2306 x = va_arg(ap, const char*);
2307 r = sd_bus_message_append_basic(m, *t, x);
2311 case SD_BUS_TYPE_ARRAY: {
2314 r = signature_element_length(t + 1, &k);
2320 memcpy(s, t + 1, k);
2323 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2328 if (n_array == (unsigned) -1) {
2333 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2339 n_array = va_arg(ap, unsigned);
2344 case SD_BUS_TYPE_VARIANT: {
2347 s = va_arg(ap, const char*);
2351 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2355 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2360 n_struct = strlen(s);
2361 n_array = (unsigned) -1;
2366 case SD_BUS_TYPE_STRUCT_BEGIN:
2367 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2370 r = signature_element_length(t, &k);
2377 memcpy(s, t + 1, k - 2);
2380 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2385 if (n_array == (unsigned) -1) {
2390 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2396 n_array = (unsigned) -1;
2412 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2416 assert_return(m, -EINVAL);
2417 assert_return(types, -EINVAL);
2418 assert_return(!m->sealed, -EPERM);
2419 assert_return(!m->poisoned, -ESTALE);
2421 va_start(ap, types);
2422 r = bus_message_append_ap(m, types, ap);
2428 _public_ int sd_bus_message_append_array_space(
2438 assert_return(m, -EINVAL);
2439 assert_return(!m->sealed, -EPERM);
2440 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2441 assert_return(ptr || size == 0, -EINVAL);
2442 assert_return(!m->poisoned, -ESTALE);
2444 /* alignment and size of the trivial types (except bool) is
2445 * identical for gvariant and dbus1 marshalling */
2446 align = bus_type_get_alignment(type);
2447 sz = bus_type_get_size(type);
2449 assert_se(align > 0);
2455 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2459 a = message_extend_body(m, align, size, false);
2463 r = sd_bus_message_close_container(m);
2471 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2478 assert_return(m, -EINVAL);
2479 assert_return(!m->sealed, -EPERM);
2480 assert_return(bus_type_is_trivial(type), -EINVAL);
2481 assert_return(ptr || size == 0, -EINVAL);
2482 assert_return(!m->poisoned, -ESTALE);
2484 r = sd_bus_message_append_array_space(m, type, size, &p);
2489 memcpy(p, ptr, size);
2494 _public_ int sd_bus_message_append_array_iovec(
2497 const struct iovec *iov,
2505 assert_return(m, -EINVAL);
2506 assert_return(!m->sealed, -EPERM);
2507 assert_return(bus_type_is_trivial(type), -EINVAL);
2508 assert_return(iov || n == 0, -EINVAL);
2509 assert_return(!m->poisoned, -ESTALE);
2511 size = IOVEC_TOTAL_SIZE(iov, n);
2513 r = sd_bus_message_append_array_space(m, type, size, &p);
2517 for (i = 0; i < n; i++) {
2519 if (iov[i].iov_base)
2520 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2522 memzero(p, iov[i].iov_len);
2524 p = (uint8_t*) p + iov[i].iov_len;
2530 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2533 _cleanup_close_ int copy_fd = -1;
2534 struct bus_body_part *part;
2546 if (!bus_type_is_trivial(type))
2551 r = memfd_set_sealed(memfd);
2555 copy_fd = dup(memfd);
2559 r = memfd_get_size(memfd, &size);
2563 align = bus_type_get_alignment(type);
2564 sz = bus_type_get_size(type);
2566 assert_se(align > 0);
2572 if (size > (uint64_t) (uint32_t) -1)
2575 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2579 a = message_extend_body(m, align, 0, false);
2583 part = message_append_part(m);
2587 part->memfd = copy_fd;
2588 part->sealed = true;
2592 m->header->body_size += size;
2593 message_extend_containers(m, size);
2595 return sd_bus_message_close_container(m);
2598 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) {
2599 _cleanup_close_ int copy_fd = -1;
2600 struct bus_body_part *part;
2601 struct bus_container *c;
2606 assert_return(m, -EINVAL);
2607 assert_return(memfd >= 0, -EINVAL);
2608 assert_return(!m->sealed, -EPERM);
2609 assert_return(!m->poisoned, -ESTALE);
2611 r = memfd_set_sealed(memfd);
2615 copy_fd = dup(memfd);
2619 r = memfd_get_size(memfd, &size);
2623 /* We require this to be NUL terminated */
2627 if (size > (uint64_t) (uint32_t) -1)
2630 c = message_get_container(m);
2631 if (c->signature && c->signature[c->index]) {
2632 /* Container signature is already set */
2634 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2639 /* Maybe we can append to the signature? But only if this is the top-level container*/
2640 if (c->enclosing != 0)
2643 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2650 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2651 a = message_extend_body(m, 4, 4, false);
2655 *(uint32_t*) a = size - 1;
2658 part = message_append_part(m);
2662 part->memfd = copy_fd;
2663 part->sealed = true;
2667 m->header->body_size += size;
2668 message_extend_containers(m, size);
2670 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2671 r = message_add_offset(m, m->header->body_size);
2678 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2684 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2688 assert_return(m, -EINVAL);
2689 assert_return(!m->sealed, -EPERM);
2690 assert_return(!m->poisoned, -ESTALE);
2692 r = sd_bus_message_open_container(m, 'a', "s");
2696 STRV_FOREACH(i, l) {
2697 r = sd_bus_message_append_basic(m, 's', *i);
2702 return sd_bus_message_close_container(m);
2705 static int bus_message_close_header(sd_bus_message *m) {
2711 if (!BUS_MESSAGE_IS_GVARIANT(m))
2714 if (m->n_header_offsets < 1)
2717 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2719 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2721 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2725 for (i = 0; i < m->n_header_offsets; i++)
2726 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2731 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2732 struct bus_body_part *part;
2742 if (m->n_containers > 0)
2748 /* In vtables the return signature of method calls is listed,
2749 * let's check if they match if this is a response */
2750 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2751 m->enforced_reply_signature &&
2752 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2755 /* If gvariant marshalling is used we need to close the body structure */
2756 r = bus_message_close_struct(m, &m->root_container, false);
2760 /* If there's a non-trivial signature set, then add it in here */
2761 if (!isempty(m->root_container.signature)) {
2762 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2768 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2773 r = bus_message_close_header(m);
2777 m->header->serial = (uint32_t) cookie;
2778 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2780 /* Add padding at the end of the fields part, since we know
2781 * the body needs to start at an 8 byte alignment. We made
2782 * sure we allocated enough space for this, so all we need to
2783 * do here is to zero it out. */
2784 l = BUS_MESSAGE_FIELDS_SIZE(m);
2787 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, a);
2789 /* If this is something we can send as memfd, then let's seal
2790 the memfd now. Note that we can send memfds as payload only
2791 for directed messages, and not for broadcasts. */
2792 if (m->destination && m->bus->use_memfd) {
2793 MESSAGE_FOREACH_PART(part, i, m)
2794 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2797 /* Try to seal it if that makes
2798 * sense. First, unmap our own map to
2799 * make sure we don't keep it busy. */
2800 bus_body_part_unmap(part);
2802 /* Then, sync up real memfd size */
2804 if (ftruncate(part->memfd, sz) < 0)
2807 /* Finally, try to seal */
2808 if (fcntl(part->memfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE) >= 0)
2809 part->sealed = true;
2813 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2814 m->root_container.index = 0;
2815 m->root_container.offset_index = 0;
2816 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2823 int bus_body_part_map(struct bus_body_part *part) {
2832 if (part->size <= 0)
2835 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2836 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2837 static const uint8_t zeroes[7] = { };
2838 part->data = (void*) zeroes;
2842 psz = PAGE_ALIGN(part->size);
2844 if (part->memfd >= 0)
2845 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, 0);
2846 else if (part->is_zero)
2847 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2851 if (p == MAP_FAILED)
2856 part->munmap_this = true;
2861 void bus_body_part_unmap(struct bus_body_part *part) {
2865 if (part->memfd < 0)
2871 if (!part->munmap_this)
2874 assert_se(munmap(part->data, part->mapped) == 0);
2878 part->munmap_this = false;
2883 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2884 size_t k, start, end;
2889 start = ALIGN_TO((size_t) *rindex, align);
2890 end = start + nbytes;
2895 /* Verify that padding is 0 */
2896 for (k = *rindex; k < start; k++)
2897 if (((const uint8_t*) p)[k] != 0)
2901 *r = (uint8_t*) p + start;
2908 static bool message_end_of_signature(sd_bus_message *m) {
2909 struct bus_container *c;
2913 c = message_get_container(m);
2914 return !c->signature || c->signature[c->index] == 0;
2917 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2918 struct bus_container *c;
2922 c = message_get_container(m);
2923 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2926 if (BUS_MESSAGE_IS_GVARIANT(m))
2927 return index >= c->end;
2929 assert(c->array_size);
2930 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2934 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2935 assert_return(m, -EINVAL);
2936 assert_return(m->sealed, -EPERM);
2938 if (complete && m->n_containers > 0)
2941 if (message_end_of_signature(m))
2944 if (message_end_of_array(m, m->rindex))
2950 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2951 struct bus_body_part *part;
2957 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2958 part = m->cached_rindex_part;
2959 begin = m->cached_rindex_part_begin;
2969 if (index + sz <= begin + part->size) {
2971 r = bus_body_part_map(part);
2976 *p = (uint8_t*) part->data + index - begin;
2978 m->cached_rindex_part = part;
2979 m->cached_rindex_part_begin = begin;
2984 begin += part->size;
2991 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2998 if (!BUS_MESSAGE_IS_GVARIANT(m))
3001 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3004 sz = bus_gvariant_get_size(c->signature);
3008 if (c->offset_index+1 >= c->n_offsets)
3011 /* Variable-size array */
3013 alignment = bus_gvariant_get_alignment(c->signature);
3014 assert(alignment > 0);
3016 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3017 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3020 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3023 /* Fixed-size array */
3024 *rindex = c->begin + (c->offset_index+1) * sz;
3030 } else if (c->enclosing == 0 ||
3031 c->enclosing == SD_BUS_TYPE_STRUCT ||
3032 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3037 if (c->offset_index+1 >= c->n_offsets)
3040 r = signature_element_length(c->signature + c->index, &n);
3044 r = signature_element_length(c->signature + c->index + n, &j);
3049 memcpy(t, c->signature + c->index + n, j);
3052 alignment = bus_gvariant_get_alignment(t);
3055 assert(alignment > 0);
3057 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3058 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3062 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3065 assert_not_reached("Unknown container type");
3070 /* Reached the end */
3077 static int message_peek_body(
3084 size_t k, start, end, padding;
3085 struct bus_body_part *part;
3092 start = ALIGN_TO((size_t) *rindex, align);
3093 padding = start - *rindex;
3094 end = start + nbytes;
3096 if (end > BUS_MESSAGE_BODY_SIZE(m))
3099 part = find_part(m, *rindex, padding, (void**) &q);
3104 /* Verify padding */
3105 for (k = 0; k < padding; k++)
3110 part = find_part(m, start, nbytes, (void**) &q);
3111 if (!part || (nbytes > 0 && !q))
3122 static bool validate_nul(const char *s, size_t l) {
3124 /* Check for NUL chars in the string */
3125 if (memchr(s, 0, l))
3128 /* Check for NUL termination */
3135 static bool validate_string(const char *s, size_t l) {
3137 if (!validate_nul(s, l))
3140 /* Check if valid UTF8 */
3141 if (!utf8_is_valid(s))
3147 static bool validate_signature(const char *s, size_t l) {
3149 if (!validate_nul(s, l))
3152 /* Check if valid signature */
3153 if (!signature_is_valid(s, true))
3159 static bool validate_object_path(const char *s, size_t l) {
3161 if (!validate_nul(s, l))
3164 if (!object_path_is_valid(s))
3170 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3171 struct bus_container *c;
3176 assert_return(m, -EINVAL);
3177 assert_return(m->sealed, -EPERM);
3178 assert_return(bus_type_is_basic(type), -EINVAL);
3180 if (message_end_of_signature(m))
3183 if (message_end_of_array(m, m->rindex))
3186 c = message_get_container(m);
3187 if (c->signature[c->index] != type)
3192 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3194 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3197 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3201 if (type == SD_BUS_TYPE_STRING)
3202 ok = validate_string(q, c->item_size-1);
3203 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3204 ok = validate_object_path(q, c->item_size-1);
3206 ok = validate_signature(q, c->item_size-1);
3212 *(const char**) p = q;
3216 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3218 if ((size_t) sz != c->item_size)
3221 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3224 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3230 case SD_BUS_TYPE_BYTE:
3232 *(uint8_t*) p = *(uint8_t*) q;
3235 case SD_BUS_TYPE_BOOLEAN:
3237 *(int*) p = !!*(uint8_t*) q;
3240 case SD_BUS_TYPE_INT16:
3241 case SD_BUS_TYPE_UINT16:
3243 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3246 case SD_BUS_TYPE_INT32:
3247 case SD_BUS_TYPE_UINT32:
3249 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3252 case SD_BUS_TYPE_INT64:
3253 case SD_BUS_TYPE_UINT64:
3254 case SD_BUS_TYPE_DOUBLE:
3256 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3259 case SD_BUS_TYPE_UNIX_FD: {
3262 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3267 *(int*) p = m->fds[j];
3273 assert_not_reached("unexpected type");
3277 r = container_next_item(m, c, &rindex);
3284 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3288 r = message_peek_body(m, &rindex, 4, 4, &q);
3292 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3293 r = message_peek_body(m, &rindex, 1, l+1, &q);
3297 if (type == SD_BUS_TYPE_OBJECT_PATH)
3298 ok = validate_object_path(q, l);
3300 ok = validate_string(q, l);
3305 *(const char**) p = q;
3307 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3310 r = message_peek_body(m, &rindex, 1, 1, &q);
3315 r = message_peek_body(m, &rindex, 1, l+1, &q);
3319 if (!validate_signature(q, l))
3323 *(const char**) p = q;
3328 align = bus_type_get_alignment(type);
3331 sz = bus_type_get_size(type);
3334 r = message_peek_body(m, &rindex, align, sz, &q);
3340 case SD_BUS_TYPE_BYTE:
3342 *(uint8_t*) p = *(uint8_t*) q;
3345 case SD_BUS_TYPE_BOOLEAN:
3347 *(int*) p = !!*(uint32_t*) q;
3350 case SD_BUS_TYPE_INT16:
3351 case SD_BUS_TYPE_UINT16:
3353 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3356 case SD_BUS_TYPE_INT32:
3357 case SD_BUS_TYPE_UINT32:
3359 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3362 case SD_BUS_TYPE_INT64:
3363 case SD_BUS_TYPE_UINT64:
3364 case SD_BUS_TYPE_DOUBLE:
3366 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3369 case SD_BUS_TYPE_UNIX_FD: {
3372 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3377 *(int*) p = m->fds[j];
3382 assert_not_reached("Unknown basic type...");
3389 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3395 static int bus_message_enter_array(
3397 struct bus_container *c,
3398 const char *contents,
3399 uint32_t **array_size,
3402 size_t *n_offsets) {
3416 if (!signature_is_single(contents, true))
3419 if (!c->signature || c->signature[c->index] == 0)
3422 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3425 if (!startswith(c->signature + c->index + 1, contents))
3430 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3433 r = message_peek_body(m, &rindex, 4, 4, &q);
3437 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3440 alignment = bus_type_get_alignment(contents[0]);
3444 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3448 *array_size = (uint32_t*) q;
3450 } else if (c->item_size <= 0) {
3452 /* gvariant: empty array */
3457 } else if (bus_gvariant_is_fixed_size(contents)) {
3459 /* gvariant: fixed length array */
3460 *item_size = bus_gvariant_get_size(contents);
3465 size_t where, p = 0, framing, sz;
3468 /* gvariant: variable length array */
3469 sz = determine_word_size(c->item_size, 0);
3471 where = rindex + c->item_size - sz;
3472 r = message_peek_body(m, &where, 1, sz, &q);
3476 framing = read_word_le(q, sz);
3477 if (framing > c->item_size - sz)
3479 if ((c->item_size - framing) % sz != 0)
3482 *n_offsets = (c->item_size - framing) / sz;
3484 where = rindex + framing;
3485 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3489 *offsets = new(size_t, *n_offsets);
3493 for (i = 0; i < *n_offsets; i++) {
3496 x = read_word_le((uint8_t*) q + i * sz, sz);
3497 if (x > c->item_size - sz)
3502 (*offsets)[i] = rindex + x;
3506 *item_size = (*offsets)[0] - rindex;
3511 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3512 c->index += 1 + strlen(contents);
3517 static int bus_message_enter_variant(
3519 struct bus_container *c,
3520 const char *contents,
3521 size_t *item_size) {
3533 if (!signature_is_single(contents, false))
3536 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3539 if (!c->signature || c->signature[c->index] == 0)
3542 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3547 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3550 k = strlen(contents);
3551 if (1+k > c->item_size)
3554 where = rindex + c->item_size - (1+k);
3555 r = message_peek_body(m, &where, 1, 1+k, &q);
3559 if (*(char*) q != 0)
3562 if (memcmp((uint8_t*) q+1, contents, k))
3565 *item_size = c->item_size - (1+k);
3568 r = message_peek_body(m, &rindex, 1, 1, &q);
3573 r = message_peek_body(m, &rindex, 1, l+1, &q);
3577 if (!validate_signature(q, l))
3580 if (!streq(q, contents))
3586 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3592 static int build_struct_offsets(
3594 const char *signature,
3598 size_t *n_offsets) {
3600 unsigned n_variable = 0, n_total = 0, v;
3601 size_t previous = 0, where;
3612 if (isempty(signature)) {
3619 sz = determine_word_size(size, 0);
3623 /* First, loop over signature and count variable elements and
3624 * elements in general. We use this to know how large the
3625 * offset array is at the end of the structure. Note that
3626 * GVariant only stores offsets for all variable size elements
3627 * that are not the last item. */
3633 r = signature_element_length(p, &n);
3642 r = bus_gvariant_is_fixed_size(t);
3647 if (r == 0 && p[n] != 0) /* except the last item */
3654 if (size < n_variable * sz)
3657 where = m->rindex + size - (n_variable * sz);
3658 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3664 *offsets = new(size_t, n_total);
3670 /* Second, loop again and build an offset table */
3676 r = signature_element_length(p, &n);
3685 k = bus_gvariant_get_size(t);
3693 x = read_word_le((uint8_t*) q + v*sz, sz);
3696 if (m->rindex + x < previous)
3699 /* The last item's end
3700 * is determined from
3703 x = size - (n_variable * sz);
3705 offset = m->rindex + x;
3711 align = bus_gvariant_get_alignment(t);
3714 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3718 previous = (*offsets)[(*n_offsets)++] = offset;
3723 assert(*n_offsets == n_total);
3725 *item_size = (*offsets)[0] - m->rindex;
3729 static int enter_struct_or_dict_entry(
3731 struct bus_container *c,
3732 const char *contents,
3735 size_t *n_offsets) {
3746 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3749 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3753 } else if (c->item_size <= 0) {
3755 /* gvariant empty struct */
3760 /* gvariant with contents */
3761 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3766 static int bus_message_enter_struct(
3768 struct bus_container *c,
3769 const char *contents,
3772 size_t *n_offsets) {
3784 if (!signature_is_valid(contents, false))
3787 if (!c->signature || c->signature[c->index] == 0)
3790 l = strlen(contents);
3792 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3793 !startswith(c->signature + c->index + 1, contents) ||
3794 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3797 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3801 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3802 c->index += 1 + l + 1;
3807 static int bus_message_enter_dict_entry(
3809 struct bus_container *c,
3810 const char *contents,
3813 size_t *n_offsets) {
3822 if (!signature_is_pair(contents))
3825 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3828 if (!c->signature || c->signature[c->index] == 0)
3831 l = strlen(contents);
3833 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3834 !startswith(c->signature + c->index + 1, contents) ||
3835 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3838 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3842 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3843 c->index += 1 + l + 1;
3848 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3850 const char *contents) {
3851 struct bus_container *c, *w;
3852 uint32_t *array_size = NULL;
3855 size_t *offsets = NULL;
3856 size_t n_offsets = 0, item_size = 0;
3859 assert_return(m, -EINVAL);
3860 assert_return(m->sealed, -EPERM);
3861 assert_return(type != 0 || !contents, -EINVAL);
3863 if (type == 0 || !contents) {
3867 /* Allow entering into anonymous containers */
3868 r = sd_bus_message_peek_type(m, &tt, &cc);
3872 if (type != 0 && type != tt)
3875 if (contents && !streq(contents, cc))
3883 * We enforce a global limit on container depth, that is much
3884 * higher than the 32 structs and 32 arrays the specification
3885 * mandates. This is simpler to implement for us, and we need
3886 * this only to ensure our container array doesn't grow
3887 * without bounds. We are happy to return any data from a
3888 * message as long as the data itself is valid, even if the
3889 * overall message might be not.
3891 * Note that the message signature is validated when
3892 * parsing the headers, and that validation does check the
3895 * Note that the specification defines no limits on the depth
3896 * of stacked variants, but we do.
3898 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3901 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3904 if (message_end_of_signature(m))
3907 if (message_end_of_array(m, m->rindex))
3910 c = message_get_container(m);
3912 signature = strdup(contents);
3916 c->saved_index = c->index;
3919 if (type == SD_BUS_TYPE_ARRAY)
3920 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3921 else if (type == SD_BUS_TYPE_VARIANT)
3922 r = bus_message_enter_variant(m, c, contents, &item_size);
3923 else if (type == SD_BUS_TYPE_STRUCT)
3924 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3925 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3926 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3936 /* OK, let's fill it in */
3937 w = m->containers + m->n_containers++;
3938 w->enclosing = type;
3939 w->signature = signature;
3940 w->peeked_signature = NULL;
3944 w->begin = m->rindex;
3945 w->end = m->rindex + c->item_size;
3947 w->array_size = array_size;
3948 w->item_size = item_size;
3949 w->offsets = offsets;
3950 w->n_offsets = n_offsets;
3951 w->offset_index = 0;
3956 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3957 struct bus_container *c;
3961 assert_return(m, -EINVAL);
3962 assert_return(m->sealed, -EPERM);
3963 assert_return(m->n_containers > 0, -ENXIO);
3965 c = message_get_container(m);
3967 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3968 if (c->signature && c->signature[c->index] != 0)
3972 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3973 if (m->rindex < c->end)
3976 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3979 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3980 if (c->begin + l != m->rindex)
3985 free(c->peeked_signature);
3989 c = message_get_container(m);
3992 c->index = c->saved_index;
3993 r = container_next_item(m, c, &m->rindex);
4001 static void message_quit_container(sd_bus_message *m) {
4002 struct bus_container *c;
4006 assert(m->n_containers > 0);
4008 c = message_get_container(m);
4011 assert(m->rindex >= c->before);
4012 m->rindex = c->before;
4014 /* Free container */
4019 /* Correct index of new top-level container */
4020 c = message_get_container(m);
4021 c->index = c->saved_index;
4024 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4025 struct bus_container *c;
4028 assert_return(m, -EINVAL);
4029 assert_return(m->sealed, -EPERM);
4031 if (message_end_of_signature(m))
4034 if (message_end_of_array(m, m->rindex))
4037 c = message_get_container(m);
4039 if (bus_type_is_basic(c->signature[c->index])) {
4043 *type = c->signature[c->index];
4047 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4053 r = signature_element_length(c->signature+c->index+1, &l);
4059 sig = strndup(c->signature + c->index + 1, l);
4063 free(c->peeked_signature);
4064 *contents = c->peeked_signature = sig;
4068 *type = SD_BUS_TYPE_ARRAY;
4073 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4074 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4080 r = signature_element_length(c->signature+c->index, &l);
4085 sig = strndup(c->signature + c->index + 1, l - 2);
4089 free(c->peeked_signature);
4090 *contents = c->peeked_signature = sig;
4094 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4099 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4103 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4106 if (c->item_size < 2)
4109 /* Look for the NUL delimiter that
4110 separates the payload from the
4111 signature. Since the body might be
4112 in a different part that then the
4113 signature we map byte by byte. */
4115 for (k = 2; k <= c->item_size; k++) {
4118 where = m->rindex + c->item_size - k;
4119 r = message_peek_body(m, &where, 1, k, &q);
4123 if (*(char*) q == 0)
4127 if (k > c->item_size)
4130 free(c->peeked_signature);
4131 c->peeked_signature = strndup((char*) q + 1, k - 1);
4132 if (!c->peeked_signature)
4135 if (!signature_is_valid(c->peeked_signature, true))
4138 *contents = c->peeked_signature;
4143 r = message_peek_body(m, &rindex, 1, 1, &q);
4148 r = message_peek_body(m, &rindex, 1, l+1, &q);
4152 if (!validate_signature(q, l))
4160 *type = SD_BUS_TYPE_VARIANT;
4175 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4176 struct bus_container *c;
4178 assert_return(m, -EINVAL);
4179 assert_return(m->sealed, -EPERM);
4182 message_reset_containers(m);
4185 c = message_get_container(m);
4187 c = message_get_container(m);
4189 c->offset_index = 0;
4191 m->rindex = c->begin;
4194 c->offset_index = 0;
4195 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4197 return !isempty(c->signature);
4200 static int message_read_ap(
4205 unsigned n_array, n_struct;
4206 TypeStack stack[BUS_CONTAINER_DEPTH];
4207 unsigned stack_ptr = 0;
4208 unsigned n_loop = 0;
4216 /* Ideally, we'd just call ourselves recursively on every
4217 * complex type. However, the state of a va_list that is
4218 * passed to a function is undefined after that function
4219 * returns. This means we need to docode the va_list linearly
4220 * in a single stackframe. We hence implement our own
4221 * home-grown stack in an array. */
4223 n_array = (unsigned) -1; /* length of current array entries */
4224 n_struct = strlen(types); /* length of current struct contents signature */
4231 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4232 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4238 r = sd_bus_message_exit_container(m);
4246 if (n_array != (unsigned) -1)
4255 case SD_BUS_TYPE_BYTE:
4256 case SD_BUS_TYPE_BOOLEAN:
4257 case SD_BUS_TYPE_INT16:
4258 case SD_BUS_TYPE_UINT16:
4259 case SD_BUS_TYPE_INT32:
4260 case SD_BUS_TYPE_UINT32:
4261 case SD_BUS_TYPE_INT64:
4262 case SD_BUS_TYPE_UINT64:
4263 case SD_BUS_TYPE_DOUBLE:
4264 case SD_BUS_TYPE_STRING:
4265 case SD_BUS_TYPE_OBJECT_PATH:
4266 case SD_BUS_TYPE_SIGNATURE:
4267 case SD_BUS_TYPE_UNIX_FD: {
4270 p = va_arg(ap, void*);
4271 r = sd_bus_message_read_basic(m, *t, p);
4284 case SD_BUS_TYPE_ARRAY: {
4287 r = signature_element_length(t + 1, &k);
4293 memcpy(s, t + 1, k);
4296 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4307 if (n_array == (unsigned) -1) {
4312 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4318 n_array = va_arg(ap, unsigned);
4323 case SD_BUS_TYPE_VARIANT: {
4326 s = va_arg(ap, const char *);
4330 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4340 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4345 n_struct = strlen(s);
4346 n_array = (unsigned) -1;
4351 case SD_BUS_TYPE_STRUCT_BEGIN:
4352 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4355 r = signature_element_length(t, &k);
4361 memcpy(s, t + 1, k - 2);
4364 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4374 if (n_array == (unsigned) -1) {
4379 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4385 n_array = (unsigned) -1;
4398 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4402 assert_return(m, -EINVAL);
4403 assert_return(m->sealed, -EPERM);
4404 assert_return(types, -EINVAL);
4406 va_start(ap, types);
4407 r = message_read_ap(m, types, ap);
4413 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4416 assert_return(m, -EINVAL);
4417 assert_return(m->sealed, -EPERM);
4418 assert_return(types, -EINVAL);
4425 case SD_BUS_TYPE_BYTE:
4426 case SD_BUS_TYPE_BOOLEAN:
4427 case SD_BUS_TYPE_INT16:
4428 case SD_BUS_TYPE_UINT16:
4429 case SD_BUS_TYPE_INT32:
4430 case SD_BUS_TYPE_UINT32:
4431 case SD_BUS_TYPE_INT64:
4432 case SD_BUS_TYPE_UINT64:
4433 case SD_BUS_TYPE_DOUBLE:
4434 case SD_BUS_TYPE_STRING:
4435 case SD_BUS_TYPE_OBJECT_PATH:
4436 case SD_BUS_TYPE_SIGNATURE:
4437 case SD_BUS_TYPE_UNIX_FD:
4439 r = sd_bus_message_read_basic(m, *types, NULL);
4443 r = sd_bus_message_skip(m, types + 1);
4449 case SD_BUS_TYPE_ARRAY: {
4452 r = signature_element_length(types + 1, &k);
4458 memcpy(s, types+1, k);
4461 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4466 r = sd_bus_message_skip(m, s);
4473 r = sd_bus_message_exit_container(m);
4478 r = sd_bus_message_skip(m, types + 1 + k);
4485 case SD_BUS_TYPE_VARIANT: {
4486 const char *contents;
4489 r = sd_bus_message_peek_type(m, &x, &contents);
4493 if (x != SD_BUS_TYPE_VARIANT)
4496 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4500 r = sd_bus_message_skip(m, contents);
4505 r = sd_bus_message_exit_container(m);
4509 r = sd_bus_message_skip(m, types + 1);
4516 case SD_BUS_TYPE_STRUCT_BEGIN:
4517 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4520 r = signature_element_length(types, &k);
4526 memcpy(s, types+1, k-2);
4529 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4533 r = sd_bus_message_skip(m, s);
4538 r = sd_bus_message_exit_container(m);
4543 r = sd_bus_message_skip(m, types + k);
4555 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4559 struct bus_container *c;
4565 assert_return(m, -EINVAL);
4566 assert_return(m->sealed, -EPERM);
4567 assert_return(bus_type_is_trivial(type), -EINVAL);
4568 assert_return(ptr, -EINVAL);
4569 assert_return(size, -EINVAL);
4570 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4572 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4576 c = message_get_container(m);
4578 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4579 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4583 sz = c->end - c->begin;
4585 align = bus_type_get_alignment(type);
4589 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4593 /* Zero length array, let's return some aligned
4594 * pointer that is not NULL */
4595 p = (uint8_t*) NULL + align;
4597 r = message_peek_body(m, &m->rindex, align, sz, &p);
4602 r = sd_bus_message_exit_container(m);
4606 *ptr = (const void*) p;
4612 message_quit_container(m);
4616 static int message_peek_fields(
4627 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4630 static int message_peek_field_uint32(
4642 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4645 /* identical for gvariant and dbus1 */
4647 r = message_peek_fields(m, ri, 4, 4, &q);
4652 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4657 static int message_peek_field_string(
4659 bool (*validate)(const char *p),
4671 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4676 r = message_peek_fields(m, ri, 1, item_size, &q);
4682 r = message_peek_field_uint32(m, ri, 4, &l);
4686 r = message_peek_fields(m, ri, 1, l+1, &q);
4692 if (!validate_nul(q, l))
4698 if (!validate_string(q, l))
4708 static int message_peek_field_signature(
4721 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4726 r = message_peek_fields(m, ri, 1, item_size, &q);
4732 r = message_peek_fields(m, ri, 1, 1, &q);
4737 r = message_peek_fields(m, ri, 1, l+1, &q);
4742 if (!validate_signature(q, l))
4751 static int message_skip_fields(
4754 uint32_t array_size,
4755 const char **signature) {
4757 size_t original_index;
4763 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4765 original_index = *ri;
4771 if (array_size != (uint32_t) -1 &&
4772 array_size <= *ri - original_index)
4779 if (t == SD_BUS_TYPE_STRING) {
4781 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4787 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4789 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4795 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4797 r = message_peek_field_signature(m, ri, 0, NULL);
4803 } else if (bus_type_is_basic(t)) {
4806 align = bus_type_get_alignment(t);
4807 k = bus_type_get_size(t);
4808 assert(align > 0 && k > 0);
4810 r = message_peek_fields(m, ri, align, k, NULL);
4816 } else if (t == SD_BUS_TYPE_ARRAY) {
4818 r = signature_element_length(*signature+1, &l);
4828 strncpy(sig, *signature + 1, l-1);
4831 alignment = bus_type_get_alignment(sig[0]);
4835 r = message_peek_field_uint32(m, ri, 0, &nas);
4838 if (nas > BUS_ARRAY_MAX_SIZE)
4841 r = message_peek_fields(m, ri, alignment, 0, NULL);
4845 r = message_skip_fields(m, ri, nas, (const char**) &s);
4850 (*signature) += 1 + l;
4852 } else if (t == SD_BUS_TYPE_VARIANT) {
4855 r = message_peek_field_signature(m, ri, 0, &s);
4859 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4865 } else if (t == SD_BUS_TYPE_STRUCT ||
4866 t == SD_BUS_TYPE_DICT_ENTRY) {
4868 r = signature_element_length(*signature, &l);
4875 strncpy(sig, *signature + 1, l-1);
4878 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4889 int bus_message_parse_fields(sd_bus_message *m) {
4892 uint32_t unix_fds = 0;
4893 bool unix_fds_set = false;
4894 void *offsets = NULL;
4895 unsigned n_offsets = 0;
4901 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4904 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4908 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4909 r = message_peek_fields(m, &ri, 1, sz, &q);
4913 framing = read_word_le(q, sz);
4914 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4916 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4920 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4924 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4929 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4930 _cleanup_free_ char *sig = NULL;
4931 const char *signature;
4933 size_t item_size = (size_t) -1;
4935 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4942 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4945 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4949 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4954 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4959 where = ri = ALIGN_TO(ri, 8);
4960 item_size = end - ri;
4961 r = message_peek_fields(m, &where, 1, item_size, &q);
4965 b = memrchr(q, 0, item_size);
4969 sig = strndup(b+1, item_size - (b+1-(char*) q));
4974 item_size = b - (char*) q;
4976 r = message_peek_field_signature(m, &ri, 0, &signature);
4982 case _BUS_MESSAGE_HEADER_INVALID:
4985 case BUS_MESSAGE_HEADER_PATH:
4990 if (!streq(signature, "o"))
4993 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
4996 case BUS_MESSAGE_HEADER_INTERFACE:
5001 if (!streq(signature, "s"))
5004 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5007 case BUS_MESSAGE_HEADER_MEMBER:
5012 if (!streq(signature, "s"))
5015 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5018 case BUS_MESSAGE_HEADER_ERROR_NAME:
5023 if (!streq(signature, "s"))
5026 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5028 m->error._need_free = -1;
5032 case BUS_MESSAGE_HEADER_DESTINATION:
5037 if (!streq(signature, "s"))
5040 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5043 case BUS_MESSAGE_HEADER_SENDER:
5048 if (!streq(signature, "s"))
5051 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5053 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5054 m->creds.unique_name = (char*) m->sender;
5055 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5061 case BUS_MESSAGE_HEADER_SIGNATURE: {
5065 if (m->root_container.signature)
5068 if (!streq(signature, "g"))
5071 r = message_peek_field_signature(m, &ri, item_size, &s);
5079 free(m->root_container.signature);
5080 m->root_container.signature = c;
5084 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5087 if (m->reply_cookie != 0)
5090 if (!streq(signature, "u"))
5093 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5097 m->reply_cookie = serial;
5099 if (m->reply_cookie == 0)
5105 case BUS_MESSAGE_HEADER_UNIX_FDS:
5109 if (!streq(signature, "u"))
5112 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5116 unix_fds_set = true;
5120 if (!BUS_MESSAGE_IS_GVARIANT(m))
5121 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5130 if (m->n_fds != unix_fds)
5133 switch (m->header->type) {
5135 case SD_BUS_MESSAGE_SIGNAL:
5136 if (!m->path || !m->interface || !m->member)
5140 case SD_BUS_MESSAGE_METHOD_CALL:
5142 if (!m->path || !m->member)
5147 case SD_BUS_MESSAGE_METHOD_RETURN:
5149 if (m->reply_cookie == 0)
5153 case SD_BUS_MESSAGE_METHOD_ERROR:
5155 if (m->reply_cookie == 0 || !m->error.name)
5160 /* Refuse non-local messages that claim they are local */
5161 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5163 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5165 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5168 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5170 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5171 r = build_struct_offsets(
5173 m->root_container.signature,
5174 BUS_MESSAGE_BODY_SIZE(m),
5175 &m->root_container.item_size,
5176 &m->root_container.offsets,
5177 &m->root_container.n_offsets);
5182 /* Try to read the error message, but if we can't it's a non-issue */
5183 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5184 sd_bus_message_read(m, "s", &m->error.message);
5189 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5190 assert_return(m, -EINVAL);
5191 assert_return(destination, -EINVAL);
5192 assert_return(!m->sealed, -EPERM);
5193 assert_return(!m->destination, -EEXIST);
5195 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5198 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5202 struct bus_body_part *part;
5208 total = BUS_MESSAGE_SIZE(m);
5214 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5215 MESSAGE_FOREACH_PART(part, i, m)
5216 e = mempcpy(e, part->data, part->size);
5218 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5226 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5232 r = sd_bus_message_enter_container(m, 'a', "s");
5239 r = sd_bus_message_read_basic(m, 's', &s);
5245 r = strv_extend(l, s);
5250 r = sd_bus_message_exit_container(m);
5257 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5261 assert_return(m, -EINVAL);
5262 assert_return(m->sealed, -EPERM);
5263 assert_return(l, -EINVAL);
5265 r = bus_message_read_strv_extend(m, &strv);
5275 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5277 const char *t = NULL;
5282 r = sd_bus_message_rewind(m, true);
5286 for (j = 0; j <= i; j++) {
5289 r = sd_bus_message_peek_type(m, &type, NULL);
5293 if (type != SD_BUS_TYPE_STRING &&
5294 type != SD_BUS_TYPE_OBJECT_PATH &&
5295 type != SD_BUS_TYPE_SIGNATURE)
5298 r = sd_bus_message_read_basic(m, type, &t);
5306 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5312 if (size < sizeof(struct bus_header))
5315 full = sizeof(struct bus_header) +
5316 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5318 return size >= full;
5321 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5327 if (h->endian == BUS_NATIVE_ENDIAN) {
5328 fs = h->fields_size;
5330 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5331 fs = bswap_32(h->fields_size);
5332 bs = bswap_32(h->body_size);
5336 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5340 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5341 assert_return(m, EINVAL);
5343 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5346 return sd_bus_error_get_errno(&m->error);
5349 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5350 struct bus_container *c;
5352 assert_return(m, NULL);
5354 c = complete ? &m->root_container : message_get_container(m);
5355 return strempty(c->signature);
5358 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5359 bool done_something = false;
5362 assert_return(m, -EINVAL);
5363 assert_return(source, -EINVAL);
5364 assert_return(!m->sealed, -EPERM);
5365 assert_return(source->sealed, -EPERM);
5368 const char *contents;
5383 r = sd_bus_message_peek_type(source, &type, &contents);
5389 done_something = true;
5391 if (bus_type_is_container(type) > 0) {
5393 r = sd_bus_message_enter_container(source, type, contents);
5397 r = sd_bus_message_open_container(m, type, contents);
5401 r = sd_bus_message_copy(m, source, true);
5405 r = sd_bus_message_close_container(m);
5409 r = sd_bus_message_exit_container(source);
5416 r = sd_bus_message_read_basic(source, type, &basic);
5422 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5423 type == SD_BUS_TYPE_SIGNATURE ||
5424 type == SD_BUS_TYPE_STRING)
5425 r = sd_bus_message_append_basic(m, type, basic.string);
5427 r = sd_bus_message_append_basic(m, type, &basic);
5434 return done_something;
5437 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5442 assert_return(m, -EINVAL);
5443 assert_return(m->sealed, -EPERM);
5444 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5445 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5446 assert_return(type || contents, -EINVAL);
5447 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5449 r = sd_bus_message_peek_type(m, &t, &c);
5453 if (type != 0 && type != t)
5456 if (contents && !streq_ptr(contents, c))
5462 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5463 assert_return(m, NULL);
5468 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5469 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5477 switch ((*m)->header->type) {
5479 case SD_BUS_MESSAGE_SIGNAL:
5480 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5486 case SD_BUS_MESSAGE_METHOD_CALL:
5487 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5493 case SD_BUS_MESSAGE_METHOD_RETURN:
5494 case SD_BUS_MESSAGE_METHOD_ERROR:
5496 n = message_new(bus, (*m)->header->type);
5500 n->reply_cookie = (*m)->reply_cookie;
5501 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5505 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5506 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5510 n->error._need_free = -1;
5519 if ((*m)->destination && !n->destination) {
5520 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5525 if ((*m)->sender && !n->sender) {
5526 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5531 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5533 r = sd_bus_message_copy(n, *m, true);
5537 timeout = (*m)->timeout;
5538 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5539 timeout = BUS_DEFAULT_TIMEOUT;
5541 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5545 sd_bus_message_unref(*m);
5552 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5556 assert_return(!m->sealed, -EPERM);
5557 assert_return(!m->sender, -EPERM);
5559 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5562 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5563 assert_return(m, -EINVAL);
5564 assert_return(priority, -EINVAL);
5566 *priority = m->priority;
5570 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5571 assert_return(m, -EINVAL);
5572 assert_return(!m->sealed, -EPERM);
5574 m->priority = priority;