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_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->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);
4454 /* If types is NULL, read exactly one element */
4456 struct bus_container *c;
4459 if (message_end_of_signature(m))
4462 if (message_end_of_array(m, m->rindex))
4465 c = message_get_container(m);
4467 r = signature_element_length(c->signature + c->index, &l);
4471 types = strndupa(c->signature + c->index, l);
4476 case 0: /* Nothing to drop */
4479 case SD_BUS_TYPE_BYTE:
4480 case SD_BUS_TYPE_BOOLEAN:
4481 case SD_BUS_TYPE_INT16:
4482 case SD_BUS_TYPE_UINT16:
4483 case SD_BUS_TYPE_INT32:
4484 case SD_BUS_TYPE_UINT32:
4485 case SD_BUS_TYPE_INT64:
4486 case SD_BUS_TYPE_UINT64:
4487 case SD_BUS_TYPE_DOUBLE:
4488 case SD_BUS_TYPE_STRING:
4489 case SD_BUS_TYPE_OBJECT_PATH:
4490 case SD_BUS_TYPE_SIGNATURE:
4491 case SD_BUS_TYPE_UNIX_FD:
4493 r = sd_bus_message_read_basic(m, *types, NULL);
4497 r = sd_bus_message_skip(m, types + 1);
4503 case SD_BUS_TYPE_ARRAY: {
4506 r = signature_element_length(types + 1, &k);
4512 memcpy(s, types+1, k);
4515 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4520 r = sd_bus_message_skip(m, s);
4527 r = sd_bus_message_exit_container(m);
4532 r = sd_bus_message_skip(m, types + 1 + k);
4539 case SD_BUS_TYPE_VARIANT: {
4540 const char *contents;
4543 r = sd_bus_message_peek_type(m, &x, &contents);
4547 if (x != SD_BUS_TYPE_VARIANT)
4550 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4554 r = sd_bus_message_skip(m, contents);
4559 r = sd_bus_message_exit_container(m);
4563 r = sd_bus_message_skip(m, types + 1);
4570 case SD_BUS_TYPE_STRUCT_BEGIN:
4571 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4574 r = signature_element_length(types, &k);
4580 memcpy(s, types+1, k-2);
4583 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4587 r = sd_bus_message_skip(m, s);
4592 r = sd_bus_message_exit_container(m);
4597 r = sd_bus_message_skip(m, types + k);
4609 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4613 struct bus_container *c;
4619 assert_return(m, -EINVAL);
4620 assert_return(m->sealed, -EPERM);
4621 assert_return(bus_type_is_trivial(type), -EINVAL);
4622 assert_return(ptr, -EINVAL);
4623 assert_return(size, -EINVAL);
4624 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4626 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4630 c = message_get_container(m);
4632 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4633 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4637 sz = c->end - c->begin;
4639 align = bus_type_get_alignment(type);
4643 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4647 /* Zero length array, let's return some aligned
4648 * pointer that is not NULL */
4649 p = (uint8_t*) NULL + align;
4651 r = message_peek_body(m, &m->rindex, align, sz, &p);
4656 r = sd_bus_message_exit_container(m);
4660 *ptr = (const void*) p;
4666 message_quit_container(m);
4670 static int message_peek_fields(
4681 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4684 static int message_peek_field_uint32(
4696 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4699 /* identical for gvariant and dbus1 */
4701 r = message_peek_fields(m, ri, 4, 4, &q);
4706 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4711 static int message_peek_field_string(
4713 bool (*validate)(const char *p),
4725 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4730 r = message_peek_fields(m, ri, 1, item_size, &q);
4736 r = message_peek_field_uint32(m, ri, 4, &l);
4740 r = message_peek_fields(m, ri, 1, l+1, &q);
4746 if (!validate_nul(q, l))
4752 if (!validate_string(q, l))
4762 static int message_peek_field_signature(
4775 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4780 r = message_peek_fields(m, ri, 1, item_size, &q);
4786 r = message_peek_fields(m, ri, 1, 1, &q);
4791 r = message_peek_fields(m, ri, 1, l+1, &q);
4796 if (!validate_signature(q, l))
4805 static int message_skip_fields(
4808 uint32_t array_size,
4809 const char **signature) {
4811 size_t original_index;
4817 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4819 original_index = *ri;
4825 if (array_size != (uint32_t) -1 &&
4826 array_size <= *ri - original_index)
4833 if (t == SD_BUS_TYPE_STRING) {
4835 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4841 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4843 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4849 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4851 r = message_peek_field_signature(m, ri, 0, NULL);
4857 } else if (bus_type_is_basic(t)) {
4860 align = bus_type_get_alignment(t);
4861 k = bus_type_get_size(t);
4862 assert(align > 0 && k > 0);
4864 r = message_peek_fields(m, ri, align, k, NULL);
4870 } else if (t == SD_BUS_TYPE_ARRAY) {
4872 r = signature_element_length(*signature+1, &l);
4882 strncpy(sig, *signature + 1, l-1);
4885 alignment = bus_type_get_alignment(sig[0]);
4889 r = message_peek_field_uint32(m, ri, 0, &nas);
4892 if (nas > BUS_ARRAY_MAX_SIZE)
4895 r = message_peek_fields(m, ri, alignment, 0, NULL);
4899 r = message_skip_fields(m, ri, nas, (const char**) &s);
4904 (*signature) += 1 + l;
4906 } else if (t == SD_BUS_TYPE_VARIANT) {
4909 r = message_peek_field_signature(m, ri, 0, &s);
4913 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4919 } else if (t == SD_BUS_TYPE_STRUCT ||
4920 t == SD_BUS_TYPE_DICT_ENTRY) {
4922 r = signature_element_length(*signature, &l);
4929 strncpy(sig, *signature + 1, l-1);
4932 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4943 int bus_message_parse_fields(sd_bus_message *m) {
4946 uint32_t unix_fds = 0;
4947 bool unix_fds_set = false;
4948 void *offsets = NULL;
4949 unsigned n_offsets = 0;
4955 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4958 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4962 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4963 r = message_peek_fields(m, &ri, 1, sz, &q);
4967 framing = read_word_le(q, sz);
4968 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4970 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4974 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4978 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4983 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4984 _cleanup_free_ char *sig = NULL;
4985 const char *signature;
4987 size_t item_size = (size_t) -1;
4989 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4996 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4999 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
5003 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5008 end = read_word_le((uint8_t*) offsets + i*sz, sz);
5013 where = ri = ALIGN_TO(ri, 8);
5014 item_size = end - ri;
5015 r = message_peek_fields(m, &where, 1, item_size, &q);
5019 b = memrchr(q, 0, item_size);
5023 sig = strndup(b+1, item_size - (b+1-(char*) q));
5028 item_size = b - (char*) q;
5030 r = message_peek_field_signature(m, &ri, 0, &signature);
5036 case _BUS_MESSAGE_HEADER_INVALID:
5039 case BUS_MESSAGE_HEADER_PATH:
5044 if (!streq(signature, "o"))
5047 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5050 case BUS_MESSAGE_HEADER_INTERFACE:
5055 if (!streq(signature, "s"))
5058 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5061 case BUS_MESSAGE_HEADER_MEMBER:
5066 if (!streq(signature, "s"))
5069 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5072 case BUS_MESSAGE_HEADER_ERROR_NAME:
5077 if (!streq(signature, "s"))
5080 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5082 m->error._need_free = -1;
5086 case BUS_MESSAGE_HEADER_DESTINATION:
5091 if (!streq(signature, "s"))
5094 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5097 case BUS_MESSAGE_HEADER_SENDER:
5102 if (!streq(signature, "s"))
5105 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5107 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5108 m->creds.unique_name = (char*) m->sender;
5109 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5115 case BUS_MESSAGE_HEADER_SIGNATURE: {
5119 if (m->root_container.signature)
5122 if (!streq(signature, "g"))
5125 r = message_peek_field_signature(m, &ri, item_size, &s);
5133 free(m->root_container.signature);
5134 m->root_container.signature = c;
5138 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5141 if (m->reply_cookie != 0)
5144 if (!streq(signature, "u"))
5147 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5151 m->reply_cookie = serial;
5153 if (m->reply_cookie == 0)
5159 case BUS_MESSAGE_HEADER_UNIX_FDS:
5163 if (!streq(signature, "u"))
5166 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5170 unix_fds_set = true;
5174 if (!BUS_MESSAGE_IS_GVARIANT(m))
5175 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5184 if (m->n_fds != unix_fds)
5187 switch (m->header->type) {
5189 case SD_BUS_MESSAGE_SIGNAL:
5190 if (!m->path || !m->interface || !m->member)
5193 if (m->reply_cookie != 0)
5198 case SD_BUS_MESSAGE_METHOD_CALL:
5200 if (!m->path || !m->member)
5203 if (m->reply_cookie != 0)
5208 case SD_BUS_MESSAGE_METHOD_RETURN:
5210 if (m->reply_cookie == 0)
5214 case SD_BUS_MESSAGE_METHOD_ERROR:
5216 if (m->reply_cookie == 0 || !m->error.name)
5221 /* Refuse non-local messages that claim they are local */
5222 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5224 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5226 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5229 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5231 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5232 r = build_struct_offsets(
5234 m->root_container.signature,
5235 BUS_MESSAGE_BODY_SIZE(m),
5236 &m->root_container.item_size,
5237 &m->root_container.offsets,
5238 &m->root_container.n_offsets);
5243 /* Try to read the error message, but if we can't it's a non-issue */
5244 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5245 sd_bus_message_read(m, "s", &m->error.message);
5250 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5251 assert_return(m, -EINVAL);
5252 assert_return(destination, -EINVAL);
5253 assert_return(!m->sealed, -EPERM);
5254 assert_return(!m->destination, -EEXIST);
5256 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5259 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5263 struct bus_body_part *part;
5269 total = BUS_MESSAGE_SIZE(m);
5275 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5276 MESSAGE_FOREACH_PART(part, i, m)
5277 e = mempcpy(e, part->data, part->size);
5279 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5287 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5293 r = sd_bus_message_enter_container(m, 'a', "s");
5300 r = sd_bus_message_read_basic(m, 's', &s);
5306 r = strv_extend(l, s);
5311 r = sd_bus_message_exit_container(m);
5318 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5322 assert_return(m, -EINVAL);
5323 assert_return(m->sealed, -EPERM);
5324 assert_return(l, -EINVAL);
5326 r = bus_message_read_strv_extend(m, &strv);
5336 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5337 const char *contents;
5346 r = sd_bus_message_rewind(m, true);
5351 r = sd_bus_message_peek_type(m, &type, &contents);
5357 /* Don't match against arguments after the first one we don't understand */
5358 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5359 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5365 r = sd_bus_message_skip(m, NULL);
5370 if (type == SD_BUS_TYPE_ARRAY) {
5372 r = sd_bus_message_read_strv(m, strv);
5379 r = sd_bus_message_read_basic(m, type, str);
5389 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5395 if (size < sizeof(struct bus_header))
5398 full = sizeof(struct bus_header) +
5399 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5401 return size >= full;
5404 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5410 if (h->endian == BUS_NATIVE_ENDIAN) {
5411 fs = h->fields_size;
5413 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5414 fs = bswap_32(h->fields_size);
5415 bs = bswap_32(h->body_size);
5419 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5423 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5424 assert_return(m, EINVAL);
5426 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5429 return sd_bus_error_get_errno(&m->error);
5432 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5433 struct bus_container *c;
5435 assert_return(m, NULL);
5437 c = complete ? &m->root_container : message_get_container(m);
5438 return strempty(c->signature);
5441 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5442 assert_return(m, -EINVAL);
5444 return isempty(m->root_container.signature);
5447 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5448 assert_return(m, -EINVAL);
5450 return streq(strempty(m->root_container.signature), strempty(signature));
5453 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5454 bool done_something = false;
5457 assert_return(m, -EINVAL);
5458 assert_return(source, -EINVAL);
5459 assert_return(!m->sealed, -EPERM);
5460 assert_return(source->sealed, -EPERM);
5463 const char *contents;
5478 r = sd_bus_message_peek_type(source, &type, &contents);
5484 done_something = true;
5486 if (bus_type_is_container(type) > 0) {
5488 r = sd_bus_message_enter_container(source, type, contents);
5492 r = sd_bus_message_open_container(m, type, contents);
5496 r = sd_bus_message_copy(m, source, true);
5500 r = sd_bus_message_close_container(m);
5504 r = sd_bus_message_exit_container(source);
5511 r = sd_bus_message_read_basic(source, type, &basic);
5517 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5518 type == SD_BUS_TYPE_SIGNATURE ||
5519 type == SD_BUS_TYPE_STRING)
5520 r = sd_bus_message_append_basic(m, type, basic.string);
5522 r = sd_bus_message_append_basic(m, type, &basic);
5529 return done_something;
5532 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5537 assert_return(m, -EINVAL);
5538 assert_return(m->sealed, -EPERM);
5539 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5540 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5541 assert_return(type || contents, -EINVAL);
5542 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5544 r = sd_bus_message_peek_type(m, &t, &c);
5548 if (type != 0 && type != t)
5551 if (contents && !streq_ptr(contents, c))
5557 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5558 assert_return(m, NULL);
5563 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5564 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5572 switch ((*m)->header->type) {
5574 case SD_BUS_MESSAGE_SIGNAL:
5575 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5581 case SD_BUS_MESSAGE_METHOD_CALL:
5582 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5588 case SD_BUS_MESSAGE_METHOD_RETURN:
5589 case SD_BUS_MESSAGE_METHOD_ERROR:
5591 n = message_new(bus, (*m)->header->type);
5595 n->reply_cookie = (*m)->reply_cookie;
5596 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5600 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5601 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5605 n->error._need_free = -1;
5614 if ((*m)->destination && !n->destination) {
5615 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5620 if ((*m)->sender && !n->sender) {
5621 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5626 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5628 r = sd_bus_message_copy(n, *m, true);
5632 timeout = (*m)->timeout;
5633 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5634 timeout = BUS_DEFAULT_TIMEOUT;
5636 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5640 sd_bus_message_unref(*m);
5647 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5651 assert_return(!m->sealed, -EPERM);
5652 assert_return(!m->sender, -EPERM);
5654 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5657 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5658 assert_return(m, -EINVAL);
5659 assert_return(priority, -EINVAL);
5661 *priority = m->priority;
5665 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5666 assert_return(m, -EINVAL);
5667 assert_return(!m->sealed, -EPERM);
5669 m->priority = priority;