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 close_nointr_nofail(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);
140 sd_bus_unref(m->bus);
143 close_many(m->fds, m->n_fds);
147 if (m->iovec != m->iovec_fixed)
150 message_reset_containers(m);
151 free(m->root_container.signature);
152 free(m->root_container.offsets);
154 free(m->root_container.peeked_signature);
156 bus_creds_done(&m->creds);
160 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
162 size_t old_size, new_size, start;
169 old_size = sizeof(struct bus_header) + m->header->fields_size;
170 start = ALIGN_TO(old_size, align);
171 new_size = start + sz;
173 if (old_size == new_size)
174 return (uint8_t*) m->header + old_size;
176 if (new_size > (size_t) ((uint32_t) -1))
179 if (m->free_header) {
180 np = realloc(m->header, ALIGN8(new_size));
184 /* Initially, the header is allocated as part of of
185 * the sd_bus_message itself, let's replace it by
188 np = malloc(ALIGN8(new_size));
192 memcpy(np, m->header, sizeof(struct bus_header));
195 /* Zero out padding */
196 if (start > old_size)
197 memset((uint8_t*) np + old_size, 0, start - old_size);
201 m->header->fields_size = new_size - sizeof(struct bus_header);
203 /* Adjust quick access pointers */
204 m->path = adjust_pointer(m->path, op, old_size, m->header);
205 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
206 m->member = adjust_pointer(m->member, op, old_size, m->header);
207 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
208 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
209 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
211 m->free_header = true;
214 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
217 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
220 return (uint8_t*) np + start;
227 static int message_append_field_string(
239 /* dbus1 doesn't allow strings over 32bit, let's enforce this
240 * globally, to not risk convertability */
242 if (l > (size_t) (uint32_t) -1)
245 /* Signature "(yv)" where the variant contains "s" */
247 if (BUS_MESSAGE_IS_GVARIANT(m)) {
249 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
250 p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
262 *ret = (char*) p + 8;
265 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
266 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
275 ((uint32_t*) p)[1] = l;
276 memcpy(p + 8, s, l + 1);
279 *ret = (char*) p + 8;
285 static int message_append_field_signature(
296 /* dbus1 doesn't allow signatures over 32bit, let's enforce
297 * this globally, to not risk convertability */
302 /* Signature "(yv)" where the variant contains "g" */
304 if (BUS_MESSAGE_IS_GVARIANT(m))
305 /* For gvariant the serialization is the same as for normal strings */
306 return message_append_field_string(m, h, 'g', s, ret);
308 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
309 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
315 p[2] = SD_BUS_TYPE_SIGNATURE;
318 memcpy(p + 5, s, l + 1);
321 *ret = (const char*) p + 5;
327 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
332 if (BUS_MESSAGE_IS_GVARIANT(m)) {
333 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
335 p = message_extend_fields(m, 8, 1 + 7 + 4 + 1 + 1, true);
341 *((uint32_t*) (p + 8)) = x;
345 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
346 p = message_extend_fields(m, 8, 4 + 4, false);
352 p[2] = SD_BUS_TYPE_UINT32;
355 ((uint32_t*) p)[1] = x;
361 int bus_message_from_header(
367 const struct ucred *ucred,
370 sd_bus_message **ret) {
373 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;
430 m->bus = sd_bus_ref(bus);
436 int bus_message_from_malloc(
442 const struct ucred *ucred,
444 sd_bus_message **ret) {
450 r = bus_message_from_header(bus, buffer, length, fds, n_fds, ucred, label, 0, &m);
454 if (length != BUS_MESSAGE_SIZE(m)) {
459 sz = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
462 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
464 m->body.sealed = true;
469 m->iovec = m->iovec_fixed;
470 m->iovec[0].iov_base = buffer;
471 m->iovec[0].iov_len = length;
473 r = bus_message_parse_fields(m);
477 /* We take possession of the memory and fds now */
478 m->free_header = true;
489 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
492 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
497 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
498 m->header->endian = BUS_NATIVE_ENDIAN;
499 m->header->type = type;
500 m->header->version = bus ? bus->message_version : 1;
501 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
502 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
505 m->bus = sd_bus_ref(bus);
510 _public_ int sd_bus_message_new_signal(
513 const char *interface,
515 sd_bus_message **m) {
520 assert_return(!bus || 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(
552 const char *destination,
554 const char *interface,
556 sd_bus_message **m) {
561 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
562 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
563 assert_return(object_path_is_valid(path), -EINVAL);
564 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
565 assert_return(member_name_is_valid(member), -EINVAL);
566 assert_return(m, -EINVAL);
568 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
572 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
575 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
580 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
586 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
599 static int message_new_reply(
600 sd_bus_message *call,
602 sd_bus_message **m) {
607 assert_return(call, -EINVAL);
608 assert_return(call->sealed, -EPERM);
609 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
610 assert_return(!call->bus || call->bus->state != BUS_UNSET, -ENOTCONN);
611 assert_return(m, -EINVAL);
613 t = message_new(call->bus, type);
617 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
618 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
620 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_cookie);
625 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
630 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
631 t->enforced_reply_signature = call->enforced_reply_signature;
641 _public_ int sd_bus_message_new_method_return(
642 sd_bus_message *call,
643 sd_bus_message **m) {
645 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
648 _public_ int sd_bus_message_new_method_error(
649 sd_bus_message *call,
650 const sd_bus_error *e,
651 sd_bus_message **m) {
656 assert_return(sd_bus_error_is_set(e), -EINVAL);
657 assert_return(m, -EINVAL);
659 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
663 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
668 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
673 t->error._need_free = -1;
683 _public_ int sd_bus_message_new_method_errorf(
684 sd_bus_message *call,
690 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
693 assert_return(name, -EINVAL);
694 assert_return(m, -EINVAL);
696 va_start(ap, format);
697 bus_error_setfv(&error, name, format, ap);
700 return sd_bus_message_new_method_error(call, &error, m);
703 _public_ int sd_bus_message_new_method_errno(
704 sd_bus_message *call,
706 const sd_bus_error *p,
707 sd_bus_message **m) {
709 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
711 if (sd_bus_error_is_set(p))
712 return sd_bus_message_new_method_error(call, p, m);
714 sd_bus_error_set_errno(&berror, error);
716 return sd_bus_message_new_method_error(call, &berror, m);
719 _public_ int sd_bus_message_new_method_errnof(
720 sd_bus_message *call,
726 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
729 va_start(ap, format);
730 bus_error_set_errnofv(&berror, error, format, ap);
733 return sd_bus_message_new_method_error(call, &berror, m);
736 int bus_message_new_synthetic_error(
739 const sd_bus_error *e,
740 sd_bus_message **m) {
745 assert(sd_bus_error_is_set(e));
748 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
752 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
753 t->reply_cookie = cookie;
755 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_cookie);
759 if (bus && bus->unique_name) {
760 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
765 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
770 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
775 t->error._need_free = -1;
785 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
786 assert_return(m, NULL);
788 assert(m->n_ref > 0);
794 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
799 assert(m->n_ref > 0);
808 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
809 assert_return(m, -EINVAL);
810 assert_return(type, -EINVAL);
812 *type = m->header->type;
816 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
817 assert_return(m, -EINVAL);
818 assert_return(cookie, -EINVAL);
819 assert_return(m->header->serial != 0, -ENODATA);
821 *cookie = BUS_MESSAGE_COOKIE(m);
825 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
826 assert_return(m, -EINVAL);
827 assert_return(cookie, -EINVAL);
828 assert_return(m->reply_cookie != 0, -ENODATA);
830 *cookie = m->reply_cookie;
834 _public_ int sd_bus_message_get_no_reply(sd_bus_message *m) {
835 assert_return(m, -EINVAL);
837 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL ? !!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
840 _public_ int sd_bus_message_get_no_auto_start(sd_bus_message *m) {
841 assert_return(m, -EINVAL);
843 return !!(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
846 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
847 assert_return(m, NULL);
852 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
853 assert_return(m, NULL);
858 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
859 assert_return(m, NULL);
864 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
865 assert_return(m, NULL);
867 return m->destination;
870 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
871 assert_return(m, NULL);
876 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
877 assert_return(m, NULL);
878 assert_return(sd_bus_error_is_set(&m->error), NULL);
883 _public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
884 assert_return(m, -EINVAL);
885 assert_return(usec, -EINVAL);
886 assert_return(m->monotonic > 0, -ENODATA);
888 *usec = m->monotonic;
892 _public_ int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
893 assert_return(m, -EINVAL);
894 assert_return(usec, -EINVAL);
895 assert_return(m->realtime > 0, -ENODATA);
901 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
902 assert_return(m, -EINVAL);
903 assert_return(seqnum, -EINVAL);
904 assert_return(m->seqnum > 0, -ENODATA);
910 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
911 assert_return(m, NULL);
913 if (m->creds.mask == 0)
919 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
920 const char *interface,
921 const char *member) {
922 assert_return(m, -EINVAL);
924 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
927 if (interface && (!m->interface || !streq(m->interface, interface)))
930 if (member && (!m->member || !streq(m->member, member)))
936 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
937 const char *interface,
938 const char *member) {
939 assert_return(m, -EINVAL);
941 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
944 if (interface && (!m->interface || !streq(m->interface, interface)))
947 if (member && (!m->member || !streq(m->member, member)))
953 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
954 assert_return(m, -EINVAL);
956 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
959 if (name && (!m->error.name || !streq(m->error.name, name)))
965 _public_ int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
966 assert_return(m, -EINVAL);
967 assert_return(!m->sealed, -EPERM);
968 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
971 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
973 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
978 _public_ int sd_bus_message_set_no_auto_start(sd_bus_message *m, int b) {
979 assert_return(m, -EINVAL);
980 assert_return(!m->sealed, -EPERM);
983 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
985 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
990 static struct bus_container *message_get_container(sd_bus_message *m) {
993 if (m->n_containers == 0)
994 return &m->root_container;
996 assert(m->containers);
997 return m->containers + m->n_containers - 1;
1000 struct bus_body_part *message_append_part(sd_bus_message *m) {
1001 struct bus_body_part *part;
1008 if (m->n_body_parts <= 0) {
1012 assert(m->body_end);
1014 part = new0(struct bus_body_part, 1);
1020 m->body_end->next = part;
1030 static void part_zero(struct bus_body_part *part, size_t sz) {
1035 /* All other fields can be left in their defaults */
1036 assert(!part->data);
1037 assert(part->memfd < 0);
1040 part->is_zero = true;
1041 part->sealed = true;
1044 static int part_make_space(
1045 struct sd_bus_message *m,
1046 struct bus_body_part *part,
1055 assert(!part->sealed);
1060 if (!part->data && part->memfd < 0)
1061 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1063 if (part->memfd >= 0) {
1065 if (part->allocated == 0 || sz > part->allocated) {
1066 uint64_t new_allocated;
1068 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1069 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &new_allocated);
1075 part->allocated = new_allocated;
1078 if (!part->data || sz > part->mapped) {
1081 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1082 if (part->mapped <= 0)
1083 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1085 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1087 if (n == MAP_FAILED) {
1096 part->munmap_this = true;
1098 if (part->allocated == 0 || sz > part->allocated) {
1099 size_t new_allocated;
1101 new_allocated = sz > 0 ? 2 * sz : 64;
1102 n = realloc(part->data, new_allocated);
1109 part->allocated = new_allocated;
1110 part->free_this = true;
1115 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1121 static int message_add_offset(sd_bus_message *m, size_t offset) {
1122 struct bus_container *c;
1125 assert(BUS_MESSAGE_IS_GVARIANT(m));
1127 /* Add offset to current container, unless this is the first
1128 * item in it, which will have the 0 offset, which we can
1130 c = message_get_container(m);
1132 if (!c->need_offsets)
1135 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1138 c->offsets[c->n_offsets++] = offset;
1142 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1143 struct bus_container *c;
1150 /* Update counters */
1151 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1154 *c->array_size += expand;
1158 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1159 size_t start_body, end_body, padding, added;
1170 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1171 end_body = start_body + sz;
1173 padding = start_body - m->header->body_size;
1174 added = padding + sz;
1176 /* Check for 32bit overflows */
1177 if (end_body > (size_t) ((uint32_t) -1)) {
1183 struct bus_body_part *part = NULL;
1187 m->n_body_parts <= 0 ||
1188 m->body_end->sealed ||
1189 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1193 part = message_append_part(m);
1197 part_zero(part, padding);
1200 part = message_append_part(m);
1204 r = part_make_space(m, part, sz, &p);
1208 struct bus_container *c;
1210 size_t os, start_part, end_part;
1216 start_part = ALIGN_TO(part->size, align);
1217 end_part = start_part + sz;
1219 r = part_make_space(m, part, end_part, &p);
1224 memset(p, 0, padding);
1225 p = (uint8_t*) p + padding;
1228 /* Readjust pointers */
1229 for (c = m->containers; c < m->containers + m->n_containers; c++)
1230 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1232 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1235 /* Return something that is not NULL and is aligned */
1236 p = (uint8_t *) NULL + align;
1238 m->header->body_size = end_body;
1239 message_extend_containers(m, added);
1242 r = message_add_offset(m, end_body);
1252 static int message_push_fd(sd_bus_message *m, int fd) {
1263 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1267 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1270 close_nointr_nofail(copy);
1275 m->fds[m->n_fds] = copy;
1281 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1282 _cleanup_close_ int fd = -1;
1283 struct bus_container *c;
1287 assert_return(m, -EINVAL);
1288 assert_return(!m->sealed, -EPERM);
1289 assert_return(bus_type_is_basic(type), -EINVAL);
1290 assert_return(!m->poisoned, -ESTALE);
1292 c = message_get_container(m);
1294 if (c->signature && c->signature[c->index]) {
1295 /* Container signature is already set */
1297 if (c->signature[c->index] != type)
1302 /* Maybe we can append to the signature? But only if this is the top-level container*/
1303 if (c->enclosing != 0)
1306 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1313 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1319 case SD_BUS_TYPE_SIGNATURE:
1320 case SD_BUS_TYPE_STRING:
1323 /* Fall through... */
1324 case SD_BUS_TYPE_OBJECT_PATH:
1332 case SD_BUS_TYPE_BOOLEAN:
1334 u8 = p && *(int*) p;
1340 case SD_BUS_TYPE_UNIX_FD:
1345 fd = message_push_fd(m, *(int*) p);
1356 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1357 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1364 a = message_extend_body(m, align, sz, true);
1371 *stored = (const uint8_t*) a;
1378 case SD_BUS_TYPE_STRING:
1379 /* To make things easy we'll serialize a NULL string
1380 * into the empty string */
1383 /* Fall through... */
1384 case SD_BUS_TYPE_OBJECT_PATH:
1390 sz = 4 + strlen(p) + 1;
1393 case SD_BUS_TYPE_SIGNATURE:
1398 sz = 1 + strlen(p) + 1;
1401 case SD_BUS_TYPE_BOOLEAN:
1403 u32 = p && *(int*) p;
1409 case SD_BUS_TYPE_UNIX_FD:
1414 fd = message_push_fd(m, *(int*) p);
1425 align = bus_type_get_alignment(type);
1426 sz = bus_type_get_size(type);
1433 a = message_extend_body(m, align, sz, false);
1437 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1438 *(uint32_t*) a = sz - 5;
1439 memcpy((uint8_t*) a + 4, p, sz - 4);
1442 *stored = (const uint8_t*) a + 4;
1444 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1445 *(uint8_t*) a = sz - 2;
1446 memcpy((uint8_t*) a + 1, p, sz - 1);
1449 *stored = (const uint8_t*) a + 1;
1458 if (type == SD_BUS_TYPE_UNIX_FD)
1461 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1468 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1469 return message_append_basic(m, type, p, NULL);
1472 _public_ int sd_bus_message_append_string_space(
1477 struct bus_container *c;
1480 assert_return(m, -EINVAL);
1481 assert_return(s, -EINVAL);
1482 assert_return(!m->sealed, -EPERM);
1483 assert_return(!m->poisoned, -ESTALE);
1485 c = message_get_container(m);
1487 if (c->signature && c->signature[c->index]) {
1488 /* Container signature is already set */
1490 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1495 /* Maybe we can append to the signature? But only if this is the top-level container*/
1496 if (c->enclosing != 0)
1499 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1506 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1507 a = message_extend_body(m, 1, size + 1, true);
1513 a = message_extend_body(m, 4, 4 + size + 1, false);
1517 *(uint32_t*) a = size;
1523 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1529 _public_ int sd_bus_message_append_string_iovec(
1531 const struct iovec *iov,
1539 assert_return(m, -EINVAL);
1540 assert_return(!m->sealed, -EPERM);
1541 assert_return(iov || n == 0, -EINVAL);
1542 assert_return(!m->poisoned, -ESTALE);
1544 size = IOVEC_TOTAL_SIZE(iov, n);
1546 r = sd_bus_message_append_string_space(m, size, &p);
1550 for (i = 0; i < n; i++) {
1552 if (iov[i].iov_base)
1553 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1555 memset(p, ' ', iov[i].iov_len);
1557 p += iov[i].iov_len;
1563 static int bus_message_open_array(
1565 struct bus_container *c,
1566 const char *contents,
1567 uint32_t **array_size,
1569 bool *need_offsets) {
1579 assert(need_offsets);
1581 if (!signature_is_single(contents, true))
1584 if (c->signature && c->signature[c->index]) {
1586 /* Verify the existing signature */
1588 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1591 if (!startswith(c->signature + c->index + 1, contents))
1594 nindex = c->index + 1 + strlen(contents);
1598 if (c->enclosing != 0)
1601 /* Extend the existing signature */
1603 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1609 nindex = e - c->signature;
1612 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1613 alignment = bus_gvariant_get_alignment(contents);
1617 /* Add alignment padding and add to offset list */
1618 if (!message_extend_body(m, alignment, 0, false))
1621 r = bus_gvariant_is_fixed_size(contents);
1625 *begin = m->header->body_size;
1626 *need_offsets = r == 0;
1630 struct bus_body_part *o;
1632 alignment = bus_type_get_alignment(contents[0]);
1636 a = message_extend_body(m, 4, 4, false);
1641 op = m->body_end->data;
1642 os = m->body_end->size;
1644 /* Add alignment between size and first element */
1645 if (!message_extend_body(m, alignment, 0, false))
1648 /* location of array size might have changed so let's readjust a */
1649 if (o == m->body_end)
1650 a = adjust_pointer(a, op, os, m->body_end->data);
1656 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1662 static int bus_message_open_variant(
1664 struct bus_container *c,
1665 const char *contents) {
1671 if (!signature_is_single(contents, false))
1674 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1677 if (c->signature && c->signature[c->index]) {
1679 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1685 if (c->enclosing != 0)
1688 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1695 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1696 /* Variants are always aligned to 8 */
1698 if (!message_extend_body(m, 8, 0, false))
1705 l = strlen(contents);
1706 a = message_extend_body(m, 1, 1 + l + 1, false);
1711 memcpy((uint8_t*) a + 1, contents, l + 1);
1714 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1720 static int bus_message_open_struct(
1722 struct bus_container *c,
1723 const char *contents,
1725 bool *need_offsets) {
1734 assert(need_offsets);
1736 if (!signature_is_valid(contents, false))
1739 if (c->signature && c->signature[c->index]) {
1742 l = strlen(contents);
1744 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1745 !startswith(c->signature + c->index + 1, contents) ||
1746 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1749 nindex = c->index + 1 + l + 1;
1753 if (c->enclosing != 0)
1756 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1762 nindex = e - c->signature;
1765 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1768 alignment = bus_gvariant_get_alignment(contents);
1772 if (!message_extend_body(m, alignment, 0, false))
1775 r = bus_gvariant_is_fixed_size(contents);
1779 *begin = m->header->body_size;
1780 *need_offsets = r == 0;
1782 /* Align contents to 8 byte boundary */
1783 if (!message_extend_body(m, 8, 0, false))
1787 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1793 static int bus_message_open_dict_entry(
1795 struct bus_container *c,
1796 const char *contents,
1798 bool *need_offsets) {
1806 assert(need_offsets);
1808 if (!signature_is_pair(contents))
1811 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1814 if (c->signature && c->signature[c->index]) {
1817 l = strlen(contents);
1819 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1820 !startswith(c->signature + c->index + 1, contents) ||
1821 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1826 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1829 alignment = bus_gvariant_get_alignment(contents);
1833 if (!message_extend_body(m, alignment, 0, false))
1836 r = bus_gvariant_is_fixed_size(contents);
1840 *begin = m->header->body_size;
1841 *need_offsets = r == 0;
1843 /* Align contents to 8 byte boundary */
1844 if (!message_extend_body(m, 8, 0, false))
1851 _public_ int sd_bus_message_open_container(
1854 const char *contents) {
1856 struct bus_container *c, *w;
1857 uint32_t *array_size = NULL;
1859 size_t before, begin;
1860 bool need_offsets = false;
1863 assert_return(m, -EINVAL);
1864 assert_return(!m->sealed, -EPERM);
1865 assert_return(contents, -EINVAL);
1866 assert_return(!m->poisoned, -ESTALE);
1868 /* Make sure we have space for one more container */
1869 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1874 c = message_get_container(m);
1876 signature = strdup(contents);
1882 /* Save old index in the parent container, in case we have to
1883 * abort this container */
1884 c->saved_index = c->index;
1885 before = m->header->body_size;
1887 if (type == SD_BUS_TYPE_ARRAY)
1888 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1889 else if (type == SD_BUS_TYPE_VARIANT)
1890 r = bus_message_open_variant(m, c, contents);
1891 else if (type == SD_BUS_TYPE_STRUCT)
1892 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1893 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1894 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1903 /* OK, let's fill it in */
1904 w = m->containers + m->n_containers++;
1905 w->enclosing = type;
1906 w->signature = signature;
1908 w->array_size = array_size;
1911 w->n_offsets = w->offsets_allocated = 0;
1913 w->need_offsets = need_offsets;
1918 static size_t determine_word_size(size_t sz, size_t extra) {
1919 if (sz + extra <= 0xFF)
1921 else if (sz + extra*2 <= 0xFFFF)
1923 else if (sz + extra*4 <= 0xFFFFFFFF)
1929 static size_t read_word_le(void *p, size_t sz) {
1939 return *(uint8_t*) p;
1944 return le16toh(x.u16);
1946 return le32toh(x.u32);
1948 return le64toh(x.u64);
1950 assert_not_reached("unknown word width");
1953 static void write_word_le(void *p, size_t sz, size_t value) {
1961 assert(sz == 8 || (value < (1ULL << (sz*8))));
1964 *(uint8_t*) p = value;
1967 x.u16 = htole16((uint16_t) value);
1969 x.u32 = htole32((uint32_t) value);
1971 x.u64 = htole64((uint64_t) value);
1973 assert_not_reached("unknown word width");
1978 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1983 if (!BUS_MESSAGE_IS_GVARIANT(m))
1986 if (c->need_offsets) {
1987 size_t payload, sz, i;
1990 /* Variable-width arrays */
1992 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
1993 sz = determine_word_size(payload, c->n_offsets);
1995 a = message_extend_body(m, 1, sz * c->n_offsets, true);
1999 for (i = 0; i < c->n_offsets; i++)
2000 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2004 /* Fixed-width or empty arrays */
2006 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
2014 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2021 if (!BUS_MESSAGE_IS_GVARIANT(m))
2024 l = strlen(c->signature);
2026 a = message_extend_body(m, 1, 1 + l, true);
2031 memcpy(a+1, c->signature, l);
2036 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2037 size_t n_variable = 0;
2046 if (!BUS_MESSAGE_IS_GVARIANT(m))
2049 p = strempty(c->signature);
2053 r = signature_element_length(p, &n);
2062 r = bus_gvariant_is_fixed_size(t);
2067 assert(!c->need_offsets || i <= c->n_offsets);
2069 /* We need to add an offset for each item that has a
2070 * variable size and that is not the last one in the
2072 if (r == 0 && p[n] != 0)
2079 assert(!c->need_offsets || i == c->n_offsets);
2080 assert(c->need_offsets || n_variable == 0);
2082 if (n_variable <= 0) {
2083 a = message_extend_body(m, 1, 0, add_offset);
2090 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2092 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2094 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2098 p = strempty(c->signature);
2099 for (i = 0, j = 0; i < c->n_offsets; i++) {
2103 r = signature_element_length(p, &n);
2114 r = bus_gvariant_is_fixed_size(t);
2117 if (r > 0 || p[0] == 0)
2121 k = n_variable - 1 - j;
2123 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2132 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2133 struct bus_container *c;
2136 assert_return(m, -EINVAL);
2137 assert_return(!m->sealed, -EPERM);
2138 assert_return(m->n_containers > 0, -EINVAL);
2139 assert_return(!m->poisoned, -ESTALE);
2141 c = message_get_container(m);
2143 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2144 if (c->signature && c->signature[c->index] != 0)
2149 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2150 r = bus_message_close_array(m, c);
2151 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2152 r = bus_message_close_variant(m, c);
2153 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2154 r = bus_message_close_struct(m, c, true);
2156 assert_not_reached("Unknown container type");
2170 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2177 stack[*i].types = types;
2178 stack[*i].n_struct = n_struct;
2179 stack[*i].n_array = n_array;
2185 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2196 *types = stack[*i].types;
2197 *n_struct = stack[*i].n_struct;
2198 *n_array = stack[*i].n_array;
2203 int bus_message_append_ap(
2208 unsigned n_array, n_struct;
2209 TypeStack stack[BUS_CONTAINER_DEPTH];
2210 unsigned stack_ptr = 0;
2218 n_array = (unsigned) -1;
2219 n_struct = strlen(types);
2224 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2225 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2231 r = sd_bus_message_close_container(m);
2239 if (n_array != (unsigned) -1)
2248 case SD_BUS_TYPE_BYTE: {
2251 x = (uint8_t) va_arg(ap, int);
2252 r = sd_bus_message_append_basic(m, *t, &x);
2256 case SD_BUS_TYPE_BOOLEAN:
2257 case SD_BUS_TYPE_INT32:
2258 case SD_BUS_TYPE_UINT32:
2259 case SD_BUS_TYPE_UNIX_FD: {
2262 /* We assume a boolean is the same as int32_t */
2263 assert_cc(sizeof(int32_t) == sizeof(int));
2265 x = va_arg(ap, uint32_t);
2266 r = sd_bus_message_append_basic(m, *t, &x);
2270 case SD_BUS_TYPE_INT16:
2271 case SD_BUS_TYPE_UINT16: {
2274 x = (uint16_t) va_arg(ap, int);
2275 r = sd_bus_message_append_basic(m, *t, &x);
2279 case SD_BUS_TYPE_INT64:
2280 case SD_BUS_TYPE_UINT64:
2281 case SD_BUS_TYPE_DOUBLE: {
2284 x = va_arg(ap, uint64_t);
2285 r = sd_bus_message_append_basic(m, *t, &x);
2289 case SD_BUS_TYPE_STRING:
2290 case SD_BUS_TYPE_OBJECT_PATH:
2291 case SD_BUS_TYPE_SIGNATURE: {
2294 x = va_arg(ap, const char*);
2295 r = sd_bus_message_append_basic(m, *t, x);
2299 case SD_BUS_TYPE_ARRAY: {
2302 r = signature_element_length(t + 1, &k);
2308 memcpy(s, t + 1, k);
2311 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2316 if (n_array == (unsigned) -1) {
2321 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2327 n_array = va_arg(ap, unsigned);
2332 case SD_BUS_TYPE_VARIANT: {
2335 s = va_arg(ap, const char*);
2339 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2343 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2348 n_struct = strlen(s);
2349 n_array = (unsigned) -1;
2354 case SD_BUS_TYPE_STRUCT_BEGIN:
2355 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2358 r = signature_element_length(t, &k);
2365 memcpy(s, t + 1, k - 2);
2368 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2373 if (n_array == (unsigned) -1) {
2378 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2384 n_array = (unsigned) -1;
2400 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2404 assert_return(m, -EINVAL);
2405 assert_return(types, -EINVAL);
2406 assert_return(!m->sealed, -EPERM);
2407 assert_return(!m->poisoned, -ESTALE);
2409 va_start(ap, types);
2410 r = bus_message_append_ap(m, types, ap);
2416 _public_ int sd_bus_message_append_array_space(
2426 assert_return(m, -EINVAL);
2427 assert_return(!m->sealed, -EPERM);
2428 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2429 assert_return(ptr || size == 0, -EINVAL);
2430 assert_return(!m->poisoned, -ESTALE);
2432 /* alignment and size of the trivial types (except bool) is
2433 * identical for gvariant and dbus1 marshalling */
2434 align = bus_type_get_alignment(type);
2435 sz = bus_type_get_size(type);
2437 assert_se(align > 0);
2443 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2447 a = message_extend_body(m, align, size, false);
2451 r = sd_bus_message_close_container(m);
2459 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2466 assert_return(m, -EINVAL);
2467 assert_return(!m->sealed, -EPERM);
2468 assert_return(bus_type_is_trivial(type), -EINVAL);
2469 assert_return(ptr || size == 0, -EINVAL);
2470 assert_return(!m->poisoned, -ESTALE);
2472 r = sd_bus_message_append_array_space(m, type, size, &p);
2477 memcpy(p, ptr, size);
2482 _public_ int sd_bus_message_append_array_iovec(
2485 const struct iovec *iov,
2493 assert_return(m, -EINVAL);
2494 assert_return(!m->sealed, -EPERM);
2495 assert_return(bus_type_is_trivial(type), -EINVAL);
2496 assert_return(iov || n == 0, -EINVAL);
2497 assert_return(!m->poisoned, -ESTALE);
2499 size = IOVEC_TOTAL_SIZE(iov, n);
2501 r = sd_bus_message_append_array_space(m, type, size, &p);
2505 for (i = 0; i < n; i++) {
2507 if (iov[i].iov_base)
2508 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2510 memset(p, 0, iov[i].iov_len);
2512 p = (uint8_t*) p + iov[i].iov_len;
2518 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2521 _cleanup_close_ int copy_fd = -1;
2522 struct bus_body_part *part;
2534 if (!bus_type_is_trivial(type))
2539 r = sd_memfd_set_sealed(memfd, true);
2543 copy_fd = sd_memfd_dup_fd(memfd);
2547 r = sd_memfd_get_size(memfd, &size);
2551 align = bus_type_get_alignment(type);
2552 sz = bus_type_get_size(type);
2554 assert_se(align > 0);
2560 if (size > (uint64_t) (uint32_t) -1)
2563 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2567 a = message_extend_body(m, align, 0, false);
2571 part = message_append_part(m);
2575 part->memfd = copy_fd;
2576 part->sealed = true;
2580 m->header->body_size += size;
2581 message_extend_containers(m, size);
2583 return sd_bus_message_close_container(m);
2586 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
2587 _cleanup_close_ int copy_fd = -1;
2588 struct bus_body_part *part;
2589 struct bus_container *c;
2594 assert_return(m, -EINVAL);
2595 assert_return(memfd, -EINVAL);
2596 assert_return(!m->sealed, -EPERM);
2597 assert_return(!m->poisoned, -ESTALE);
2599 r = sd_memfd_set_sealed(memfd, true);
2603 copy_fd = sd_memfd_dup_fd(memfd);
2607 r = sd_memfd_get_size(memfd, &size);
2611 /* We require this to be NUL terminated */
2615 if (size > (uint64_t) (uint32_t) -1)
2618 c = message_get_container(m);
2619 if (c->signature && c->signature[c->index]) {
2620 /* Container signature is already set */
2622 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2627 /* Maybe we can append to the signature? But only if this is the top-level container*/
2628 if (c->enclosing != 0)
2631 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2638 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2639 a = message_extend_body(m, 4, 4, false);
2643 *(uint32_t*) a = size - 1;
2646 part = message_append_part(m);
2650 part->memfd = copy_fd;
2651 part->sealed = true;
2655 m->header->body_size += size;
2656 message_extend_containers(m, size);
2658 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2659 r = message_add_offset(m, m->header->body_size);
2666 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2672 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2676 assert_return(m, -EINVAL);
2677 assert_return(!m->sealed, -EPERM);
2678 assert_return(!m->poisoned, -ESTALE);
2680 r = sd_bus_message_open_container(m, 'a', "s");
2684 STRV_FOREACH(i, l) {
2685 r = sd_bus_message_append_basic(m, 's', *i);
2690 return sd_bus_message_close_container(m);
2693 static int bus_message_close_header(sd_bus_message *m) {
2699 if (!BUS_MESSAGE_IS_GVARIANT(m))
2702 if (m->n_header_offsets < 1)
2705 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2707 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2709 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2713 for (i = 0; i < m->n_header_offsets; i++)
2714 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2719 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2720 struct bus_body_part *part;
2730 if (m->n_containers > 0)
2736 /* In vtables the return signature of method calls is listed,
2737 * let's check if they match if this is a response */
2738 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2739 m->enforced_reply_signature &&
2740 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2743 /* If gvariant marshalling is used we need to close the body structure */
2744 r = bus_message_close_struct(m, &m->root_container, false);
2748 /* If there's a non-trivial signature set, then add it in here */
2749 if (!isempty(m->root_container.signature)) {
2750 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2756 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2761 r = bus_message_close_header(m);
2765 m->header->serial = (uint32_t) cookie;
2766 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2768 /* Add padding at the end of the fields part, since we know
2769 * the body needs to start at an 8 byte alignment. We made
2770 * sure we allocated enough space for this, so all we need to
2771 * do here is to zero it out. */
2772 l = BUS_MESSAGE_FIELDS_SIZE(m);
2775 memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
2777 /* If this is something we can send as memfd, then let's seal
2778 the memfd now. Note that we can send memfds as payload only
2779 for directed messages, and not for broadcasts. */
2780 if (m->destination && m->bus && m->bus->use_memfd) {
2781 MESSAGE_FOREACH_PART(part, i, m)
2782 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2785 /* Try to seal it if that makes
2786 * sense. First, unmap our own map to
2787 * make sure we don't keep it busy. */
2788 bus_body_part_unmap(part);
2790 /* Then, sync up real memfd size */
2792 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &sz) < 0)
2795 /* Finally, try to seal */
2796 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
2797 part->sealed = true;
2801 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2802 m->root_container.index = 0;
2803 m->root_container.offset_index = 0;
2804 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2811 int bus_body_part_map(struct bus_body_part *part) {
2820 if (part->size <= 0)
2823 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2824 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2825 static const uint8_t zeroes[7] = { };
2826 part->data = (void*) zeroes;
2830 psz = PAGE_ALIGN(part->size);
2832 if (part->memfd >= 0)
2833 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2834 else if (part->is_zero)
2835 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2839 if (p == MAP_FAILED)
2844 part->munmap_this = true;
2849 void bus_body_part_unmap(struct bus_body_part *part) {
2853 if (part->memfd < 0)
2859 if (!part->munmap_this)
2862 assert_se(munmap(part->data, part->mapped) == 0);
2866 part->munmap_this = false;
2871 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2872 size_t k, start, end;
2877 start = ALIGN_TO((size_t) *rindex, align);
2878 end = start + nbytes;
2883 /* Verify that padding is 0 */
2884 for (k = *rindex; k < start; k++)
2885 if (((const uint8_t*) p)[k] != 0)
2889 *r = (uint8_t*) p + start;
2896 static bool message_end_of_signature(sd_bus_message *m) {
2897 struct bus_container *c;
2901 c = message_get_container(m);
2902 return !c->signature || c->signature[c->index] == 0;
2905 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2906 struct bus_container *c;
2910 c = message_get_container(m);
2911 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2914 if (BUS_MESSAGE_IS_GVARIANT(m))
2915 return index >= c->end;
2917 assert(c->array_size);
2918 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2922 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2923 assert_return(m, -EINVAL);
2924 assert_return(m->sealed, -EPERM);
2926 if (complete && m->n_containers > 0)
2929 if (message_end_of_signature(m))
2932 if (message_end_of_array(m, m->rindex))
2938 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2939 struct bus_body_part *part;
2945 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2946 part = m->cached_rindex_part;
2947 begin = m->cached_rindex_part_begin;
2957 if (index + sz <= begin + part->size) {
2959 r = bus_body_part_map(part);
2964 *p = (uint8_t*) part->data + index - begin;
2966 m->cached_rindex_part = part;
2967 m->cached_rindex_part_begin = begin;
2972 begin += part->size;
2979 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2986 if (!BUS_MESSAGE_IS_GVARIANT(m))
2989 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2992 sz = bus_gvariant_get_size(c->signature);
2996 if (c->offset_index+1 >= c->n_offsets)
2999 /* Variable-size array */
3001 alignment = bus_gvariant_get_alignment(c->signature);
3002 assert(alignment > 0);
3004 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3005 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3008 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3011 /* Fixed-size array */
3012 *rindex = c->begin + (c->offset_index+1) * sz;
3018 } else if (c->enclosing == 0 ||
3019 c->enclosing == SD_BUS_TYPE_STRUCT ||
3020 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3025 if (c->offset_index+1 >= c->n_offsets)
3028 r = signature_element_length(c->signature + c->index, &n);
3032 r = signature_element_length(c->signature + c->index + n, &j);
3037 memcpy(t, c->signature + c->index + n, j);
3040 alignment = bus_gvariant_get_alignment(t);
3043 assert(alignment > 0);
3045 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3046 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3050 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3053 assert_not_reached("Unknown container type");
3058 /* Reached the end */
3065 static int message_peek_body(
3072 size_t k, start, end, padding;
3073 struct bus_body_part *part;
3080 start = ALIGN_TO((size_t) *rindex, align);
3081 padding = start - *rindex;
3082 end = start + nbytes;
3084 if (end > BUS_MESSAGE_BODY_SIZE(m))
3087 part = find_part(m, *rindex, padding, (void**) &q);
3092 /* Verify padding */
3093 for (k = 0; k < padding; k++)
3098 part = find_part(m, start, nbytes, (void**) &q);
3099 if (!part || (nbytes > 0 && !q))
3110 static bool validate_nul(const char *s, size_t l) {
3112 /* Check for NUL chars in the string */
3113 if (memchr(s, 0, l))
3116 /* Check for NUL termination */
3123 static bool validate_string(const char *s, size_t l) {
3125 if (!validate_nul(s, l))
3128 /* Check if valid UTF8 */
3129 if (!utf8_is_valid(s))
3135 static bool validate_signature(const char *s, size_t l) {
3137 if (!validate_nul(s, l))
3140 /* Check if valid signature */
3141 if (!signature_is_valid(s, true))
3147 static bool validate_object_path(const char *s, size_t l) {
3149 if (!validate_nul(s, l))
3152 if (!object_path_is_valid(s))
3158 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3159 struct bus_container *c;
3164 assert_return(m, -EINVAL);
3165 assert_return(m->sealed, -EPERM);
3166 assert_return(bus_type_is_basic(type), -EINVAL);
3168 if (message_end_of_signature(m))
3171 if (message_end_of_array(m, m->rindex))
3174 c = message_get_container(m);
3175 if (c->signature[c->index] != type)
3180 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3182 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3185 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3189 if (type == SD_BUS_TYPE_STRING)
3190 ok = validate_string(q, c->item_size-1);
3191 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3192 ok = validate_object_path(q, c->item_size-1);
3194 ok = validate_signature(q, c->item_size-1);
3200 *(const char**) p = q;
3204 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3206 if ((size_t) sz != c->item_size)
3209 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3212 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3218 case SD_BUS_TYPE_BYTE:
3220 *(uint8_t*) p = *(uint8_t*) q;
3223 case SD_BUS_TYPE_BOOLEAN:
3225 *(int*) p = !!*(uint8_t*) q;
3228 case SD_BUS_TYPE_INT16:
3229 case SD_BUS_TYPE_UINT16:
3231 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3234 case SD_BUS_TYPE_INT32:
3235 case SD_BUS_TYPE_UINT32:
3237 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3240 case SD_BUS_TYPE_INT64:
3241 case SD_BUS_TYPE_UINT64:
3242 case SD_BUS_TYPE_DOUBLE:
3244 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3247 case SD_BUS_TYPE_UNIX_FD: {
3250 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3255 *(int*) p = m->fds[j];
3261 assert_not_reached("unexpected type");
3265 r = container_next_item(m, c, &rindex);
3272 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3276 r = message_peek_body(m, &rindex, 4, 4, &q);
3280 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3281 r = message_peek_body(m, &rindex, 1, l+1, &q);
3285 if (type == SD_BUS_TYPE_OBJECT_PATH)
3286 ok = validate_object_path(q, l);
3288 ok = validate_string(q, l);
3293 *(const char**) p = q;
3295 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3298 r = message_peek_body(m, &rindex, 1, 1, &q);
3303 r = message_peek_body(m, &rindex, 1, l+1, &q);
3307 if (!validate_signature(q, l))
3311 *(const char**) p = q;
3316 align = bus_type_get_alignment(type);
3319 sz = bus_type_get_size(type);
3322 r = message_peek_body(m, &rindex, align, sz, &q);
3328 case SD_BUS_TYPE_BYTE:
3330 *(uint8_t*) p = *(uint8_t*) q;
3333 case SD_BUS_TYPE_BOOLEAN:
3335 *(int*) p = !!*(uint32_t*) q;
3338 case SD_BUS_TYPE_INT16:
3339 case SD_BUS_TYPE_UINT16:
3341 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3344 case SD_BUS_TYPE_INT32:
3345 case SD_BUS_TYPE_UINT32:
3347 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3350 case SD_BUS_TYPE_INT64:
3351 case SD_BUS_TYPE_UINT64:
3352 case SD_BUS_TYPE_DOUBLE:
3354 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3357 case SD_BUS_TYPE_UNIX_FD: {
3360 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3365 *(int*) p = m->fds[j];
3370 assert_not_reached("Unknown basic type...");
3377 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3383 static int bus_message_enter_array(
3385 struct bus_container *c,
3386 const char *contents,
3387 uint32_t **array_size,
3390 size_t *n_offsets) {
3404 if (!signature_is_single(contents, true))
3407 if (!c->signature || c->signature[c->index] == 0)
3410 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3413 if (!startswith(c->signature + c->index + 1, contents))
3418 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3421 r = message_peek_body(m, &rindex, 4, 4, &q);
3425 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3428 alignment = bus_type_get_alignment(contents[0]);
3432 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3436 *array_size = (uint32_t*) q;
3438 } else if (c->item_size <= 0) {
3440 /* gvariant: empty array */
3445 } else if (bus_gvariant_is_fixed_size(contents)) {
3447 /* gvariant: fixed length array */
3448 *item_size = bus_gvariant_get_size(contents);
3453 size_t where, p = 0, framing, sz;
3456 /* gvariant: variable length array */
3457 sz = determine_word_size(c->item_size, 0);
3459 where = rindex + c->item_size - sz;
3460 r = message_peek_body(m, &where, 1, sz, &q);
3464 framing = read_word_le(q, sz);
3465 if (framing > c->item_size - sz)
3467 if ((c->item_size - framing) % sz != 0)
3470 *n_offsets = (c->item_size - framing) / sz;
3472 where = rindex + framing;
3473 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3477 *offsets = new(size_t, *n_offsets);
3481 for (i = 0; i < *n_offsets; i++) {
3484 x = read_word_le((uint8_t*) q + i * sz, sz);
3485 if (x > c->item_size - sz)
3490 (*offsets)[i] = rindex + x;
3494 *item_size = (*offsets)[0] - rindex;
3499 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3500 c->index += 1 + strlen(contents);
3505 static int bus_message_enter_variant(
3507 struct bus_container *c,
3508 const char *contents,
3509 size_t *item_size) {
3521 if (!signature_is_single(contents, false))
3524 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3527 if (!c->signature || c->signature[c->index] == 0)
3530 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3535 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3538 k = strlen(contents);
3539 if (1+k > c->item_size)
3542 where = rindex + c->item_size - (1+k);
3543 r = message_peek_body(m, &where, 1, 1+k, &q);
3547 if (*(char*) q != 0)
3550 if (memcmp((uint8_t*) q+1, contents, k))
3553 *item_size = c->item_size - (1+k);
3556 r = message_peek_body(m, &rindex, 1, 1, &q);
3561 r = message_peek_body(m, &rindex, 1, l+1, &q);
3565 if (!validate_signature(q, l))
3568 if (!streq(q, contents))
3574 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3580 static int build_struct_offsets(
3582 const char *signature,
3586 size_t *n_offsets) {
3588 unsigned n_variable = 0, n_total = 0, v;
3589 size_t previous = 0, where;
3600 if (isempty(signature)) {
3607 sz = determine_word_size(size, 0);
3611 /* First, loop over signature and count variable elements and
3612 * elements in general. We use this to know how large the
3613 * offset array is at the end of the structure. Note that
3614 * GVariant only stores offsets for all variable size elements
3615 * that are not the last item. */
3621 r = signature_element_length(p, &n);
3630 r = bus_gvariant_is_fixed_size(t);
3635 if (r == 0 && p[n] != 0) /* except the last item */
3642 if (size < n_variable * sz)
3645 where = m->rindex + size - (n_variable * sz);
3646 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3652 *offsets = new(size_t, n_total);
3658 /* Second, loop again and build an offset table */
3664 r = signature_element_length(p, &n);
3673 k = bus_gvariant_get_size(t);
3681 x = read_word_le((uint8_t*) q + v*sz, sz);
3684 if (m->rindex + x < previous)
3687 /* The last item's end
3688 * is determined from
3691 x = size - (n_variable * sz);
3693 offset = m->rindex + x;
3699 align = bus_gvariant_get_alignment(t);
3702 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3706 previous = (*offsets)[(*n_offsets)++] = offset;
3711 assert(*n_offsets == n_total);
3713 *item_size = (*offsets)[0] - m->rindex;
3717 static int enter_struct_or_dict_entry(
3719 struct bus_container *c,
3720 const char *contents,
3723 size_t *n_offsets) {
3734 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3737 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3741 } else if (c->item_size <= 0) {
3743 /* gvariant empty struct */
3748 /* gvariant with contents */
3749 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3754 static int bus_message_enter_struct(
3756 struct bus_container *c,
3757 const char *contents,
3760 size_t *n_offsets) {
3772 if (!signature_is_valid(contents, false))
3775 if (!c->signature || c->signature[c->index] == 0)
3778 l = strlen(contents);
3780 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3781 !startswith(c->signature + c->index + 1, contents) ||
3782 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3785 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3789 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3790 c->index += 1 + l + 1;
3795 static int bus_message_enter_dict_entry(
3797 struct bus_container *c,
3798 const char *contents,
3801 size_t *n_offsets) {
3810 if (!signature_is_pair(contents))
3813 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3816 if (!c->signature || c->signature[c->index] == 0)
3819 l = strlen(contents);
3821 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3822 !startswith(c->signature + c->index + 1, contents) ||
3823 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3826 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3830 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3831 c->index += 1 + l + 1;
3836 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3838 const char *contents) {
3839 struct bus_container *c, *w;
3840 uint32_t *array_size = NULL;
3843 size_t *offsets = NULL;
3844 size_t n_offsets = 0, item_size = 0;
3847 assert_return(m, -EINVAL);
3848 assert_return(m->sealed, -EPERM);
3849 assert_return(type != 0 || !contents, -EINVAL);
3851 if (type == 0 || !contents) {
3855 /* Allow entering into anonymous containers */
3856 r = sd_bus_message_peek_type(m, &tt, &cc);
3860 if (type != 0 && type != tt)
3863 if (contents && !streq(contents, cc))
3871 * We enforce a global limit on container depth, that is much
3872 * higher than the 32 structs and 32 arrays the specification
3873 * mandates. This is simpler to implement for us, and we need
3874 * this only to ensure our container array doesn't grow
3875 * without bounds. We are happy to return any data from a
3876 * message as long as the data itself is valid, even if the
3877 * overall message might be not.
3879 * Note that the message signature is validated when
3880 * parsing the headers, and that validation does check the
3883 * Note that the specification defines no limits on the depth
3884 * of stacked variants, but we do.
3886 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3889 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3892 if (message_end_of_signature(m))
3895 if (message_end_of_array(m, m->rindex))
3898 c = message_get_container(m);
3900 signature = strdup(contents);
3904 c->saved_index = c->index;
3907 if (type == SD_BUS_TYPE_ARRAY)
3908 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3909 else if (type == SD_BUS_TYPE_VARIANT)
3910 r = bus_message_enter_variant(m, c, contents, &item_size);
3911 else if (type == SD_BUS_TYPE_STRUCT)
3912 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3913 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3914 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3924 /* OK, let's fill it in */
3925 w = m->containers + m->n_containers++;
3926 w->enclosing = type;
3927 w->signature = signature;
3928 w->peeked_signature = NULL;
3932 w->begin = m->rindex;
3933 w->end = m->rindex + c->item_size;
3935 w->array_size = array_size;
3936 w->item_size = item_size;
3937 w->offsets = offsets;
3938 w->n_offsets = n_offsets;
3939 w->offset_index = 0;
3944 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3945 struct bus_container *c;
3949 assert_return(m, -EINVAL);
3950 assert_return(m->sealed, -EPERM);
3951 assert_return(m->n_containers > 0, -ENXIO);
3953 c = message_get_container(m);
3955 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3956 if (c->signature && c->signature[c->index] != 0)
3960 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3961 if (m->rindex < c->end)
3964 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3967 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3968 if (c->begin + l != m->rindex)
3973 free(c->peeked_signature);
3977 c = message_get_container(m);
3980 c->index = c->saved_index;
3981 r = container_next_item(m, c, &m->rindex);
3989 static void message_quit_container(sd_bus_message *m) {
3990 struct bus_container *c;
3994 assert(m->n_containers > 0);
3996 c = message_get_container(m);
3999 assert(m->rindex >= c->before);
4000 m->rindex = c->before;
4002 /* Free container */
4007 /* Correct index of new top-level container */
4008 c = message_get_container(m);
4009 c->index = c->saved_index;
4012 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4013 struct bus_container *c;
4016 assert_return(m, -EINVAL);
4017 assert_return(m->sealed, -EPERM);
4019 if (message_end_of_signature(m))
4022 if (message_end_of_array(m, m->rindex))
4025 c = message_get_container(m);
4027 if (bus_type_is_basic(c->signature[c->index])) {
4031 *type = c->signature[c->index];
4035 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4041 r = signature_element_length(c->signature+c->index+1, &l);
4047 sig = strndup(c->signature + c->index + 1, l);
4051 free(c->peeked_signature);
4052 *contents = c->peeked_signature = sig;
4056 *type = SD_BUS_TYPE_ARRAY;
4061 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4062 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4068 r = signature_element_length(c->signature+c->index, &l);
4073 sig = strndup(c->signature + c->index + 1, l - 2);
4077 free(c->peeked_signature);
4078 *contents = c->peeked_signature = sig;
4082 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4087 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4091 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4094 if (c->item_size < 2)
4097 /* Look for the NUL delimiter that
4098 separates the payload from the
4099 signature. Since the body might be
4100 in a different part that then the
4101 signature we map byte by byte. */
4103 for (k = 2; k <= c->item_size; k++) {
4106 where = m->rindex + c->item_size - k;
4107 r = message_peek_body(m, &where, 1, k, &q);
4111 if (*(char*) q == 0)
4115 if (k > c->item_size)
4118 free(c->peeked_signature);
4119 c->peeked_signature = strndup((char*) q + 1, k - 1);
4120 if (!c->peeked_signature)
4123 if (!signature_is_valid(c->peeked_signature, true))
4126 *contents = c->peeked_signature;
4131 r = message_peek_body(m, &rindex, 1, 1, &q);
4136 r = message_peek_body(m, &rindex, 1, l+1, &q);
4140 if (!validate_signature(q, l))
4148 *type = SD_BUS_TYPE_VARIANT;
4163 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4164 struct bus_container *c;
4166 assert_return(m, -EINVAL);
4167 assert_return(m->sealed, -EPERM);
4170 message_reset_containers(m);
4173 c = message_get_container(m);
4175 c = message_get_container(m);
4177 c->offset_index = 0;
4179 m->rindex = c->begin;
4182 c->offset_index = 0;
4183 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4185 return !isempty(c->signature);
4188 static int message_read_ap(
4193 unsigned n_array, n_struct;
4194 TypeStack stack[BUS_CONTAINER_DEPTH];
4195 unsigned stack_ptr = 0;
4196 unsigned n_loop = 0;
4204 /* Ideally, we'd just call ourselves recursively on every
4205 * complex type. However, the state of a va_list that is
4206 * passed to a function is undefined after that function
4207 * returns. This means we need to docode the va_list linearly
4208 * in a single stackframe. We hence implement our own
4209 * home-grown stack in an array. */
4211 n_array = (unsigned) -1; /* lenght of current array entries */
4212 n_struct = strlen(types); /* length of current struct contents signature */
4219 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4220 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4226 r = sd_bus_message_exit_container(m);
4234 if (n_array != (unsigned) -1)
4243 case SD_BUS_TYPE_BYTE:
4244 case SD_BUS_TYPE_BOOLEAN:
4245 case SD_BUS_TYPE_INT16:
4246 case SD_BUS_TYPE_UINT16:
4247 case SD_BUS_TYPE_INT32:
4248 case SD_BUS_TYPE_UINT32:
4249 case SD_BUS_TYPE_INT64:
4250 case SD_BUS_TYPE_UINT64:
4251 case SD_BUS_TYPE_DOUBLE:
4252 case SD_BUS_TYPE_STRING:
4253 case SD_BUS_TYPE_OBJECT_PATH:
4254 case SD_BUS_TYPE_SIGNATURE:
4255 case SD_BUS_TYPE_UNIX_FD: {
4258 p = va_arg(ap, void*);
4259 r = sd_bus_message_read_basic(m, *t, p);
4272 case SD_BUS_TYPE_ARRAY: {
4275 r = signature_element_length(t + 1, &k);
4281 memcpy(s, t + 1, k);
4284 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4295 if (n_array == (unsigned) -1) {
4300 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4306 n_array = va_arg(ap, unsigned);
4311 case SD_BUS_TYPE_VARIANT: {
4314 s = va_arg(ap, const char *);
4318 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4328 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4333 n_struct = strlen(s);
4334 n_array = (unsigned) -1;
4339 case SD_BUS_TYPE_STRUCT_BEGIN:
4340 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4343 r = signature_element_length(t, &k);
4349 memcpy(s, t + 1, k - 2);
4352 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4362 if (n_array == (unsigned) -1) {
4367 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4373 n_array = (unsigned) -1;
4386 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4390 assert_return(m, -EINVAL);
4391 assert_return(m->sealed, -EPERM);
4392 assert_return(types, -EINVAL);
4394 va_start(ap, types);
4395 r = message_read_ap(m, types, ap);
4401 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4404 assert_return(m, -EINVAL);
4405 assert_return(m->sealed, -EPERM);
4406 assert_return(types, -EINVAL);
4413 case SD_BUS_TYPE_BYTE:
4414 case SD_BUS_TYPE_BOOLEAN:
4415 case SD_BUS_TYPE_INT16:
4416 case SD_BUS_TYPE_UINT16:
4417 case SD_BUS_TYPE_INT32:
4418 case SD_BUS_TYPE_UINT32:
4419 case SD_BUS_TYPE_INT64:
4420 case SD_BUS_TYPE_UINT64:
4421 case SD_BUS_TYPE_DOUBLE:
4422 case SD_BUS_TYPE_STRING:
4423 case SD_BUS_TYPE_OBJECT_PATH:
4424 case SD_BUS_TYPE_SIGNATURE:
4425 case SD_BUS_TYPE_UNIX_FD:
4427 r = sd_bus_message_read_basic(m, *types, NULL);
4431 r = sd_bus_message_skip(m, types + 1);
4437 case SD_BUS_TYPE_ARRAY: {
4440 r = signature_element_length(types + 1, &k);
4446 memcpy(s, types+1, k);
4449 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4454 r = sd_bus_message_skip(m, s);
4461 r = sd_bus_message_exit_container(m);
4466 r = sd_bus_message_skip(m, types + 1 + k);
4473 case SD_BUS_TYPE_VARIANT: {
4474 const char *contents;
4477 r = sd_bus_message_peek_type(m, &x, &contents);
4481 if (x != SD_BUS_TYPE_VARIANT)
4484 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4488 r = sd_bus_message_skip(m, contents);
4493 r = sd_bus_message_exit_container(m);
4497 r = sd_bus_message_skip(m, types + 1);
4504 case SD_BUS_TYPE_STRUCT_BEGIN:
4505 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4508 r = signature_element_length(types, &k);
4514 memcpy(s, types+1, k-2);
4517 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4521 r = sd_bus_message_skip(m, s);
4526 r = sd_bus_message_exit_container(m);
4531 r = sd_bus_message_skip(m, types + k);
4543 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4547 struct bus_container *c;
4553 assert_return(m, -EINVAL);
4554 assert_return(m->sealed, -EPERM);
4555 assert_return(bus_type_is_trivial(type), -EINVAL);
4556 assert_return(ptr, -EINVAL);
4557 assert_return(size, -EINVAL);
4558 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4560 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4564 c = message_get_container(m);
4566 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4567 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4571 sz = c->end - c->begin;
4573 align = bus_type_get_alignment(type);
4577 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4581 /* Zero length array, let's return some aligned
4582 * pointer that is not NULL */
4583 p = (uint8_t*) NULL + align;
4585 r = message_peek_body(m, &m->rindex, align, sz, &p);
4590 r = sd_bus_message_exit_container(m);
4594 *ptr = (const void*) p;
4600 message_quit_container(m);
4604 static int message_peek_fields(
4615 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4618 static int message_peek_field_uint32(
4630 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4633 /* identical for gvariant and dbus1 */
4635 r = message_peek_fields(m, ri, 4, 4, &q);
4640 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4645 static int message_peek_field_string(
4647 bool (*validate)(const char *p),
4659 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4664 r = message_peek_fields(m, ri, 1, item_size, &q);
4670 r = message_peek_field_uint32(m, ri, 4, &l);
4674 r = message_peek_fields(m, ri, 1, l+1, &q);
4680 if (!validate_nul(q, l))
4686 if (!validate_string(q, l))
4696 static int message_peek_field_signature(
4709 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4714 r = message_peek_fields(m, ri, 1, item_size, &q);
4720 r = message_peek_fields(m, ri, 1, 1, &q);
4725 r = message_peek_fields(m, ri, 1, l+1, &q);
4730 if (!validate_signature(q, l))
4739 static int message_skip_fields(
4742 uint32_t array_size,
4743 const char **signature) {
4745 size_t original_index;
4751 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4753 original_index = *ri;
4759 if (array_size != (uint32_t) -1 &&
4760 array_size <= *ri - original_index)
4767 if (t == SD_BUS_TYPE_STRING) {
4769 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4775 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4777 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4783 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4785 r = message_peek_field_signature(m, ri, 0, NULL);
4791 } else if (bus_type_is_basic(t)) {
4794 align = bus_type_get_alignment(t);
4795 k = bus_type_get_size(t);
4796 assert(align > 0 && k > 0);
4798 r = message_peek_fields(m, ri, align, k, NULL);
4804 } else if (t == SD_BUS_TYPE_ARRAY) {
4806 r = signature_element_length(*signature+1, &l);
4816 strncpy(sig, *signature + 1, l-1);
4819 alignment = bus_type_get_alignment(sig[0]);
4823 r = message_peek_field_uint32(m, ri, 0, &nas);
4826 if (nas > BUS_ARRAY_MAX_SIZE)
4829 r = message_peek_fields(m, ri, alignment, 0, NULL);
4833 r = message_skip_fields(m, ri, nas, (const char**) &s);
4838 (*signature) += 1 + l;
4840 } else if (t == SD_BUS_TYPE_VARIANT) {
4843 r = message_peek_field_signature(m, ri, 0, &s);
4847 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4853 } else if (t == SD_BUS_TYPE_STRUCT ||
4854 t == SD_BUS_TYPE_DICT_ENTRY) {
4856 r = signature_element_length(*signature, &l);
4863 strncpy(sig, *signature + 1, l-1);
4866 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4877 int bus_message_parse_fields(sd_bus_message *m) {
4880 uint32_t unix_fds = 0;
4881 void *offsets = NULL;
4882 unsigned n_offsets = 0;
4888 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4891 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4895 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4896 r = message_peek_fields(m, &ri, 1, sz, &q);
4900 framing = read_word_le(q, sz);
4901 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4903 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4907 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4911 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4916 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4917 _cleanup_free_ char *sig = NULL;
4918 const char *signature;
4920 size_t item_size = (size_t) -1;
4922 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4929 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4932 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4936 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4941 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4946 where = ri = ALIGN_TO(ri, 8);
4947 item_size = end - ri;
4948 r = message_peek_fields(m, &where, 1, item_size, &q);
4952 b = memrchr(q, 0, item_size);
4956 sig = strndup(b+1, item_size - (b+1-(char*) q));
4961 item_size = b - (char*) q;
4963 r = message_peek_field_signature(m, &ri, 0, &signature);
4969 case _BUS_MESSAGE_HEADER_INVALID:
4972 case BUS_MESSAGE_HEADER_PATH:
4977 if (!streq(signature, "o"))
4980 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
4983 case BUS_MESSAGE_HEADER_INTERFACE:
4988 if (!streq(signature, "s"))
4991 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
4994 case BUS_MESSAGE_HEADER_MEMBER:
4999 if (!streq(signature, "s"))
5002 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5005 case BUS_MESSAGE_HEADER_ERROR_NAME:
5010 if (!streq(signature, "s"))
5013 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5015 m->error._need_free = -1;
5019 case BUS_MESSAGE_HEADER_DESTINATION:
5024 if (!streq(signature, "s"))
5027 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5030 case BUS_MESSAGE_HEADER_SENDER:
5035 if (!streq(signature, "s"))
5038 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5040 if (r >= 0 && m->sender[0] == ':' && m->bus && m->bus->bus_client && !m->bus->is_kernel) {
5041 m->creds.unique_name = (char*) m->sender;
5042 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5048 case BUS_MESSAGE_HEADER_SIGNATURE: {
5052 if (m->root_container.signature)
5055 if (!streq(signature, "g"))
5058 r = message_peek_field_signature(m, &ri, item_size, &s);
5066 free(m->root_container.signature);
5067 m->root_container.signature = c;
5071 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5072 if (m->reply_cookie != 0)
5075 if (!streq(signature, "u"))
5078 r = message_peek_field_uint32(m, &ri, item_size, &m->reply_cookie);
5082 if (m->reply_cookie == 0)
5087 case BUS_MESSAGE_HEADER_UNIX_FDS:
5091 if (!streq(signature, "u"))
5094 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5104 if (!BUS_MESSAGE_IS_GVARIANT(m))
5105 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5114 if (m->n_fds != unix_fds)
5117 switch (m->header->type) {
5119 case SD_BUS_MESSAGE_SIGNAL:
5120 if (!m->path || !m->interface || !m->member)
5124 case SD_BUS_MESSAGE_METHOD_CALL:
5126 if (!m->path || !m->member)
5131 case SD_BUS_MESSAGE_METHOD_RETURN:
5133 if (m->reply_cookie == 0)
5137 case SD_BUS_MESSAGE_METHOD_ERROR:
5139 if (m->reply_cookie == 0 || !m->error.name)
5144 /* Refuse non-local messages that claim they are local */
5145 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5147 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5149 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5152 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5154 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5155 r = build_struct_offsets(
5157 m->root_container.signature,
5158 BUS_MESSAGE_BODY_SIZE(m),
5159 &m->root_container.item_size,
5160 &m->root_container.offsets,
5161 &m->root_container.n_offsets);
5166 /* Try to read the error message, but if we can't it's a non-issue */
5167 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5168 sd_bus_message_read(m, "s", &m->error.message);
5173 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5174 assert_return(m, -EINVAL);
5175 assert_return(destination, -EINVAL);
5176 assert_return(!m->sealed, -EPERM);
5177 assert_return(!m->destination, -EEXIST);
5179 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5182 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5186 struct bus_body_part *part;
5192 total = BUS_MESSAGE_SIZE(m);
5198 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5199 MESSAGE_FOREACH_PART(part, i, m)
5200 e = mempcpy(e, part->data, part->size);
5202 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5210 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5216 r = sd_bus_message_enter_container(m, 'a', "s");
5223 r = sd_bus_message_read_basic(m, 's', &s);
5229 r = strv_extend(l, s);
5234 r = sd_bus_message_exit_container(m);
5241 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5245 assert_return(m, -EINVAL);
5246 assert_return(m->sealed, -EPERM);
5247 assert_return(l, -EINVAL);
5249 r = bus_message_read_strv_extend(m, &strv);
5259 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5261 const char *t = NULL;
5266 r = sd_bus_message_rewind(m, true);
5270 for (j = 0; j <= i; j++) {
5273 r = sd_bus_message_peek_type(m, &type, NULL);
5277 if (type != SD_BUS_TYPE_STRING &&
5278 type != SD_BUS_TYPE_OBJECT_PATH &&
5279 type != SD_BUS_TYPE_SIGNATURE)
5282 r = sd_bus_message_read_basic(m, type, &t);
5290 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5296 if (size < sizeof(struct bus_header))
5299 full = sizeof(struct bus_header) +
5300 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5302 return size >= full;
5305 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5311 if (h->endian == BUS_NATIVE_ENDIAN) {
5312 fs = h->fields_size;
5314 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5315 fs = bswap_32(h->fields_size);
5316 bs = bswap_32(h->body_size);
5320 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5324 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5325 assert_return(m, -EINVAL);
5327 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5330 return sd_bus_error_get_errno(&m->error);
5333 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5334 struct bus_container *c;
5336 assert_return(m, NULL);
5338 c = complete ? &m->root_container : message_get_container(m);
5339 return strempty(c->signature);
5342 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5343 bool done_something = false;
5346 assert_return(m, -EINVAL);
5347 assert_return(source, -EINVAL);
5348 assert_return(!m->sealed, -EPERM);
5349 assert_return(source->sealed, -EPERM);
5352 const char *contents;
5367 r = sd_bus_message_peek_type(source, &type, &contents);
5373 done_something = true;
5375 if (bus_type_is_container(type) > 0) {
5377 r = sd_bus_message_enter_container(source, type, contents);
5381 r = sd_bus_message_open_container(m, type, contents);
5385 r = sd_bus_message_copy(m, source, true);
5389 r = sd_bus_message_close_container(m);
5393 r = sd_bus_message_exit_container(source);
5400 r = sd_bus_message_read_basic(source, type, &basic);
5406 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5407 type == SD_BUS_TYPE_SIGNATURE ||
5408 type == SD_BUS_TYPE_STRING)
5409 r = sd_bus_message_append_basic(m, type, basic.string);
5411 r = sd_bus_message_append_basic(m, type, &basic);
5418 return done_something;
5421 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5426 assert_return(m, -EINVAL);
5427 assert_return(m->sealed, -EPERM);
5428 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5429 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5430 assert_return(type || contents, -EINVAL);
5431 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5433 r = sd_bus_message_peek_type(m, &t, &c);
5437 if (type != 0 && type != t)
5440 if (contents && !streq_ptr(contents, c))
5446 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5447 assert_return(m, NULL);
5452 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5453 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5461 switch ((*m)->header->type) {
5463 case SD_BUS_MESSAGE_SIGNAL:
5464 r = sd_bus_message_new_signal(bus, (*m)->path, (*m)->interface, (*m)->member, &n);
5470 case SD_BUS_MESSAGE_METHOD_CALL:
5471 r = sd_bus_message_new_method_call(bus, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member, &n);
5477 case SD_BUS_MESSAGE_METHOD_RETURN:
5478 case SD_BUS_MESSAGE_METHOD_ERROR:
5480 n = message_new(bus, (*m)->header->type);
5484 n->reply_cookie = (*m)->reply_cookie;
5485 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, n->reply_cookie);
5489 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5490 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5494 n->error._need_free = -1;
5503 if ((*m)->destination && !n->destination) {
5504 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5509 if ((*m)->sender && !n->sender) {
5510 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5515 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5517 r = sd_bus_message_copy(n, *m, true);
5521 timeout = (*m)->timeout;
5522 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5523 timeout = BUS_DEFAULT_TIMEOUT;
5525 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5529 sd_bus_message_unref(*m);
5536 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5540 assert_return(!m->sealed, -EPERM);
5541 assert_return(!m->sender, -EPERM);
5543 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);