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, part->memfd_offset);
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) {
2066 assert(c->signature);
2068 if (!BUS_MESSAGE_IS_GVARIANT(m))
2071 l = strlen(c->signature);
2073 a = message_extend_body(m, 1, 1 + l, true);
2078 memcpy(a+1, c->signature, l);
2083 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2084 size_t n_variable = 0;
2093 if (!BUS_MESSAGE_IS_GVARIANT(m))
2096 p = strempty(c->signature);
2100 r = signature_element_length(p, &n);
2109 r = bus_gvariant_is_fixed_size(t);
2114 assert(!c->need_offsets || i <= c->n_offsets);
2116 /* We need to add an offset for each item that has a
2117 * variable size and that is not the last one in the
2119 if (r == 0 && p[n] != 0)
2126 assert(!c->need_offsets || i == c->n_offsets);
2127 assert(c->need_offsets || n_variable == 0);
2129 if (n_variable <= 0) {
2130 a = message_extend_body(m, 1, 0, add_offset);
2137 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2139 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2141 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2145 p = strempty(c->signature);
2146 for (i = 0, j = 0; i < c->n_offsets; i++) {
2150 r = signature_element_length(p, &n);
2161 r = bus_gvariant_is_fixed_size(t);
2164 if (r > 0 || p[0] == 0)
2168 k = n_variable - 1 - j;
2170 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2179 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2180 struct bus_container *c;
2183 assert_return(m, -EINVAL);
2184 assert_return(!m->sealed, -EPERM);
2185 assert_return(m->n_containers > 0, -EINVAL);
2186 assert_return(!m->poisoned, -ESTALE);
2188 c = message_get_container(m);
2190 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2191 if (c->signature && c->signature[c->index] != 0)
2196 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2197 r = bus_message_close_array(m, c);
2198 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2199 r = bus_message_close_variant(m, c);
2200 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2201 r = bus_message_close_struct(m, c, true);
2203 assert_not_reached("Unknown container type");
2217 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2224 stack[*i].types = types;
2225 stack[*i].n_struct = n_struct;
2226 stack[*i].n_array = n_array;
2232 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2243 *types = stack[*i].types;
2244 *n_struct = stack[*i].n_struct;
2245 *n_array = stack[*i].n_array;
2250 int bus_message_append_ap(
2255 unsigned n_array, n_struct;
2256 TypeStack stack[BUS_CONTAINER_DEPTH];
2257 unsigned stack_ptr = 0;
2265 n_array = (unsigned) -1;
2266 n_struct = strlen(types);
2271 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2272 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2278 r = sd_bus_message_close_container(m);
2286 if (n_array != (unsigned) -1)
2295 case SD_BUS_TYPE_BYTE: {
2298 x = (uint8_t) va_arg(ap, int);
2299 r = sd_bus_message_append_basic(m, *t, &x);
2303 case SD_BUS_TYPE_BOOLEAN:
2304 case SD_BUS_TYPE_INT32:
2305 case SD_BUS_TYPE_UINT32:
2306 case SD_BUS_TYPE_UNIX_FD: {
2309 /* We assume a boolean is the same as int32_t */
2310 assert_cc(sizeof(int32_t) == sizeof(int));
2312 x = va_arg(ap, uint32_t);
2313 r = sd_bus_message_append_basic(m, *t, &x);
2317 case SD_BUS_TYPE_INT16:
2318 case SD_BUS_TYPE_UINT16: {
2321 x = (uint16_t) va_arg(ap, int);
2322 r = sd_bus_message_append_basic(m, *t, &x);
2326 case SD_BUS_TYPE_INT64:
2327 case SD_BUS_TYPE_UINT64:
2328 case SD_BUS_TYPE_DOUBLE: {
2331 x = va_arg(ap, uint64_t);
2332 r = sd_bus_message_append_basic(m, *t, &x);
2336 case SD_BUS_TYPE_STRING:
2337 case SD_BUS_TYPE_OBJECT_PATH:
2338 case SD_BUS_TYPE_SIGNATURE: {
2341 x = va_arg(ap, const char*);
2342 r = sd_bus_message_append_basic(m, *t, x);
2346 case SD_BUS_TYPE_ARRAY: {
2349 r = signature_element_length(t + 1, &k);
2355 memcpy(s, t + 1, k);
2358 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2363 if (n_array == (unsigned) -1) {
2368 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2374 n_array = va_arg(ap, unsigned);
2379 case SD_BUS_TYPE_VARIANT: {
2382 s = va_arg(ap, const char*);
2386 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2390 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2395 n_struct = strlen(s);
2396 n_array = (unsigned) -1;
2401 case SD_BUS_TYPE_STRUCT_BEGIN:
2402 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2405 r = signature_element_length(t, &k);
2412 memcpy(s, t + 1, k - 2);
2415 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2420 if (n_array == (unsigned) -1) {
2425 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2431 n_array = (unsigned) -1;
2447 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2451 assert_return(m, -EINVAL);
2452 assert_return(types, -EINVAL);
2453 assert_return(!m->sealed, -EPERM);
2454 assert_return(!m->poisoned, -ESTALE);
2456 va_start(ap, types);
2457 r = bus_message_append_ap(m, types, ap);
2463 _public_ int sd_bus_message_append_array_space(
2473 assert_return(m, -EINVAL);
2474 assert_return(!m->sealed, -EPERM);
2475 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2476 assert_return(ptr || size == 0, -EINVAL);
2477 assert_return(!m->poisoned, -ESTALE);
2479 /* alignment and size of the trivial types (except bool) is
2480 * identical for gvariant and dbus1 marshalling */
2481 align = bus_type_get_alignment(type);
2482 sz = bus_type_get_size(type);
2484 assert_se(align > 0);
2490 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2494 a = message_extend_body(m, align, size, false);
2498 r = sd_bus_message_close_container(m);
2506 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2513 assert_return(m, -EINVAL);
2514 assert_return(!m->sealed, -EPERM);
2515 assert_return(bus_type_is_trivial(type), -EINVAL);
2516 assert_return(ptr || size == 0, -EINVAL);
2517 assert_return(!m->poisoned, -ESTALE);
2519 r = sd_bus_message_append_array_space(m, type, size, &p);
2524 memcpy(p, ptr, size);
2529 _public_ int sd_bus_message_append_array_iovec(
2532 const struct iovec *iov,
2540 assert_return(m, -EINVAL);
2541 assert_return(!m->sealed, -EPERM);
2542 assert_return(bus_type_is_trivial(type), -EINVAL);
2543 assert_return(iov || n == 0, -EINVAL);
2544 assert_return(!m->poisoned, -ESTALE);
2546 size = IOVEC_TOTAL_SIZE(iov, n);
2548 r = sd_bus_message_append_array_space(m, type, size, &p);
2552 for (i = 0; i < n; i++) {
2554 if (iov[i].iov_base)
2555 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2557 memzero(p, iov[i].iov_len);
2559 p = (uint8_t*) p + iov[i].iov_len;
2565 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2568 _cleanup_close_ int copy_fd = -1;
2569 struct bus_body_part *part;
2581 if (!bus_type_is_trivial(type))
2586 r = memfd_set_sealed(memfd);
2590 copy_fd = dup(memfd);
2594 r = memfd_get_size(memfd, &size);
2598 align = bus_type_get_alignment(type);
2599 sz = bus_type_get_size(type);
2601 assert_se(align > 0);
2607 if (size > (uint64_t) (uint32_t) -1)
2610 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2614 a = message_extend_body(m, align, 0, false);
2618 part = message_append_part(m);
2622 part->memfd = copy_fd;
2623 part->memfd_offset = 0;
2624 part->sealed = true;
2628 m->header->body_size += size;
2629 message_extend_containers(m, size);
2631 return sd_bus_message_close_container(m);
2634 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) {
2635 _cleanup_close_ int copy_fd = -1;
2636 struct bus_body_part *part;
2637 struct bus_container *c;
2642 assert_return(m, -EINVAL);
2643 assert_return(memfd >= 0, -EINVAL);
2644 assert_return(!m->sealed, -EPERM);
2645 assert_return(!m->poisoned, -ESTALE);
2647 r = memfd_set_sealed(memfd);
2651 copy_fd = dup(memfd);
2655 r = memfd_get_size(memfd, &size);
2659 /* We require this to be NUL terminated */
2663 if (size > (uint64_t) (uint32_t) -1)
2666 c = message_get_container(m);
2667 if (c->signature && c->signature[c->index]) {
2668 /* Container signature is already set */
2670 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2675 /* Maybe we can append to the signature? But only if this is the top-level container*/
2676 if (c->enclosing != 0)
2679 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2686 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2687 a = message_extend_body(m, 4, 4, false);
2691 *(uint32_t*) a = size - 1;
2694 part = message_append_part(m);
2698 part->memfd = copy_fd;
2699 part->memfd_offset = 0;
2700 part->sealed = true;
2704 m->header->body_size += size;
2705 message_extend_containers(m, size);
2707 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2708 r = message_add_offset(m, m->header->body_size);
2715 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2721 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2725 assert_return(m, -EINVAL);
2726 assert_return(!m->sealed, -EPERM);
2727 assert_return(!m->poisoned, -ESTALE);
2729 r = sd_bus_message_open_container(m, 'a', "s");
2733 STRV_FOREACH(i, l) {
2734 r = sd_bus_message_append_basic(m, 's', *i);
2739 return sd_bus_message_close_container(m);
2742 static int bus_message_close_header(sd_bus_message *m) {
2748 if (!BUS_MESSAGE_IS_GVARIANT(m))
2751 if (m->n_header_offsets < 1)
2754 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2756 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2758 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2762 for (i = 0; i < m->n_header_offsets; i++)
2763 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2768 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2769 struct bus_body_part *part;
2779 if (m->n_containers > 0)
2785 /* In vtables the return signature of method calls is listed,
2786 * let's check if they match if this is a response */
2787 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2788 m->enforced_reply_signature &&
2789 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2792 /* If gvariant marshalling is used we need to close the body structure */
2793 r = bus_message_close_struct(m, &m->root_container, false);
2797 /* If there's a non-trivial signature set, then add it in here */
2798 if (!isempty(m->root_container.signature)) {
2799 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2805 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2810 r = bus_message_close_header(m);
2814 m->header->serial = (uint32_t) cookie;
2815 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2817 /* Add padding at the end of the fields part, since we know
2818 * the body needs to start at an 8 byte alignment. We made
2819 * sure we allocated enough space for this, so all we need to
2820 * do here is to zero it out. */
2821 l = BUS_MESSAGE_FIELDS_SIZE(m);
2824 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, a);
2826 /* If this is something we can send as memfd, then let's seal
2827 the memfd now. Note that we can send memfds as payload only
2828 for directed messages, and not for broadcasts. */
2829 if (m->destination && m->bus->use_memfd) {
2830 MESSAGE_FOREACH_PART(part, i, m)
2831 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2834 /* Try to seal it if that makes
2835 * sense. First, unmap our own map to
2836 * make sure we don't keep it busy. */
2837 bus_body_part_unmap(part);
2839 /* Then, sync up real memfd size */
2841 r = memfd_set_size(part->memfd, sz);
2845 /* Finally, try to seal */
2846 if (memfd_set_sealed(part->memfd) >= 0)
2847 part->sealed = true;
2851 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2852 m->root_container.index = 0;
2853 m->root_container.offset_index = 0;
2854 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2861 int bus_body_part_map(struct bus_body_part *part) {
2870 if (part->size <= 0)
2873 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2874 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2875 static const uint8_t zeroes[7] = { };
2876 part->data = (void*) zeroes;
2880 psz = PAGE_ALIGN(part->size);
2882 if (part->memfd >= 0)
2883 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset);
2884 else if (part->is_zero)
2885 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2889 if (p == MAP_FAILED)
2894 part->munmap_this = true;
2899 void bus_body_part_unmap(struct bus_body_part *part) {
2903 if (part->memfd < 0)
2909 if (!part->munmap_this)
2912 assert_se(munmap(part->data, part->mapped) == 0);
2916 part->munmap_this = false;
2921 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2922 size_t k, start, end;
2927 start = ALIGN_TO((size_t) *rindex, align);
2928 end = start + nbytes;
2933 /* Verify that padding is 0 */
2934 for (k = *rindex; k < start; k++)
2935 if (((const uint8_t*) p)[k] != 0)
2939 *r = (uint8_t*) p + start;
2946 static bool message_end_of_signature(sd_bus_message *m) {
2947 struct bus_container *c;
2951 c = message_get_container(m);
2952 return !c->signature || c->signature[c->index] == 0;
2955 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2956 struct bus_container *c;
2960 c = message_get_container(m);
2961 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2964 if (BUS_MESSAGE_IS_GVARIANT(m))
2965 return index >= c->end;
2967 assert(c->array_size);
2968 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2972 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2973 assert_return(m, -EINVAL);
2974 assert_return(m->sealed, -EPERM);
2976 if (complete && m->n_containers > 0)
2979 if (message_end_of_signature(m))
2982 if (message_end_of_array(m, m->rindex))
2988 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2989 struct bus_body_part *part;
2995 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2996 part = m->cached_rindex_part;
2997 begin = m->cached_rindex_part_begin;
3007 if (index + sz <= begin + part->size) {
3009 r = bus_body_part_map(part);
3014 *p = (uint8_t*) part->data + index - begin;
3016 m->cached_rindex_part = part;
3017 m->cached_rindex_part_begin = begin;
3022 begin += part->size;
3029 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3036 if (!BUS_MESSAGE_IS_GVARIANT(m))
3039 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3042 sz = bus_gvariant_get_size(c->signature);
3046 if (c->offset_index+1 >= c->n_offsets)
3049 /* Variable-size array */
3051 alignment = bus_gvariant_get_alignment(c->signature);
3052 assert(alignment > 0);
3054 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3055 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3058 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3061 /* Fixed-size array */
3062 *rindex = c->begin + (c->offset_index+1) * sz;
3068 } else if (c->enclosing == 0 ||
3069 c->enclosing == SD_BUS_TYPE_STRUCT ||
3070 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3075 if (c->offset_index+1 >= c->n_offsets)
3078 r = signature_element_length(c->signature + c->index, &n);
3082 r = signature_element_length(c->signature + c->index + n, &j);
3087 memcpy(t, c->signature + c->index + n, j);
3090 alignment = bus_gvariant_get_alignment(t);
3093 assert(alignment > 0);
3095 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3096 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3100 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3103 assert_not_reached("Unknown container type");
3108 /* Reached the end */
3115 static int message_peek_body(
3122 size_t k, start, end, padding;
3123 struct bus_body_part *part;
3130 start = ALIGN_TO((size_t) *rindex, align);
3131 padding = start - *rindex;
3132 end = start + nbytes;
3134 if (end > BUS_MESSAGE_BODY_SIZE(m))
3137 part = find_part(m, *rindex, padding, (void**) &q);
3142 /* Verify padding */
3143 for (k = 0; k < padding; k++)
3148 part = find_part(m, start, nbytes, (void**) &q);
3149 if (!part || (nbytes > 0 && !q))
3160 static bool validate_nul(const char *s, size_t l) {
3162 /* Check for NUL chars in the string */
3163 if (memchr(s, 0, l))
3166 /* Check for NUL termination */
3173 static bool validate_string(const char *s, size_t l) {
3175 if (!validate_nul(s, l))
3178 /* Check if valid UTF8 */
3179 if (!utf8_is_valid(s))
3185 static bool validate_signature(const char *s, size_t l) {
3187 if (!validate_nul(s, l))
3190 /* Check if valid signature */
3191 if (!signature_is_valid(s, true))
3197 static bool validate_object_path(const char *s, size_t l) {
3199 if (!validate_nul(s, l))
3202 if (!object_path_is_valid(s))
3208 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3209 struct bus_container *c;
3214 assert_return(m, -EINVAL);
3215 assert_return(m->sealed, -EPERM);
3216 assert_return(bus_type_is_basic(type), -EINVAL);
3218 if (message_end_of_signature(m))
3221 if (message_end_of_array(m, m->rindex))
3224 c = message_get_container(m);
3225 if (c->signature[c->index] != type)
3230 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3232 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3235 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3239 if (type == SD_BUS_TYPE_STRING)
3240 ok = validate_string(q, c->item_size-1);
3241 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3242 ok = validate_object_path(q, c->item_size-1);
3244 ok = validate_signature(q, c->item_size-1);
3250 *(const char**) p = q;
3254 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3256 if ((size_t) sz != c->item_size)
3259 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3262 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3268 case SD_BUS_TYPE_BYTE:
3270 *(uint8_t*) p = *(uint8_t*) q;
3273 case SD_BUS_TYPE_BOOLEAN:
3275 *(int*) p = !!*(uint8_t*) q;
3278 case SD_BUS_TYPE_INT16:
3279 case SD_BUS_TYPE_UINT16:
3281 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3284 case SD_BUS_TYPE_INT32:
3285 case SD_BUS_TYPE_UINT32:
3287 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3290 case SD_BUS_TYPE_INT64:
3291 case SD_BUS_TYPE_UINT64:
3292 case SD_BUS_TYPE_DOUBLE:
3294 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3297 case SD_BUS_TYPE_UNIX_FD: {
3300 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3305 *(int*) p = m->fds[j];
3311 assert_not_reached("unexpected type");
3315 r = container_next_item(m, c, &rindex);
3322 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3326 r = message_peek_body(m, &rindex, 4, 4, &q);
3330 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3331 r = message_peek_body(m, &rindex, 1, l+1, &q);
3335 if (type == SD_BUS_TYPE_OBJECT_PATH)
3336 ok = validate_object_path(q, l);
3338 ok = validate_string(q, l);
3343 *(const char**) p = q;
3345 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3348 r = message_peek_body(m, &rindex, 1, 1, &q);
3353 r = message_peek_body(m, &rindex, 1, l+1, &q);
3357 if (!validate_signature(q, l))
3361 *(const char**) p = q;
3366 align = bus_type_get_alignment(type);
3369 sz = bus_type_get_size(type);
3372 r = message_peek_body(m, &rindex, align, sz, &q);
3378 case SD_BUS_TYPE_BYTE:
3380 *(uint8_t*) p = *(uint8_t*) q;
3383 case SD_BUS_TYPE_BOOLEAN:
3385 *(int*) p = !!*(uint32_t*) q;
3388 case SD_BUS_TYPE_INT16:
3389 case SD_BUS_TYPE_UINT16:
3391 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3394 case SD_BUS_TYPE_INT32:
3395 case SD_BUS_TYPE_UINT32:
3397 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3400 case SD_BUS_TYPE_INT64:
3401 case SD_BUS_TYPE_UINT64:
3402 case SD_BUS_TYPE_DOUBLE:
3404 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3407 case SD_BUS_TYPE_UNIX_FD: {
3410 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3415 *(int*) p = m->fds[j];
3420 assert_not_reached("Unknown basic type...");
3427 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3433 static int bus_message_enter_array(
3435 struct bus_container *c,
3436 const char *contents,
3437 uint32_t **array_size,
3440 size_t *n_offsets) {
3454 if (!signature_is_single(contents, true))
3457 if (!c->signature || c->signature[c->index] == 0)
3460 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3463 if (!startswith(c->signature + c->index + 1, contents))
3468 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3471 r = message_peek_body(m, &rindex, 4, 4, &q);
3475 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3478 alignment = bus_type_get_alignment(contents[0]);
3482 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3486 *array_size = (uint32_t*) q;
3488 } else if (c->item_size <= 0) {
3490 /* gvariant: empty array */
3495 } else if (bus_gvariant_is_fixed_size(contents)) {
3497 /* gvariant: fixed length array */
3498 *item_size = bus_gvariant_get_size(contents);
3503 size_t where, p = 0, framing, sz;
3506 /* gvariant: variable length array */
3507 sz = determine_word_size(c->item_size, 0);
3509 where = rindex + c->item_size - sz;
3510 r = message_peek_body(m, &where, 1, sz, &q);
3514 framing = read_word_le(q, sz);
3515 if (framing > c->item_size - sz)
3517 if ((c->item_size - framing) % sz != 0)
3520 *n_offsets = (c->item_size - framing) / sz;
3522 where = rindex + framing;
3523 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3527 *offsets = new(size_t, *n_offsets);
3531 for (i = 0; i < *n_offsets; i++) {
3534 x = read_word_le((uint8_t*) q + i * sz, sz);
3535 if (x > c->item_size - sz)
3540 (*offsets)[i] = rindex + x;
3544 *item_size = (*offsets)[0] - rindex;
3549 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3550 c->index += 1 + strlen(contents);
3555 static int bus_message_enter_variant(
3557 struct bus_container *c,
3558 const char *contents,
3559 size_t *item_size) {
3571 if (!signature_is_single(contents, false))
3574 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3577 if (!c->signature || c->signature[c->index] == 0)
3580 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3585 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3588 k = strlen(contents);
3589 if (1+k > c->item_size)
3592 where = rindex + c->item_size - (1+k);
3593 r = message_peek_body(m, &where, 1, 1+k, &q);
3597 if (*(char*) q != 0)
3600 if (memcmp((uint8_t*) q+1, contents, k))
3603 *item_size = c->item_size - (1+k);
3606 r = message_peek_body(m, &rindex, 1, 1, &q);
3611 r = message_peek_body(m, &rindex, 1, l+1, &q);
3615 if (!validate_signature(q, l))
3618 if (!streq(q, contents))
3624 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3630 static int build_struct_offsets(
3632 const char *signature,
3636 size_t *n_offsets) {
3638 unsigned n_variable = 0, n_total = 0, v;
3639 size_t previous = 0, where;
3650 if (isempty(signature)) {
3657 sz = determine_word_size(size, 0);
3661 /* First, loop over signature and count variable elements and
3662 * elements in general. We use this to know how large the
3663 * offset array is at the end of the structure. Note that
3664 * GVariant only stores offsets for all variable size elements
3665 * that are not the last item. */
3671 r = signature_element_length(p, &n);
3680 r = bus_gvariant_is_fixed_size(t);
3685 if (r == 0 && p[n] != 0) /* except the last item */
3692 if (size < n_variable * sz)
3695 where = m->rindex + size - (n_variable * sz);
3696 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3702 *offsets = new(size_t, n_total);
3708 /* Second, loop again and build an offset table */
3714 r = signature_element_length(p, &n);
3723 k = bus_gvariant_get_size(t);
3731 x = read_word_le((uint8_t*) q + v*sz, sz);
3734 if (m->rindex + x < previous)
3737 /* The last item's end
3738 * is determined from
3741 x = size - (n_variable * sz);
3743 offset = m->rindex + x;
3749 align = bus_gvariant_get_alignment(t);
3752 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3756 previous = (*offsets)[(*n_offsets)++] = offset;
3761 assert(*n_offsets == n_total);
3763 *item_size = (*offsets)[0] - m->rindex;
3767 static int enter_struct_or_dict_entry(
3769 struct bus_container *c,
3770 const char *contents,
3773 size_t *n_offsets) {
3784 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3787 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3791 } else if (c->item_size <= 0) {
3793 /* gvariant empty struct */
3798 /* gvariant with contents */
3799 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3804 static int bus_message_enter_struct(
3806 struct bus_container *c,
3807 const char *contents,
3810 size_t *n_offsets) {
3822 if (!signature_is_valid(contents, false))
3825 if (!c->signature || c->signature[c->index] == 0)
3828 l = strlen(contents);
3830 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3831 !startswith(c->signature + c->index + 1, contents) ||
3832 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3835 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3839 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3840 c->index += 1 + l + 1;
3845 static int bus_message_enter_dict_entry(
3847 struct bus_container *c,
3848 const char *contents,
3851 size_t *n_offsets) {
3860 if (!signature_is_pair(contents))
3863 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3866 if (!c->signature || c->signature[c->index] == 0)
3869 l = strlen(contents);
3871 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3872 !startswith(c->signature + c->index + 1, contents) ||
3873 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3876 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3880 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3881 c->index += 1 + l + 1;
3886 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3888 const char *contents) {
3889 struct bus_container *c, *w;
3890 uint32_t *array_size = NULL;
3893 size_t *offsets = NULL;
3894 size_t n_offsets = 0, item_size = 0;
3897 assert_return(m, -EINVAL);
3898 assert_return(m->sealed, -EPERM);
3899 assert_return(type != 0 || !contents, -EINVAL);
3901 if (type == 0 || !contents) {
3905 /* Allow entering into anonymous containers */
3906 r = sd_bus_message_peek_type(m, &tt, &cc);
3910 if (type != 0 && type != tt)
3913 if (contents && !streq(contents, cc))
3921 * We enforce a global limit on container depth, that is much
3922 * higher than the 32 structs and 32 arrays the specification
3923 * mandates. This is simpler to implement for us, and we need
3924 * this only to ensure our container array doesn't grow
3925 * without bounds. We are happy to return any data from a
3926 * message as long as the data itself is valid, even if the
3927 * overall message might be not.
3929 * Note that the message signature is validated when
3930 * parsing the headers, and that validation does check the
3933 * Note that the specification defines no limits on the depth
3934 * of stacked variants, but we do.
3936 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3939 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3942 if (message_end_of_signature(m))
3945 if (message_end_of_array(m, m->rindex))
3948 c = message_get_container(m);
3950 signature = strdup(contents);
3954 c->saved_index = c->index;
3957 if (type == SD_BUS_TYPE_ARRAY)
3958 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3959 else if (type == SD_BUS_TYPE_VARIANT)
3960 r = bus_message_enter_variant(m, c, contents, &item_size);
3961 else if (type == SD_BUS_TYPE_STRUCT)
3962 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3963 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3964 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3974 /* OK, let's fill it in */
3975 w = m->containers + m->n_containers++;
3976 w->enclosing = type;
3977 w->signature = signature;
3978 w->peeked_signature = NULL;
3982 w->begin = m->rindex;
3983 w->end = m->rindex + c->item_size;
3985 w->array_size = array_size;
3986 w->item_size = item_size;
3987 w->offsets = offsets;
3988 w->n_offsets = n_offsets;
3989 w->offset_index = 0;
3994 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3995 struct bus_container *c;
3999 assert_return(m, -EINVAL);
4000 assert_return(m->sealed, -EPERM);
4001 assert_return(m->n_containers > 0, -ENXIO);
4003 c = message_get_container(m);
4005 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4006 if (c->signature && c->signature[c->index] != 0)
4010 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4011 if (m->rindex < c->end)
4014 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4017 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4018 if (c->begin + l != m->rindex)
4023 free(c->peeked_signature);
4027 c = message_get_container(m);
4030 c->index = c->saved_index;
4031 r = container_next_item(m, c, &m->rindex);
4039 static void message_quit_container(sd_bus_message *m) {
4040 struct bus_container *c;
4044 assert(m->n_containers > 0);
4046 c = message_get_container(m);
4049 assert(m->rindex >= c->before);
4050 m->rindex = c->before;
4052 /* Free container */
4057 /* Correct index of new top-level container */
4058 c = message_get_container(m);
4059 c->index = c->saved_index;
4062 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4063 struct bus_container *c;
4066 assert_return(m, -EINVAL);
4067 assert_return(m->sealed, -EPERM);
4069 if (message_end_of_signature(m))
4072 if (message_end_of_array(m, m->rindex))
4075 c = message_get_container(m);
4077 if (bus_type_is_basic(c->signature[c->index])) {
4081 *type = c->signature[c->index];
4085 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4091 r = signature_element_length(c->signature+c->index+1, &l);
4097 sig = strndup(c->signature + c->index + 1, l);
4101 free(c->peeked_signature);
4102 *contents = c->peeked_signature = sig;
4106 *type = SD_BUS_TYPE_ARRAY;
4111 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4112 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4118 r = signature_element_length(c->signature+c->index, &l);
4123 sig = strndup(c->signature + c->index + 1, l - 2);
4127 free(c->peeked_signature);
4128 *contents = c->peeked_signature = sig;
4132 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4137 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4141 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4144 if (c->item_size < 2)
4147 /* Look for the NUL delimiter that
4148 separates the payload from the
4149 signature. Since the body might be
4150 in a different part that then the
4151 signature we map byte by byte. */
4153 for (k = 2; k <= c->item_size; k++) {
4156 where = m->rindex + c->item_size - k;
4157 r = message_peek_body(m, &where, 1, k, &q);
4161 if (*(char*) q == 0)
4165 if (k > c->item_size)
4168 free(c->peeked_signature);
4169 c->peeked_signature = strndup((char*) q + 1, k - 1);
4170 if (!c->peeked_signature)
4173 if (!signature_is_valid(c->peeked_signature, true))
4176 *contents = c->peeked_signature;
4181 r = message_peek_body(m, &rindex, 1, 1, &q);
4186 r = message_peek_body(m, &rindex, 1, l+1, &q);
4190 if (!validate_signature(q, l))
4198 *type = SD_BUS_TYPE_VARIANT;
4213 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4214 struct bus_container *c;
4216 assert_return(m, -EINVAL);
4217 assert_return(m->sealed, -EPERM);
4220 message_reset_containers(m);
4223 c = message_get_container(m);
4225 c = message_get_container(m);
4227 c->offset_index = 0;
4229 m->rindex = c->begin;
4232 c->offset_index = 0;
4233 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4235 return !isempty(c->signature);
4238 static int message_read_ap(
4243 unsigned n_array, n_struct;
4244 TypeStack stack[BUS_CONTAINER_DEPTH];
4245 unsigned stack_ptr = 0;
4246 unsigned n_loop = 0;
4254 /* Ideally, we'd just call ourselves recursively on every
4255 * complex type. However, the state of a va_list that is
4256 * passed to a function is undefined after that function
4257 * returns. This means we need to docode the va_list linearly
4258 * in a single stackframe. We hence implement our own
4259 * home-grown stack in an array. */
4261 n_array = (unsigned) -1; /* length of current array entries */
4262 n_struct = strlen(types); /* length of current struct contents signature */
4269 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4270 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4276 r = sd_bus_message_exit_container(m);
4284 if (n_array != (unsigned) -1)
4293 case SD_BUS_TYPE_BYTE:
4294 case SD_BUS_TYPE_BOOLEAN:
4295 case SD_BUS_TYPE_INT16:
4296 case SD_BUS_TYPE_UINT16:
4297 case SD_BUS_TYPE_INT32:
4298 case SD_BUS_TYPE_UINT32:
4299 case SD_BUS_TYPE_INT64:
4300 case SD_BUS_TYPE_UINT64:
4301 case SD_BUS_TYPE_DOUBLE:
4302 case SD_BUS_TYPE_STRING:
4303 case SD_BUS_TYPE_OBJECT_PATH:
4304 case SD_BUS_TYPE_SIGNATURE:
4305 case SD_BUS_TYPE_UNIX_FD: {
4308 p = va_arg(ap, void*);
4309 r = sd_bus_message_read_basic(m, *t, p);
4322 case SD_BUS_TYPE_ARRAY: {
4325 r = signature_element_length(t + 1, &k);
4331 memcpy(s, t + 1, k);
4334 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4345 if (n_array == (unsigned) -1) {
4350 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4356 n_array = va_arg(ap, unsigned);
4361 case SD_BUS_TYPE_VARIANT: {
4364 s = va_arg(ap, const char *);
4368 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4378 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4383 n_struct = strlen(s);
4384 n_array = (unsigned) -1;
4389 case SD_BUS_TYPE_STRUCT_BEGIN:
4390 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4393 r = signature_element_length(t, &k);
4399 memcpy(s, t + 1, k - 2);
4402 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4412 if (n_array == (unsigned) -1) {
4417 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4423 n_array = (unsigned) -1;
4436 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4440 assert_return(m, -EINVAL);
4441 assert_return(m->sealed, -EPERM);
4442 assert_return(types, -EINVAL);
4444 va_start(ap, types);
4445 r = message_read_ap(m, types, ap);
4451 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4454 assert_return(m, -EINVAL);
4455 assert_return(m->sealed, -EPERM);
4457 /* If types is NULL, read exactly one element */
4459 struct bus_container *c;
4462 if (message_end_of_signature(m))
4465 if (message_end_of_array(m, m->rindex))
4468 c = message_get_container(m);
4470 r = signature_element_length(c->signature + c->index, &l);
4474 types = strndupa(c->signature + c->index, l);
4479 case 0: /* Nothing to drop */
4482 case SD_BUS_TYPE_BYTE:
4483 case SD_BUS_TYPE_BOOLEAN:
4484 case SD_BUS_TYPE_INT16:
4485 case SD_BUS_TYPE_UINT16:
4486 case SD_BUS_TYPE_INT32:
4487 case SD_BUS_TYPE_UINT32:
4488 case SD_BUS_TYPE_INT64:
4489 case SD_BUS_TYPE_UINT64:
4490 case SD_BUS_TYPE_DOUBLE:
4491 case SD_BUS_TYPE_STRING:
4492 case SD_BUS_TYPE_OBJECT_PATH:
4493 case SD_BUS_TYPE_SIGNATURE:
4494 case SD_BUS_TYPE_UNIX_FD:
4496 r = sd_bus_message_read_basic(m, *types, NULL);
4500 r = sd_bus_message_skip(m, types + 1);
4506 case SD_BUS_TYPE_ARRAY: {
4509 r = signature_element_length(types + 1, &k);
4515 memcpy(s, types+1, k);
4518 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4523 r = sd_bus_message_skip(m, s);
4530 r = sd_bus_message_exit_container(m);
4535 r = sd_bus_message_skip(m, types + 1 + k);
4542 case SD_BUS_TYPE_VARIANT: {
4543 const char *contents;
4546 r = sd_bus_message_peek_type(m, &x, &contents);
4550 if (x != SD_BUS_TYPE_VARIANT)
4553 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4557 r = sd_bus_message_skip(m, contents);
4562 r = sd_bus_message_exit_container(m);
4566 r = sd_bus_message_skip(m, types + 1);
4573 case SD_BUS_TYPE_STRUCT_BEGIN:
4574 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4577 r = signature_element_length(types, &k);
4583 memcpy(s, types+1, k-2);
4586 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4590 r = sd_bus_message_skip(m, s);
4595 r = sd_bus_message_exit_container(m);
4600 r = sd_bus_message_skip(m, types + k);
4612 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4616 struct bus_container *c;
4622 assert_return(m, -EINVAL);
4623 assert_return(m->sealed, -EPERM);
4624 assert_return(bus_type_is_trivial(type), -EINVAL);
4625 assert_return(ptr, -EINVAL);
4626 assert_return(size, -EINVAL);
4627 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4629 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4633 c = message_get_container(m);
4635 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4636 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4640 sz = c->end - c->begin;
4642 align = bus_type_get_alignment(type);
4646 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4650 /* Zero length array, let's return some aligned
4651 * pointer that is not NULL */
4652 p = (uint8_t*) NULL + align;
4654 r = message_peek_body(m, &m->rindex, align, sz, &p);
4659 r = sd_bus_message_exit_container(m);
4663 *ptr = (const void*) p;
4669 message_quit_container(m);
4673 static int message_peek_fields(
4684 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4687 static int message_peek_field_uint32(
4699 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4702 /* identical for gvariant and dbus1 */
4704 r = message_peek_fields(m, ri, 4, 4, &q);
4709 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4714 static int message_peek_field_string(
4716 bool (*validate)(const char *p),
4728 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4733 r = message_peek_fields(m, ri, 1, item_size, &q);
4739 r = message_peek_field_uint32(m, ri, 4, &l);
4743 r = message_peek_fields(m, ri, 1, l+1, &q);
4749 if (!validate_nul(q, l))
4755 if (!validate_string(q, l))
4765 static int message_peek_field_signature(
4778 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4783 r = message_peek_fields(m, ri, 1, item_size, &q);
4789 r = message_peek_fields(m, ri, 1, 1, &q);
4794 r = message_peek_fields(m, ri, 1, l+1, &q);
4799 if (!validate_signature(q, l))
4808 static int message_skip_fields(
4811 uint32_t array_size,
4812 const char **signature) {
4814 size_t original_index;
4820 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4822 original_index = *ri;
4828 if (array_size != (uint32_t) -1 &&
4829 array_size <= *ri - original_index)
4836 if (t == SD_BUS_TYPE_STRING) {
4838 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4844 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4846 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4852 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4854 r = message_peek_field_signature(m, ri, 0, NULL);
4860 } else if (bus_type_is_basic(t)) {
4863 align = bus_type_get_alignment(t);
4864 k = bus_type_get_size(t);
4865 assert(align > 0 && k > 0);
4867 r = message_peek_fields(m, ri, align, k, NULL);
4873 } else if (t == SD_BUS_TYPE_ARRAY) {
4875 r = signature_element_length(*signature+1, &l);
4885 strncpy(sig, *signature + 1, l-1);
4888 alignment = bus_type_get_alignment(sig[0]);
4892 r = message_peek_field_uint32(m, ri, 0, &nas);
4895 if (nas > BUS_ARRAY_MAX_SIZE)
4898 r = message_peek_fields(m, ri, alignment, 0, NULL);
4902 r = message_skip_fields(m, ri, nas, (const char**) &s);
4907 (*signature) += 1 + l;
4909 } else if (t == SD_BUS_TYPE_VARIANT) {
4912 r = message_peek_field_signature(m, ri, 0, &s);
4916 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4922 } else if (t == SD_BUS_TYPE_STRUCT ||
4923 t == SD_BUS_TYPE_DICT_ENTRY) {
4925 r = signature_element_length(*signature, &l);
4932 strncpy(sig, *signature + 1, l-1);
4935 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4946 int bus_message_parse_fields(sd_bus_message *m) {
4949 uint32_t unix_fds = 0;
4950 bool unix_fds_set = false;
4951 void *offsets = NULL;
4952 unsigned n_offsets = 0;
4958 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4961 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4965 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4966 r = message_peek_fields(m, &ri, 1, sz, &q);
4970 framing = read_word_le(q, sz);
4971 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4973 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4977 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4981 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4986 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4987 _cleanup_free_ char *sig = NULL;
4988 const char *signature;
4990 size_t item_size = (size_t) -1;
4992 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4999 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5002 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
5006 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5011 end = read_word_le((uint8_t*) offsets + i*sz, sz);
5016 where = ri = ALIGN_TO(ri, 8);
5017 item_size = end - ri;
5018 r = message_peek_fields(m, &where, 1, item_size, &q);
5022 b = memrchr(q, 0, item_size);
5026 sig = strndup(b+1, item_size - (b+1-(char*) q));
5031 item_size = b - (char*) q;
5033 r = message_peek_field_signature(m, &ri, 0, &signature);
5039 case _BUS_MESSAGE_HEADER_INVALID:
5042 case BUS_MESSAGE_HEADER_PATH:
5047 if (!streq(signature, "o"))
5050 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5053 case BUS_MESSAGE_HEADER_INTERFACE:
5058 if (!streq(signature, "s"))
5061 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5064 case BUS_MESSAGE_HEADER_MEMBER:
5069 if (!streq(signature, "s"))
5072 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5075 case BUS_MESSAGE_HEADER_ERROR_NAME:
5080 if (!streq(signature, "s"))
5083 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5085 m->error._need_free = -1;
5089 case BUS_MESSAGE_HEADER_DESTINATION:
5094 if (!streq(signature, "s"))
5097 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5100 case BUS_MESSAGE_HEADER_SENDER:
5105 if (!streq(signature, "s"))
5108 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5110 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5111 m->creds.unique_name = (char*) m->sender;
5112 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5118 case BUS_MESSAGE_HEADER_SIGNATURE: {
5122 if (m->root_container.signature)
5125 if (!streq(signature, "g"))
5128 r = message_peek_field_signature(m, &ri, item_size, &s);
5136 free(m->root_container.signature);
5137 m->root_container.signature = c;
5141 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5144 if (m->reply_cookie != 0)
5147 if (!streq(signature, "u"))
5150 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5154 m->reply_cookie = serial;
5156 if (m->reply_cookie == 0)
5162 case BUS_MESSAGE_HEADER_UNIX_FDS:
5166 if (!streq(signature, "u"))
5169 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5173 unix_fds_set = true;
5177 if (!BUS_MESSAGE_IS_GVARIANT(m))
5178 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5187 if (m->n_fds != unix_fds)
5190 switch (m->header->type) {
5192 case SD_BUS_MESSAGE_SIGNAL:
5193 if (!m->path || !m->interface || !m->member)
5196 if (m->reply_cookie != 0)
5201 case SD_BUS_MESSAGE_METHOD_CALL:
5203 if (!m->path || !m->member)
5206 if (m->reply_cookie != 0)
5211 case SD_BUS_MESSAGE_METHOD_RETURN:
5213 if (m->reply_cookie == 0)
5217 case SD_BUS_MESSAGE_METHOD_ERROR:
5219 if (m->reply_cookie == 0 || !m->error.name)
5224 /* Refuse non-local messages that claim they are local */
5225 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5227 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5229 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5232 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5234 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5235 r = build_struct_offsets(
5237 m->root_container.signature,
5238 BUS_MESSAGE_BODY_SIZE(m),
5239 &m->root_container.item_size,
5240 &m->root_container.offsets,
5241 &m->root_container.n_offsets);
5246 /* Try to read the error message, but if we can't it's a non-issue */
5247 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5248 sd_bus_message_read(m, "s", &m->error.message);
5253 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5254 assert_return(m, -EINVAL);
5255 assert_return(destination, -EINVAL);
5256 assert_return(!m->sealed, -EPERM);
5257 assert_return(!m->destination, -EEXIST);
5259 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5262 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5266 struct bus_body_part *part;
5272 total = BUS_MESSAGE_SIZE(m);
5278 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5279 MESSAGE_FOREACH_PART(part, i, m)
5280 e = mempcpy(e, part->data, part->size);
5282 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5290 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5296 r = sd_bus_message_enter_container(m, 'a', "s");
5303 r = sd_bus_message_read_basic(m, 's', &s);
5309 r = strv_extend(l, s);
5314 r = sd_bus_message_exit_container(m);
5321 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5325 assert_return(m, -EINVAL);
5326 assert_return(m->sealed, -EPERM);
5327 assert_return(l, -EINVAL);
5329 r = bus_message_read_strv_extend(m, &strv);
5339 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5340 const char *contents;
5349 r = sd_bus_message_rewind(m, true);
5354 r = sd_bus_message_peek_type(m, &type, &contents);
5360 /* Don't match against arguments after the first one we don't understand */
5361 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5362 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5368 r = sd_bus_message_skip(m, NULL);
5373 if (type == SD_BUS_TYPE_ARRAY) {
5375 r = sd_bus_message_read_strv(m, strv);
5382 r = sd_bus_message_read_basic(m, type, str);
5392 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5398 if (size < sizeof(struct bus_header))
5401 full = sizeof(struct bus_header) +
5402 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5404 return size >= full;
5407 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5413 if (h->endian == BUS_NATIVE_ENDIAN) {
5414 fs = h->fields_size;
5416 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5417 fs = bswap_32(h->fields_size);
5418 bs = bswap_32(h->body_size);
5422 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5426 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5427 assert_return(m, EINVAL);
5429 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5432 return sd_bus_error_get_errno(&m->error);
5435 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5436 struct bus_container *c;
5438 assert_return(m, NULL);
5440 c = complete ? &m->root_container : message_get_container(m);
5441 return strempty(c->signature);
5444 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5445 assert_return(m, -EINVAL);
5447 return isempty(m->root_container.signature);
5450 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5451 assert_return(m, -EINVAL);
5453 return streq(strempty(m->root_container.signature), strempty(signature));
5456 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5457 bool done_something = false;
5460 assert_return(m, -EINVAL);
5461 assert_return(source, -EINVAL);
5462 assert_return(!m->sealed, -EPERM);
5463 assert_return(source->sealed, -EPERM);
5466 const char *contents;
5481 r = sd_bus_message_peek_type(source, &type, &contents);
5487 done_something = true;
5489 if (bus_type_is_container(type) > 0) {
5491 r = sd_bus_message_enter_container(source, type, contents);
5495 r = sd_bus_message_open_container(m, type, contents);
5499 r = sd_bus_message_copy(m, source, true);
5503 r = sd_bus_message_close_container(m);
5507 r = sd_bus_message_exit_container(source);
5514 r = sd_bus_message_read_basic(source, type, &basic);
5520 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5521 type == SD_BUS_TYPE_SIGNATURE ||
5522 type == SD_BUS_TYPE_STRING)
5523 r = sd_bus_message_append_basic(m, type, basic.string);
5525 r = sd_bus_message_append_basic(m, type, &basic);
5532 return done_something;
5535 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5540 assert_return(m, -EINVAL);
5541 assert_return(m->sealed, -EPERM);
5542 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5543 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5544 assert_return(type || contents, -EINVAL);
5545 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5547 r = sd_bus_message_peek_type(m, &t, &c);
5551 if (type != 0 && type != t)
5554 if (contents && !streq_ptr(contents, c))
5560 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5561 assert_return(m, NULL);
5566 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5567 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5575 switch ((*m)->header->type) {
5577 case SD_BUS_MESSAGE_SIGNAL:
5578 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5584 case SD_BUS_MESSAGE_METHOD_CALL:
5585 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5591 case SD_BUS_MESSAGE_METHOD_RETURN:
5592 case SD_BUS_MESSAGE_METHOD_ERROR:
5594 n = message_new(bus, (*m)->header->type);
5598 n->reply_cookie = (*m)->reply_cookie;
5599 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5603 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5604 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5608 n->error._need_free = -1;
5617 if ((*m)->destination && !n->destination) {
5618 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5623 if ((*m)->sender && !n->sender) {
5624 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5629 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5631 r = sd_bus_message_copy(n, *m, true);
5635 timeout = (*m)->timeout;
5636 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5637 timeout = BUS_DEFAULT_TIMEOUT;
5639 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5643 sd_bus_message_unref(*m);
5650 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5654 assert_return(!m->sealed, -EPERM);
5655 assert_return(!m->sender, -EPERM);
5657 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5660 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5661 assert_return(m, -EINVAL);
5662 assert_return(priority, -EINVAL);
5664 *priority = m->priority;
5668 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5669 assert_return(m, -EINVAL);
5670 assert_return(!m->sealed, -EPERM);
5672 m->priority = priority;