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"
33 #include "bus-message.h"
34 #include "bus-internal.h"
36 #include "bus-signature.h"
37 #include "bus-gvariant.h"
40 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
42 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
47 if (old_base == new_base)
50 if ((uint8_t*) p < (uint8_t*) old_base)
53 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
56 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
59 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
63 if (part->memfd >= 0) {
64 /* If we can reuse the memfd, try that. For that it
65 * can't be sealed yet. */
68 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
71 assert_se(munmap(part->data, part->mapped) == 0);
73 safe_close(part->memfd);
76 } else if (part->munmap_this)
77 munmap(part->data, part->mapped);
78 else if (part->free_this)
85 static void message_reset_parts(sd_bus_message *m) {
86 struct bus_body_part *part;
91 while (m->n_body_parts > 0) {
92 struct bus_body_part *next = part->next;
93 message_free_part(m, part);
100 m->cached_rindex_part = NULL;
101 m->cached_rindex_part_begin = 0;
104 static void message_reset_containers(sd_bus_message *m) {
109 for (i = 0; i < m->n_containers; i++) {
110 free(m->containers[i].signature);
111 free(m->containers[i].offsets);
115 m->containers = NULL;
117 m->n_containers = m->containers_allocated = 0;
118 m->root_container.index = 0;
121 static void message_free(sd_bus_message *m) {
127 message_reset_parts(m);
132 if (m->release_kdbus) {
135 off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
136 ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &off);
139 sd_bus_unref(m->bus);
142 close_many(m->fds, m->n_fds);
146 if (m->iovec != m->iovec_fixed)
149 message_reset_containers(m);
150 free(m->root_container.signature);
151 free(m->root_container.offsets);
153 free(m->root_container.peeked_signature);
155 bus_creds_done(&m->creds);
159 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
161 size_t old_size, new_size, start;
168 old_size = sizeof(struct bus_header) + m->header->fields_size;
169 start = ALIGN_TO(old_size, align);
170 new_size = start + sz;
172 if (old_size == new_size)
173 return (uint8_t*) m->header + old_size;
175 if (new_size > (size_t) ((uint32_t) -1))
178 if (m->free_header) {
179 np = realloc(m->header, ALIGN8(new_size));
183 /* Initially, the header is allocated as part of of
184 * the sd_bus_message itself, let's replace it by
187 np = malloc(ALIGN8(new_size));
191 memcpy(np, m->header, sizeof(struct bus_header));
194 /* Zero out padding */
195 if (start > old_size)
196 memzero((uint8_t*) np + old_size, start - old_size);
200 m->header->fields_size = new_size - sizeof(struct bus_header);
202 /* Adjust quick access pointers */
203 m->path = adjust_pointer(m->path, op, old_size, m->header);
204 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
205 m->member = adjust_pointer(m->member, op, old_size, m->header);
206 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
207 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
208 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
210 m->free_header = true;
213 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
216 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
219 return (uint8_t*) np + start;
226 static int message_append_field_string(
238 /* dbus1 doesn't allow strings over 32bit, let's enforce this
239 * globally, to not risk convertability */
241 if (l > (size_t) (uint32_t) -1)
244 /* Signature "(yv)" where the variant contains "s" */
246 if (BUS_MESSAGE_IS_GVARIANT(m)) {
248 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
249 p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
261 *ret = (char*) p + 8;
264 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
265 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
274 ((uint32_t*) p)[1] = l;
275 memcpy(p + 8, s, l + 1);
278 *ret = (char*) p + 8;
284 static int message_append_field_signature(
295 /* dbus1 doesn't allow signatures over 32bit, let's enforce
296 * this globally, to not risk convertability */
301 /* Signature "(yv)" where the variant contains "g" */
303 if (BUS_MESSAGE_IS_GVARIANT(m))
304 /* For gvariant the serialization is the same as for normal strings */
305 return message_append_field_string(m, h, 'g', s, ret);
307 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
308 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
314 p[2] = SD_BUS_TYPE_SIGNATURE;
317 memcpy(p + 5, s, l + 1);
320 *ret = (const char*) p + 5;
326 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
331 if (BUS_MESSAGE_IS_GVARIANT(m)) {
332 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
334 p = message_extend_fields(m, 8, 1 + 7 + 4 + 1 + 1, true);
340 *((uint32_t*) (p + 8)) = x;
344 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
345 p = message_extend_fields(m, 8, 4 + 4, false);
351 p[2] = SD_BUS_TYPE_UINT32;
354 ((uint32_t*) p)[1] = x;
360 int bus_message_from_header(
366 const struct ucred *ucred,
369 sd_bus_message **ret) {
372 struct bus_header *h;
376 assert(buffer || length <= 0);
377 assert(fds || n_fds <= 0);
380 if (length < sizeof(struct bus_header))
384 if (h->version != 1 &&
391 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
394 if (h->endian != BUS_LITTLE_ENDIAN &&
395 h->endian != BUS_BIG_ENDIAN)
398 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
401 label_sz = strlen(label);
416 m->creds.uid = ucred->uid;
417 m->creds.pid = ucred->pid;
418 m->creds.gid = ucred->gid;
419 m->creds.mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID;
423 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
424 memcpy(m->creds.label, label, label_sz + 1);
426 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
429 m->bus = sd_bus_ref(bus);
435 int bus_message_from_malloc(
441 const struct ucred *ucred,
443 sd_bus_message **ret) {
449 r = bus_message_from_header(bus, buffer, length, fds, n_fds, ucred, label, 0, &m);
453 if (length != BUS_MESSAGE_SIZE(m)) {
458 sz = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
461 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
463 m->body.sealed = true;
468 m->iovec = m->iovec_fixed;
469 m->iovec[0].iov_base = buffer;
470 m->iovec[0].iov_len = length;
472 r = bus_message_parse_fields(m);
476 /* We take possession of the memory and fds now */
477 m->free_header = true;
488 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
493 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
498 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
499 m->header->endian = BUS_NATIVE_ENDIAN;
500 m->header->type = type;
501 m->header->version = bus ? bus->message_version : 1;
502 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
503 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
504 m->bus = sd_bus_ref(bus);
509 _public_ int sd_bus_message_new_signal(
513 const char *interface,
514 const char *member) {
519 assert_return(bus, -ENOTCONN);
520 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
521 assert_return(object_path_is_valid(path), -EINVAL);
522 assert_return(interface_name_is_valid(interface), -EINVAL);
523 assert_return(member_name_is_valid(member), -EINVAL);
524 assert_return(m, -EINVAL);
526 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
530 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
532 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
535 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
538 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
546 sd_bus_message_unref(t);
550 _public_ int sd_bus_message_new_method_call(
553 const char *destination,
555 const char *interface,
556 const char *member) {
561 assert_return(bus, -ENOTCONN);
562 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
563 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
564 assert_return(object_path_is_valid(path), -EINVAL);
565 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
566 assert_return(member_name_is_valid(member), -EINVAL);
567 assert_return(m, -EINVAL);
569 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
573 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
576 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
581 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
587 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
600 static int message_new_reply(
601 sd_bus_message *call,
603 sd_bus_message **m) {
608 assert_return(call, -EINVAL);
609 assert_return(call->sealed, -EPERM);
610 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
611 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
612 assert_return(m, -EINVAL);
614 t = message_new(call->bus, type);
618 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
619 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
621 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
626 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
631 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
632 t->enforced_reply_signature = call->enforced_reply_signature;
642 _public_ int sd_bus_message_new_method_return(
643 sd_bus_message *call,
644 sd_bus_message **m) {
646 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
649 _public_ int sd_bus_message_new_method_error(
650 sd_bus_message *call,
652 const sd_bus_error *e) {
657 assert_return(sd_bus_error_is_set(e), -EINVAL);
658 assert_return(m, -EINVAL);
660 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
664 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
669 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
674 t->error._need_free = -1;
684 _public_ int sd_bus_message_new_method_errorf(
685 sd_bus_message *call,
691 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
694 assert_return(name, -EINVAL);
695 assert_return(m, -EINVAL);
697 va_start(ap, format);
698 bus_error_setfv(&error, name, format, ap);
701 return sd_bus_message_new_method_error(call, m, &error);
704 _public_ int sd_bus_message_new_method_errno(
705 sd_bus_message *call,
708 const sd_bus_error *p) {
710 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
712 if (sd_bus_error_is_set(p))
713 return sd_bus_message_new_method_error(call, m, p);
715 sd_bus_error_set_errno(&berror, error);
717 return sd_bus_message_new_method_error(call, m, &berror);
720 _public_ int sd_bus_message_new_method_errnof(
721 sd_bus_message *call,
727 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
730 va_start(ap, format);
731 bus_error_set_errnofv(&berror, error, format, ap);
734 return sd_bus_message_new_method_error(call, m, &berror);
737 int bus_message_new_synthetic_error(
740 const sd_bus_error *e,
741 sd_bus_message **m) {
747 assert(sd_bus_error_is_set(e));
750 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
754 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
755 t->reply_cookie = cookie;
757 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
761 if (bus && bus->unique_name) {
762 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
767 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
772 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
777 t->error._need_free = -1;
787 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
788 assert_return(m, NULL);
790 assert(m->n_ref > 0);
796 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
801 assert(m->n_ref > 0);
811 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
812 assert_return(m, -EINVAL);
813 assert_return(type, -EINVAL);
815 *type = m->header->type;
819 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
820 assert_return(m, -EINVAL);
821 assert_return(cookie, -EINVAL);
822 assert_return(m->header->serial != 0, -ENODATA);
824 *cookie = BUS_MESSAGE_COOKIE(m);
828 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
829 assert_return(m, -EINVAL);
830 assert_return(cookie, -EINVAL);
831 assert_return(m->reply_cookie != 0, -ENODATA);
833 *cookie = m->reply_cookie;
837 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
838 assert_return(m, -EINVAL);
840 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
841 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
844 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
845 assert_return(m, -EINVAL);
847 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
850 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
851 assert_return(m, NULL);
856 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
857 assert_return(m, NULL);
862 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
863 assert_return(m, NULL);
868 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
869 assert_return(m, NULL);
871 return m->destination;
874 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
875 assert_return(m, NULL);
880 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
881 assert_return(m, NULL);
882 assert_return(sd_bus_error_is_set(&m->error), NULL);
887 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
888 assert_return(m, -EINVAL);
889 assert_return(usec, -EINVAL);
891 if (m->monotonic <= 0)
894 *usec = m->monotonic;
898 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
899 assert_return(m, -EINVAL);
900 assert_return(usec, -EINVAL);
902 if (m->realtime <= 0)
909 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
910 assert_return(m, -EINVAL);
911 assert_return(seqnum, -EINVAL);
920 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
921 assert_return(m, NULL);
923 if (m->creds.mask == 0)
929 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
930 const char *interface,
931 const char *member) {
932 assert_return(m, -EINVAL);
934 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
937 if (interface && (!m->interface || !streq(m->interface, interface)))
940 if (member && (!m->member || !streq(m->member, member)))
946 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
947 const char *interface,
948 const char *member) {
949 assert_return(m, -EINVAL);
951 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
954 if (interface && (!m->interface || !streq(m->interface, interface)))
957 if (member && (!m->member || !streq(m->member, member)))
963 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
964 assert_return(m, -EINVAL);
966 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
969 if (name && (!m->error.name || !streq(m->error.name, name)))
975 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
976 assert_return(m, -EINVAL);
977 assert_return(!m->sealed, -EPERM);
978 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
981 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
983 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
988 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
989 assert_return(m, -EINVAL);
990 assert_return(!m->sealed, -EPERM);
993 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
995 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1000 static struct bus_container *message_get_container(sd_bus_message *m) {
1003 if (m->n_containers == 0)
1004 return &m->root_container;
1006 assert(m->containers);
1007 return m->containers + m->n_containers - 1;
1010 struct bus_body_part *message_append_part(sd_bus_message *m) {
1011 struct bus_body_part *part;
1018 if (m->n_body_parts <= 0) {
1022 assert(m->body_end);
1024 part = new0(struct bus_body_part, 1);
1030 m->body_end->next = part;
1040 static void part_zero(struct bus_body_part *part, size_t sz) {
1045 /* All other fields can be left in their defaults */
1046 assert(!part->data);
1047 assert(part->memfd < 0);
1050 part->is_zero = true;
1051 part->sealed = true;
1054 static int part_make_space(
1055 struct sd_bus_message *m,
1056 struct bus_body_part *part,
1065 assert(!part->sealed);
1070 if (!part->data && part->memfd < 0)
1071 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1073 if (part->memfd >= 0) {
1075 if (part->allocated == 0 || sz > part->allocated) {
1076 uint64_t new_allocated;
1078 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1079 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &new_allocated);
1085 part->allocated = new_allocated;
1088 if (!part->data || sz > part->mapped) {
1091 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1092 if (part->mapped <= 0)
1093 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1095 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1097 if (n == MAP_FAILED) {
1106 part->munmap_this = true;
1108 if (part->allocated == 0 || sz > part->allocated) {
1109 size_t new_allocated;
1111 new_allocated = sz > 0 ? 2 * sz : 64;
1112 n = realloc(part->data, new_allocated);
1119 part->allocated = new_allocated;
1120 part->free_this = true;
1125 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1131 static int message_add_offset(sd_bus_message *m, size_t offset) {
1132 struct bus_container *c;
1135 assert(BUS_MESSAGE_IS_GVARIANT(m));
1137 /* Add offset to current container, unless this is the first
1138 * item in it, which will have the 0 offset, which we can
1140 c = message_get_container(m);
1142 if (!c->need_offsets)
1145 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1148 c->offsets[c->n_offsets++] = offset;
1152 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1153 struct bus_container *c;
1160 /* Update counters */
1161 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1164 *c->array_size += expand;
1168 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1169 size_t start_body, end_body, padding, added;
1180 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1181 end_body = start_body + sz;
1183 padding = start_body - m->header->body_size;
1184 added = padding + sz;
1186 /* Check for 32bit overflows */
1187 if (end_body > (size_t) ((uint32_t) -1)) {
1193 struct bus_body_part *part = NULL;
1197 m->n_body_parts <= 0 ||
1198 m->body_end->sealed ||
1199 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1203 part = message_append_part(m);
1207 part_zero(part, padding);
1210 part = message_append_part(m);
1214 r = part_make_space(m, part, sz, &p);
1218 struct bus_container *c;
1220 size_t os, start_part, end_part;
1226 start_part = ALIGN_TO(part->size, align);
1227 end_part = start_part + sz;
1229 r = part_make_space(m, part, end_part, &p);
1234 memzero(p, padding);
1235 p = (uint8_t*) p + padding;
1238 /* Readjust pointers */
1239 for (c = m->containers; c < m->containers + m->n_containers; c++)
1240 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1242 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1245 /* Return something that is not NULL and is aligned */
1246 p = (uint8_t *) NULL + align;
1248 m->header->body_size = end_body;
1249 message_extend_containers(m, added);
1252 r = message_add_offset(m, end_body);
1262 static int message_push_fd(sd_bus_message *m, int fd) {
1273 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1277 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1285 m->fds[m->n_fds] = copy;
1291 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1292 _cleanup_close_ int fd = -1;
1293 struct bus_container *c;
1297 assert_return(m, -EINVAL);
1298 assert_return(!m->sealed, -EPERM);
1299 assert_return(bus_type_is_basic(type), -EINVAL);
1300 assert_return(!m->poisoned, -ESTALE);
1302 c = message_get_container(m);
1304 if (c->signature && c->signature[c->index]) {
1305 /* Container signature is already set */
1307 if (c->signature[c->index] != type)
1312 /* Maybe we can append to the signature? But only if this is the top-level container*/
1313 if (c->enclosing != 0)
1316 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1323 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1329 case SD_BUS_TYPE_SIGNATURE:
1330 case SD_BUS_TYPE_STRING:
1333 /* Fall through... */
1334 case SD_BUS_TYPE_OBJECT_PATH:
1342 case SD_BUS_TYPE_BOOLEAN:
1344 u8 = p && *(int*) p;
1350 case SD_BUS_TYPE_UNIX_FD:
1355 fd = message_push_fd(m, *(int*) p);
1366 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1367 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1374 a = message_extend_body(m, align, sz, true);
1381 *stored = (const uint8_t*) a;
1388 case SD_BUS_TYPE_STRING:
1389 /* To make things easy we'll serialize a NULL string
1390 * into the empty string */
1393 /* Fall through... */
1394 case SD_BUS_TYPE_OBJECT_PATH:
1400 sz = 4 + strlen(p) + 1;
1403 case SD_BUS_TYPE_SIGNATURE:
1408 sz = 1 + strlen(p) + 1;
1411 case SD_BUS_TYPE_BOOLEAN:
1413 u32 = p && *(int*) p;
1419 case SD_BUS_TYPE_UNIX_FD:
1424 fd = message_push_fd(m, *(int*) p);
1435 align = bus_type_get_alignment(type);
1436 sz = bus_type_get_size(type);
1443 a = message_extend_body(m, align, sz, false);
1447 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1448 *(uint32_t*) a = sz - 5;
1449 memcpy((uint8_t*) a + 4, p, sz - 4);
1452 *stored = (const uint8_t*) a + 4;
1454 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1455 *(uint8_t*) a = sz - 2;
1456 memcpy((uint8_t*) a + 1, p, sz - 1);
1459 *stored = (const uint8_t*) a + 1;
1468 if (type == SD_BUS_TYPE_UNIX_FD)
1471 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1478 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1479 return message_append_basic(m, type, p, NULL);
1482 _public_ int sd_bus_message_append_string_space(
1487 struct bus_container *c;
1490 assert_return(m, -EINVAL);
1491 assert_return(s, -EINVAL);
1492 assert_return(!m->sealed, -EPERM);
1493 assert_return(!m->poisoned, -ESTALE);
1495 c = message_get_container(m);
1497 if (c->signature && c->signature[c->index]) {
1498 /* Container signature is already set */
1500 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1505 /* Maybe we can append to the signature? But only if this is the top-level container*/
1506 if (c->enclosing != 0)
1509 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1516 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1517 a = message_extend_body(m, 1, size + 1, true);
1523 a = message_extend_body(m, 4, 4 + size + 1, false);
1527 *(uint32_t*) a = size;
1533 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1539 _public_ int sd_bus_message_append_string_iovec(
1541 const struct iovec *iov,
1549 assert_return(m, -EINVAL);
1550 assert_return(!m->sealed, -EPERM);
1551 assert_return(iov || n == 0, -EINVAL);
1552 assert_return(!m->poisoned, -ESTALE);
1554 size = IOVEC_TOTAL_SIZE(iov, n);
1556 r = sd_bus_message_append_string_space(m, size, &p);
1560 for (i = 0; i < n; i++) {
1562 if (iov[i].iov_base)
1563 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1565 memset(p, ' ', iov[i].iov_len);
1567 p += iov[i].iov_len;
1573 static int bus_message_open_array(
1575 struct bus_container *c,
1576 const char *contents,
1577 uint32_t **array_size,
1579 bool *need_offsets) {
1589 assert(need_offsets);
1591 if (!signature_is_single(contents, true))
1594 if (c->signature && c->signature[c->index]) {
1596 /* Verify the existing signature */
1598 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1601 if (!startswith(c->signature + c->index + 1, contents))
1604 nindex = c->index + 1 + strlen(contents);
1608 if (c->enclosing != 0)
1611 /* Extend the existing signature */
1613 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1619 nindex = e - c->signature;
1622 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1623 alignment = bus_gvariant_get_alignment(contents);
1627 /* Add alignment padding and add to offset list */
1628 if (!message_extend_body(m, alignment, 0, false))
1631 r = bus_gvariant_is_fixed_size(contents);
1635 *begin = m->header->body_size;
1636 *need_offsets = r == 0;
1640 struct bus_body_part *o;
1642 alignment = bus_type_get_alignment(contents[0]);
1646 a = message_extend_body(m, 4, 4, false);
1651 op = m->body_end->data;
1652 os = m->body_end->size;
1654 /* Add alignment between size and first element */
1655 if (!message_extend_body(m, alignment, 0, false))
1658 /* location of array size might have changed so let's readjust a */
1659 if (o == m->body_end)
1660 a = adjust_pointer(a, op, os, m->body_end->data);
1666 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1672 static int bus_message_open_variant(
1674 struct bus_container *c,
1675 const char *contents) {
1681 if (!signature_is_single(contents, false))
1684 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1687 if (c->signature && c->signature[c->index]) {
1689 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1695 if (c->enclosing != 0)
1698 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1705 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1706 /* Variants are always aligned to 8 */
1708 if (!message_extend_body(m, 8, 0, false))
1715 l = strlen(contents);
1716 a = message_extend_body(m, 1, 1 + l + 1, false);
1721 memcpy((uint8_t*) a + 1, contents, l + 1);
1724 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1730 static int bus_message_open_struct(
1732 struct bus_container *c,
1733 const char *contents,
1735 bool *need_offsets) {
1744 assert(need_offsets);
1746 if (!signature_is_valid(contents, false))
1749 if (c->signature && c->signature[c->index]) {
1752 l = strlen(contents);
1754 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1755 !startswith(c->signature + c->index + 1, contents) ||
1756 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1759 nindex = c->index + 1 + l + 1;
1763 if (c->enclosing != 0)
1766 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1772 nindex = e - c->signature;
1775 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1778 alignment = bus_gvariant_get_alignment(contents);
1782 if (!message_extend_body(m, alignment, 0, false))
1785 r = bus_gvariant_is_fixed_size(contents);
1789 *begin = m->header->body_size;
1790 *need_offsets = r == 0;
1792 /* Align contents to 8 byte boundary */
1793 if (!message_extend_body(m, 8, 0, false))
1797 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1803 static int bus_message_open_dict_entry(
1805 struct bus_container *c,
1806 const char *contents,
1808 bool *need_offsets) {
1816 assert(need_offsets);
1818 if (!signature_is_pair(contents))
1821 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1824 if (c->signature && c->signature[c->index]) {
1827 l = strlen(contents);
1829 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1830 !startswith(c->signature + c->index + 1, contents) ||
1831 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1836 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1839 alignment = bus_gvariant_get_alignment(contents);
1843 if (!message_extend_body(m, alignment, 0, false))
1846 r = bus_gvariant_is_fixed_size(contents);
1850 *begin = m->header->body_size;
1851 *need_offsets = r == 0;
1853 /* Align contents to 8 byte boundary */
1854 if (!message_extend_body(m, 8, 0, false))
1861 _public_ int sd_bus_message_open_container(
1864 const char *contents) {
1866 struct bus_container *c, *w;
1867 uint32_t *array_size = NULL;
1869 size_t before, begin = 0;
1870 bool need_offsets = false;
1873 assert_return(m, -EINVAL);
1874 assert_return(!m->sealed, -EPERM);
1875 assert_return(contents, -EINVAL);
1876 assert_return(!m->poisoned, -ESTALE);
1878 /* Make sure we have space for one more container */
1879 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1884 c = message_get_container(m);
1886 signature = strdup(contents);
1892 /* Save old index in the parent container, in case we have to
1893 * abort this container */
1894 c->saved_index = c->index;
1895 before = m->header->body_size;
1897 if (type == SD_BUS_TYPE_ARRAY)
1898 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1899 else if (type == SD_BUS_TYPE_VARIANT)
1900 r = bus_message_open_variant(m, c, contents);
1901 else if (type == SD_BUS_TYPE_STRUCT)
1902 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1903 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1904 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1913 /* OK, let's fill it in */
1914 w = m->containers + m->n_containers++;
1915 w->enclosing = type;
1916 w->signature = signature;
1918 w->array_size = array_size;
1921 w->n_offsets = w->offsets_allocated = 0;
1923 w->need_offsets = need_offsets;
1928 static size_t determine_word_size(size_t sz, size_t extra) {
1929 if (sz + extra <= 0xFF)
1931 else if (sz + extra*2 <= 0xFFFF)
1933 else if (sz + extra*4 <= 0xFFFFFFFF)
1939 static size_t read_word_le(void *p, size_t sz) {
1949 return *(uint8_t*) p;
1954 return le16toh(x.u16);
1956 return le32toh(x.u32);
1958 return le64toh(x.u64);
1960 assert_not_reached("unknown word width");
1963 static void write_word_le(void *p, size_t sz, size_t value) {
1971 assert(sz == 8 || (value < (1ULL << (sz*8))));
1974 *(uint8_t*) p = value;
1977 x.u16 = htole16((uint16_t) value);
1979 x.u32 = htole32((uint32_t) value);
1981 x.u64 = htole64((uint64_t) value);
1983 assert_not_reached("unknown word width");
1988 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1993 if (!BUS_MESSAGE_IS_GVARIANT(m))
1996 if (c->need_offsets) {
1997 size_t payload, sz, i;
2000 /* Variable-width arrays */
2002 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2003 sz = determine_word_size(payload, c->n_offsets);
2005 a = message_extend_body(m, 1, sz * c->n_offsets, true);
2009 for (i = 0; i < c->n_offsets; i++)
2010 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2014 /* Fixed-width or empty arrays */
2016 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
2024 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2031 if (!BUS_MESSAGE_IS_GVARIANT(m))
2034 l = strlen(c->signature);
2036 a = message_extend_body(m, 1, 1 + l, true);
2041 memcpy(a+1, c->signature, l);
2046 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2047 size_t n_variable = 0;
2056 if (!BUS_MESSAGE_IS_GVARIANT(m))
2059 p = strempty(c->signature);
2063 r = signature_element_length(p, &n);
2072 r = bus_gvariant_is_fixed_size(t);
2077 assert(!c->need_offsets || i <= c->n_offsets);
2079 /* We need to add an offset for each item that has a
2080 * variable size and that is not the last one in the
2082 if (r == 0 && p[n] != 0)
2089 assert(!c->need_offsets || i == c->n_offsets);
2090 assert(c->need_offsets || n_variable == 0);
2092 if (n_variable <= 0) {
2093 a = message_extend_body(m, 1, 0, add_offset);
2100 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2102 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2104 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2108 p = strempty(c->signature);
2109 for (i = 0, j = 0; i < c->n_offsets; i++) {
2113 r = signature_element_length(p, &n);
2124 r = bus_gvariant_is_fixed_size(t);
2127 if (r > 0 || p[0] == 0)
2131 k = n_variable - 1 - j;
2133 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2142 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2143 struct bus_container *c;
2146 assert_return(m, -EINVAL);
2147 assert_return(!m->sealed, -EPERM);
2148 assert_return(m->n_containers > 0, -EINVAL);
2149 assert_return(!m->poisoned, -ESTALE);
2151 c = message_get_container(m);
2153 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2154 if (c->signature && c->signature[c->index] != 0)
2159 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2160 r = bus_message_close_array(m, c);
2161 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2162 r = bus_message_close_variant(m, c);
2163 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2164 r = bus_message_close_struct(m, c, true);
2166 assert_not_reached("Unknown container type");
2180 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2187 stack[*i].types = types;
2188 stack[*i].n_struct = n_struct;
2189 stack[*i].n_array = n_array;
2195 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2206 *types = stack[*i].types;
2207 *n_struct = stack[*i].n_struct;
2208 *n_array = stack[*i].n_array;
2213 int bus_message_append_ap(
2218 unsigned n_array, n_struct;
2219 TypeStack stack[BUS_CONTAINER_DEPTH];
2220 unsigned stack_ptr = 0;
2228 n_array = (unsigned) -1;
2229 n_struct = strlen(types);
2234 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2235 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2241 r = sd_bus_message_close_container(m);
2249 if (n_array != (unsigned) -1)
2258 case SD_BUS_TYPE_BYTE: {
2261 x = (uint8_t) va_arg(ap, int);
2262 r = sd_bus_message_append_basic(m, *t, &x);
2266 case SD_BUS_TYPE_BOOLEAN:
2267 case SD_BUS_TYPE_INT32:
2268 case SD_BUS_TYPE_UINT32:
2269 case SD_BUS_TYPE_UNIX_FD: {
2272 /* We assume a boolean is the same as int32_t */
2273 assert_cc(sizeof(int32_t) == sizeof(int));
2275 x = va_arg(ap, uint32_t);
2276 r = sd_bus_message_append_basic(m, *t, &x);
2280 case SD_BUS_TYPE_INT16:
2281 case SD_BUS_TYPE_UINT16: {
2284 x = (uint16_t) va_arg(ap, int);
2285 r = sd_bus_message_append_basic(m, *t, &x);
2289 case SD_BUS_TYPE_INT64:
2290 case SD_BUS_TYPE_UINT64:
2291 case SD_BUS_TYPE_DOUBLE: {
2294 x = va_arg(ap, uint64_t);
2295 r = sd_bus_message_append_basic(m, *t, &x);
2299 case SD_BUS_TYPE_STRING:
2300 case SD_BUS_TYPE_OBJECT_PATH:
2301 case SD_BUS_TYPE_SIGNATURE: {
2304 x = va_arg(ap, const char*);
2305 r = sd_bus_message_append_basic(m, *t, x);
2309 case SD_BUS_TYPE_ARRAY: {
2312 r = signature_element_length(t + 1, &k);
2318 memcpy(s, t + 1, k);
2321 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2326 if (n_array == (unsigned) -1) {
2331 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2337 n_array = va_arg(ap, unsigned);
2342 case SD_BUS_TYPE_VARIANT: {
2345 s = va_arg(ap, const char*);
2349 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2353 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2358 n_struct = strlen(s);
2359 n_array = (unsigned) -1;
2364 case SD_BUS_TYPE_STRUCT_BEGIN:
2365 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2368 r = signature_element_length(t, &k);
2375 memcpy(s, t + 1, k - 2);
2378 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2383 if (n_array == (unsigned) -1) {
2388 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2394 n_array = (unsigned) -1;
2410 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2414 assert_return(m, -EINVAL);
2415 assert_return(types, -EINVAL);
2416 assert_return(!m->sealed, -EPERM);
2417 assert_return(!m->poisoned, -ESTALE);
2419 va_start(ap, types);
2420 r = bus_message_append_ap(m, types, ap);
2426 _public_ int sd_bus_message_append_array_space(
2436 assert_return(m, -EINVAL);
2437 assert_return(!m->sealed, -EPERM);
2438 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2439 assert_return(ptr || size == 0, -EINVAL);
2440 assert_return(!m->poisoned, -ESTALE);
2442 /* alignment and size of the trivial types (except bool) is
2443 * identical for gvariant and dbus1 marshalling */
2444 align = bus_type_get_alignment(type);
2445 sz = bus_type_get_size(type);
2447 assert_se(align > 0);
2453 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2457 a = message_extend_body(m, align, size, false);
2461 r = sd_bus_message_close_container(m);
2469 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2476 assert_return(m, -EINVAL);
2477 assert_return(!m->sealed, -EPERM);
2478 assert_return(bus_type_is_trivial(type), -EINVAL);
2479 assert_return(ptr || size == 0, -EINVAL);
2480 assert_return(!m->poisoned, -ESTALE);
2482 r = sd_bus_message_append_array_space(m, type, size, &p);
2487 memcpy(p, ptr, size);
2492 _public_ int sd_bus_message_append_array_iovec(
2495 const struct iovec *iov,
2503 assert_return(m, -EINVAL);
2504 assert_return(!m->sealed, -EPERM);
2505 assert_return(bus_type_is_trivial(type), -EINVAL);
2506 assert_return(iov || n == 0, -EINVAL);
2507 assert_return(!m->poisoned, -ESTALE);
2509 size = IOVEC_TOTAL_SIZE(iov, n);
2511 r = sd_bus_message_append_array_space(m, type, size, &p);
2515 for (i = 0; i < n; i++) {
2517 if (iov[i].iov_base)
2518 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2520 memzero(p, iov[i].iov_len);
2522 p = (uint8_t*) p + iov[i].iov_len;
2528 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2531 _cleanup_close_ int copy_fd = -1;
2532 struct bus_body_part *part;
2544 if (!bus_type_is_trivial(type))
2549 r = sd_memfd_set_sealed(memfd, true);
2553 copy_fd = sd_memfd_dup_fd(memfd);
2557 r = sd_memfd_get_size(memfd, &size);
2561 align = bus_type_get_alignment(type);
2562 sz = bus_type_get_size(type);
2564 assert_se(align > 0);
2570 if (size > (uint64_t) (uint32_t) -1)
2573 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2577 a = message_extend_body(m, align, 0, false);
2581 part = message_append_part(m);
2585 part->memfd = copy_fd;
2586 part->sealed = true;
2590 m->header->body_size += size;
2591 message_extend_containers(m, size);
2593 return sd_bus_message_close_container(m);
2596 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
2597 _cleanup_close_ int copy_fd = -1;
2598 struct bus_body_part *part;
2599 struct bus_container *c;
2604 assert_return(m, -EINVAL);
2605 assert_return(memfd, -EINVAL);
2606 assert_return(!m->sealed, -EPERM);
2607 assert_return(!m->poisoned, -ESTALE);
2609 r = sd_memfd_set_sealed(memfd, true);
2613 copy_fd = sd_memfd_dup_fd(memfd);
2617 r = sd_memfd_get_size(memfd, &size);
2621 /* We require this to be NUL terminated */
2625 if (size > (uint64_t) (uint32_t) -1)
2628 c = message_get_container(m);
2629 if (c->signature && c->signature[c->index]) {
2630 /* Container signature is already set */
2632 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2637 /* Maybe we can append to the signature? But only if this is the top-level container*/
2638 if (c->enclosing != 0)
2641 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2648 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2649 a = message_extend_body(m, 4, 4, false);
2653 *(uint32_t*) a = size - 1;
2656 part = message_append_part(m);
2660 part->memfd = copy_fd;
2661 part->sealed = true;
2665 m->header->body_size += size;
2666 message_extend_containers(m, size);
2668 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2669 r = message_add_offset(m, m->header->body_size);
2676 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2682 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2686 assert_return(m, -EINVAL);
2687 assert_return(!m->sealed, -EPERM);
2688 assert_return(!m->poisoned, -ESTALE);
2690 r = sd_bus_message_open_container(m, 'a', "s");
2694 STRV_FOREACH(i, l) {
2695 r = sd_bus_message_append_basic(m, 's', *i);
2700 return sd_bus_message_close_container(m);
2703 static int bus_message_close_header(sd_bus_message *m) {
2709 if (!BUS_MESSAGE_IS_GVARIANT(m))
2712 if (m->n_header_offsets < 1)
2715 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2717 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2719 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2723 for (i = 0; i < m->n_header_offsets; i++)
2724 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2729 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2730 struct bus_body_part *part;
2740 if (m->n_containers > 0)
2746 /* In vtables the return signature of method calls is listed,
2747 * let's check if they match if this is a response */
2748 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2749 m->enforced_reply_signature &&
2750 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2753 /* If gvariant marshalling is used we need to close the body structure */
2754 r = bus_message_close_struct(m, &m->root_container, false);
2758 /* If there's a non-trivial signature set, then add it in here */
2759 if (!isempty(m->root_container.signature)) {
2760 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2766 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2771 r = bus_message_close_header(m);
2775 m->header->serial = (uint32_t) cookie;
2776 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2778 /* Add padding at the end of the fields part, since we know
2779 * the body needs to start at an 8 byte alignment. We made
2780 * sure we allocated enough space for this, so all we need to
2781 * do here is to zero it out. */
2782 l = BUS_MESSAGE_FIELDS_SIZE(m);
2785 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, a);
2787 /* If this is something we can send as memfd, then let's seal
2788 the memfd now. Note that we can send memfds as payload only
2789 for directed messages, and not for broadcasts. */
2790 if (m->destination && m->bus->use_memfd) {
2791 MESSAGE_FOREACH_PART(part, i, m)
2792 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2795 /* Try to seal it if that makes
2796 * sense. First, unmap our own map to
2797 * make sure we don't keep it busy. */
2798 bus_body_part_unmap(part);
2800 /* Then, sync up real memfd size */
2802 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &sz) < 0)
2805 /* Finally, try to seal */
2806 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
2807 part->sealed = true;
2811 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2812 m->root_container.index = 0;
2813 m->root_container.offset_index = 0;
2814 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2821 int bus_body_part_map(struct bus_body_part *part) {
2830 if (part->size <= 0)
2833 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2834 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2835 static const uint8_t zeroes[7] = { };
2836 part->data = (void*) zeroes;
2840 psz = PAGE_ALIGN(part->size);
2842 if (part->memfd >= 0)
2843 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, 0);
2844 else if (part->is_zero)
2845 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2849 if (p == MAP_FAILED)
2854 part->munmap_this = true;
2859 void bus_body_part_unmap(struct bus_body_part *part) {
2863 if (part->memfd < 0)
2869 if (!part->munmap_this)
2872 assert_se(munmap(part->data, part->mapped) == 0);
2876 part->munmap_this = false;
2881 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2882 size_t k, start, end;
2887 start = ALIGN_TO((size_t) *rindex, align);
2888 end = start + nbytes;
2893 /* Verify that padding is 0 */
2894 for (k = *rindex; k < start; k++)
2895 if (((const uint8_t*) p)[k] != 0)
2899 *r = (uint8_t*) p + start;
2906 static bool message_end_of_signature(sd_bus_message *m) {
2907 struct bus_container *c;
2911 c = message_get_container(m);
2912 return !c->signature || c->signature[c->index] == 0;
2915 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2916 struct bus_container *c;
2920 c = message_get_container(m);
2921 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2924 if (BUS_MESSAGE_IS_GVARIANT(m))
2925 return index >= c->end;
2927 assert(c->array_size);
2928 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2932 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2933 assert_return(m, -EINVAL);
2934 assert_return(m->sealed, -EPERM);
2936 if (complete && m->n_containers > 0)
2939 if (message_end_of_signature(m))
2942 if (message_end_of_array(m, m->rindex))
2948 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2949 struct bus_body_part *part;
2955 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2956 part = m->cached_rindex_part;
2957 begin = m->cached_rindex_part_begin;
2967 if (index + sz <= begin + part->size) {
2969 r = bus_body_part_map(part);
2974 *p = (uint8_t*) part->data + index - begin;
2976 m->cached_rindex_part = part;
2977 m->cached_rindex_part_begin = begin;
2982 begin += part->size;
2989 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2996 if (!BUS_MESSAGE_IS_GVARIANT(m))
2999 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3002 sz = bus_gvariant_get_size(c->signature);
3006 if (c->offset_index+1 >= c->n_offsets)
3009 /* Variable-size array */
3011 alignment = bus_gvariant_get_alignment(c->signature);
3012 assert(alignment > 0);
3014 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3015 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3018 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3021 /* Fixed-size array */
3022 *rindex = c->begin + (c->offset_index+1) * sz;
3028 } else if (c->enclosing == 0 ||
3029 c->enclosing == SD_BUS_TYPE_STRUCT ||
3030 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3035 if (c->offset_index+1 >= c->n_offsets)
3038 r = signature_element_length(c->signature + c->index, &n);
3042 r = signature_element_length(c->signature + c->index + n, &j);
3047 memcpy(t, c->signature + c->index + n, j);
3050 alignment = bus_gvariant_get_alignment(t);
3053 assert(alignment > 0);
3055 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3056 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3060 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3063 assert_not_reached("Unknown container type");
3068 /* Reached the end */
3075 static int message_peek_body(
3082 size_t k, start, end, padding;
3083 struct bus_body_part *part;
3090 start = ALIGN_TO((size_t) *rindex, align);
3091 padding = start - *rindex;
3092 end = start + nbytes;
3094 if (end > BUS_MESSAGE_BODY_SIZE(m))
3097 part = find_part(m, *rindex, padding, (void**) &q);
3102 /* Verify padding */
3103 for (k = 0; k < padding; k++)
3108 part = find_part(m, start, nbytes, (void**) &q);
3109 if (!part || (nbytes > 0 && !q))
3120 static bool validate_nul(const char *s, size_t l) {
3122 /* Check for NUL chars in the string */
3123 if (memchr(s, 0, l))
3126 /* Check for NUL termination */
3133 static bool validate_string(const char *s, size_t l) {
3135 if (!validate_nul(s, l))
3138 /* Check if valid UTF8 */
3139 if (!utf8_is_valid(s))
3145 static bool validate_signature(const char *s, size_t l) {
3147 if (!validate_nul(s, l))
3150 /* Check if valid signature */
3151 if (!signature_is_valid(s, true))
3157 static bool validate_object_path(const char *s, size_t l) {
3159 if (!validate_nul(s, l))
3162 if (!object_path_is_valid(s))
3168 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3169 struct bus_container *c;
3174 assert_return(m, -EINVAL);
3175 assert_return(m->sealed, -EPERM);
3176 assert_return(bus_type_is_basic(type), -EINVAL);
3178 if (message_end_of_signature(m))
3181 if (message_end_of_array(m, m->rindex))
3184 c = message_get_container(m);
3185 if (c->signature[c->index] != type)
3190 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3192 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3195 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3199 if (type == SD_BUS_TYPE_STRING)
3200 ok = validate_string(q, c->item_size-1);
3201 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3202 ok = validate_object_path(q, c->item_size-1);
3204 ok = validate_signature(q, c->item_size-1);
3210 *(const char**) p = q;
3214 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3216 if ((size_t) sz != c->item_size)
3219 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3222 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3228 case SD_BUS_TYPE_BYTE:
3230 *(uint8_t*) p = *(uint8_t*) q;
3233 case SD_BUS_TYPE_BOOLEAN:
3235 *(int*) p = !!*(uint8_t*) q;
3238 case SD_BUS_TYPE_INT16:
3239 case SD_BUS_TYPE_UINT16:
3241 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3244 case SD_BUS_TYPE_INT32:
3245 case SD_BUS_TYPE_UINT32:
3247 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3250 case SD_BUS_TYPE_INT64:
3251 case SD_BUS_TYPE_UINT64:
3252 case SD_BUS_TYPE_DOUBLE:
3254 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3257 case SD_BUS_TYPE_UNIX_FD: {
3260 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3265 *(int*) p = m->fds[j];
3271 assert_not_reached("unexpected type");
3275 r = container_next_item(m, c, &rindex);
3282 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3286 r = message_peek_body(m, &rindex, 4, 4, &q);
3290 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3291 r = message_peek_body(m, &rindex, 1, l+1, &q);
3295 if (type == SD_BUS_TYPE_OBJECT_PATH)
3296 ok = validate_object_path(q, l);
3298 ok = validate_string(q, l);
3303 *(const char**) p = q;
3305 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3308 r = message_peek_body(m, &rindex, 1, 1, &q);
3313 r = message_peek_body(m, &rindex, 1, l+1, &q);
3317 if (!validate_signature(q, l))
3321 *(const char**) p = q;
3326 align = bus_type_get_alignment(type);
3329 sz = bus_type_get_size(type);
3332 r = message_peek_body(m, &rindex, align, sz, &q);
3338 case SD_BUS_TYPE_BYTE:
3340 *(uint8_t*) p = *(uint8_t*) q;
3343 case SD_BUS_TYPE_BOOLEAN:
3345 *(int*) p = !!*(uint32_t*) q;
3348 case SD_BUS_TYPE_INT16:
3349 case SD_BUS_TYPE_UINT16:
3351 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3354 case SD_BUS_TYPE_INT32:
3355 case SD_BUS_TYPE_UINT32:
3357 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3360 case SD_BUS_TYPE_INT64:
3361 case SD_BUS_TYPE_UINT64:
3362 case SD_BUS_TYPE_DOUBLE:
3364 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3367 case SD_BUS_TYPE_UNIX_FD: {
3370 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3375 *(int*) p = m->fds[j];
3380 assert_not_reached("Unknown basic type...");
3387 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3393 static int bus_message_enter_array(
3395 struct bus_container *c,
3396 const char *contents,
3397 uint32_t **array_size,
3400 size_t *n_offsets) {
3414 if (!signature_is_single(contents, true))
3417 if (!c->signature || c->signature[c->index] == 0)
3420 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3423 if (!startswith(c->signature + c->index + 1, contents))
3428 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3431 r = message_peek_body(m, &rindex, 4, 4, &q);
3435 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3438 alignment = bus_type_get_alignment(contents[0]);
3442 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3446 *array_size = (uint32_t*) q;
3448 } else if (c->item_size <= 0) {
3450 /* gvariant: empty array */
3455 } else if (bus_gvariant_is_fixed_size(contents)) {
3457 /* gvariant: fixed length array */
3458 *item_size = bus_gvariant_get_size(contents);
3463 size_t where, p = 0, framing, sz;
3466 /* gvariant: variable length array */
3467 sz = determine_word_size(c->item_size, 0);
3469 where = rindex + c->item_size - sz;
3470 r = message_peek_body(m, &where, 1, sz, &q);
3474 framing = read_word_le(q, sz);
3475 if (framing > c->item_size - sz)
3477 if ((c->item_size - framing) % sz != 0)
3480 *n_offsets = (c->item_size - framing) / sz;
3482 where = rindex + framing;
3483 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3487 *offsets = new(size_t, *n_offsets);
3491 for (i = 0; i < *n_offsets; i++) {
3494 x = read_word_le((uint8_t*) q + i * sz, sz);
3495 if (x > c->item_size - sz)
3500 (*offsets)[i] = rindex + x;
3504 *item_size = (*offsets)[0] - rindex;
3509 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3510 c->index += 1 + strlen(contents);
3515 static int bus_message_enter_variant(
3517 struct bus_container *c,
3518 const char *contents,
3519 size_t *item_size) {
3531 if (!signature_is_single(contents, false))
3534 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3537 if (!c->signature || c->signature[c->index] == 0)
3540 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3545 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3548 k = strlen(contents);
3549 if (1+k > c->item_size)
3552 where = rindex + c->item_size - (1+k);
3553 r = message_peek_body(m, &where, 1, 1+k, &q);
3557 if (*(char*) q != 0)
3560 if (memcmp((uint8_t*) q+1, contents, k))
3563 *item_size = c->item_size - (1+k);
3566 r = message_peek_body(m, &rindex, 1, 1, &q);
3571 r = message_peek_body(m, &rindex, 1, l+1, &q);
3575 if (!validate_signature(q, l))
3578 if (!streq(q, contents))
3584 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3590 static int build_struct_offsets(
3592 const char *signature,
3596 size_t *n_offsets) {
3598 unsigned n_variable = 0, n_total = 0, v;
3599 size_t previous = 0, where;
3610 if (isempty(signature)) {
3617 sz = determine_word_size(size, 0);
3621 /* First, loop over signature and count variable elements and
3622 * elements in general. We use this to know how large the
3623 * offset array is at the end of the structure. Note that
3624 * GVariant only stores offsets for all variable size elements
3625 * that are not the last item. */
3631 r = signature_element_length(p, &n);
3640 r = bus_gvariant_is_fixed_size(t);
3645 if (r == 0 && p[n] != 0) /* except the last item */
3652 if (size < n_variable * sz)
3655 where = m->rindex + size - (n_variable * sz);
3656 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3662 *offsets = new(size_t, n_total);
3668 /* Second, loop again and build an offset table */
3674 r = signature_element_length(p, &n);
3683 k = bus_gvariant_get_size(t);
3691 x = read_word_le((uint8_t*) q + v*sz, sz);
3694 if (m->rindex + x < previous)
3697 /* The last item's end
3698 * is determined from
3701 x = size - (n_variable * sz);
3703 offset = m->rindex + x;
3709 align = bus_gvariant_get_alignment(t);
3712 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3716 previous = (*offsets)[(*n_offsets)++] = offset;
3721 assert(*n_offsets == n_total);
3723 *item_size = (*offsets)[0] - m->rindex;
3727 static int enter_struct_or_dict_entry(
3729 struct bus_container *c,
3730 const char *contents,
3733 size_t *n_offsets) {
3744 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3747 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3751 } else if (c->item_size <= 0) {
3753 /* gvariant empty struct */
3758 /* gvariant with contents */
3759 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3764 static int bus_message_enter_struct(
3766 struct bus_container *c,
3767 const char *contents,
3770 size_t *n_offsets) {
3782 if (!signature_is_valid(contents, false))
3785 if (!c->signature || c->signature[c->index] == 0)
3788 l = strlen(contents);
3790 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3791 !startswith(c->signature + c->index + 1, contents) ||
3792 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3795 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3799 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3800 c->index += 1 + l + 1;
3805 static int bus_message_enter_dict_entry(
3807 struct bus_container *c,
3808 const char *contents,
3811 size_t *n_offsets) {
3820 if (!signature_is_pair(contents))
3823 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3826 if (!c->signature || c->signature[c->index] == 0)
3829 l = strlen(contents);
3831 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3832 !startswith(c->signature + c->index + 1, contents) ||
3833 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3836 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3840 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3841 c->index += 1 + l + 1;
3846 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3848 const char *contents) {
3849 struct bus_container *c, *w;
3850 uint32_t *array_size = NULL;
3853 size_t *offsets = NULL;
3854 size_t n_offsets = 0, item_size = 0;
3857 assert_return(m, -EINVAL);
3858 assert_return(m->sealed, -EPERM);
3859 assert_return(type != 0 || !contents, -EINVAL);
3861 if (type == 0 || !contents) {
3865 /* Allow entering into anonymous containers */
3866 r = sd_bus_message_peek_type(m, &tt, &cc);
3870 if (type != 0 && type != tt)
3873 if (contents && !streq(contents, cc))
3881 * We enforce a global limit on container depth, that is much
3882 * higher than the 32 structs and 32 arrays the specification
3883 * mandates. This is simpler to implement for us, and we need
3884 * this only to ensure our container array doesn't grow
3885 * without bounds. We are happy to return any data from a
3886 * message as long as the data itself is valid, even if the
3887 * overall message might be not.
3889 * Note that the message signature is validated when
3890 * parsing the headers, and that validation does check the
3893 * Note that the specification defines no limits on the depth
3894 * of stacked variants, but we do.
3896 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3899 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3902 if (message_end_of_signature(m))
3905 if (message_end_of_array(m, m->rindex))
3908 c = message_get_container(m);
3910 signature = strdup(contents);
3914 c->saved_index = c->index;
3917 if (type == SD_BUS_TYPE_ARRAY)
3918 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3919 else if (type == SD_BUS_TYPE_VARIANT)
3920 r = bus_message_enter_variant(m, c, contents, &item_size);
3921 else if (type == SD_BUS_TYPE_STRUCT)
3922 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3923 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3924 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3934 /* OK, let's fill it in */
3935 w = m->containers + m->n_containers++;
3936 w->enclosing = type;
3937 w->signature = signature;
3938 w->peeked_signature = NULL;
3942 w->begin = m->rindex;
3943 w->end = m->rindex + c->item_size;
3945 w->array_size = array_size;
3946 w->item_size = item_size;
3947 w->offsets = offsets;
3948 w->n_offsets = n_offsets;
3949 w->offset_index = 0;
3954 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3955 struct bus_container *c;
3959 assert_return(m, -EINVAL);
3960 assert_return(m->sealed, -EPERM);
3961 assert_return(m->n_containers > 0, -ENXIO);
3963 c = message_get_container(m);
3965 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3966 if (c->signature && c->signature[c->index] != 0)
3970 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3971 if (m->rindex < c->end)
3974 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3977 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3978 if (c->begin + l != m->rindex)
3983 free(c->peeked_signature);
3987 c = message_get_container(m);
3990 c->index = c->saved_index;
3991 r = container_next_item(m, c, &m->rindex);
3999 static void message_quit_container(sd_bus_message *m) {
4000 struct bus_container *c;
4004 assert(m->n_containers > 0);
4006 c = message_get_container(m);
4009 assert(m->rindex >= c->before);
4010 m->rindex = c->before;
4012 /* Free container */
4017 /* Correct index of new top-level container */
4018 c = message_get_container(m);
4019 c->index = c->saved_index;
4022 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4023 struct bus_container *c;
4026 assert_return(m, -EINVAL);
4027 assert_return(m->sealed, -EPERM);
4029 if (message_end_of_signature(m))
4032 if (message_end_of_array(m, m->rindex))
4035 c = message_get_container(m);
4037 if (bus_type_is_basic(c->signature[c->index])) {
4041 *type = c->signature[c->index];
4045 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4051 r = signature_element_length(c->signature+c->index+1, &l);
4057 sig = strndup(c->signature + c->index + 1, l);
4061 free(c->peeked_signature);
4062 *contents = c->peeked_signature = sig;
4066 *type = SD_BUS_TYPE_ARRAY;
4071 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4072 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4078 r = signature_element_length(c->signature+c->index, &l);
4083 sig = strndup(c->signature + c->index + 1, l - 2);
4087 free(c->peeked_signature);
4088 *contents = c->peeked_signature = sig;
4092 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4097 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4101 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4104 if (c->item_size < 2)
4107 /* Look for the NUL delimiter that
4108 separates the payload from the
4109 signature. Since the body might be
4110 in a different part that then the
4111 signature we map byte by byte. */
4113 for (k = 2; k <= c->item_size; k++) {
4116 where = m->rindex + c->item_size - k;
4117 r = message_peek_body(m, &where, 1, k, &q);
4121 if (*(char*) q == 0)
4125 if (k > c->item_size)
4128 free(c->peeked_signature);
4129 c->peeked_signature = strndup((char*) q + 1, k - 1);
4130 if (!c->peeked_signature)
4133 if (!signature_is_valid(c->peeked_signature, true))
4136 *contents = c->peeked_signature;
4141 r = message_peek_body(m, &rindex, 1, 1, &q);
4146 r = message_peek_body(m, &rindex, 1, l+1, &q);
4150 if (!validate_signature(q, l))
4158 *type = SD_BUS_TYPE_VARIANT;
4173 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4174 struct bus_container *c;
4176 assert_return(m, -EINVAL);
4177 assert_return(m->sealed, -EPERM);
4180 message_reset_containers(m);
4183 c = message_get_container(m);
4185 c = message_get_container(m);
4187 c->offset_index = 0;
4189 m->rindex = c->begin;
4192 c->offset_index = 0;
4193 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4195 return !isempty(c->signature);
4198 static int message_read_ap(
4203 unsigned n_array, n_struct;
4204 TypeStack stack[BUS_CONTAINER_DEPTH];
4205 unsigned stack_ptr = 0;
4206 unsigned n_loop = 0;
4214 /* Ideally, we'd just call ourselves recursively on every
4215 * complex type. However, the state of a va_list that is
4216 * passed to a function is undefined after that function
4217 * returns. This means we need to docode the va_list linearly
4218 * in a single stackframe. We hence implement our own
4219 * home-grown stack in an array. */
4221 n_array = (unsigned) -1; /* length of current array entries */
4222 n_struct = strlen(types); /* length of current struct contents signature */
4229 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4230 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4236 r = sd_bus_message_exit_container(m);
4244 if (n_array != (unsigned) -1)
4253 case SD_BUS_TYPE_BYTE:
4254 case SD_BUS_TYPE_BOOLEAN:
4255 case SD_BUS_TYPE_INT16:
4256 case SD_BUS_TYPE_UINT16:
4257 case SD_BUS_TYPE_INT32:
4258 case SD_BUS_TYPE_UINT32:
4259 case SD_BUS_TYPE_INT64:
4260 case SD_BUS_TYPE_UINT64:
4261 case SD_BUS_TYPE_DOUBLE:
4262 case SD_BUS_TYPE_STRING:
4263 case SD_BUS_TYPE_OBJECT_PATH:
4264 case SD_BUS_TYPE_SIGNATURE:
4265 case SD_BUS_TYPE_UNIX_FD: {
4268 p = va_arg(ap, void*);
4269 r = sd_bus_message_read_basic(m, *t, p);
4282 case SD_BUS_TYPE_ARRAY: {
4285 r = signature_element_length(t + 1, &k);
4291 memcpy(s, t + 1, k);
4294 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4305 if (n_array == (unsigned) -1) {
4310 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4316 n_array = va_arg(ap, unsigned);
4321 case SD_BUS_TYPE_VARIANT: {
4324 s = va_arg(ap, const char *);
4328 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4338 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4343 n_struct = strlen(s);
4344 n_array = (unsigned) -1;
4349 case SD_BUS_TYPE_STRUCT_BEGIN:
4350 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4353 r = signature_element_length(t, &k);
4359 memcpy(s, t + 1, k - 2);
4362 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4372 if (n_array == (unsigned) -1) {
4377 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4383 n_array = (unsigned) -1;
4396 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4400 assert_return(m, -EINVAL);
4401 assert_return(m->sealed, -EPERM);
4402 assert_return(types, -EINVAL);
4404 va_start(ap, types);
4405 r = message_read_ap(m, types, ap);
4411 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4414 assert_return(m, -EINVAL);
4415 assert_return(m->sealed, -EPERM);
4416 assert_return(types, -EINVAL);
4423 case SD_BUS_TYPE_BYTE:
4424 case SD_BUS_TYPE_BOOLEAN:
4425 case SD_BUS_TYPE_INT16:
4426 case SD_BUS_TYPE_UINT16:
4427 case SD_BUS_TYPE_INT32:
4428 case SD_BUS_TYPE_UINT32:
4429 case SD_BUS_TYPE_INT64:
4430 case SD_BUS_TYPE_UINT64:
4431 case SD_BUS_TYPE_DOUBLE:
4432 case SD_BUS_TYPE_STRING:
4433 case SD_BUS_TYPE_OBJECT_PATH:
4434 case SD_BUS_TYPE_SIGNATURE:
4435 case SD_BUS_TYPE_UNIX_FD:
4437 r = sd_bus_message_read_basic(m, *types, NULL);
4441 r = sd_bus_message_skip(m, types + 1);
4447 case SD_BUS_TYPE_ARRAY: {
4450 r = signature_element_length(types + 1, &k);
4456 memcpy(s, types+1, k);
4459 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4464 r = sd_bus_message_skip(m, s);
4471 r = sd_bus_message_exit_container(m);
4476 r = sd_bus_message_skip(m, types + 1 + k);
4483 case SD_BUS_TYPE_VARIANT: {
4484 const char *contents;
4487 r = sd_bus_message_peek_type(m, &x, &contents);
4491 if (x != SD_BUS_TYPE_VARIANT)
4494 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4498 r = sd_bus_message_skip(m, contents);
4503 r = sd_bus_message_exit_container(m);
4507 r = sd_bus_message_skip(m, types + 1);
4514 case SD_BUS_TYPE_STRUCT_BEGIN:
4515 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4518 r = signature_element_length(types, &k);
4524 memcpy(s, types+1, k-2);
4527 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4531 r = sd_bus_message_skip(m, s);
4536 r = sd_bus_message_exit_container(m);
4541 r = sd_bus_message_skip(m, types + k);
4553 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4557 struct bus_container *c;
4563 assert_return(m, -EINVAL);
4564 assert_return(m->sealed, -EPERM);
4565 assert_return(bus_type_is_trivial(type), -EINVAL);
4566 assert_return(ptr, -EINVAL);
4567 assert_return(size, -EINVAL);
4568 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4570 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4574 c = message_get_container(m);
4576 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4577 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4581 sz = c->end - c->begin;
4583 align = bus_type_get_alignment(type);
4587 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4591 /* Zero length array, let's return some aligned
4592 * pointer that is not NULL */
4593 p = (uint8_t*) NULL + align;
4595 r = message_peek_body(m, &m->rindex, align, sz, &p);
4600 r = sd_bus_message_exit_container(m);
4604 *ptr = (const void*) p;
4610 message_quit_container(m);
4614 static int message_peek_fields(
4625 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4628 static int message_peek_field_uint32(
4640 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4643 /* identical for gvariant and dbus1 */
4645 r = message_peek_fields(m, ri, 4, 4, &q);
4650 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4655 static int message_peek_field_string(
4657 bool (*validate)(const char *p),
4669 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4674 r = message_peek_fields(m, ri, 1, item_size, &q);
4680 r = message_peek_field_uint32(m, ri, 4, &l);
4684 r = message_peek_fields(m, ri, 1, l+1, &q);
4690 if (!validate_nul(q, l))
4696 if (!validate_string(q, l))
4706 static int message_peek_field_signature(
4719 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4724 r = message_peek_fields(m, ri, 1, item_size, &q);
4730 r = message_peek_fields(m, ri, 1, 1, &q);
4735 r = message_peek_fields(m, ri, 1, l+1, &q);
4740 if (!validate_signature(q, l))
4749 static int message_skip_fields(
4752 uint32_t array_size,
4753 const char **signature) {
4755 size_t original_index;
4761 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4763 original_index = *ri;
4769 if (array_size != (uint32_t) -1 &&
4770 array_size <= *ri - original_index)
4777 if (t == SD_BUS_TYPE_STRING) {
4779 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4785 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4787 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4793 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4795 r = message_peek_field_signature(m, ri, 0, NULL);
4801 } else if (bus_type_is_basic(t)) {
4804 align = bus_type_get_alignment(t);
4805 k = bus_type_get_size(t);
4806 assert(align > 0 && k > 0);
4808 r = message_peek_fields(m, ri, align, k, NULL);
4814 } else if (t == SD_BUS_TYPE_ARRAY) {
4816 r = signature_element_length(*signature+1, &l);
4826 strncpy(sig, *signature + 1, l-1);
4829 alignment = bus_type_get_alignment(sig[0]);
4833 r = message_peek_field_uint32(m, ri, 0, &nas);
4836 if (nas > BUS_ARRAY_MAX_SIZE)
4839 r = message_peek_fields(m, ri, alignment, 0, NULL);
4843 r = message_skip_fields(m, ri, nas, (const char**) &s);
4848 (*signature) += 1 + l;
4850 } else if (t == SD_BUS_TYPE_VARIANT) {
4853 r = message_peek_field_signature(m, ri, 0, &s);
4857 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4863 } else if (t == SD_BUS_TYPE_STRUCT ||
4864 t == SD_BUS_TYPE_DICT_ENTRY) {
4866 r = signature_element_length(*signature, &l);
4873 strncpy(sig, *signature + 1, l-1);
4876 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4887 int bus_message_parse_fields(sd_bus_message *m) {
4890 uint32_t unix_fds = 0;
4891 bool unix_fds_set = false;
4892 void *offsets = NULL;
4893 unsigned n_offsets = 0;
4899 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4902 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4906 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4907 r = message_peek_fields(m, &ri, 1, sz, &q);
4911 framing = read_word_le(q, sz);
4912 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4914 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4918 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4922 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4927 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4928 _cleanup_free_ char *sig = NULL;
4929 const char *signature;
4931 size_t item_size = (size_t) -1;
4933 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4940 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4943 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4947 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4952 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4957 where = ri = ALIGN_TO(ri, 8);
4958 item_size = end - ri;
4959 r = message_peek_fields(m, &where, 1, item_size, &q);
4963 b = memrchr(q, 0, item_size);
4967 sig = strndup(b+1, item_size - (b+1-(char*) q));
4972 item_size = b - (char*) q;
4974 r = message_peek_field_signature(m, &ri, 0, &signature);
4980 case _BUS_MESSAGE_HEADER_INVALID:
4983 case BUS_MESSAGE_HEADER_PATH:
4988 if (!streq(signature, "o"))
4991 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
4994 case BUS_MESSAGE_HEADER_INTERFACE:
4999 if (!streq(signature, "s"))
5002 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5005 case BUS_MESSAGE_HEADER_MEMBER:
5010 if (!streq(signature, "s"))
5013 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5016 case BUS_MESSAGE_HEADER_ERROR_NAME:
5021 if (!streq(signature, "s"))
5024 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5026 m->error._need_free = -1;
5030 case BUS_MESSAGE_HEADER_DESTINATION:
5035 if (!streq(signature, "s"))
5038 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5041 case BUS_MESSAGE_HEADER_SENDER:
5046 if (!streq(signature, "s"))
5049 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5051 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5052 m->creds.unique_name = (char*) m->sender;
5053 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5059 case BUS_MESSAGE_HEADER_SIGNATURE: {
5063 if (m->root_container.signature)
5066 if (!streq(signature, "g"))
5069 r = message_peek_field_signature(m, &ri, item_size, &s);
5077 free(m->root_container.signature);
5078 m->root_container.signature = c;
5082 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5085 if (m->reply_cookie != 0)
5088 if (!streq(signature, "u"))
5091 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5095 m->reply_cookie = serial;
5097 if (m->reply_cookie == 0)
5103 case BUS_MESSAGE_HEADER_UNIX_FDS:
5107 if (!streq(signature, "u"))
5110 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5114 unix_fds_set = true;
5118 if (!BUS_MESSAGE_IS_GVARIANT(m))
5119 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5128 if (m->n_fds != unix_fds)
5131 switch (m->header->type) {
5133 case SD_BUS_MESSAGE_SIGNAL:
5134 if (!m->path || !m->interface || !m->member)
5138 case SD_BUS_MESSAGE_METHOD_CALL:
5140 if (!m->path || !m->member)
5145 case SD_BUS_MESSAGE_METHOD_RETURN:
5147 if (m->reply_cookie == 0)
5151 case SD_BUS_MESSAGE_METHOD_ERROR:
5153 if (m->reply_cookie == 0 || !m->error.name)
5158 /* Refuse non-local messages that claim they are local */
5159 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5161 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5163 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5166 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5168 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5169 r = build_struct_offsets(
5171 m->root_container.signature,
5172 BUS_MESSAGE_BODY_SIZE(m),
5173 &m->root_container.item_size,
5174 &m->root_container.offsets,
5175 &m->root_container.n_offsets);
5180 /* Try to read the error message, but if we can't it's a non-issue */
5181 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5182 sd_bus_message_read(m, "s", &m->error.message);
5187 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5188 assert_return(m, -EINVAL);
5189 assert_return(destination, -EINVAL);
5190 assert_return(!m->sealed, -EPERM);
5191 assert_return(!m->destination, -EEXIST);
5193 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5196 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5200 struct bus_body_part *part;
5206 total = BUS_MESSAGE_SIZE(m);
5212 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5213 MESSAGE_FOREACH_PART(part, i, m)
5214 e = mempcpy(e, part->data, part->size);
5216 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5224 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5230 r = sd_bus_message_enter_container(m, 'a', "s");
5237 r = sd_bus_message_read_basic(m, 's', &s);
5243 r = strv_extend(l, s);
5248 r = sd_bus_message_exit_container(m);
5255 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5259 assert_return(m, -EINVAL);
5260 assert_return(m->sealed, -EPERM);
5261 assert_return(l, -EINVAL);
5263 r = bus_message_read_strv_extend(m, &strv);
5273 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5275 const char *t = NULL;
5280 r = sd_bus_message_rewind(m, true);
5284 for (j = 0; j <= i; j++) {
5287 r = sd_bus_message_peek_type(m, &type, NULL);
5291 if (type != SD_BUS_TYPE_STRING &&
5292 type != SD_BUS_TYPE_OBJECT_PATH &&
5293 type != SD_BUS_TYPE_SIGNATURE)
5296 r = sd_bus_message_read_basic(m, type, &t);
5304 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5310 if (size < sizeof(struct bus_header))
5313 full = sizeof(struct bus_header) +
5314 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5316 return size >= full;
5319 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5325 if (h->endian == BUS_NATIVE_ENDIAN) {
5326 fs = h->fields_size;
5328 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5329 fs = bswap_32(h->fields_size);
5330 bs = bswap_32(h->body_size);
5334 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5338 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5339 assert_return(m, -EINVAL);
5341 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5344 return sd_bus_error_get_errno(&m->error);
5347 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5348 struct bus_container *c;
5350 assert_return(m, NULL);
5352 c = complete ? &m->root_container : message_get_container(m);
5353 return strempty(c->signature);
5356 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5357 bool done_something = false;
5360 assert_return(m, -EINVAL);
5361 assert_return(source, -EINVAL);
5362 assert_return(!m->sealed, -EPERM);
5363 assert_return(source->sealed, -EPERM);
5366 const char *contents;
5381 r = sd_bus_message_peek_type(source, &type, &contents);
5387 done_something = true;
5389 if (bus_type_is_container(type) > 0) {
5391 r = sd_bus_message_enter_container(source, type, contents);
5395 r = sd_bus_message_open_container(m, type, contents);
5399 r = sd_bus_message_copy(m, source, true);
5403 r = sd_bus_message_close_container(m);
5407 r = sd_bus_message_exit_container(source);
5414 r = sd_bus_message_read_basic(source, type, &basic);
5420 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5421 type == SD_BUS_TYPE_SIGNATURE ||
5422 type == SD_BUS_TYPE_STRING)
5423 r = sd_bus_message_append_basic(m, type, basic.string);
5425 r = sd_bus_message_append_basic(m, type, &basic);
5432 return done_something;
5435 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5440 assert_return(m, -EINVAL);
5441 assert_return(m->sealed, -EPERM);
5442 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5443 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5444 assert_return(type || contents, -EINVAL);
5445 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5447 r = sd_bus_message_peek_type(m, &t, &c);
5451 if (type != 0 && type != t)
5454 if (contents && !streq_ptr(contents, c))
5460 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5461 assert_return(m, NULL);
5466 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5467 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5475 switch ((*m)->header->type) {
5477 case SD_BUS_MESSAGE_SIGNAL:
5478 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5484 case SD_BUS_MESSAGE_METHOD_CALL:
5485 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5491 case SD_BUS_MESSAGE_METHOD_RETURN:
5492 case SD_BUS_MESSAGE_METHOD_ERROR:
5494 n = message_new(bus, (*m)->header->type);
5498 n->reply_cookie = (*m)->reply_cookie;
5499 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5503 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5504 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5508 n->error._need_free = -1;
5517 if ((*m)->destination && !n->destination) {
5518 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5523 if ((*m)->sender && !n->sender) {
5524 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5529 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5531 r = sd_bus_message_copy(n, *m, true);
5535 timeout = (*m)->timeout;
5536 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5537 timeout = BUS_DEFAULT_TIMEOUT;
5539 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5543 sd_bus_message_unref(*m);
5550 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5554 assert_return(!m->sealed, -EPERM);
5555 assert_return(!m->sender, -EPERM);
5557 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5560 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5561 assert_return(m, -EINVAL);
5562 assert_return(priority, -EINVAL);
5564 *priority = m->priority;
5568 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5569 assert_return(m, -EINVAL);
5570 assert_return(!m->sealed, -EPERM);
5572 m->priority = priority;