1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include "time-util.h"
30 #include "cgroup-util.h"
31 #include "memfd-util.h"
34 #include "bus-message.h"
35 #include "bus-internal.h"
37 #include "bus-signature.h"
38 #include "bus-gvariant.h"
41 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
43 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
48 if (old_base == new_base)
51 if ((uint8_t*) p < (uint8_t*) old_base)
54 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
57 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
60 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
64 if (part->memfd >= 0) {
65 /* If we can reuse the memfd, try that. For that it
66 * can't be sealed yet. */
69 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
72 assert_se(munmap(part->data, part->mapped) == 0);
74 safe_close(part->memfd);
77 } else if (part->munmap_this)
78 munmap(part->data, part->mapped);
79 else if (part->free_this)
86 static void message_reset_parts(sd_bus_message *m) {
87 struct bus_body_part *part;
92 while (m->n_body_parts > 0) {
93 struct bus_body_part *next = part->next;
94 message_free_part(m, part);
101 m->cached_rindex_part = NULL;
102 m->cached_rindex_part_begin = 0;
105 static void message_reset_containers(sd_bus_message *m) {
110 for (i = 0; i < m->n_containers; i++) {
111 free(m->containers[i].signature);
112 free(m->containers[i].offsets);
116 m->containers = NULL;
118 m->n_containers = m->containers_allocated = 0;
119 m->root_container.index = 0;
122 static void message_free(sd_bus_message *m) {
128 message_reset_parts(m);
130 if (m->release_kdbus) {
131 struct kdbus_cmd_free cmd_free;
134 cmd_free.offset = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
135 (void) ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &cmd_free);
141 sd_bus_unref(m->bus);
144 close_many(m->fds, m->n_fds);
148 if (m->iovec != m->iovec_fixed)
151 if (m->destination_ptr) {
152 free(m->destination_ptr);
153 m->destination_ptr = NULL;
156 message_reset_containers(m);
157 free(m->root_container.signature);
158 free(m->root_container.offsets);
160 free(m->root_container.peeked_signature);
162 bus_creds_done(&m->creds);
166 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
168 size_t old_size, new_size, start;
175 old_size = sizeof(struct bus_header) + m->header->fields_size;
176 start = ALIGN_TO(old_size, align);
177 new_size = start + sz;
179 if (old_size == new_size)
180 return (uint8_t*) m->header + old_size;
182 if (new_size > (size_t) ((uint32_t) -1))
185 if (m->free_header) {
186 np = realloc(m->header, ALIGN8(new_size));
190 /* Initially, the header is allocated as part of of
191 * the sd_bus_message itself, let's replace it by
194 np = malloc(ALIGN8(new_size));
198 memcpy(np, m->header, sizeof(struct bus_header));
201 /* Zero out padding */
202 if (start > old_size)
203 memzero((uint8_t*) np + old_size, start - old_size);
207 m->header->fields_size = new_size - sizeof(struct bus_header);
209 /* Adjust quick access pointers */
210 m->path = adjust_pointer(m->path, op, old_size, m->header);
211 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
212 m->member = adjust_pointer(m->member, op, old_size, m->header);
213 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
214 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
215 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
217 m->free_header = true;
220 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
223 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
226 return (uint8_t*) np + start;
233 static int message_append_field_string(
245 /* dbus1 doesn't allow strings over 32bit, let's enforce this
246 * globally, to not risk convertability */
248 if (l > (size_t) (uint32_t) -1)
251 /* Signature "(yv)" where the variant contains "s" */
253 if (BUS_MESSAGE_IS_GVARIANT(m)) {
255 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
256 p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
268 *ret = (char*) p + 8;
271 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
272 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
281 ((uint32_t*) p)[1] = l;
282 memcpy(p + 8, s, l + 1);
285 *ret = (char*) p + 8;
291 static int message_append_field_signature(
302 /* dbus1 doesn't allow signatures over 32bit, let's enforce
303 * this globally, to not risk convertability */
308 /* Signature "(yv)" where the variant contains "g" */
310 if (BUS_MESSAGE_IS_GVARIANT(m))
311 /* For gvariant the serialization is the same as for normal strings */
312 return message_append_field_string(m, h, 'g', s, ret);
314 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
315 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
321 p[2] = SD_BUS_TYPE_SIGNATURE;
324 memcpy(p + 5, s, l + 1);
327 *ret = (const char*) p + 5;
333 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
338 if (BUS_MESSAGE_IS_GVARIANT(m)) {
339 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
341 p = message_extend_fields(m, 8, 1 + 7 + 4 + 1 + 1, true);
347 *((uint32_t*) (p + 8)) = x;
351 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
352 p = message_extend_fields(m, 8, 4 + 4, false);
358 p[2] = SD_BUS_TYPE_UINT32;
361 ((uint32_t*) p)[1] = x;
367 int bus_message_from_header(
373 const struct ucred *ucred,
376 sd_bus_message **ret) {
379 struct bus_header *h;
383 assert(buffer || length <= 0);
384 assert(fds || n_fds <= 0);
387 if (length < sizeof(struct bus_header))
391 if (h->version != 1 &&
398 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
401 if (h->endian != BUS_LITTLE_ENDIAN &&
402 h->endian != BUS_BIG_ENDIAN)
405 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
408 label_sz = strlen(label);
423 m->creds.pid = ucred->pid;
424 m->creds.uid = ucred->uid;
425 m->creds.gid = ucred->gid;
427 /* Due to namespace translations some data might be
428 * missing from this ucred record. */
429 if (m->creds.pid > 0)
430 m->creds.mask |= SD_BUS_CREDS_PID;
432 if (m->creds.uid != (uid_t) -1)
433 m->creds.mask |= SD_BUS_CREDS_UID;
435 if (m->creds.gid != (gid_t) -1)
436 m->creds.mask |= SD_BUS_CREDS_GID;
440 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
441 memcpy(m->creds.label, label, label_sz + 1);
443 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
446 m->bus = sd_bus_ref(bus);
452 int bus_message_from_malloc(
458 const struct ucred *ucred,
460 sd_bus_message **ret) {
466 r = bus_message_from_header(bus, buffer, length, fds, n_fds, ucred, label, 0, &m);
470 if (length != BUS_MESSAGE_SIZE(m)) {
475 sz = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
478 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
480 m->body.sealed = true;
485 m->iovec = m->iovec_fixed;
486 m->iovec[0].iov_base = buffer;
487 m->iovec[0].iov_len = length;
489 r = bus_message_parse_fields(m);
493 /* We take possession of the memory and fds now */
494 m->free_header = true;
505 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
510 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
515 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
516 m->header->endian = BUS_NATIVE_ENDIAN;
517 m->header->type = type;
518 m->header->version = bus ? bus->message_version : 1;
519 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
520 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
521 m->bus = sd_bus_ref(bus);
526 _public_ int sd_bus_message_new_signal(
530 const char *interface,
531 const char *member) {
536 assert_return(bus, -ENOTCONN);
537 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
538 assert_return(object_path_is_valid(path), -EINVAL);
539 assert_return(interface_name_is_valid(interface), -EINVAL);
540 assert_return(member_name_is_valid(member), -EINVAL);
541 assert_return(m, -EINVAL);
543 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
547 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
549 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
552 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
555 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
563 sd_bus_message_unref(t);
567 _public_ int sd_bus_message_new_method_call(
570 const char *destination,
572 const char *interface,
573 const char *member) {
578 assert_return(bus, -ENOTCONN);
579 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
580 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
581 assert_return(object_path_is_valid(path), -EINVAL);
582 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
583 assert_return(member_name_is_valid(member), -EINVAL);
584 assert_return(m, -EINVAL);
586 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
590 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
593 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
598 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
604 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
617 static int message_new_reply(
618 sd_bus_message *call,
620 sd_bus_message **m) {
625 assert_return(call, -EINVAL);
626 assert_return(call->sealed, -EPERM);
627 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
628 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
629 assert_return(m, -EINVAL);
631 t = message_new(call->bus, type);
635 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
636 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
638 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
643 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
648 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
649 t->enforced_reply_signature = call->enforced_reply_signature;
659 _public_ int sd_bus_message_new_method_return(
660 sd_bus_message *call,
661 sd_bus_message **m) {
663 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
666 _public_ int sd_bus_message_new_method_error(
667 sd_bus_message *call,
669 const sd_bus_error *e) {
674 assert_return(sd_bus_error_is_set(e), -EINVAL);
675 assert_return(m, -EINVAL);
677 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
681 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
686 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
691 t->error._need_free = -1;
701 _public_ int sd_bus_message_new_method_errorf(
702 sd_bus_message *call,
708 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
711 assert_return(name, -EINVAL);
712 assert_return(m, -EINVAL);
714 va_start(ap, format);
715 bus_error_setfv(&error, name, format, ap);
718 return sd_bus_message_new_method_error(call, m, &error);
721 _public_ int sd_bus_message_new_method_errno(
722 sd_bus_message *call,
725 const sd_bus_error *p) {
727 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
729 if (sd_bus_error_is_set(p))
730 return sd_bus_message_new_method_error(call, m, p);
732 sd_bus_error_set_errno(&berror, error);
734 return sd_bus_message_new_method_error(call, m, &berror);
737 _public_ int sd_bus_message_new_method_errnof(
738 sd_bus_message *call,
744 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
747 va_start(ap, format);
748 bus_error_set_errnofv(&berror, error, format, ap);
751 return sd_bus_message_new_method_error(call, m, &berror);
754 int bus_message_new_synthetic_error(
757 const sd_bus_error *e,
758 sd_bus_message **m) {
764 assert(sd_bus_error_is_set(e));
767 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
771 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
772 t->reply_cookie = cookie;
774 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
778 if (bus && bus->unique_name) {
779 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
784 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
789 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
794 t->error._need_free = -1;
804 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
805 assert_return(m, NULL);
807 assert(m->n_ref > 0);
813 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
818 assert(m->n_ref > 0);
828 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
829 assert_return(m, -EINVAL);
830 assert_return(type, -EINVAL);
832 *type = m->header->type;
836 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
837 assert_return(m, -EINVAL);
838 assert_return(cookie, -EINVAL);
839 assert_return(m->header->serial != 0, -ENODATA);
841 *cookie = BUS_MESSAGE_COOKIE(m);
845 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
846 assert_return(m, -EINVAL);
847 assert_return(cookie, -EINVAL);
848 assert_return(m->reply_cookie != 0, -ENODATA);
850 *cookie = m->reply_cookie;
854 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
855 assert_return(m, -EINVAL);
857 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
858 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
861 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
862 assert_return(m, -EINVAL);
864 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
867 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
868 assert_return(m, -EINVAL);
870 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
871 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
874 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
875 assert_return(m, NULL);
880 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
881 assert_return(m, NULL);
886 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
887 assert_return(m, NULL);
892 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
893 assert_return(m, NULL);
895 return m->destination;
898 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
899 assert_return(m, NULL);
904 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
905 assert_return(m, NULL);
906 assert_return(sd_bus_error_is_set(&m->error), NULL);
911 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
912 assert_return(m, -EINVAL);
913 assert_return(usec, -EINVAL);
915 if (m->monotonic <= 0)
918 *usec = m->monotonic;
922 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
923 assert_return(m, -EINVAL);
924 assert_return(usec, -EINVAL);
926 if (m->realtime <= 0)
933 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
934 assert_return(m, -EINVAL);
935 assert_return(seqnum, -EINVAL);
944 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
945 assert_return(m, NULL);
947 if (m->creds.mask == 0)
953 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
954 const char *interface,
955 const char *member) {
956 assert_return(m, -EINVAL);
958 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
961 if (interface && (!m->interface || !streq(m->interface, interface)))
964 if (member && (!m->member || !streq(m->member, member)))
970 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
971 const char *interface,
972 const char *member) {
973 assert_return(m, -EINVAL);
975 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
978 if (interface && (!m->interface || !streq(m->interface, interface)))
981 if (member && (!m->member || !streq(m->member, member)))
987 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
988 assert_return(m, -EINVAL);
990 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
993 if (name && (!m->error.name || !streq(m->error.name, name)))
999 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1000 assert_return(m, -EINVAL);
1001 assert_return(!m->sealed, -EPERM);
1002 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1005 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1007 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1012 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1013 assert_return(m, -EINVAL);
1014 assert_return(!m->sealed, -EPERM);
1017 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1019 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1024 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1025 assert_return(m, -EINVAL);
1026 assert_return(!m->sealed, -EPERM);
1029 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1031 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1036 static struct bus_container *message_get_container(sd_bus_message *m) {
1039 if (m->n_containers == 0)
1040 return &m->root_container;
1042 assert(m->containers);
1043 return m->containers + m->n_containers - 1;
1046 struct bus_body_part *message_append_part(sd_bus_message *m) {
1047 struct bus_body_part *part;
1054 if (m->n_body_parts <= 0) {
1058 assert(m->body_end);
1060 part = new0(struct bus_body_part, 1);
1066 m->body_end->next = part;
1076 static void part_zero(struct bus_body_part *part, size_t sz) {
1081 /* All other fields can be left in their defaults */
1082 assert(!part->data);
1083 assert(part->memfd < 0);
1086 part->is_zero = true;
1087 part->sealed = true;
1090 static int part_make_space(
1091 struct sd_bus_message *m,
1092 struct bus_body_part *part,
1101 assert(!part->sealed);
1106 if (!part->data && part->memfd < 0)
1107 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1109 if (part->memfd >= 0) {
1111 if (part->allocated == 0 || sz > part->allocated) {
1112 uint64_t new_allocated;
1114 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1115 r = memfd_set_size(part->memfd, new_allocated);
1121 part->allocated = new_allocated;
1124 if (!part->data || sz > part->mapped) {
1127 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1128 if (part->mapped <= 0)
1129 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1131 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1133 if (n == MAP_FAILED) {
1142 part->munmap_this = true;
1144 if (part->allocated == 0 || sz > part->allocated) {
1145 size_t new_allocated;
1147 new_allocated = sz > 0 ? 2 * sz : 64;
1148 n = realloc(part->data, new_allocated);
1155 part->allocated = new_allocated;
1156 part->free_this = true;
1161 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1167 static int message_add_offset(sd_bus_message *m, size_t offset) {
1168 struct bus_container *c;
1171 assert(BUS_MESSAGE_IS_GVARIANT(m));
1173 /* Add offset to current container, unless this is the first
1174 * item in it, which will have the 0 offset, which we can
1176 c = message_get_container(m);
1178 if (!c->need_offsets)
1181 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1184 c->offsets[c->n_offsets++] = offset;
1188 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1189 struct bus_container *c;
1196 /* Update counters */
1197 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1200 *c->array_size += expand;
1204 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1205 size_t start_body, end_body, padding, added;
1216 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1217 end_body = start_body + sz;
1219 padding = start_body - m->header->body_size;
1220 added = padding + sz;
1222 /* Check for 32bit overflows */
1223 if (end_body > (size_t) ((uint32_t) -1)) {
1229 struct bus_body_part *part = NULL;
1233 m->n_body_parts <= 0 ||
1234 m->body_end->sealed ||
1235 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1239 part = message_append_part(m);
1243 part_zero(part, padding);
1246 part = message_append_part(m);
1250 r = part_make_space(m, part, sz, &p);
1254 struct bus_container *c;
1256 size_t os, start_part, end_part;
1262 start_part = ALIGN_TO(part->size, align);
1263 end_part = start_part + sz;
1265 r = part_make_space(m, part, end_part, &p);
1270 memzero(p, padding);
1271 p = (uint8_t*) p + padding;
1274 /* Readjust pointers */
1275 for (c = m->containers; c < m->containers + m->n_containers; c++)
1276 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1278 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1281 /* Return something that is not NULL and is aligned */
1282 p = (uint8_t *) NULL + align;
1284 m->header->body_size = end_body;
1285 message_extend_containers(m, added);
1288 r = message_add_offset(m, end_body);
1298 static int message_push_fd(sd_bus_message *m, int fd) {
1309 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1313 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1321 m->fds[m->n_fds] = copy;
1327 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1328 _cleanup_close_ int fd = -1;
1329 struct bus_container *c;
1333 assert_return(m, -EINVAL);
1334 assert_return(!m->sealed, -EPERM);
1335 assert_return(bus_type_is_basic(type), -EINVAL);
1336 assert_return(!m->poisoned, -ESTALE);
1338 c = message_get_container(m);
1340 if (c->signature && c->signature[c->index]) {
1341 /* Container signature is already set */
1343 if (c->signature[c->index] != type)
1348 /* Maybe we can append to the signature? But only if this is the top-level container*/
1349 if (c->enclosing != 0)
1352 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1359 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1365 case SD_BUS_TYPE_SIGNATURE:
1366 case SD_BUS_TYPE_STRING:
1369 /* Fall through... */
1370 case SD_BUS_TYPE_OBJECT_PATH:
1378 case SD_BUS_TYPE_BOOLEAN:
1380 u8 = p && *(int*) p;
1386 case SD_BUS_TYPE_UNIX_FD:
1391 fd = message_push_fd(m, *(int*) p);
1402 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1403 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1410 a = message_extend_body(m, align, sz, true);
1417 *stored = (const uint8_t*) a;
1424 case SD_BUS_TYPE_STRING:
1425 /* To make things easy we'll serialize a NULL string
1426 * into the empty string */
1429 /* Fall through... */
1430 case SD_BUS_TYPE_OBJECT_PATH:
1436 sz = 4 + strlen(p) + 1;
1439 case SD_BUS_TYPE_SIGNATURE:
1444 sz = 1 + strlen(p) + 1;
1447 case SD_BUS_TYPE_BOOLEAN:
1449 u32 = p && *(int*) p;
1455 case SD_BUS_TYPE_UNIX_FD:
1460 fd = message_push_fd(m, *(int*) p);
1471 align = bus_type_get_alignment(type);
1472 sz = bus_type_get_size(type);
1479 a = message_extend_body(m, align, sz, false);
1483 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1484 *(uint32_t*) a = sz - 5;
1485 memcpy((uint8_t*) a + 4, p, sz - 4);
1488 *stored = (const uint8_t*) a + 4;
1490 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1491 *(uint8_t*) a = sz - 2;
1492 memcpy((uint8_t*) a + 1, p, sz - 1);
1495 *stored = (const uint8_t*) a + 1;
1504 if (type == SD_BUS_TYPE_UNIX_FD)
1507 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1514 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1515 return message_append_basic(m, type, p, NULL);
1518 _public_ int sd_bus_message_append_string_space(
1523 struct bus_container *c;
1526 assert_return(m, -EINVAL);
1527 assert_return(s, -EINVAL);
1528 assert_return(!m->sealed, -EPERM);
1529 assert_return(!m->poisoned, -ESTALE);
1531 c = message_get_container(m);
1533 if (c->signature && c->signature[c->index]) {
1534 /* Container signature is already set */
1536 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1541 /* Maybe we can append to the signature? But only if this is the top-level container*/
1542 if (c->enclosing != 0)
1545 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1552 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1553 a = message_extend_body(m, 1, size + 1, true);
1559 a = message_extend_body(m, 4, 4 + size + 1, false);
1563 *(uint32_t*) a = size;
1569 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1575 _public_ int sd_bus_message_append_string_iovec(
1577 const struct iovec *iov,
1585 assert_return(m, -EINVAL);
1586 assert_return(!m->sealed, -EPERM);
1587 assert_return(iov || n == 0, -EINVAL);
1588 assert_return(!m->poisoned, -ESTALE);
1590 size = IOVEC_TOTAL_SIZE(iov, n);
1592 r = sd_bus_message_append_string_space(m, size, &p);
1596 for (i = 0; i < n; i++) {
1598 if (iov[i].iov_base)
1599 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1601 memset(p, ' ', iov[i].iov_len);
1603 p += iov[i].iov_len;
1609 static int bus_message_open_array(
1611 struct bus_container *c,
1612 const char *contents,
1613 uint32_t **array_size,
1615 bool *need_offsets) {
1625 assert(need_offsets);
1627 if (!signature_is_single(contents, true))
1630 if (c->signature && c->signature[c->index]) {
1632 /* Verify the existing signature */
1634 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1637 if (!startswith(c->signature + c->index + 1, contents))
1640 nindex = c->index + 1 + strlen(contents);
1644 if (c->enclosing != 0)
1647 /* Extend the existing signature */
1649 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1655 nindex = e - c->signature;
1658 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1659 alignment = bus_gvariant_get_alignment(contents);
1663 /* Add alignment padding and add to offset list */
1664 if (!message_extend_body(m, alignment, 0, false))
1667 r = bus_gvariant_is_fixed_size(contents);
1671 *begin = m->header->body_size;
1672 *need_offsets = r == 0;
1676 struct bus_body_part *o;
1678 alignment = bus_type_get_alignment(contents[0]);
1682 a = message_extend_body(m, 4, 4, false);
1687 op = m->body_end->data;
1688 os = m->body_end->size;
1690 /* Add alignment between size and first element */
1691 if (!message_extend_body(m, alignment, 0, false))
1694 /* location of array size might have changed so let's readjust a */
1695 if (o == m->body_end)
1696 a = adjust_pointer(a, op, os, m->body_end->data);
1702 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1708 static int bus_message_open_variant(
1710 struct bus_container *c,
1711 const char *contents) {
1717 if (!signature_is_single(contents, false))
1720 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1723 if (c->signature && c->signature[c->index]) {
1725 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1731 if (c->enclosing != 0)
1734 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1741 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1742 /* Variants are always aligned to 8 */
1744 if (!message_extend_body(m, 8, 0, false))
1751 l = strlen(contents);
1752 a = message_extend_body(m, 1, 1 + l + 1, false);
1757 memcpy((uint8_t*) a + 1, contents, l + 1);
1760 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1766 static int bus_message_open_struct(
1768 struct bus_container *c,
1769 const char *contents,
1771 bool *need_offsets) {
1780 assert(need_offsets);
1782 if (!signature_is_valid(contents, false))
1785 if (c->signature && c->signature[c->index]) {
1788 l = strlen(contents);
1790 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1791 !startswith(c->signature + c->index + 1, contents) ||
1792 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1795 nindex = c->index + 1 + l + 1;
1799 if (c->enclosing != 0)
1802 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1808 nindex = e - c->signature;
1811 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1814 alignment = bus_gvariant_get_alignment(contents);
1818 if (!message_extend_body(m, alignment, 0, false))
1821 r = bus_gvariant_is_fixed_size(contents);
1825 *begin = m->header->body_size;
1826 *need_offsets = r == 0;
1828 /* Align contents to 8 byte boundary */
1829 if (!message_extend_body(m, 8, 0, false))
1833 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1839 static int bus_message_open_dict_entry(
1841 struct bus_container *c,
1842 const char *contents,
1844 bool *need_offsets) {
1852 assert(need_offsets);
1854 if (!signature_is_pair(contents))
1857 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1860 if (c->signature && c->signature[c->index]) {
1863 l = strlen(contents);
1865 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1866 !startswith(c->signature + c->index + 1, contents) ||
1867 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1872 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1875 alignment = bus_gvariant_get_alignment(contents);
1879 if (!message_extend_body(m, alignment, 0, false))
1882 r = bus_gvariant_is_fixed_size(contents);
1886 *begin = m->header->body_size;
1887 *need_offsets = r == 0;
1889 /* Align contents to 8 byte boundary */
1890 if (!message_extend_body(m, 8, 0, false))
1897 _public_ int sd_bus_message_open_container(
1900 const char *contents) {
1902 struct bus_container *c, *w;
1903 uint32_t *array_size = NULL;
1905 size_t before, begin = 0;
1906 bool need_offsets = false;
1909 assert_return(m, -EINVAL);
1910 assert_return(!m->sealed, -EPERM);
1911 assert_return(contents, -EINVAL);
1912 assert_return(!m->poisoned, -ESTALE);
1914 /* Make sure we have space for one more container */
1915 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1920 c = message_get_container(m);
1922 signature = strdup(contents);
1928 /* Save old index in the parent container, in case we have to
1929 * abort this container */
1930 c->saved_index = c->index;
1931 before = m->header->body_size;
1933 if (type == SD_BUS_TYPE_ARRAY)
1934 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1935 else if (type == SD_BUS_TYPE_VARIANT)
1936 r = bus_message_open_variant(m, c, contents);
1937 else if (type == SD_BUS_TYPE_STRUCT)
1938 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1939 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1940 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1949 /* OK, let's fill it in */
1950 w = m->containers + m->n_containers++;
1951 w->enclosing = type;
1952 w->signature = signature;
1954 w->array_size = array_size;
1957 w->n_offsets = w->offsets_allocated = 0;
1959 w->need_offsets = need_offsets;
1964 static size_t determine_word_size(size_t sz, size_t extra) {
1965 if (sz + extra <= 0xFF)
1967 else if (sz + extra*2 <= 0xFFFF)
1969 else if (sz + extra*4 <= 0xFFFFFFFF)
1975 static size_t read_word_le(void *p, size_t sz) {
1985 return *(uint8_t*) p;
1990 return le16toh(x.u16);
1992 return le32toh(x.u32);
1994 return le64toh(x.u64);
1996 assert_not_reached("unknown word width");
1999 static void write_word_le(void *p, size_t sz, size_t value) {
2007 assert(sz == 8 || (value < (1ULL << (sz*8))));
2010 *(uint8_t*) p = value;
2013 x.u16 = htole16((uint16_t) value);
2015 x.u32 = htole32((uint32_t) value);
2017 x.u64 = htole64((uint64_t) value);
2019 assert_not_reached("unknown word width");
2024 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2029 if (!BUS_MESSAGE_IS_GVARIANT(m))
2032 if (c->need_offsets) {
2033 size_t payload, sz, i;
2036 /* Variable-width arrays */
2038 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2039 sz = determine_word_size(payload, c->n_offsets);
2041 a = message_extend_body(m, 1, sz * c->n_offsets, true);
2045 for (i = 0; i < c->n_offsets; i++)
2046 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2050 /* Fixed-width or empty arrays */
2052 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
2060 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2067 if (!BUS_MESSAGE_IS_GVARIANT(m))
2070 l = strlen(c->signature);
2072 a = message_extend_body(m, 1, 1 + l, true);
2077 memcpy(a+1, c->signature, l);
2082 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2083 size_t n_variable = 0;
2092 if (!BUS_MESSAGE_IS_GVARIANT(m))
2095 p = strempty(c->signature);
2099 r = signature_element_length(p, &n);
2108 r = bus_gvariant_is_fixed_size(t);
2113 assert(!c->need_offsets || i <= c->n_offsets);
2115 /* We need to add an offset for each item that has a
2116 * variable size and that is not the last one in the
2118 if (r == 0 && p[n] != 0)
2125 assert(!c->need_offsets || i == c->n_offsets);
2126 assert(c->need_offsets || n_variable == 0);
2128 if (n_variable <= 0) {
2129 a = message_extend_body(m, 1, 0, add_offset);
2136 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2138 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2140 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2144 p = strempty(c->signature);
2145 for (i = 0, j = 0; i < c->n_offsets; i++) {
2149 r = signature_element_length(p, &n);
2160 r = bus_gvariant_is_fixed_size(t);
2163 if (r > 0 || p[0] == 0)
2167 k = n_variable - 1 - j;
2169 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2178 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2179 struct bus_container *c;
2182 assert_return(m, -EINVAL);
2183 assert_return(!m->sealed, -EPERM);
2184 assert_return(m->n_containers > 0, -EINVAL);
2185 assert_return(!m->poisoned, -ESTALE);
2187 c = message_get_container(m);
2189 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2190 if (c->signature && c->signature[c->index] != 0)
2195 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2196 r = bus_message_close_array(m, c);
2197 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2198 r = bus_message_close_variant(m, c);
2199 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2200 r = bus_message_close_struct(m, c, true);
2202 assert_not_reached("Unknown container type");
2216 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2223 stack[*i].types = types;
2224 stack[*i].n_struct = n_struct;
2225 stack[*i].n_array = n_array;
2231 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2242 *types = stack[*i].types;
2243 *n_struct = stack[*i].n_struct;
2244 *n_array = stack[*i].n_array;
2249 int bus_message_append_ap(
2254 unsigned n_array, n_struct;
2255 TypeStack stack[BUS_CONTAINER_DEPTH];
2256 unsigned stack_ptr = 0;
2264 n_array = (unsigned) -1;
2265 n_struct = strlen(types);
2270 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2271 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2277 r = sd_bus_message_close_container(m);
2285 if (n_array != (unsigned) -1)
2294 case SD_BUS_TYPE_BYTE: {
2297 x = (uint8_t) va_arg(ap, int);
2298 r = sd_bus_message_append_basic(m, *t, &x);
2302 case SD_BUS_TYPE_BOOLEAN:
2303 case SD_BUS_TYPE_INT32:
2304 case SD_BUS_TYPE_UINT32:
2305 case SD_BUS_TYPE_UNIX_FD: {
2308 /* We assume a boolean is the same as int32_t */
2309 assert_cc(sizeof(int32_t) == sizeof(int));
2311 x = va_arg(ap, uint32_t);
2312 r = sd_bus_message_append_basic(m, *t, &x);
2316 case SD_BUS_TYPE_INT16:
2317 case SD_BUS_TYPE_UINT16: {
2320 x = (uint16_t) va_arg(ap, int);
2321 r = sd_bus_message_append_basic(m, *t, &x);
2325 case SD_BUS_TYPE_INT64:
2326 case SD_BUS_TYPE_UINT64:
2327 case SD_BUS_TYPE_DOUBLE: {
2330 x = va_arg(ap, uint64_t);
2331 r = sd_bus_message_append_basic(m, *t, &x);
2335 case SD_BUS_TYPE_STRING:
2336 case SD_BUS_TYPE_OBJECT_PATH:
2337 case SD_BUS_TYPE_SIGNATURE: {
2340 x = va_arg(ap, const char*);
2341 r = sd_bus_message_append_basic(m, *t, x);
2345 case SD_BUS_TYPE_ARRAY: {
2348 r = signature_element_length(t + 1, &k);
2354 memcpy(s, t + 1, k);
2357 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2362 if (n_array == (unsigned) -1) {
2367 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2373 n_array = va_arg(ap, unsigned);
2378 case SD_BUS_TYPE_VARIANT: {
2381 s = va_arg(ap, const char*);
2385 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2389 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2394 n_struct = strlen(s);
2395 n_array = (unsigned) -1;
2400 case SD_BUS_TYPE_STRUCT_BEGIN:
2401 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2404 r = signature_element_length(t, &k);
2411 memcpy(s, t + 1, k - 2);
2414 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2419 if (n_array == (unsigned) -1) {
2424 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2430 n_array = (unsigned) -1;
2446 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2450 assert_return(m, -EINVAL);
2451 assert_return(types, -EINVAL);
2452 assert_return(!m->sealed, -EPERM);
2453 assert_return(!m->poisoned, -ESTALE);
2455 va_start(ap, types);
2456 r = bus_message_append_ap(m, types, ap);
2462 _public_ int sd_bus_message_append_array_space(
2472 assert_return(m, -EINVAL);
2473 assert_return(!m->sealed, -EPERM);
2474 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2475 assert_return(ptr || size == 0, -EINVAL);
2476 assert_return(!m->poisoned, -ESTALE);
2478 /* alignment and size of the trivial types (except bool) is
2479 * identical for gvariant and dbus1 marshalling */
2480 align = bus_type_get_alignment(type);
2481 sz = bus_type_get_size(type);
2483 assert_se(align > 0);
2489 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2493 a = message_extend_body(m, align, size, false);
2497 r = sd_bus_message_close_container(m);
2505 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2512 assert_return(m, -EINVAL);
2513 assert_return(!m->sealed, -EPERM);
2514 assert_return(bus_type_is_trivial(type), -EINVAL);
2515 assert_return(ptr || size == 0, -EINVAL);
2516 assert_return(!m->poisoned, -ESTALE);
2518 r = sd_bus_message_append_array_space(m, type, size, &p);
2523 memcpy(p, ptr, size);
2528 _public_ int sd_bus_message_append_array_iovec(
2531 const struct iovec *iov,
2539 assert_return(m, -EINVAL);
2540 assert_return(!m->sealed, -EPERM);
2541 assert_return(bus_type_is_trivial(type), -EINVAL);
2542 assert_return(iov || n == 0, -EINVAL);
2543 assert_return(!m->poisoned, -ESTALE);
2545 size = IOVEC_TOTAL_SIZE(iov, n);
2547 r = sd_bus_message_append_array_space(m, type, size, &p);
2551 for (i = 0; i < n; i++) {
2553 if (iov[i].iov_base)
2554 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2556 memzero(p, iov[i].iov_len);
2558 p = (uint8_t*) p + iov[i].iov_len;
2564 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2567 _cleanup_close_ int copy_fd = -1;
2568 struct bus_body_part *part;
2580 if (!bus_type_is_trivial(type))
2585 r = memfd_set_sealed(memfd);
2589 copy_fd = dup(memfd);
2593 r = memfd_get_size(memfd, &size);
2597 align = bus_type_get_alignment(type);
2598 sz = bus_type_get_size(type);
2600 assert_se(align > 0);
2606 if (size > (uint64_t) (uint32_t) -1)
2609 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2613 a = message_extend_body(m, align, 0, false);
2617 part = message_append_part(m);
2621 part->memfd = copy_fd;
2622 part->sealed = true;
2626 m->header->body_size += size;
2627 message_extend_containers(m, size);
2629 return sd_bus_message_close_container(m);
2632 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) {
2633 _cleanup_close_ int copy_fd = -1;
2634 struct bus_body_part *part;
2635 struct bus_container *c;
2640 assert_return(m, -EINVAL);
2641 assert_return(memfd >= 0, -EINVAL);
2642 assert_return(!m->sealed, -EPERM);
2643 assert_return(!m->poisoned, -ESTALE);
2645 r = memfd_set_sealed(memfd);
2649 copy_fd = dup(memfd);
2653 r = memfd_get_size(memfd, &size);
2657 /* We require this to be NUL terminated */
2661 if (size > (uint64_t) (uint32_t) -1)
2664 c = message_get_container(m);
2665 if (c->signature && c->signature[c->index]) {
2666 /* Container signature is already set */
2668 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2673 /* Maybe we can append to the signature? But only if this is the top-level container*/
2674 if (c->enclosing != 0)
2677 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2684 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2685 a = message_extend_body(m, 4, 4, false);
2689 *(uint32_t*) a = size - 1;
2692 part = message_append_part(m);
2696 part->memfd = copy_fd;
2697 part->sealed = true;
2701 m->header->body_size += size;
2702 message_extend_containers(m, size);
2704 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2705 r = message_add_offset(m, m->header->body_size);
2712 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2718 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2722 assert_return(m, -EINVAL);
2723 assert_return(!m->sealed, -EPERM);
2724 assert_return(!m->poisoned, -ESTALE);
2726 r = sd_bus_message_open_container(m, 'a', "s");
2730 STRV_FOREACH(i, l) {
2731 r = sd_bus_message_append_basic(m, 's', *i);
2736 return sd_bus_message_close_container(m);
2739 static int bus_message_close_header(sd_bus_message *m) {
2745 if (!BUS_MESSAGE_IS_GVARIANT(m))
2748 if (m->n_header_offsets < 1)
2751 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2753 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2755 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2759 for (i = 0; i < m->n_header_offsets; i++)
2760 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2765 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2766 struct bus_body_part *part;
2776 if (m->n_containers > 0)
2782 /* In vtables the return signature of method calls is listed,
2783 * let's check if they match if this is a response */
2784 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2785 m->enforced_reply_signature &&
2786 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2789 /* If gvariant marshalling is used we need to close the body structure */
2790 r = bus_message_close_struct(m, &m->root_container, false);
2794 /* If there's a non-trivial signature set, then add it in here */
2795 if (!isempty(m->root_container.signature)) {
2796 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2802 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2807 r = bus_message_close_header(m);
2811 m->header->serial = (uint32_t) cookie;
2812 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2814 /* Add padding at the end of the fields part, since we know
2815 * the body needs to start at an 8 byte alignment. We made
2816 * sure we allocated enough space for this, so all we need to
2817 * do here is to zero it out. */
2818 l = BUS_MESSAGE_FIELDS_SIZE(m);
2821 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, a);
2823 /* If this is something we can send as memfd, then let's seal
2824 the memfd now. Note that we can send memfds as payload only
2825 for directed messages, and not for broadcasts. */
2826 if (m->destination && m->bus->use_memfd) {
2827 MESSAGE_FOREACH_PART(part, i, m)
2828 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2831 /* Try to seal it if that makes
2832 * sense. First, unmap our own map to
2833 * make sure we don't keep it busy. */
2834 bus_body_part_unmap(part);
2836 /* Then, sync up real memfd size */
2838 r = memfd_set_size(part->memfd, sz);
2842 /* Finally, try to seal */
2843 if (memfd_set_sealed(part->memfd) >= 0)
2844 part->sealed = true;
2848 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2849 m->root_container.index = 0;
2850 m->root_container.offset_index = 0;
2851 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2858 int bus_body_part_map(struct bus_body_part *part) {
2867 if (part->size <= 0)
2870 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2871 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2872 static const uint8_t zeroes[7] = { };
2873 part->data = (void*) zeroes;
2877 psz = PAGE_ALIGN(part->size);
2879 if (part->memfd >= 0)
2880 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, 0);
2881 else if (part->is_zero)
2882 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2886 if (p == MAP_FAILED)
2891 part->munmap_this = true;
2896 void bus_body_part_unmap(struct bus_body_part *part) {
2900 if (part->memfd < 0)
2906 if (!part->munmap_this)
2909 assert_se(munmap(part->data, part->mapped) == 0);
2913 part->munmap_this = false;
2918 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2919 size_t k, start, end;
2924 start = ALIGN_TO((size_t) *rindex, align);
2925 end = start + nbytes;
2930 /* Verify that padding is 0 */
2931 for (k = *rindex; k < start; k++)
2932 if (((const uint8_t*) p)[k] != 0)
2936 *r = (uint8_t*) p + start;
2943 static bool message_end_of_signature(sd_bus_message *m) {
2944 struct bus_container *c;
2948 c = message_get_container(m);
2949 return !c->signature || c->signature[c->index] == 0;
2952 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2953 struct bus_container *c;
2957 c = message_get_container(m);
2958 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2961 if (BUS_MESSAGE_IS_GVARIANT(m))
2962 return index >= c->end;
2964 assert(c->array_size);
2965 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2969 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2970 assert_return(m, -EINVAL);
2971 assert_return(m->sealed, -EPERM);
2973 if (complete && m->n_containers > 0)
2976 if (message_end_of_signature(m))
2979 if (message_end_of_array(m, m->rindex))
2985 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2986 struct bus_body_part *part;
2992 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2993 part = m->cached_rindex_part;
2994 begin = m->cached_rindex_part_begin;
3004 if (index + sz <= begin + part->size) {
3006 r = bus_body_part_map(part);
3011 *p = (uint8_t*) part->data + index - begin;
3013 m->cached_rindex_part = part;
3014 m->cached_rindex_part_begin = begin;
3019 begin += part->size;
3026 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3033 if (!BUS_MESSAGE_IS_GVARIANT(m))
3036 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3039 sz = bus_gvariant_get_size(c->signature);
3043 if (c->offset_index+1 >= c->n_offsets)
3046 /* Variable-size array */
3048 alignment = bus_gvariant_get_alignment(c->signature);
3049 assert(alignment > 0);
3051 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3052 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3055 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3058 /* Fixed-size array */
3059 *rindex = c->begin + (c->offset_index+1) * sz;
3065 } else if (c->enclosing == 0 ||
3066 c->enclosing == SD_BUS_TYPE_STRUCT ||
3067 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3072 if (c->offset_index+1 >= c->n_offsets)
3075 r = signature_element_length(c->signature + c->index, &n);
3079 r = signature_element_length(c->signature + c->index + n, &j);
3084 memcpy(t, c->signature + c->index + n, j);
3087 alignment = bus_gvariant_get_alignment(t);
3090 assert(alignment > 0);
3092 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3093 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3097 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3100 assert_not_reached("Unknown container type");
3105 /* Reached the end */
3112 static int message_peek_body(
3119 size_t k, start, end, padding;
3120 struct bus_body_part *part;
3127 start = ALIGN_TO((size_t) *rindex, align);
3128 padding = start - *rindex;
3129 end = start + nbytes;
3131 if (end > BUS_MESSAGE_BODY_SIZE(m))
3134 part = find_part(m, *rindex, padding, (void**) &q);
3139 /* Verify padding */
3140 for (k = 0; k < padding; k++)
3145 part = find_part(m, start, nbytes, (void**) &q);
3146 if (!part || (nbytes > 0 && !q))
3157 static bool validate_nul(const char *s, size_t l) {
3159 /* Check for NUL chars in the string */
3160 if (memchr(s, 0, l))
3163 /* Check for NUL termination */
3170 static bool validate_string(const char *s, size_t l) {
3172 if (!validate_nul(s, l))
3175 /* Check if valid UTF8 */
3176 if (!utf8_is_valid(s))
3182 static bool validate_signature(const char *s, size_t l) {
3184 if (!validate_nul(s, l))
3187 /* Check if valid signature */
3188 if (!signature_is_valid(s, true))
3194 static bool validate_object_path(const char *s, size_t l) {
3196 if (!validate_nul(s, l))
3199 if (!object_path_is_valid(s))
3205 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3206 struct bus_container *c;
3211 assert_return(m, -EINVAL);
3212 assert_return(m->sealed, -EPERM);
3213 assert_return(bus_type_is_basic(type), -EINVAL);
3215 if (message_end_of_signature(m))
3218 if (message_end_of_array(m, m->rindex))
3221 c = message_get_container(m);
3222 if (c->signature[c->index] != type)
3227 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3229 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3232 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3236 if (type == SD_BUS_TYPE_STRING)
3237 ok = validate_string(q, c->item_size-1);
3238 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3239 ok = validate_object_path(q, c->item_size-1);
3241 ok = validate_signature(q, c->item_size-1);
3247 *(const char**) p = q;
3251 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3253 if ((size_t) sz != c->item_size)
3256 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3259 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3265 case SD_BUS_TYPE_BYTE:
3267 *(uint8_t*) p = *(uint8_t*) q;
3270 case SD_BUS_TYPE_BOOLEAN:
3272 *(int*) p = !!*(uint8_t*) q;
3275 case SD_BUS_TYPE_INT16:
3276 case SD_BUS_TYPE_UINT16:
3278 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3281 case SD_BUS_TYPE_INT32:
3282 case SD_BUS_TYPE_UINT32:
3284 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3287 case SD_BUS_TYPE_INT64:
3288 case SD_BUS_TYPE_UINT64:
3289 case SD_BUS_TYPE_DOUBLE:
3291 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3294 case SD_BUS_TYPE_UNIX_FD: {
3297 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3302 *(int*) p = m->fds[j];
3308 assert_not_reached("unexpected type");
3312 r = container_next_item(m, c, &rindex);
3319 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3323 r = message_peek_body(m, &rindex, 4, 4, &q);
3327 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3328 r = message_peek_body(m, &rindex, 1, l+1, &q);
3332 if (type == SD_BUS_TYPE_OBJECT_PATH)
3333 ok = validate_object_path(q, l);
3335 ok = validate_string(q, l);
3340 *(const char**) p = q;
3342 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3345 r = message_peek_body(m, &rindex, 1, 1, &q);
3350 r = message_peek_body(m, &rindex, 1, l+1, &q);
3354 if (!validate_signature(q, l))
3358 *(const char**) p = q;
3363 align = bus_type_get_alignment(type);
3366 sz = bus_type_get_size(type);
3369 r = message_peek_body(m, &rindex, align, sz, &q);
3375 case SD_BUS_TYPE_BYTE:
3377 *(uint8_t*) p = *(uint8_t*) q;
3380 case SD_BUS_TYPE_BOOLEAN:
3382 *(int*) p = !!*(uint32_t*) q;
3385 case SD_BUS_TYPE_INT16:
3386 case SD_BUS_TYPE_UINT16:
3388 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3391 case SD_BUS_TYPE_INT32:
3392 case SD_BUS_TYPE_UINT32:
3394 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3397 case SD_BUS_TYPE_INT64:
3398 case SD_BUS_TYPE_UINT64:
3399 case SD_BUS_TYPE_DOUBLE:
3401 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3404 case SD_BUS_TYPE_UNIX_FD: {
3407 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3412 *(int*) p = m->fds[j];
3417 assert_not_reached("Unknown basic type...");
3424 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3430 static int bus_message_enter_array(
3432 struct bus_container *c,
3433 const char *contents,
3434 uint32_t **array_size,
3437 size_t *n_offsets) {
3451 if (!signature_is_single(contents, true))
3454 if (!c->signature || c->signature[c->index] == 0)
3457 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3460 if (!startswith(c->signature + c->index + 1, contents))
3465 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3468 r = message_peek_body(m, &rindex, 4, 4, &q);
3472 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3475 alignment = bus_type_get_alignment(contents[0]);
3479 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3483 *array_size = (uint32_t*) q;
3485 } else if (c->item_size <= 0) {
3487 /* gvariant: empty array */
3492 } else if (bus_gvariant_is_fixed_size(contents)) {
3494 /* gvariant: fixed length array */
3495 *item_size = bus_gvariant_get_size(contents);
3500 size_t where, p = 0, framing, sz;
3503 /* gvariant: variable length array */
3504 sz = determine_word_size(c->item_size, 0);
3506 where = rindex + c->item_size - sz;
3507 r = message_peek_body(m, &where, 1, sz, &q);
3511 framing = read_word_le(q, sz);
3512 if (framing > c->item_size - sz)
3514 if ((c->item_size - framing) % sz != 0)
3517 *n_offsets = (c->item_size - framing) / sz;
3519 where = rindex + framing;
3520 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3524 *offsets = new(size_t, *n_offsets);
3528 for (i = 0; i < *n_offsets; i++) {
3531 x = read_word_le((uint8_t*) q + i * sz, sz);
3532 if (x > c->item_size - sz)
3537 (*offsets)[i] = rindex + x;
3541 *item_size = (*offsets)[0] - rindex;
3546 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3547 c->index += 1 + strlen(contents);
3552 static int bus_message_enter_variant(
3554 struct bus_container *c,
3555 const char *contents,
3556 size_t *item_size) {
3568 if (!signature_is_single(contents, false))
3571 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3574 if (!c->signature || c->signature[c->index] == 0)
3577 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3582 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3585 k = strlen(contents);
3586 if (1+k > c->item_size)
3589 where = rindex + c->item_size - (1+k);
3590 r = message_peek_body(m, &where, 1, 1+k, &q);
3594 if (*(char*) q != 0)
3597 if (memcmp((uint8_t*) q+1, contents, k))
3600 *item_size = c->item_size - (1+k);
3603 r = message_peek_body(m, &rindex, 1, 1, &q);
3608 r = message_peek_body(m, &rindex, 1, l+1, &q);
3612 if (!validate_signature(q, l))
3615 if (!streq(q, contents))
3621 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3627 static int build_struct_offsets(
3629 const char *signature,
3633 size_t *n_offsets) {
3635 unsigned n_variable = 0, n_total = 0, v;
3636 size_t previous = 0, where;
3647 if (isempty(signature)) {
3654 sz = determine_word_size(size, 0);
3658 /* First, loop over signature and count variable elements and
3659 * elements in general. We use this to know how large the
3660 * offset array is at the end of the structure. Note that
3661 * GVariant only stores offsets for all variable size elements
3662 * that are not the last item. */
3668 r = signature_element_length(p, &n);
3677 r = bus_gvariant_is_fixed_size(t);
3682 if (r == 0 && p[n] != 0) /* except the last item */
3689 if (size < n_variable * sz)
3692 where = m->rindex + size - (n_variable * sz);
3693 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3699 *offsets = new(size_t, n_total);
3705 /* Second, loop again and build an offset table */
3711 r = signature_element_length(p, &n);
3720 k = bus_gvariant_get_size(t);
3728 x = read_word_le((uint8_t*) q + v*sz, sz);
3731 if (m->rindex + x < previous)
3734 /* The last item's end
3735 * is determined from
3738 x = size - (n_variable * sz);
3740 offset = m->rindex + x;
3746 align = bus_gvariant_get_alignment(t);
3749 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3753 previous = (*offsets)[(*n_offsets)++] = offset;
3758 assert(*n_offsets == n_total);
3760 *item_size = (*offsets)[0] - m->rindex;
3764 static int enter_struct_or_dict_entry(
3766 struct bus_container *c,
3767 const char *contents,
3770 size_t *n_offsets) {
3781 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3784 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3788 } else if (c->item_size <= 0) {
3790 /* gvariant empty struct */
3795 /* gvariant with contents */
3796 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3801 static int bus_message_enter_struct(
3803 struct bus_container *c,
3804 const char *contents,
3807 size_t *n_offsets) {
3819 if (!signature_is_valid(contents, false))
3822 if (!c->signature || c->signature[c->index] == 0)
3825 l = strlen(contents);
3827 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3828 !startswith(c->signature + c->index + 1, contents) ||
3829 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3832 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3836 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3837 c->index += 1 + l + 1;
3842 static int bus_message_enter_dict_entry(
3844 struct bus_container *c,
3845 const char *contents,
3848 size_t *n_offsets) {
3857 if (!signature_is_pair(contents))
3860 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3863 if (!c->signature || c->signature[c->index] == 0)
3866 l = strlen(contents);
3868 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3869 !startswith(c->signature + c->index + 1, contents) ||
3870 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3873 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3877 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3878 c->index += 1 + l + 1;
3883 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3885 const char *contents) {
3886 struct bus_container *c, *w;
3887 uint32_t *array_size = NULL;
3890 size_t *offsets = NULL;
3891 size_t n_offsets = 0, item_size = 0;
3894 assert_return(m, -EINVAL);
3895 assert_return(m->sealed, -EPERM);
3896 assert_return(type != 0 || !contents, -EINVAL);
3898 if (type == 0 || !contents) {
3902 /* Allow entering into anonymous containers */
3903 r = sd_bus_message_peek_type(m, &tt, &cc);
3907 if (type != 0 && type != tt)
3910 if (contents && !streq(contents, cc))
3918 * We enforce a global limit on container depth, that is much
3919 * higher than the 32 structs and 32 arrays the specification
3920 * mandates. This is simpler to implement for us, and we need
3921 * this only to ensure our container array doesn't grow
3922 * without bounds. We are happy to return any data from a
3923 * message as long as the data itself is valid, even if the
3924 * overall message might be not.
3926 * Note that the message signature is validated when
3927 * parsing the headers, and that validation does check the
3930 * Note that the specification defines no limits on the depth
3931 * of stacked variants, but we do.
3933 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3936 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3939 if (message_end_of_signature(m))
3942 if (message_end_of_array(m, m->rindex))
3945 c = message_get_container(m);
3947 signature = strdup(contents);
3951 c->saved_index = c->index;
3954 if (type == SD_BUS_TYPE_ARRAY)
3955 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3956 else if (type == SD_BUS_TYPE_VARIANT)
3957 r = bus_message_enter_variant(m, c, contents, &item_size);
3958 else if (type == SD_BUS_TYPE_STRUCT)
3959 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3960 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3961 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3971 /* OK, let's fill it in */
3972 w = m->containers + m->n_containers++;
3973 w->enclosing = type;
3974 w->signature = signature;
3975 w->peeked_signature = NULL;
3979 w->begin = m->rindex;
3980 w->end = m->rindex + c->item_size;
3982 w->array_size = array_size;
3983 w->item_size = item_size;
3984 w->offsets = offsets;
3985 w->n_offsets = n_offsets;
3986 w->offset_index = 0;
3991 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3992 struct bus_container *c;
3996 assert_return(m, -EINVAL);
3997 assert_return(m->sealed, -EPERM);
3998 assert_return(m->n_containers > 0, -ENXIO);
4000 c = message_get_container(m);
4002 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4003 if (c->signature && c->signature[c->index] != 0)
4007 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4008 if (m->rindex < c->end)
4011 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4014 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4015 if (c->begin + l != m->rindex)
4020 free(c->peeked_signature);
4024 c = message_get_container(m);
4027 c->index = c->saved_index;
4028 r = container_next_item(m, c, &m->rindex);
4036 static void message_quit_container(sd_bus_message *m) {
4037 struct bus_container *c;
4041 assert(m->n_containers > 0);
4043 c = message_get_container(m);
4046 assert(m->rindex >= c->before);
4047 m->rindex = c->before;
4049 /* Free container */
4054 /* Correct index of new top-level container */
4055 c = message_get_container(m);
4056 c->index = c->saved_index;
4059 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4060 struct bus_container *c;
4063 assert_return(m, -EINVAL);
4064 assert_return(m->sealed, -EPERM);
4066 if (message_end_of_signature(m))
4069 if (message_end_of_array(m, m->rindex))
4072 c = message_get_container(m);
4074 if (bus_type_is_basic(c->signature[c->index])) {
4078 *type = c->signature[c->index];
4082 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4088 r = signature_element_length(c->signature+c->index+1, &l);
4094 sig = strndup(c->signature + c->index + 1, l);
4098 free(c->peeked_signature);
4099 *contents = c->peeked_signature = sig;
4103 *type = SD_BUS_TYPE_ARRAY;
4108 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4109 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4115 r = signature_element_length(c->signature+c->index, &l);
4120 sig = strndup(c->signature + c->index + 1, l - 2);
4124 free(c->peeked_signature);
4125 *contents = c->peeked_signature = sig;
4129 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4134 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4138 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4141 if (c->item_size < 2)
4144 /* Look for the NUL delimiter that
4145 separates the payload from the
4146 signature. Since the body might be
4147 in a different part that then the
4148 signature we map byte by byte. */
4150 for (k = 2; k <= c->item_size; k++) {
4153 where = m->rindex + c->item_size - k;
4154 r = message_peek_body(m, &where, 1, k, &q);
4158 if (*(char*) q == 0)
4162 if (k > c->item_size)
4165 free(c->peeked_signature);
4166 c->peeked_signature = strndup((char*) q + 1, k - 1);
4167 if (!c->peeked_signature)
4170 if (!signature_is_valid(c->peeked_signature, true))
4173 *contents = c->peeked_signature;
4178 r = message_peek_body(m, &rindex, 1, 1, &q);
4183 r = message_peek_body(m, &rindex, 1, l+1, &q);
4187 if (!validate_signature(q, l))
4195 *type = SD_BUS_TYPE_VARIANT;
4210 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4211 struct bus_container *c;
4213 assert_return(m, -EINVAL);
4214 assert_return(m->sealed, -EPERM);
4217 message_reset_containers(m);
4220 c = message_get_container(m);
4222 c = message_get_container(m);
4224 c->offset_index = 0;
4226 m->rindex = c->begin;
4229 c->offset_index = 0;
4230 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4232 return !isempty(c->signature);
4235 static int message_read_ap(
4240 unsigned n_array, n_struct;
4241 TypeStack stack[BUS_CONTAINER_DEPTH];
4242 unsigned stack_ptr = 0;
4243 unsigned n_loop = 0;
4251 /* Ideally, we'd just call ourselves recursively on every
4252 * complex type. However, the state of a va_list that is
4253 * passed to a function is undefined after that function
4254 * returns. This means we need to docode the va_list linearly
4255 * in a single stackframe. We hence implement our own
4256 * home-grown stack in an array. */
4258 n_array = (unsigned) -1; /* length of current array entries */
4259 n_struct = strlen(types); /* length of current struct contents signature */
4266 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4267 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4273 r = sd_bus_message_exit_container(m);
4281 if (n_array != (unsigned) -1)
4290 case SD_BUS_TYPE_BYTE:
4291 case SD_BUS_TYPE_BOOLEAN:
4292 case SD_BUS_TYPE_INT16:
4293 case SD_BUS_TYPE_UINT16:
4294 case SD_BUS_TYPE_INT32:
4295 case SD_BUS_TYPE_UINT32:
4296 case SD_BUS_TYPE_INT64:
4297 case SD_BUS_TYPE_UINT64:
4298 case SD_BUS_TYPE_DOUBLE:
4299 case SD_BUS_TYPE_STRING:
4300 case SD_BUS_TYPE_OBJECT_PATH:
4301 case SD_BUS_TYPE_SIGNATURE:
4302 case SD_BUS_TYPE_UNIX_FD: {
4305 p = va_arg(ap, void*);
4306 r = sd_bus_message_read_basic(m, *t, p);
4319 case SD_BUS_TYPE_ARRAY: {
4322 r = signature_element_length(t + 1, &k);
4328 memcpy(s, t + 1, k);
4331 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4342 if (n_array == (unsigned) -1) {
4347 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4353 n_array = va_arg(ap, unsigned);
4358 case SD_BUS_TYPE_VARIANT: {
4361 s = va_arg(ap, const char *);
4365 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4375 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4380 n_struct = strlen(s);
4381 n_array = (unsigned) -1;
4386 case SD_BUS_TYPE_STRUCT_BEGIN:
4387 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4390 r = signature_element_length(t, &k);
4396 memcpy(s, t + 1, k - 2);
4399 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4409 if (n_array == (unsigned) -1) {
4414 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4420 n_array = (unsigned) -1;
4433 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4437 assert_return(m, -EINVAL);
4438 assert_return(m->sealed, -EPERM);
4439 assert_return(types, -EINVAL);
4441 va_start(ap, types);
4442 r = message_read_ap(m, types, ap);
4448 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4451 assert_return(m, -EINVAL);
4452 assert_return(m->sealed, -EPERM);
4453 assert_return(types, -EINVAL);
4460 case SD_BUS_TYPE_BYTE:
4461 case SD_BUS_TYPE_BOOLEAN:
4462 case SD_BUS_TYPE_INT16:
4463 case SD_BUS_TYPE_UINT16:
4464 case SD_BUS_TYPE_INT32:
4465 case SD_BUS_TYPE_UINT32:
4466 case SD_BUS_TYPE_INT64:
4467 case SD_BUS_TYPE_UINT64:
4468 case SD_BUS_TYPE_DOUBLE:
4469 case SD_BUS_TYPE_STRING:
4470 case SD_BUS_TYPE_OBJECT_PATH:
4471 case SD_BUS_TYPE_SIGNATURE:
4472 case SD_BUS_TYPE_UNIX_FD:
4474 r = sd_bus_message_read_basic(m, *types, NULL);
4478 r = sd_bus_message_skip(m, types + 1);
4484 case SD_BUS_TYPE_ARRAY: {
4487 r = signature_element_length(types + 1, &k);
4493 memcpy(s, types+1, k);
4496 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4501 r = sd_bus_message_skip(m, s);
4508 r = sd_bus_message_exit_container(m);
4513 r = sd_bus_message_skip(m, types + 1 + k);
4520 case SD_BUS_TYPE_VARIANT: {
4521 const char *contents;
4524 r = sd_bus_message_peek_type(m, &x, &contents);
4528 if (x != SD_BUS_TYPE_VARIANT)
4531 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4535 r = sd_bus_message_skip(m, contents);
4540 r = sd_bus_message_exit_container(m);
4544 r = sd_bus_message_skip(m, types + 1);
4551 case SD_BUS_TYPE_STRUCT_BEGIN:
4552 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4555 r = signature_element_length(types, &k);
4561 memcpy(s, types+1, k-2);
4564 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4568 r = sd_bus_message_skip(m, s);
4573 r = sd_bus_message_exit_container(m);
4578 r = sd_bus_message_skip(m, types + k);
4590 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4594 struct bus_container *c;
4600 assert_return(m, -EINVAL);
4601 assert_return(m->sealed, -EPERM);
4602 assert_return(bus_type_is_trivial(type), -EINVAL);
4603 assert_return(ptr, -EINVAL);
4604 assert_return(size, -EINVAL);
4605 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4607 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4611 c = message_get_container(m);
4613 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4614 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4618 sz = c->end - c->begin;
4620 align = bus_type_get_alignment(type);
4624 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4628 /* Zero length array, let's return some aligned
4629 * pointer that is not NULL */
4630 p = (uint8_t*) NULL + align;
4632 r = message_peek_body(m, &m->rindex, align, sz, &p);
4637 r = sd_bus_message_exit_container(m);
4641 *ptr = (const void*) p;
4647 message_quit_container(m);
4651 static int message_peek_fields(
4662 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4665 static int message_peek_field_uint32(
4677 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4680 /* identical for gvariant and dbus1 */
4682 r = message_peek_fields(m, ri, 4, 4, &q);
4687 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4692 static int message_peek_field_string(
4694 bool (*validate)(const char *p),
4706 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4711 r = message_peek_fields(m, ri, 1, item_size, &q);
4717 r = message_peek_field_uint32(m, ri, 4, &l);
4721 r = message_peek_fields(m, ri, 1, l+1, &q);
4727 if (!validate_nul(q, l))
4733 if (!validate_string(q, l))
4743 static int message_peek_field_signature(
4756 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4761 r = message_peek_fields(m, ri, 1, item_size, &q);
4767 r = message_peek_fields(m, ri, 1, 1, &q);
4772 r = message_peek_fields(m, ri, 1, l+1, &q);
4777 if (!validate_signature(q, l))
4786 static int message_skip_fields(
4789 uint32_t array_size,
4790 const char **signature) {
4792 size_t original_index;
4798 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4800 original_index = *ri;
4806 if (array_size != (uint32_t) -1 &&
4807 array_size <= *ri - original_index)
4814 if (t == SD_BUS_TYPE_STRING) {
4816 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4822 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4824 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4830 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4832 r = message_peek_field_signature(m, ri, 0, NULL);
4838 } else if (bus_type_is_basic(t)) {
4841 align = bus_type_get_alignment(t);
4842 k = bus_type_get_size(t);
4843 assert(align > 0 && k > 0);
4845 r = message_peek_fields(m, ri, align, k, NULL);
4851 } else if (t == SD_BUS_TYPE_ARRAY) {
4853 r = signature_element_length(*signature+1, &l);
4863 strncpy(sig, *signature + 1, l-1);
4866 alignment = bus_type_get_alignment(sig[0]);
4870 r = message_peek_field_uint32(m, ri, 0, &nas);
4873 if (nas > BUS_ARRAY_MAX_SIZE)
4876 r = message_peek_fields(m, ri, alignment, 0, NULL);
4880 r = message_skip_fields(m, ri, nas, (const char**) &s);
4885 (*signature) += 1 + l;
4887 } else if (t == SD_BUS_TYPE_VARIANT) {
4890 r = message_peek_field_signature(m, ri, 0, &s);
4894 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4900 } else if (t == SD_BUS_TYPE_STRUCT ||
4901 t == SD_BUS_TYPE_DICT_ENTRY) {
4903 r = signature_element_length(*signature, &l);
4910 strncpy(sig, *signature + 1, l-1);
4913 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4924 int bus_message_parse_fields(sd_bus_message *m) {
4927 uint32_t unix_fds = 0;
4928 bool unix_fds_set = false;
4929 void *offsets = NULL;
4930 unsigned n_offsets = 0;
4936 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4939 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4943 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4944 r = message_peek_fields(m, &ri, 1, sz, &q);
4948 framing = read_word_le(q, sz);
4949 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4951 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4955 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4959 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4964 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4965 _cleanup_free_ char *sig = NULL;
4966 const char *signature;
4968 size_t item_size = (size_t) -1;
4970 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4977 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4980 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4984 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4989 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4994 where = ri = ALIGN_TO(ri, 8);
4995 item_size = end - ri;
4996 r = message_peek_fields(m, &where, 1, item_size, &q);
5000 b = memrchr(q, 0, item_size);
5004 sig = strndup(b+1, item_size - (b+1-(char*) q));
5009 item_size = b - (char*) q;
5011 r = message_peek_field_signature(m, &ri, 0, &signature);
5017 case _BUS_MESSAGE_HEADER_INVALID:
5020 case BUS_MESSAGE_HEADER_PATH:
5025 if (!streq(signature, "o"))
5028 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5031 case BUS_MESSAGE_HEADER_INTERFACE:
5036 if (!streq(signature, "s"))
5039 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5042 case BUS_MESSAGE_HEADER_MEMBER:
5047 if (!streq(signature, "s"))
5050 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5053 case BUS_MESSAGE_HEADER_ERROR_NAME:
5058 if (!streq(signature, "s"))
5061 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5063 m->error._need_free = -1;
5067 case BUS_MESSAGE_HEADER_DESTINATION:
5072 if (!streq(signature, "s"))
5075 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5078 case BUS_MESSAGE_HEADER_SENDER:
5083 if (!streq(signature, "s"))
5086 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5088 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5089 m->creds.unique_name = (char*) m->sender;
5090 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5096 case BUS_MESSAGE_HEADER_SIGNATURE: {
5100 if (m->root_container.signature)
5103 if (!streq(signature, "g"))
5106 r = message_peek_field_signature(m, &ri, item_size, &s);
5114 free(m->root_container.signature);
5115 m->root_container.signature = c;
5119 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5122 if (m->reply_cookie != 0)
5125 if (!streq(signature, "u"))
5128 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5132 m->reply_cookie = serial;
5134 if (m->reply_cookie == 0)
5140 case BUS_MESSAGE_HEADER_UNIX_FDS:
5144 if (!streq(signature, "u"))
5147 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5151 unix_fds_set = true;
5155 if (!BUS_MESSAGE_IS_GVARIANT(m))
5156 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5165 if (m->n_fds != unix_fds)
5168 switch (m->header->type) {
5170 case SD_BUS_MESSAGE_SIGNAL:
5171 if (!m->path || !m->interface || !m->member)
5175 case SD_BUS_MESSAGE_METHOD_CALL:
5177 if (!m->path || !m->member)
5182 case SD_BUS_MESSAGE_METHOD_RETURN:
5184 if (m->reply_cookie == 0)
5188 case SD_BUS_MESSAGE_METHOD_ERROR:
5190 if (m->reply_cookie == 0 || !m->error.name)
5195 /* Refuse non-local messages that claim they are local */
5196 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5198 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5200 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5203 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5205 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5206 r = build_struct_offsets(
5208 m->root_container.signature,
5209 BUS_MESSAGE_BODY_SIZE(m),
5210 &m->root_container.item_size,
5211 &m->root_container.offsets,
5212 &m->root_container.n_offsets);
5217 /* Try to read the error message, but if we can't it's a non-issue */
5218 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5219 sd_bus_message_read(m, "s", &m->error.message);
5224 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5225 assert_return(m, -EINVAL);
5226 assert_return(destination, -EINVAL);
5227 assert_return(!m->sealed, -EPERM);
5228 assert_return(!m->destination, -EEXIST);
5230 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5233 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5237 struct bus_body_part *part;
5243 total = BUS_MESSAGE_SIZE(m);
5249 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5250 MESSAGE_FOREACH_PART(part, i, m)
5251 e = mempcpy(e, part->data, part->size);
5253 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5261 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5267 r = sd_bus_message_enter_container(m, 'a', "s");
5274 r = sd_bus_message_read_basic(m, 's', &s);
5280 r = strv_extend(l, s);
5285 r = sd_bus_message_exit_container(m);
5292 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5296 assert_return(m, -EINVAL);
5297 assert_return(m->sealed, -EPERM);
5298 assert_return(l, -EINVAL);
5300 r = bus_message_read_strv_extend(m, &strv);
5310 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5312 const char *t = NULL;
5317 r = sd_bus_message_rewind(m, true);
5321 for (j = 0; j <= i; j++) {
5324 r = sd_bus_message_peek_type(m, &type, NULL);
5328 if (type != SD_BUS_TYPE_STRING &&
5329 type != SD_BUS_TYPE_OBJECT_PATH &&
5330 type != SD_BUS_TYPE_SIGNATURE)
5333 r = sd_bus_message_read_basic(m, type, &t);
5341 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5347 if (size < sizeof(struct bus_header))
5350 full = sizeof(struct bus_header) +
5351 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5353 return size >= full;
5356 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5362 if (h->endian == BUS_NATIVE_ENDIAN) {
5363 fs = h->fields_size;
5365 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5366 fs = bswap_32(h->fields_size);
5367 bs = bswap_32(h->body_size);
5371 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5375 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5376 assert_return(m, EINVAL);
5378 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5381 return sd_bus_error_get_errno(&m->error);
5384 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5385 struct bus_container *c;
5387 assert_return(m, NULL);
5389 c = complete ? &m->root_container : message_get_container(m);
5390 return strempty(c->signature);
5393 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5394 assert_return(m, -EINVAL);
5396 return isempty(m->root_container.signature);
5399 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5400 bool done_something = false;
5403 assert_return(m, -EINVAL);
5404 assert_return(source, -EINVAL);
5405 assert_return(!m->sealed, -EPERM);
5406 assert_return(source->sealed, -EPERM);
5409 const char *contents;
5424 r = sd_bus_message_peek_type(source, &type, &contents);
5430 done_something = true;
5432 if (bus_type_is_container(type) > 0) {
5434 r = sd_bus_message_enter_container(source, type, contents);
5438 r = sd_bus_message_open_container(m, type, contents);
5442 r = sd_bus_message_copy(m, source, true);
5446 r = sd_bus_message_close_container(m);
5450 r = sd_bus_message_exit_container(source);
5457 r = sd_bus_message_read_basic(source, type, &basic);
5463 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5464 type == SD_BUS_TYPE_SIGNATURE ||
5465 type == SD_BUS_TYPE_STRING)
5466 r = sd_bus_message_append_basic(m, type, basic.string);
5468 r = sd_bus_message_append_basic(m, type, &basic);
5475 return done_something;
5478 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5483 assert_return(m, -EINVAL);
5484 assert_return(m->sealed, -EPERM);
5485 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5486 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5487 assert_return(type || contents, -EINVAL);
5488 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5490 r = sd_bus_message_peek_type(m, &t, &c);
5494 if (type != 0 && type != t)
5497 if (contents && !streq_ptr(contents, c))
5503 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5504 assert_return(m, NULL);
5509 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5510 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5518 switch ((*m)->header->type) {
5520 case SD_BUS_MESSAGE_SIGNAL:
5521 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5527 case SD_BUS_MESSAGE_METHOD_CALL:
5528 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5534 case SD_BUS_MESSAGE_METHOD_RETURN:
5535 case SD_BUS_MESSAGE_METHOD_ERROR:
5537 n = message_new(bus, (*m)->header->type);
5541 n->reply_cookie = (*m)->reply_cookie;
5542 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5546 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5547 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5551 n->error._need_free = -1;
5560 if ((*m)->destination && !n->destination) {
5561 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5566 if ((*m)->sender && !n->sender) {
5567 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5572 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5574 r = sd_bus_message_copy(n, *m, true);
5578 timeout = (*m)->timeout;
5579 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5580 timeout = BUS_DEFAULT_TIMEOUT;
5582 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5586 sd_bus_message_unref(*m);
5593 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5597 assert_return(!m->sealed, -EPERM);
5598 assert_return(!m->sender, -EPERM);
5600 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5603 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5604 assert_return(m, -EINVAL);
5605 assert_return(priority, -EINVAL);
5607 *priority = m->priority;
5611 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5612 assert_return(m, -EINVAL);
5613 assert_return(!m->sealed, -EPERM);
5615 m->priority = priority;