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->mmap_begin, part->mapped) == 0);
74 safe_close(part->memfd);
77 } else if (part->munmap_this)
78 munmap(part->mmap_begin, 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_INVALID)
433 m->creds.mask |= SD_BUS_CREDS_UID;
435 if (m->creds.gid != GID_INVALID)
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->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1133 if (n == MAP_FAILED) {
1138 part->mmap_begin = part->data = n;
1140 part->memfd_offset = 0;
1143 part->munmap_this = true;
1145 if (part->allocated == 0 || sz > part->allocated) {
1146 size_t new_allocated;
1148 new_allocated = sz > 0 ? 2 * sz : 64;
1149 n = realloc(part->data, new_allocated);
1156 part->allocated = new_allocated;
1157 part->free_this = true;
1162 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1168 static int message_add_offset(sd_bus_message *m, size_t offset) {
1169 struct bus_container *c;
1172 assert(BUS_MESSAGE_IS_GVARIANT(m));
1174 /* Add offset to current container, unless this is the first
1175 * item in it, which will have the 0 offset, which we can
1177 c = message_get_container(m);
1179 if (!c->need_offsets)
1182 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1185 c->offsets[c->n_offsets++] = offset;
1189 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1190 struct bus_container *c;
1197 /* Update counters */
1198 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1201 *c->array_size += expand;
1205 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1206 size_t start_body, end_body, padding, added;
1217 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1218 end_body = start_body + sz;
1220 padding = start_body - m->header->body_size;
1221 added = padding + sz;
1223 /* Check for 32bit overflows */
1224 if (end_body > (size_t) ((uint32_t) -1)) {
1230 struct bus_body_part *part = NULL;
1234 m->n_body_parts <= 0 ||
1235 m->body_end->sealed ||
1236 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1240 part = message_append_part(m);
1244 part_zero(part, padding);
1247 part = message_append_part(m);
1251 r = part_make_space(m, part, sz, &p);
1255 struct bus_container *c;
1257 size_t os, start_part, end_part;
1263 start_part = ALIGN_TO(part->size, align);
1264 end_part = start_part + sz;
1266 r = part_make_space(m, part, end_part, &p);
1271 memzero(p, padding);
1272 p = (uint8_t*) p + padding;
1275 /* Readjust pointers */
1276 for (c = m->containers; c < m->containers + m->n_containers; c++)
1277 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1279 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1282 /* Return something that is not NULL and is aligned */
1283 p = (uint8_t *) NULL + align;
1285 m->header->body_size = end_body;
1286 message_extend_containers(m, added);
1289 r = message_add_offset(m, end_body);
1299 static int message_push_fd(sd_bus_message *m, int fd) {
1310 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1314 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1322 m->fds[m->n_fds] = copy;
1328 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1329 _cleanup_close_ int fd = -1;
1330 struct bus_container *c;
1334 assert_return(m, -EINVAL);
1335 assert_return(!m->sealed, -EPERM);
1336 assert_return(bus_type_is_basic(type), -EINVAL);
1337 assert_return(!m->poisoned, -ESTALE);
1339 c = message_get_container(m);
1341 if (c->signature && c->signature[c->index]) {
1342 /* Container signature is already set */
1344 if (c->signature[c->index] != type)
1349 /* Maybe we can append to the signature? But only if this is the top-level container*/
1350 if (c->enclosing != 0)
1353 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1360 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1366 case SD_BUS_TYPE_SIGNATURE:
1367 case SD_BUS_TYPE_STRING:
1370 /* Fall through... */
1371 case SD_BUS_TYPE_OBJECT_PATH:
1379 case SD_BUS_TYPE_BOOLEAN:
1381 u8 = p && *(int*) p;
1387 case SD_BUS_TYPE_UNIX_FD:
1392 fd = message_push_fd(m, *(int*) p);
1403 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1404 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1411 a = message_extend_body(m, align, sz, true);
1418 *stored = (const uint8_t*) a;
1425 case SD_BUS_TYPE_STRING:
1426 /* To make things easy we'll serialize a NULL string
1427 * into the empty string */
1430 /* Fall through... */
1431 case SD_BUS_TYPE_OBJECT_PATH:
1437 sz = 4 + strlen(p) + 1;
1440 case SD_BUS_TYPE_SIGNATURE:
1445 sz = 1 + strlen(p) + 1;
1448 case SD_BUS_TYPE_BOOLEAN:
1450 u32 = p && *(int*) p;
1456 case SD_BUS_TYPE_UNIX_FD:
1461 fd = message_push_fd(m, *(int*) p);
1472 align = bus_type_get_alignment(type);
1473 sz = bus_type_get_size(type);
1480 a = message_extend_body(m, align, sz, false);
1484 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1485 *(uint32_t*) a = sz - 5;
1486 memcpy((uint8_t*) a + 4, p, sz - 4);
1489 *stored = (const uint8_t*) a + 4;
1491 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1492 *(uint8_t*) a = sz - 2;
1493 memcpy((uint8_t*) a + 1, p, sz - 1);
1496 *stored = (const uint8_t*) a + 1;
1505 if (type == SD_BUS_TYPE_UNIX_FD)
1508 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1515 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1516 return message_append_basic(m, type, p, NULL);
1519 _public_ int sd_bus_message_append_string_space(
1524 struct bus_container *c;
1527 assert_return(m, -EINVAL);
1528 assert_return(s, -EINVAL);
1529 assert_return(!m->sealed, -EPERM);
1530 assert_return(!m->poisoned, -ESTALE);
1532 c = message_get_container(m);
1534 if (c->signature && c->signature[c->index]) {
1535 /* Container signature is already set */
1537 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1542 /* Maybe we can append to the signature? But only if this is the top-level container*/
1543 if (c->enclosing != 0)
1546 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1553 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1554 a = message_extend_body(m, 1, size + 1, true);
1560 a = message_extend_body(m, 4, 4 + size + 1, false);
1564 *(uint32_t*) a = size;
1570 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1576 _public_ int sd_bus_message_append_string_iovec(
1578 const struct iovec *iov,
1586 assert_return(m, -EINVAL);
1587 assert_return(!m->sealed, -EPERM);
1588 assert_return(iov || n == 0, -EINVAL);
1589 assert_return(!m->poisoned, -ESTALE);
1591 size = IOVEC_TOTAL_SIZE(iov, n);
1593 r = sd_bus_message_append_string_space(m, size, &p);
1597 for (i = 0; i < n; i++) {
1599 if (iov[i].iov_base)
1600 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1602 memset(p, ' ', iov[i].iov_len);
1604 p += iov[i].iov_len;
1610 static int bus_message_open_array(
1612 struct bus_container *c,
1613 const char *contents,
1614 uint32_t **array_size,
1616 bool *need_offsets) {
1626 assert(need_offsets);
1628 if (!signature_is_single(contents, true))
1631 if (c->signature && c->signature[c->index]) {
1633 /* Verify the existing signature */
1635 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1638 if (!startswith(c->signature + c->index + 1, contents))
1641 nindex = c->index + 1 + strlen(contents);
1645 if (c->enclosing != 0)
1648 /* Extend the existing signature */
1650 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1656 nindex = e - c->signature;
1659 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1660 alignment = bus_gvariant_get_alignment(contents);
1664 /* Add alignment padding and add to offset list */
1665 if (!message_extend_body(m, alignment, 0, false))
1668 r = bus_gvariant_is_fixed_size(contents);
1672 *begin = m->header->body_size;
1673 *need_offsets = r == 0;
1677 struct bus_body_part *o;
1679 alignment = bus_type_get_alignment(contents[0]);
1683 a = message_extend_body(m, 4, 4, false);
1688 op = m->body_end->data;
1689 os = m->body_end->size;
1691 /* Add alignment between size and first element */
1692 if (!message_extend_body(m, alignment, 0, false))
1695 /* location of array size might have changed so let's readjust a */
1696 if (o == m->body_end)
1697 a = adjust_pointer(a, op, os, m->body_end->data);
1703 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1709 static int bus_message_open_variant(
1711 struct bus_container *c,
1712 const char *contents) {
1718 if (!signature_is_single(contents, false))
1721 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1724 if (c->signature && c->signature[c->index]) {
1726 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1732 if (c->enclosing != 0)
1735 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1742 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1743 /* Variants are always aligned to 8 */
1745 if (!message_extend_body(m, 8, 0, false))
1752 l = strlen(contents);
1753 a = message_extend_body(m, 1, 1 + l + 1, false);
1758 memcpy((uint8_t*) a + 1, contents, l + 1);
1761 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1767 static int bus_message_open_struct(
1769 struct bus_container *c,
1770 const char *contents,
1772 bool *need_offsets) {
1781 assert(need_offsets);
1783 if (!signature_is_valid(contents, false))
1786 if (c->signature && c->signature[c->index]) {
1789 l = strlen(contents);
1791 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1792 !startswith(c->signature + c->index + 1, contents) ||
1793 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1796 nindex = c->index + 1 + l + 1;
1800 if (c->enclosing != 0)
1803 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1809 nindex = e - c->signature;
1812 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1815 alignment = bus_gvariant_get_alignment(contents);
1819 if (!message_extend_body(m, alignment, 0, false))
1822 r = bus_gvariant_is_fixed_size(contents);
1826 *begin = m->header->body_size;
1827 *need_offsets = r == 0;
1829 /* Align contents to 8 byte boundary */
1830 if (!message_extend_body(m, 8, 0, false))
1834 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1840 static int bus_message_open_dict_entry(
1842 struct bus_container *c,
1843 const char *contents,
1845 bool *need_offsets) {
1853 assert(need_offsets);
1855 if (!signature_is_pair(contents))
1858 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1861 if (c->signature && c->signature[c->index]) {
1864 l = strlen(contents);
1866 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1867 !startswith(c->signature + c->index + 1, contents) ||
1868 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1873 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1876 alignment = bus_gvariant_get_alignment(contents);
1880 if (!message_extend_body(m, alignment, 0, false))
1883 r = bus_gvariant_is_fixed_size(contents);
1887 *begin = m->header->body_size;
1888 *need_offsets = r == 0;
1890 /* Align contents to 8 byte boundary */
1891 if (!message_extend_body(m, 8, 0, false))
1898 _public_ int sd_bus_message_open_container(
1901 const char *contents) {
1903 struct bus_container *c, *w;
1904 uint32_t *array_size = NULL;
1906 size_t before, begin = 0;
1907 bool need_offsets = false;
1910 assert_return(m, -EINVAL);
1911 assert_return(!m->sealed, -EPERM);
1912 assert_return(contents, -EINVAL);
1913 assert_return(!m->poisoned, -ESTALE);
1915 /* Make sure we have space for one more container */
1916 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1921 c = message_get_container(m);
1923 signature = strdup(contents);
1929 /* Save old index in the parent container, in case we have to
1930 * abort this container */
1931 c->saved_index = c->index;
1932 before = m->header->body_size;
1934 if (type == SD_BUS_TYPE_ARRAY)
1935 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1936 else if (type == SD_BUS_TYPE_VARIANT)
1937 r = bus_message_open_variant(m, c, contents);
1938 else if (type == SD_BUS_TYPE_STRUCT)
1939 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1940 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1941 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1950 /* OK, let's fill it in */
1951 w = m->containers + m->n_containers++;
1952 w->enclosing = type;
1953 w->signature = signature;
1955 w->array_size = array_size;
1958 w->n_offsets = w->offsets_allocated = 0;
1960 w->need_offsets = need_offsets;
1965 static size_t determine_word_size(size_t sz, size_t extra) {
1966 if (sz + extra <= 0xFF)
1968 else if (sz + extra*2 <= 0xFFFF)
1970 else if (sz + extra*4 <= 0xFFFFFFFF)
1976 static size_t read_word_le(void *p, size_t sz) {
1986 return *(uint8_t*) p;
1991 return le16toh(x.u16);
1993 return le32toh(x.u32);
1995 return le64toh(x.u64);
1997 assert_not_reached("unknown word width");
2000 static void write_word_le(void *p, size_t sz, size_t value) {
2008 assert(sz == 8 || (value < (1ULL << (sz*8))));
2011 *(uint8_t*) p = value;
2014 x.u16 = htole16((uint16_t) value);
2016 x.u32 = htole32((uint32_t) value);
2018 x.u64 = htole64((uint64_t) value);
2020 assert_not_reached("unknown word width");
2025 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2030 if (!BUS_MESSAGE_IS_GVARIANT(m))
2033 if (c->need_offsets) {
2034 size_t payload, sz, i;
2037 /* Variable-width arrays */
2039 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2040 sz = determine_word_size(payload, c->n_offsets);
2042 a = message_extend_body(m, 1, sz * c->n_offsets, true);
2046 for (i = 0; i < c->n_offsets; i++)
2047 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2051 /* Fixed-width or empty arrays */
2053 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
2061 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2067 assert(c->signature);
2069 if (!BUS_MESSAGE_IS_GVARIANT(m))
2072 l = strlen(c->signature);
2074 a = message_extend_body(m, 1, 1 + l, true);
2079 memcpy(a+1, c->signature, l);
2084 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2085 size_t n_variable = 0;
2094 if (!BUS_MESSAGE_IS_GVARIANT(m))
2097 p = strempty(c->signature);
2101 r = signature_element_length(p, &n);
2110 r = bus_gvariant_is_fixed_size(t);
2115 assert(!c->need_offsets || i <= c->n_offsets);
2117 /* We need to add an offset for each item that has a
2118 * variable size and that is not the last one in the
2120 if (r == 0 && p[n] != 0)
2127 assert(!c->need_offsets || i == c->n_offsets);
2128 assert(c->need_offsets || n_variable == 0);
2130 if (n_variable <= 0) {
2131 a = message_extend_body(m, 1, 0, add_offset);
2138 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2140 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2142 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2146 p = strempty(c->signature);
2147 for (i = 0, j = 0; i < c->n_offsets; i++) {
2151 r = signature_element_length(p, &n);
2162 r = bus_gvariant_is_fixed_size(t);
2165 if (r > 0 || p[0] == 0)
2169 k = n_variable - 1 - j;
2171 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2180 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2181 struct bus_container *c;
2184 assert_return(m, -EINVAL);
2185 assert_return(!m->sealed, -EPERM);
2186 assert_return(m->n_containers > 0, -EINVAL);
2187 assert_return(!m->poisoned, -ESTALE);
2189 c = message_get_container(m);
2191 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2192 if (c->signature && c->signature[c->index] != 0)
2197 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2198 r = bus_message_close_array(m, c);
2199 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2200 r = bus_message_close_variant(m, c);
2201 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2202 r = bus_message_close_struct(m, c, true);
2204 assert_not_reached("Unknown container type");
2218 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2225 stack[*i].types = types;
2226 stack[*i].n_struct = n_struct;
2227 stack[*i].n_array = n_array;
2233 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2244 *types = stack[*i].types;
2245 *n_struct = stack[*i].n_struct;
2246 *n_array = stack[*i].n_array;
2251 int bus_message_append_ap(
2256 unsigned n_array, n_struct;
2257 TypeStack stack[BUS_CONTAINER_DEPTH];
2258 unsigned stack_ptr = 0;
2266 n_array = (unsigned) -1;
2267 n_struct = strlen(types);
2272 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2273 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2279 r = sd_bus_message_close_container(m);
2287 if (n_array != (unsigned) -1)
2296 case SD_BUS_TYPE_BYTE: {
2299 x = (uint8_t) va_arg(ap, int);
2300 r = sd_bus_message_append_basic(m, *t, &x);
2304 case SD_BUS_TYPE_BOOLEAN:
2305 case SD_BUS_TYPE_INT32:
2306 case SD_BUS_TYPE_UINT32:
2307 case SD_BUS_TYPE_UNIX_FD: {
2310 /* We assume a boolean is the same as int32_t */
2311 assert_cc(sizeof(int32_t) == sizeof(int));
2313 x = va_arg(ap, uint32_t);
2314 r = sd_bus_message_append_basic(m, *t, &x);
2318 case SD_BUS_TYPE_INT16:
2319 case SD_BUS_TYPE_UINT16: {
2322 x = (uint16_t) va_arg(ap, int);
2323 r = sd_bus_message_append_basic(m, *t, &x);
2327 case SD_BUS_TYPE_INT64:
2328 case SD_BUS_TYPE_UINT64:
2329 case SD_BUS_TYPE_DOUBLE: {
2332 x = va_arg(ap, uint64_t);
2333 r = sd_bus_message_append_basic(m, *t, &x);
2337 case SD_BUS_TYPE_STRING:
2338 case SD_BUS_TYPE_OBJECT_PATH:
2339 case SD_BUS_TYPE_SIGNATURE: {
2342 x = va_arg(ap, const char*);
2343 r = sd_bus_message_append_basic(m, *t, x);
2347 case SD_BUS_TYPE_ARRAY: {
2350 r = signature_element_length(t + 1, &k);
2356 memcpy(s, t + 1, k);
2359 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2364 if (n_array == (unsigned) -1) {
2369 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2375 n_array = va_arg(ap, unsigned);
2380 case SD_BUS_TYPE_VARIANT: {
2383 s = va_arg(ap, const char*);
2387 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2391 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2396 n_struct = strlen(s);
2397 n_array = (unsigned) -1;
2402 case SD_BUS_TYPE_STRUCT_BEGIN:
2403 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2406 r = signature_element_length(t, &k);
2413 memcpy(s, t + 1, k - 2);
2416 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2421 if (n_array == (unsigned) -1) {
2426 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2432 n_array = (unsigned) -1;
2448 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2452 assert_return(m, -EINVAL);
2453 assert_return(types, -EINVAL);
2454 assert_return(!m->sealed, -EPERM);
2455 assert_return(!m->poisoned, -ESTALE);
2457 va_start(ap, types);
2458 r = bus_message_append_ap(m, types, ap);
2464 _public_ int sd_bus_message_append_array_space(
2474 assert_return(m, -EINVAL);
2475 assert_return(!m->sealed, -EPERM);
2476 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2477 assert_return(ptr || size == 0, -EINVAL);
2478 assert_return(!m->poisoned, -ESTALE);
2480 /* alignment and size of the trivial types (except bool) is
2481 * identical for gvariant and dbus1 marshalling */
2482 align = bus_type_get_alignment(type);
2483 sz = bus_type_get_size(type);
2485 assert_se(align > 0);
2491 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2495 a = message_extend_body(m, align, size, false);
2499 r = sd_bus_message_close_container(m);
2507 _public_ int sd_bus_message_append_array(
2515 assert_return(m, -EINVAL);
2516 assert_return(!m->sealed, -EPERM);
2517 assert_return(bus_type_is_trivial(type), -EINVAL);
2518 assert_return(ptr || size == 0, -EINVAL);
2519 assert_return(!m->poisoned, -ESTALE);
2521 r = sd_bus_message_append_array_space(m, type, size, &p);
2526 memcpy(p, ptr, size);
2531 _public_ int sd_bus_message_append_array_iovec(
2534 const struct iovec *iov,
2542 assert_return(m, -EINVAL);
2543 assert_return(!m->sealed, -EPERM);
2544 assert_return(bus_type_is_trivial(type), -EINVAL);
2545 assert_return(iov || n == 0, -EINVAL);
2546 assert_return(!m->poisoned, -ESTALE);
2548 size = IOVEC_TOTAL_SIZE(iov, n);
2550 r = sd_bus_message_append_array_space(m, type, size, &p);
2554 for (i = 0; i < n; i++) {
2556 if (iov[i].iov_base)
2557 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2559 memzero(p, iov[i].iov_len);
2561 p = (uint8_t*) p + iov[i].iov_len;
2567 _public_ int sd_bus_message_append_array_memfd(
2574 _cleanup_close_ int copy_fd = -1;
2575 struct bus_body_part *part;
2581 assert_return(m, -EINVAL);
2582 assert_return(memfd >= 0, -EINVAL);
2583 assert_return(bus_type_is_trivial(type), -EINVAL);
2584 assert_return(size > 0, -EINVAL);
2585 assert_return(!m->sealed, -EPERM);
2586 assert_return(!m->poisoned, -ESTALE);
2588 r = memfd_set_sealed(memfd);
2592 copy_fd = dup(memfd);
2596 r = memfd_get_size(memfd, &real_size);
2600 if (offset == 0 && size == (uint64_t) -1)
2602 else if (offset + size > real_size)
2605 align = bus_type_get_alignment(type);
2606 sz = bus_type_get_size(type);
2608 assert_se(align > 0);
2611 if (offset % align != 0)
2617 if (size > (uint64_t) (uint32_t) -1)
2620 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2624 a = message_extend_body(m, align, 0, false);
2628 part = message_append_part(m);
2632 part->memfd = copy_fd;
2633 part->memfd_offset = offset;
2634 part->sealed = true;
2638 m->header->body_size += size;
2639 message_extend_containers(m, size);
2641 return sd_bus_message_close_container(m);
2644 _public_ int sd_bus_message_append_string_memfd(
2650 _cleanup_close_ int copy_fd = -1;
2651 struct bus_body_part *part;
2652 struct bus_container *c;
2657 assert_return(m, -EINVAL);
2658 assert_return(memfd >= 0, -EINVAL);
2659 assert_return(size > 0, -EINVAL);
2660 assert_return(!m->sealed, -EPERM);
2661 assert_return(!m->poisoned, -ESTALE);
2663 r = memfd_set_sealed(memfd);
2667 copy_fd = dup(memfd);
2671 r = memfd_get_size(memfd, &real_size);
2675 if (offset == 0 && size == (uint64_t) -1)
2677 else if (offset + size > real_size)
2680 /* We require this to be NUL terminated */
2684 if (size > (uint64_t) (uint32_t) -1)
2687 c = message_get_container(m);
2688 if (c->signature && c->signature[c->index]) {
2689 /* Container signature is already set */
2691 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2696 /* Maybe we can append to the signature? But only if this is the top-level container*/
2697 if (c->enclosing != 0)
2700 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2707 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2708 a = message_extend_body(m, 4, 4, false);
2712 *(uint32_t*) a = size - 1;
2715 part = message_append_part(m);
2719 part->memfd = copy_fd;
2720 part->memfd_offset = offset;
2721 part->sealed = true;
2725 m->header->body_size += size;
2726 message_extend_containers(m, size);
2728 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2729 r = message_add_offset(m, m->header->body_size);
2736 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2742 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2746 assert_return(m, -EINVAL);
2747 assert_return(!m->sealed, -EPERM);
2748 assert_return(!m->poisoned, -ESTALE);
2750 r = sd_bus_message_open_container(m, 'a', "s");
2754 STRV_FOREACH(i, l) {
2755 r = sd_bus_message_append_basic(m, 's', *i);
2760 return sd_bus_message_close_container(m);
2763 static int bus_message_close_header(sd_bus_message *m) {
2769 if (!BUS_MESSAGE_IS_GVARIANT(m))
2772 if (m->n_header_offsets < 1)
2775 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2777 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2779 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2783 for (i = 0; i < m->n_header_offsets; i++)
2784 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2789 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2790 struct bus_body_part *part;
2800 if (m->n_containers > 0)
2806 /* In vtables the return signature of method calls is listed,
2807 * let's check if they match if this is a response */
2808 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2809 m->enforced_reply_signature &&
2810 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2813 /* If gvariant marshalling is used we need to close the body structure */
2814 r = bus_message_close_struct(m, &m->root_container, false);
2818 /* If there's a non-trivial signature set, then add it in here */
2819 if (!isempty(m->root_container.signature)) {
2820 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2826 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2831 r = bus_message_close_header(m);
2835 m->header->serial = (uint32_t) cookie;
2836 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2838 /* Add padding at the end of the fields part, since we know
2839 * the body needs to start at an 8 byte alignment. We made
2840 * sure we allocated enough space for this, so all we need to
2841 * do here is to zero it out. */
2842 l = BUS_MESSAGE_FIELDS_SIZE(m);
2845 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, a);
2847 /* If this is something we can send as memfd, then let's seal
2848 the memfd now. Note that we can send memfds as payload only
2849 for directed messages, and not for broadcasts. */
2850 if (m->destination && m->bus->use_memfd) {
2851 MESSAGE_FOREACH_PART(part, i, m)
2852 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2855 /* Try to seal it if that makes
2856 * sense. First, unmap our own map to
2857 * make sure we don't keep it busy. */
2858 bus_body_part_unmap(part);
2860 /* Then, sync up real memfd size */
2862 r = memfd_set_size(part->memfd, sz);
2866 /* Finally, try to seal */
2867 if (memfd_set_sealed(part->memfd) >= 0)
2868 part->sealed = true;
2872 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2873 m->root_container.index = 0;
2874 m->root_container.offset_index = 0;
2875 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2882 int bus_body_part_map(struct bus_body_part *part) {
2891 if (part->size <= 0)
2894 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2895 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2896 static const uint8_t zeroes[7] = { };
2897 part->data = (void*) zeroes;
2901 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
2902 psz = PAGE_ALIGN(part->size + shift);
2904 if (part->memfd >= 0)
2905 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
2906 else if (part->is_zero)
2907 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2911 if (p == MAP_FAILED)
2915 part->mmap_begin = p;
2916 part->data = (uint8_t*) p + shift;
2917 part->munmap_this = true;
2922 void bus_body_part_unmap(struct bus_body_part *part) {
2926 if (part->memfd < 0)
2929 if (!part->mmap_begin)
2932 if (!part->munmap_this)
2935 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
2937 part->mmap_begin = NULL;
2940 part->munmap_this = false;
2945 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2946 size_t k, start, end;
2951 start = ALIGN_TO((size_t) *rindex, align);
2952 end = start + nbytes;
2957 /* Verify that padding is 0 */
2958 for (k = *rindex; k < start; k++)
2959 if (((const uint8_t*) p)[k] != 0)
2963 *r = (uint8_t*) p + start;
2970 static bool message_end_of_signature(sd_bus_message *m) {
2971 struct bus_container *c;
2975 c = message_get_container(m);
2976 return !c->signature || c->signature[c->index] == 0;
2979 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2980 struct bus_container *c;
2984 c = message_get_container(m);
2985 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2988 if (BUS_MESSAGE_IS_GVARIANT(m))
2989 return index >= c->end;
2991 assert(c->array_size);
2992 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2996 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2997 assert_return(m, -EINVAL);
2998 assert_return(m->sealed, -EPERM);
3000 if (complete && m->n_containers > 0)
3003 if (message_end_of_signature(m))
3006 if (message_end_of_array(m, m->rindex))
3012 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3013 struct bus_body_part *part;
3019 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3020 part = m->cached_rindex_part;
3021 begin = m->cached_rindex_part_begin;
3031 if (index + sz <= begin + part->size) {
3033 r = bus_body_part_map(part);
3038 *p = (uint8_t*) part->data + index - begin;
3040 m->cached_rindex_part = part;
3041 m->cached_rindex_part_begin = begin;
3046 begin += part->size;
3053 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3060 if (!BUS_MESSAGE_IS_GVARIANT(m))
3063 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3066 sz = bus_gvariant_get_size(c->signature);
3070 if (c->offset_index+1 >= c->n_offsets)
3073 /* Variable-size array */
3075 alignment = bus_gvariant_get_alignment(c->signature);
3076 assert(alignment > 0);
3078 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3079 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3082 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3085 /* Fixed-size array */
3086 *rindex = c->begin + (c->offset_index+1) * sz;
3092 } else if (c->enclosing == 0 ||
3093 c->enclosing == SD_BUS_TYPE_STRUCT ||
3094 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3099 if (c->offset_index+1 >= c->n_offsets)
3102 r = signature_element_length(c->signature + c->index, &n);
3106 r = signature_element_length(c->signature + c->index + n, &j);
3111 memcpy(t, c->signature + c->index + n, j);
3114 alignment = bus_gvariant_get_alignment(t);
3117 assert(alignment > 0);
3119 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3120 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3124 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3127 assert_not_reached("Unknown container type");
3132 /* Reached the end */
3139 static int message_peek_body(
3146 size_t k, start, end, padding;
3147 struct bus_body_part *part;
3154 start = ALIGN_TO((size_t) *rindex, align);
3155 padding = start - *rindex;
3156 end = start + nbytes;
3158 if (end > BUS_MESSAGE_BODY_SIZE(m))
3161 part = find_part(m, *rindex, padding, (void**) &q);
3166 /* Verify padding */
3167 for (k = 0; k < padding; k++)
3172 part = find_part(m, start, nbytes, (void**) &q);
3173 if (!part || (nbytes > 0 && !q))
3184 static bool validate_nul(const char *s, size_t l) {
3186 /* Check for NUL chars in the string */
3187 if (memchr(s, 0, l))
3190 /* Check for NUL termination */
3197 static bool validate_string(const char *s, size_t l) {
3199 if (!validate_nul(s, l))
3202 /* Check if valid UTF8 */
3203 if (!utf8_is_valid(s))
3209 static bool validate_signature(const char *s, size_t l) {
3211 if (!validate_nul(s, l))
3214 /* Check if valid signature */
3215 if (!signature_is_valid(s, true))
3221 static bool validate_object_path(const char *s, size_t l) {
3223 if (!validate_nul(s, l))
3226 if (!object_path_is_valid(s))
3232 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3233 struct bus_container *c;
3238 assert_return(m, -EINVAL);
3239 assert_return(m->sealed, -EPERM);
3240 assert_return(bus_type_is_basic(type), -EINVAL);
3242 if (message_end_of_signature(m))
3245 if (message_end_of_array(m, m->rindex))
3248 c = message_get_container(m);
3249 if (c->signature[c->index] != type)
3254 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3256 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3259 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3263 if (type == SD_BUS_TYPE_STRING)
3264 ok = validate_string(q, c->item_size-1);
3265 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3266 ok = validate_object_path(q, c->item_size-1);
3268 ok = validate_signature(q, c->item_size-1);
3274 *(const char**) p = q;
3278 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3280 if ((size_t) sz != c->item_size)
3283 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3286 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3292 case SD_BUS_TYPE_BYTE:
3294 *(uint8_t*) p = *(uint8_t*) q;
3297 case SD_BUS_TYPE_BOOLEAN:
3299 *(int*) p = !!*(uint8_t*) q;
3302 case SD_BUS_TYPE_INT16:
3303 case SD_BUS_TYPE_UINT16:
3305 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3308 case SD_BUS_TYPE_INT32:
3309 case SD_BUS_TYPE_UINT32:
3311 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3314 case SD_BUS_TYPE_INT64:
3315 case SD_BUS_TYPE_UINT64:
3316 case SD_BUS_TYPE_DOUBLE:
3318 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3321 case SD_BUS_TYPE_UNIX_FD: {
3324 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3329 *(int*) p = m->fds[j];
3335 assert_not_reached("unexpected type");
3339 r = container_next_item(m, c, &rindex);
3346 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3350 r = message_peek_body(m, &rindex, 4, 4, &q);
3354 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3355 r = message_peek_body(m, &rindex, 1, l+1, &q);
3359 if (type == SD_BUS_TYPE_OBJECT_PATH)
3360 ok = validate_object_path(q, l);
3362 ok = validate_string(q, l);
3367 *(const char**) p = q;
3369 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3372 r = message_peek_body(m, &rindex, 1, 1, &q);
3377 r = message_peek_body(m, &rindex, 1, l+1, &q);
3381 if (!validate_signature(q, l))
3385 *(const char**) p = q;
3390 align = bus_type_get_alignment(type);
3393 sz = bus_type_get_size(type);
3396 r = message_peek_body(m, &rindex, align, sz, &q);
3402 case SD_BUS_TYPE_BYTE:
3404 *(uint8_t*) p = *(uint8_t*) q;
3407 case SD_BUS_TYPE_BOOLEAN:
3409 *(int*) p = !!*(uint32_t*) q;
3412 case SD_BUS_TYPE_INT16:
3413 case SD_BUS_TYPE_UINT16:
3415 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3418 case SD_BUS_TYPE_INT32:
3419 case SD_BUS_TYPE_UINT32:
3421 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3424 case SD_BUS_TYPE_INT64:
3425 case SD_BUS_TYPE_UINT64:
3426 case SD_BUS_TYPE_DOUBLE:
3428 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3431 case SD_BUS_TYPE_UNIX_FD: {
3434 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3439 *(int*) p = m->fds[j];
3444 assert_not_reached("Unknown basic type...");
3451 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3457 static int bus_message_enter_array(
3459 struct bus_container *c,
3460 const char *contents,
3461 uint32_t **array_size,
3464 size_t *n_offsets) {
3478 if (!signature_is_single(contents, true))
3481 if (!c->signature || c->signature[c->index] == 0)
3484 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3487 if (!startswith(c->signature + c->index + 1, contents))
3492 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3495 r = message_peek_body(m, &rindex, 4, 4, &q);
3499 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3502 alignment = bus_type_get_alignment(contents[0]);
3506 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3510 *array_size = (uint32_t*) q;
3512 } else if (c->item_size <= 0) {
3514 /* gvariant: empty array */
3519 } else if (bus_gvariant_is_fixed_size(contents)) {
3521 /* gvariant: fixed length array */
3522 *item_size = bus_gvariant_get_size(contents);
3527 size_t where, p = 0, framing, sz;
3530 /* gvariant: variable length array */
3531 sz = determine_word_size(c->item_size, 0);
3533 where = rindex + c->item_size - sz;
3534 r = message_peek_body(m, &where, 1, sz, &q);
3538 framing = read_word_le(q, sz);
3539 if (framing > c->item_size - sz)
3541 if ((c->item_size - framing) % sz != 0)
3544 *n_offsets = (c->item_size - framing) / sz;
3546 where = rindex + framing;
3547 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3551 *offsets = new(size_t, *n_offsets);
3555 for (i = 0; i < *n_offsets; i++) {
3558 x = read_word_le((uint8_t*) q + i * sz, sz);
3559 if (x > c->item_size - sz)
3564 (*offsets)[i] = rindex + x;
3568 *item_size = (*offsets)[0] - rindex;
3573 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3574 c->index += 1 + strlen(contents);
3579 static int bus_message_enter_variant(
3581 struct bus_container *c,
3582 const char *contents,
3583 size_t *item_size) {
3595 if (!signature_is_single(contents, false))
3598 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3601 if (!c->signature || c->signature[c->index] == 0)
3604 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3609 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3612 k = strlen(contents);
3613 if (1+k > c->item_size)
3616 where = rindex + c->item_size - (1+k);
3617 r = message_peek_body(m, &where, 1, 1+k, &q);
3621 if (*(char*) q != 0)
3624 if (memcmp((uint8_t*) q+1, contents, k))
3627 *item_size = c->item_size - (1+k);
3630 r = message_peek_body(m, &rindex, 1, 1, &q);
3635 r = message_peek_body(m, &rindex, 1, l+1, &q);
3639 if (!validate_signature(q, l))
3642 if (!streq(q, contents))
3648 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3654 static int build_struct_offsets(
3656 const char *signature,
3660 size_t *n_offsets) {
3662 unsigned n_variable = 0, n_total = 0, v;
3663 size_t previous = 0, where;
3674 if (isempty(signature)) {
3681 sz = determine_word_size(size, 0);
3685 /* First, loop over signature and count variable elements and
3686 * elements in general. We use this to know how large the
3687 * offset array is at the end of the structure. Note that
3688 * GVariant only stores offsets for all variable size elements
3689 * that are not the last item. */
3695 r = signature_element_length(p, &n);
3704 r = bus_gvariant_is_fixed_size(t);
3709 if (r == 0 && p[n] != 0) /* except the last item */
3716 if (size < n_variable * sz)
3719 where = m->rindex + size - (n_variable * sz);
3720 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3726 *offsets = new(size_t, n_total);
3732 /* Second, loop again and build an offset table */
3738 r = signature_element_length(p, &n);
3747 k = bus_gvariant_get_size(t);
3755 x = read_word_le((uint8_t*) q + v*sz, sz);
3758 if (m->rindex + x < previous)
3761 /* The last item's end
3762 * is determined from
3765 x = size - (n_variable * sz);
3767 offset = m->rindex + x;
3773 align = bus_gvariant_get_alignment(t);
3776 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3780 previous = (*offsets)[(*n_offsets)++] = offset;
3785 assert(*n_offsets == n_total);
3787 *item_size = (*offsets)[0] - m->rindex;
3791 static int enter_struct_or_dict_entry(
3793 struct bus_container *c,
3794 const char *contents,
3797 size_t *n_offsets) {
3808 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3811 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3815 } else if (c->item_size <= 0) {
3817 /* gvariant empty struct */
3822 /* gvariant with contents */
3823 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3828 static int bus_message_enter_struct(
3830 struct bus_container *c,
3831 const char *contents,
3834 size_t *n_offsets) {
3846 if (!signature_is_valid(contents, false))
3849 if (!c->signature || c->signature[c->index] == 0)
3852 l = strlen(contents);
3854 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3855 !startswith(c->signature + c->index + 1, contents) ||
3856 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3859 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3863 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3864 c->index += 1 + l + 1;
3869 static int bus_message_enter_dict_entry(
3871 struct bus_container *c,
3872 const char *contents,
3875 size_t *n_offsets) {
3884 if (!signature_is_pair(contents))
3887 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3890 if (!c->signature || c->signature[c->index] == 0)
3893 l = strlen(contents);
3895 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3896 !startswith(c->signature + c->index + 1, contents) ||
3897 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3900 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3904 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3905 c->index += 1 + l + 1;
3910 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3912 const char *contents) {
3913 struct bus_container *c, *w;
3914 uint32_t *array_size = NULL;
3917 size_t *offsets = NULL;
3918 size_t n_offsets = 0, item_size = 0;
3921 assert_return(m, -EINVAL);
3922 assert_return(m->sealed, -EPERM);
3923 assert_return(type != 0 || !contents, -EINVAL);
3925 if (type == 0 || !contents) {
3929 /* Allow entering into anonymous containers */
3930 r = sd_bus_message_peek_type(m, &tt, &cc);
3934 if (type != 0 && type != tt)
3937 if (contents && !streq(contents, cc))
3945 * We enforce a global limit on container depth, that is much
3946 * higher than the 32 structs and 32 arrays the specification
3947 * mandates. This is simpler to implement for us, and we need
3948 * this only to ensure our container array doesn't grow
3949 * without bounds. We are happy to return any data from a
3950 * message as long as the data itself is valid, even if the
3951 * overall message might be not.
3953 * Note that the message signature is validated when
3954 * parsing the headers, and that validation does check the
3957 * Note that the specification defines no limits on the depth
3958 * of stacked variants, but we do.
3960 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3963 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3966 if (message_end_of_signature(m))
3969 if (message_end_of_array(m, m->rindex))
3972 c = message_get_container(m);
3974 signature = strdup(contents);
3978 c->saved_index = c->index;
3981 if (type == SD_BUS_TYPE_ARRAY)
3982 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3983 else if (type == SD_BUS_TYPE_VARIANT)
3984 r = bus_message_enter_variant(m, c, contents, &item_size);
3985 else if (type == SD_BUS_TYPE_STRUCT)
3986 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3987 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3988 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3998 /* OK, let's fill it in */
3999 w = m->containers + m->n_containers++;
4000 w->enclosing = type;
4001 w->signature = signature;
4002 w->peeked_signature = NULL;
4006 w->begin = m->rindex;
4007 w->end = m->rindex + c->item_size;
4009 w->array_size = array_size;
4010 w->item_size = item_size;
4011 w->offsets = offsets;
4012 w->n_offsets = n_offsets;
4013 w->offset_index = 0;
4018 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4019 struct bus_container *c;
4023 assert_return(m, -EINVAL);
4024 assert_return(m->sealed, -EPERM);
4025 assert_return(m->n_containers > 0, -ENXIO);
4027 c = message_get_container(m);
4029 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4030 if (c->signature && c->signature[c->index] != 0)
4034 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4035 if (m->rindex < c->end)
4038 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4041 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4042 if (c->begin + l != m->rindex)
4047 free(c->peeked_signature);
4051 c = message_get_container(m);
4054 c->index = c->saved_index;
4055 r = container_next_item(m, c, &m->rindex);
4063 static void message_quit_container(sd_bus_message *m) {
4064 struct bus_container *c;
4068 assert(m->n_containers > 0);
4070 c = message_get_container(m);
4073 assert(m->rindex >= c->before);
4074 m->rindex = c->before;
4076 /* Free container */
4081 /* Correct index of new top-level container */
4082 c = message_get_container(m);
4083 c->index = c->saved_index;
4086 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4087 struct bus_container *c;
4090 assert_return(m, -EINVAL);
4091 assert_return(m->sealed, -EPERM);
4093 if (message_end_of_signature(m))
4096 if (message_end_of_array(m, m->rindex))
4099 c = message_get_container(m);
4101 if (bus_type_is_basic(c->signature[c->index])) {
4105 *type = c->signature[c->index];
4109 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4115 r = signature_element_length(c->signature+c->index+1, &l);
4121 sig = strndup(c->signature + c->index + 1, l);
4125 free(c->peeked_signature);
4126 *contents = c->peeked_signature = sig;
4130 *type = SD_BUS_TYPE_ARRAY;
4135 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4136 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4142 r = signature_element_length(c->signature+c->index, &l);
4147 sig = strndup(c->signature + c->index + 1, l - 2);
4151 free(c->peeked_signature);
4152 *contents = c->peeked_signature = sig;
4156 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4161 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4165 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4168 if (c->item_size < 2)
4171 /* Look for the NUL delimiter that
4172 separates the payload from the
4173 signature. Since the body might be
4174 in a different part that then the
4175 signature we map byte by byte. */
4177 for (k = 2; k <= c->item_size; k++) {
4180 where = m->rindex + c->item_size - k;
4181 r = message_peek_body(m, &where, 1, k, &q);
4185 if (*(char*) q == 0)
4189 if (k > c->item_size)
4192 free(c->peeked_signature);
4193 c->peeked_signature = strndup((char*) q + 1, k - 1);
4194 if (!c->peeked_signature)
4197 if (!signature_is_valid(c->peeked_signature, true))
4200 *contents = c->peeked_signature;
4205 r = message_peek_body(m, &rindex, 1, 1, &q);
4210 r = message_peek_body(m, &rindex, 1, l+1, &q);
4214 if (!validate_signature(q, l))
4222 *type = SD_BUS_TYPE_VARIANT;
4237 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4238 struct bus_container *c;
4240 assert_return(m, -EINVAL);
4241 assert_return(m->sealed, -EPERM);
4244 message_reset_containers(m);
4247 c = message_get_container(m);
4249 c = message_get_container(m);
4251 c->offset_index = 0;
4253 m->rindex = c->begin;
4256 c->offset_index = 0;
4257 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4259 return !isempty(c->signature);
4262 static int message_read_ap(
4267 unsigned n_array, n_struct;
4268 TypeStack stack[BUS_CONTAINER_DEPTH];
4269 unsigned stack_ptr = 0;
4270 unsigned n_loop = 0;
4278 /* Ideally, we'd just call ourselves recursively on every
4279 * complex type. However, the state of a va_list that is
4280 * passed to a function is undefined after that function
4281 * returns. This means we need to docode the va_list linearly
4282 * in a single stackframe. We hence implement our own
4283 * home-grown stack in an array. */
4285 n_array = (unsigned) -1; /* length of current array entries */
4286 n_struct = strlen(types); /* length of current struct contents signature */
4293 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4294 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4300 r = sd_bus_message_exit_container(m);
4308 if (n_array != (unsigned) -1)
4317 case SD_BUS_TYPE_BYTE:
4318 case SD_BUS_TYPE_BOOLEAN:
4319 case SD_BUS_TYPE_INT16:
4320 case SD_BUS_TYPE_UINT16:
4321 case SD_BUS_TYPE_INT32:
4322 case SD_BUS_TYPE_UINT32:
4323 case SD_BUS_TYPE_INT64:
4324 case SD_BUS_TYPE_UINT64:
4325 case SD_BUS_TYPE_DOUBLE:
4326 case SD_BUS_TYPE_STRING:
4327 case SD_BUS_TYPE_OBJECT_PATH:
4328 case SD_BUS_TYPE_SIGNATURE:
4329 case SD_BUS_TYPE_UNIX_FD: {
4332 p = va_arg(ap, void*);
4333 r = sd_bus_message_read_basic(m, *t, p);
4346 case SD_BUS_TYPE_ARRAY: {
4349 r = signature_element_length(t + 1, &k);
4355 memcpy(s, t + 1, k);
4358 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4369 if (n_array == (unsigned) -1) {
4374 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4380 n_array = va_arg(ap, unsigned);
4385 case SD_BUS_TYPE_VARIANT: {
4388 s = va_arg(ap, const char *);
4392 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4402 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4407 n_struct = strlen(s);
4408 n_array = (unsigned) -1;
4413 case SD_BUS_TYPE_STRUCT_BEGIN:
4414 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4417 r = signature_element_length(t, &k);
4423 memcpy(s, t + 1, k - 2);
4426 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4436 if (n_array == (unsigned) -1) {
4441 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4447 n_array = (unsigned) -1;
4460 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4464 assert_return(m, -EINVAL);
4465 assert_return(m->sealed, -EPERM);
4466 assert_return(types, -EINVAL);
4468 va_start(ap, types);
4469 r = message_read_ap(m, types, ap);
4475 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4478 assert_return(m, -EINVAL);
4479 assert_return(m->sealed, -EPERM);
4481 /* If types is NULL, read exactly one element */
4483 struct bus_container *c;
4486 if (message_end_of_signature(m))
4489 if (message_end_of_array(m, m->rindex))
4492 c = message_get_container(m);
4494 r = signature_element_length(c->signature + c->index, &l);
4498 types = strndupa(c->signature + c->index, l);
4503 case 0: /* Nothing to drop */
4506 case SD_BUS_TYPE_BYTE:
4507 case SD_BUS_TYPE_BOOLEAN:
4508 case SD_BUS_TYPE_INT16:
4509 case SD_BUS_TYPE_UINT16:
4510 case SD_BUS_TYPE_INT32:
4511 case SD_BUS_TYPE_UINT32:
4512 case SD_BUS_TYPE_INT64:
4513 case SD_BUS_TYPE_UINT64:
4514 case SD_BUS_TYPE_DOUBLE:
4515 case SD_BUS_TYPE_STRING:
4516 case SD_BUS_TYPE_OBJECT_PATH:
4517 case SD_BUS_TYPE_SIGNATURE:
4518 case SD_BUS_TYPE_UNIX_FD:
4520 r = sd_bus_message_read_basic(m, *types, NULL);
4524 r = sd_bus_message_skip(m, types + 1);
4530 case SD_BUS_TYPE_ARRAY: {
4533 r = signature_element_length(types + 1, &k);
4539 memcpy(s, types+1, k);
4542 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4547 r = sd_bus_message_skip(m, s);
4554 r = sd_bus_message_exit_container(m);
4559 r = sd_bus_message_skip(m, types + 1 + k);
4566 case SD_BUS_TYPE_VARIANT: {
4567 const char *contents;
4570 r = sd_bus_message_peek_type(m, &x, &contents);
4574 if (x != SD_BUS_TYPE_VARIANT)
4577 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4581 r = sd_bus_message_skip(m, contents);
4586 r = sd_bus_message_exit_container(m);
4590 r = sd_bus_message_skip(m, types + 1);
4597 case SD_BUS_TYPE_STRUCT_BEGIN:
4598 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4601 r = signature_element_length(types, &k);
4607 memcpy(s, types+1, k-2);
4610 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4614 r = sd_bus_message_skip(m, s);
4619 r = sd_bus_message_exit_container(m);
4624 r = sd_bus_message_skip(m, types + k);
4636 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4640 struct bus_container *c;
4646 assert_return(m, -EINVAL);
4647 assert_return(m->sealed, -EPERM);
4648 assert_return(bus_type_is_trivial(type), -EINVAL);
4649 assert_return(ptr, -EINVAL);
4650 assert_return(size, -EINVAL);
4651 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4653 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4657 c = message_get_container(m);
4659 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4660 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4664 sz = c->end - c->begin;
4666 align = bus_type_get_alignment(type);
4670 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4674 /* Zero length array, let's return some aligned
4675 * pointer that is not NULL */
4676 p = (uint8_t*) NULL + align;
4678 r = message_peek_body(m, &m->rindex, align, sz, &p);
4683 r = sd_bus_message_exit_container(m);
4687 *ptr = (const void*) p;
4693 message_quit_container(m);
4697 static int message_peek_fields(
4708 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4711 static int message_peek_field_uint32(
4723 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4726 /* identical for gvariant and dbus1 */
4728 r = message_peek_fields(m, ri, 4, 4, &q);
4733 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4738 static int message_peek_field_string(
4740 bool (*validate)(const char *p),
4752 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4757 r = message_peek_fields(m, ri, 1, item_size, &q);
4763 r = message_peek_field_uint32(m, ri, 4, &l);
4767 r = message_peek_fields(m, ri, 1, l+1, &q);
4773 if (!validate_nul(q, l))
4779 if (!validate_string(q, l))
4789 static int message_peek_field_signature(
4802 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4807 r = message_peek_fields(m, ri, 1, item_size, &q);
4813 r = message_peek_fields(m, ri, 1, 1, &q);
4818 r = message_peek_fields(m, ri, 1, l+1, &q);
4823 if (!validate_signature(q, l))
4832 static int message_skip_fields(
4835 uint32_t array_size,
4836 const char **signature) {
4838 size_t original_index;
4844 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4846 original_index = *ri;
4852 if (array_size != (uint32_t) -1 &&
4853 array_size <= *ri - original_index)
4860 if (t == SD_BUS_TYPE_STRING) {
4862 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4868 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4870 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4876 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4878 r = message_peek_field_signature(m, ri, 0, NULL);
4884 } else if (bus_type_is_basic(t)) {
4887 align = bus_type_get_alignment(t);
4888 k = bus_type_get_size(t);
4889 assert(align > 0 && k > 0);
4891 r = message_peek_fields(m, ri, align, k, NULL);
4897 } else if (t == SD_BUS_TYPE_ARRAY) {
4899 r = signature_element_length(*signature+1, &l);
4909 strncpy(sig, *signature + 1, l-1);
4912 alignment = bus_type_get_alignment(sig[0]);
4916 r = message_peek_field_uint32(m, ri, 0, &nas);
4919 if (nas > BUS_ARRAY_MAX_SIZE)
4922 r = message_peek_fields(m, ri, alignment, 0, NULL);
4926 r = message_skip_fields(m, ri, nas, (const char**) &s);
4931 (*signature) += 1 + l;
4933 } else if (t == SD_BUS_TYPE_VARIANT) {
4936 r = message_peek_field_signature(m, ri, 0, &s);
4940 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4946 } else if (t == SD_BUS_TYPE_STRUCT ||
4947 t == SD_BUS_TYPE_DICT_ENTRY) {
4949 r = signature_element_length(*signature, &l);
4956 strncpy(sig, *signature + 1, l-1);
4959 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4970 int bus_message_parse_fields(sd_bus_message *m) {
4973 uint32_t unix_fds = 0;
4974 bool unix_fds_set = false;
4975 void *offsets = NULL;
4976 unsigned n_offsets = 0;
4982 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4985 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4989 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4990 r = message_peek_fields(m, &ri, 1, sz, &q);
4994 framing = read_word_le(q, sz);
4995 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4997 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
5001 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
5005 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
5010 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
5011 _cleanup_free_ char *sig = NULL;
5012 const char *signature;
5014 size_t item_size = (size_t) -1;
5016 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5023 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5026 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
5030 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5035 end = read_word_le((uint8_t*) offsets + i*sz, sz);
5040 where = ri = ALIGN_TO(ri, 8);
5041 item_size = end - ri;
5042 r = message_peek_fields(m, &where, 1, item_size, &q);
5046 b = memrchr(q, 0, item_size);
5050 sig = strndup(b+1, item_size - (b+1-(char*) q));
5055 item_size = b - (char*) q;
5057 r = message_peek_field_signature(m, &ri, 0, &signature);
5063 case _BUS_MESSAGE_HEADER_INVALID:
5066 case BUS_MESSAGE_HEADER_PATH:
5071 if (!streq(signature, "o"))
5074 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5077 case BUS_MESSAGE_HEADER_INTERFACE:
5082 if (!streq(signature, "s"))
5085 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5088 case BUS_MESSAGE_HEADER_MEMBER:
5093 if (!streq(signature, "s"))
5096 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5099 case BUS_MESSAGE_HEADER_ERROR_NAME:
5104 if (!streq(signature, "s"))
5107 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5109 m->error._need_free = -1;
5113 case BUS_MESSAGE_HEADER_DESTINATION:
5118 if (!streq(signature, "s"))
5121 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5124 case BUS_MESSAGE_HEADER_SENDER:
5129 if (!streq(signature, "s"))
5132 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5134 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5135 m->creds.unique_name = (char*) m->sender;
5136 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5142 case BUS_MESSAGE_HEADER_SIGNATURE: {
5146 if (m->root_container.signature)
5149 if (!streq(signature, "g"))
5152 r = message_peek_field_signature(m, &ri, item_size, &s);
5160 free(m->root_container.signature);
5161 m->root_container.signature = c;
5165 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5168 if (m->reply_cookie != 0)
5171 if (!streq(signature, "u"))
5174 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5178 m->reply_cookie = serial;
5180 if (m->reply_cookie == 0)
5186 case BUS_MESSAGE_HEADER_UNIX_FDS:
5190 if (!streq(signature, "u"))
5193 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5197 unix_fds_set = true;
5201 if (!BUS_MESSAGE_IS_GVARIANT(m))
5202 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5211 if (m->n_fds != unix_fds)
5214 switch (m->header->type) {
5216 case SD_BUS_MESSAGE_SIGNAL:
5217 if (!m->path || !m->interface || !m->member)
5220 if (m->reply_cookie != 0)
5225 case SD_BUS_MESSAGE_METHOD_CALL:
5227 if (!m->path || !m->member)
5230 if (m->reply_cookie != 0)
5235 case SD_BUS_MESSAGE_METHOD_RETURN:
5237 if (m->reply_cookie == 0)
5241 case SD_BUS_MESSAGE_METHOD_ERROR:
5243 if (m->reply_cookie == 0 || !m->error.name)
5248 /* Refuse non-local messages that claim they are local */
5249 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5251 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5253 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5256 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5258 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5259 r = build_struct_offsets(
5261 m->root_container.signature,
5262 BUS_MESSAGE_BODY_SIZE(m),
5263 &m->root_container.item_size,
5264 &m->root_container.offsets,
5265 &m->root_container.n_offsets);
5270 /* Try to read the error message, but if we can't it's a non-issue */
5271 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5272 sd_bus_message_read(m, "s", &m->error.message);
5277 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5278 assert_return(m, -EINVAL);
5279 assert_return(destination, -EINVAL);
5280 assert_return(!m->sealed, -EPERM);
5281 assert_return(!m->destination, -EEXIST);
5283 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5286 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5290 struct bus_body_part *part;
5296 total = BUS_MESSAGE_SIZE(m);
5302 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5303 MESSAGE_FOREACH_PART(part, i, m)
5304 e = mempcpy(e, part->data, part->size);
5306 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5314 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5320 r = sd_bus_message_enter_container(m, 'a', "s");
5327 r = sd_bus_message_read_basic(m, 's', &s);
5333 r = strv_extend(l, s);
5338 r = sd_bus_message_exit_container(m);
5345 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5349 assert_return(m, -EINVAL);
5350 assert_return(m->sealed, -EPERM);
5351 assert_return(l, -EINVAL);
5353 r = bus_message_read_strv_extend(m, &strv);
5363 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5364 const char *contents;
5373 r = sd_bus_message_rewind(m, true);
5378 r = sd_bus_message_peek_type(m, &type, &contents);
5384 /* Don't match against arguments after the first one we don't understand */
5385 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5386 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5392 r = sd_bus_message_skip(m, NULL);
5397 if (type == SD_BUS_TYPE_ARRAY) {
5399 r = sd_bus_message_read_strv(m, strv);
5406 r = sd_bus_message_read_basic(m, type, str);
5416 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5422 if (size < sizeof(struct bus_header))
5425 full = sizeof(struct bus_header) +
5426 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5428 return size >= full;
5431 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5437 if (h->endian == BUS_NATIVE_ENDIAN) {
5438 fs = h->fields_size;
5440 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5441 fs = bswap_32(h->fields_size);
5442 bs = bswap_32(h->body_size);
5446 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5450 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5451 assert_return(m, EINVAL);
5453 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5456 return sd_bus_error_get_errno(&m->error);
5459 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5460 struct bus_container *c;
5462 assert_return(m, NULL);
5464 c = complete ? &m->root_container : message_get_container(m);
5465 return strempty(c->signature);
5468 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5469 assert_return(m, -EINVAL);
5471 return isempty(m->root_container.signature);
5474 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5475 assert_return(m, -EINVAL);
5477 return streq(strempty(m->root_container.signature), strempty(signature));
5480 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5481 bool done_something = false;
5484 assert_return(m, -EINVAL);
5485 assert_return(source, -EINVAL);
5486 assert_return(!m->sealed, -EPERM);
5487 assert_return(source->sealed, -EPERM);
5490 const char *contents;
5505 r = sd_bus_message_peek_type(source, &type, &contents);
5511 done_something = true;
5513 if (bus_type_is_container(type) > 0) {
5515 r = sd_bus_message_enter_container(source, type, contents);
5519 r = sd_bus_message_open_container(m, type, contents);
5523 r = sd_bus_message_copy(m, source, true);
5527 r = sd_bus_message_close_container(m);
5531 r = sd_bus_message_exit_container(source);
5538 r = sd_bus_message_read_basic(source, type, &basic);
5544 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5545 type == SD_BUS_TYPE_SIGNATURE ||
5546 type == SD_BUS_TYPE_STRING)
5547 r = sd_bus_message_append_basic(m, type, basic.string);
5549 r = sd_bus_message_append_basic(m, type, &basic);
5556 return done_something;
5559 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5564 assert_return(m, -EINVAL);
5565 assert_return(m->sealed, -EPERM);
5566 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5567 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5568 assert_return(type || contents, -EINVAL);
5569 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5571 r = sd_bus_message_peek_type(m, &t, &c);
5575 if (type != 0 && type != t)
5578 if (contents && !streq_ptr(contents, c))
5584 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5585 assert_return(m, NULL);
5590 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5591 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5599 switch ((*m)->header->type) {
5601 case SD_BUS_MESSAGE_SIGNAL:
5602 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5608 case SD_BUS_MESSAGE_METHOD_CALL:
5609 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5615 case SD_BUS_MESSAGE_METHOD_RETURN:
5616 case SD_BUS_MESSAGE_METHOD_ERROR:
5618 n = message_new(bus, (*m)->header->type);
5622 n->reply_cookie = (*m)->reply_cookie;
5623 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5627 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5628 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5632 n->error._need_free = -1;
5641 if ((*m)->destination && !n->destination) {
5642 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5647 if ((*m)->sender && !n->sender) {
5648 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5653 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5655 r = sd_bus_message_copy(n, *m, true);
5659 timeout = (*m)->timeout;
5660 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5661 timeout = BUS_DEFAULT_TIMEOUT;
5663 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5667 sd_bus_message_unref(*m);
5674 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5678 assert_return(!m->sealed, -EPERM);
5679 assert_return(!m->sender, -EPERM);
5681 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5684 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5685 assert_return(m, -EINVAL);
5686 assert_return(priority, -EINVAL);
5688 *priority = m->priority;
5692 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5693 assert_return(m, -EINVAL);
5694 assert_return(!m->sealed, -EPERM);
5696 m->priority = priority;