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);
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 memzero((uint8_t*) np + old_size, 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(
514 const char *interface,
515 const char *member) {
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(
553 const char *destination,
555 const char *interface,
556 const char *member) {
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, (uint32_t) 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,
651 const sd_bus_error *e) {
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, m, &error);
703 _public_ int sd_bus_message_new_method_errno(
704 sd_bus_message *call,
707 const sd_bus_error *p) {
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, m, p);
714 sd_bus_error_set_errno(&berror, error);
716 return sd_bus_message_new_method_error(call, m, &berror);
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, m, &berror);
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, (uint32_t) 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_expect_reply(sd_bus_message *m) {
835 assert_return(m, -EINVAL);
837 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
838 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
841 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
842 assert_return(m, -EINVAL);
844 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
847 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
848 assert_return(m, NULL);
853 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
854 assert_return(m, NULL);
859 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
860 assert_return(m, NULL);
865 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
866 assert_return(m, NULL);
868 return m->destination;
871 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
872 assert_return(m, NULL);
877 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
878 assert_return(m, NULL);
879 assert_return(sd_bus_error_is_set(&m->error), NULL);
884 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
885 assert_return(m, -EINVAL);
886 assert_return(usec, -EINVAL);
888 if (m->monotonic <= 0)
891 *usec = m->monotonic;
895 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
896 assert_return(m, -EINVAL);
897 assert_return(usec, -EINVAL);
899 if (m->realtime <= 0)
906 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
907 assert_return(m, -EINVAL);
908 assert_return(seqnum, -EINVAL);
917 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
918 assert_return(m, NULL);
920 if (m->creds.mask == 0)
926 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
927 const char *interface,
928 const char *member) {
929 assert_return(m, -EINVAL);
931 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
934 if (interface && (!m->interface || !streq(m->interface, interface)))
937 if (member && (!m->member || !streq(m->member, member)))
943 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
944 const char *interface,
945 const char *member) {
946 assert_return(m, -EINVAL);
948 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
951 if (interface && (!m->interface || !streq(m->interface, interface)))
954 if (member && (!m->member || !streq(m->member, member)))
960 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
961 assert_return(m, -EINVAL);
963 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
966 if (name && (!m->error.name || !streq(m->error.name, name)))
972 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
973 assert_return(m, -EINVAL);
974 assert_return(!m->sealed, -EPERM);
975 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
978 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
980 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
985 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
986 assert_return(m, -EINVAL);
987 assert_return(!m->sealed, -EPERM);
990 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
992 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
997 static struct bus_container *message_get_container(sd_bus_message *m) {
1000 if (m->n_containers == 0)
1001 return &m->root_container;
1003 assert(m->containers);
1004 return m->containers + m->n_containers - 1;
1007 struct bus_body_part *message_append_part(sd_bus_message *m) {
1008 struct bus_body_part *part;
1015 if (m->n_body_parts <= 0) {
1019 assert(m->body_end);
1021 part = new0(struct bus_body_part, 1);
1027 m->body_end->next = part;
1037 static void part_zero(struct bus_body_part *part, size_t sz) {
1042 /* All other fields can be left in their defaults */
1043 assert(!part->data);
1044 assert(part->memfd < 0);
1047 part->is_zero = true;
1048 part->sealed = true;
1051 static int part_make_space(
1052 struct sd_bus_message *m,
1053 struct bus_body_part *part,
1062 assert(!part->sealed);
1067 if (!part->data && part->memfd < 0)
1068 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1070 if (part->memfd >= 0) {
1072 if (part->allocated == 0 || sz > part->allocated) {
1073 uint64_t new_allocated;
1075 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1076 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &new_allocated);
1082 part->allocated = new_allocated;
1085 if (!part->data || sz > part->mapped) {
1088 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1089 if (part->mapped <= 0)
1090 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1092 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1094 if (n == MAP_FAILED) {
1103 part->munmap_this = true;
1105 if (part->allocated == 0 || sz > part->allocated) {
1106 size_t new_allocated;
1108 new_allocated = sz > 0 ? 2 * sz : 64;
1109 n = realloc(part->data, new_allocated);
1116 part->allocated = new_allocated;
1117 part->free_this = true;
1122 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1128 static int message_add_offset(sd_bus_message *m, size_t offset) {
1129 struct bus_container *c;
1132 assert(BUS_MESSAGE_IS_GVARIANT(m));
1134 /* Add offset to current container, unless this is the first
1135 * item in it, which will have the 0 offset, which we can
1137 c = message_get_container(m);
1139 if (!c->need_offsets)
1142 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1145 c->offsets[c->n_offsets++] = offset;
1149 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1150 struct bus_container *c;
1157 /* Update counters */
1158 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1161 *c->array_size += expand;
1165 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1166 size_t start_body, end_body, padding, added;
1177 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1178 end_body = start_body + sz;
1180 padding = start_body - m->header->body_size;
1181 added = padding + sz;
1183 /* Check for 32bit overflows */
1184 if (end_body > (size_t) ((uint32_t) -1)) {
1190 struct bus_body_part *part = NULL;
1194 m->n_body_parts <= 0 ||
1195 m->body_end->sealed ||
1196 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1200 part = message_append_part(m);
1204 part_zero(part, padding);
1207 part = message_append_part(m);
1211 r = part_make_space(m, part, sz, &p);
1215 struct bus_container *c;
1217 size_t os, start_part, end_part;
1223 start_part = ALIGN_TO(part->size, align);
1224 end_part = start_part + sz;
1226 r = part_make_space(m, part, end_part, &p);
1231 memzero(p, padding);
1232 p = (uint8_t*) p + padding;
1235 /* Readjust pointers */
1236 for (c = m->containers; c < m->containers + m->n_containers; c++)
1237 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1239 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1242 /* Return something that is not NULL and is aligned */
1243 p = (uint8_t *) NULL + align;
1245 m->header->body_size = end_body;
1246 message_extend_containers(m, added);
1249 r = message_add_offset(m, end_body);
1259 static int message_push_fd(sd_bus_message *m, int fd) {
1270 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1274 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1282 m->fds[m->n_fds] = copy;
1288 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1289 _cleanup_close_ int fd = -1;
1290 struct bus_container *c;
1294 assert_return(m, -EINVAL);
1295 assert_return(!m->sealed, -EPERM);
1296 assert_return(bus_type_is_basic(type), -EINVAL);
1297 assert_return(!m->poisoned, -ESTALE);
1299 c = message_get_container(m);
1301 if (c->signature && c->signature[c->index]) {
1302 /* Container signature is already set */
1304 if (c->signature[c->index] != type)
1309 /* Maybe we can append to the signature? But only if this is the top-level container*/
1310 if (c->enclosing != 0)
1313 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1320 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1326 case SD_BUS_TYPE_SIGNATURE:
1327 case SD_BUS_TYPE_STRING:
1330 /* Fall through... */
1331 case SD_BUS_TYPE_OBJECT_PATH:
1339 case SD_BUS_TYPE_BOOLEAN:
1341 u8 = p && *(int*) p;
1347 case SD_BUS_TYPE_UNIX_FD:
1352 fd = message_push_fd(m, *(int*) p);
1363 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1364 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1371 a = message_extend_body(m, align, sz, true);
1378 *stored = (const uint8_t*) a;
1385 case SD_BUS_TYPE_STRING:
1386 /* To make things easy we'll serialize a NULL string
1387 * into the empty string */
1390 /* Fall through... */
1391 case SD_BUS_TYPE_OBJECT_PATH:
1397 sz = 4 + strlen(p) + 1;
1400 case SD_BUS_TYPE_SIGNATURE:
1405 sz = 1 + strlen(p) + 1;
1408 case SD_BUS_TYPE_BOOLEAN:
1410 u32 = p && *(int*) p;
1416 case SD_BUS_TYPE_UNIX_FD:
1421 fd = message_push_fd(m, *(int*) p);
1432 align = bus_type_get_alignment(type);
1433 sz = bus_type_get_size(type);
1440 a = message_extend_body(m, align, sz, false);
1444 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1445 *(uint32_t*) a = sz - 5;
1446 memcpy((uint8_t*) a + 4, p, sz - 4);
1449 *stored = (const uint8_t*) a + 4;
1451 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1452 *(uint8_t*) a = sz - 2;
1453 memcpy((uint8_t*) a + 1, p, sz - 1);
1456 *stored = (const uint8_t*) a + 1;
1465 if (type == SD_BUS_TYPE_UNIX_FD)
1468 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1475 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1476 return message_append_basic(m, type, p, NULL);
1479 _public_ int sd_bus_message_append_string_space(
1484 struct bus_container *c;
1487 assert_return(m, -EINVAL);
1488 assert_return(s, -EINVAL);
1489 assert_return(!m->sealed, -EPERM);
1490 assert_return(!m->poisoned, -ESTALE);
1492 c = message_get_container(m);
1494 if (c->signature && c->signature[c->index]) {
1495 /* Container signature is already set */
1497 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1502 /* Maybe we can append to the signature? But only if this is the top-level container*/
1503 if (c->enclosing != 0)
1506 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1513 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1514 a = message_extend_body(m, 1, size + 1, true);
1520 a = message_extend_body(m, 4, 4 + size + 1, false);
1524 *(uint32_t*) a = size;
1530 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1536 _public_ int sd_bus_message_append_string_iovec(
1538 const struct iovec *iov,
1546 assert_return(m, -EINVAL);
1547 assert_return(!m->sealed, -EPERM);
1548 assert_return(iov || n == 0, -EINVAL);
1549 assert_return(!m->poisoned, -ESTALE);
1551 size = IOVEC_TOTAL_SIZE(iov, n);
1553 r = sd_bus_message_append_string_space(m, size, &p);
1557 for (i = 0; i < n; i++) {
1559 if (iov[i].iov_base)
1560 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1562 memset(p, ' ', iov[i].iov_len);
1564 p += iov[i].iov_len;
1570 static int bus_message_open_array(
1572 struct bus_container *c,
1573 const char *contents,
1574 uint32_t **array_size,
1576 bool *need_offsets) {
1586 assert(need_offsets);
1588 if (!signature_is_single(contents, true))
1591 if (c->signature && c->signature[c->index]) {
1593 /* Verify the existing signature */
1595 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1598 if (!startswith(c->signature + c->index + 1, contents))
1601 nindex = c->index + 1 + strlen(contents);
1605 if (c->enclosing != 0)
1608 /* Extend the existing signature */
1610 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1616 nindex = e - c->signature;
1619 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1620 alignment = bus_gvariant_get_alignment(contents);
1624 /* Add alignment padding and add to offset list */
1625 if (!message_extend_body(m, alignment, 0, false))
1628 r = bus_gvariant_is_fixed_size(contents);
1632 *begin = m->header->body_size;
1633 *need_offsets = r == 0;
1637 struct bus_body_part *o;
1639 alignment = bus_type_get_alignment(contents[0]);
1643 a = message_extend_body(m, 4, 4, false);
1648 op = m->body_end->data;
1649 os = m->body_end->size;
1651 /* Add alignment between size and first element */
1652 if (!message_extend_body(m, alignment, 0, false))
1655 /* location of array size might have changed so let's readjust a */
1656 if (o == m->body_end)
1657 a = adjust_pointer(a, op, os, m->body_end->data);
1663 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1669 static int bus_message_open_variant(
1671 struct bus_container *c,
1672 const char *contents) {
1678 if (!signature_is_single(contents, false))
1681 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1684 if (c->signature && c->signature[c->index]) {
1686 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1692 if (c->enclosing != 0)
1695 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1702 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1703 /* Variants are always aligned to 8 */
1705 if (!message_extend_body(m, 8, 0, false))
1712 l = strlen(contents);
1713 a = message_extend_body(m, 1, 1 + l + 1, false);
1718 memcpy((uint8_t*) a + 1, contents, l + 1);
1721 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1727 static int bus_message_open_struct(
1729 struct bus_container *c,
1730 const char *contents,
1732 bool *need_offsets) {
1741 assert(need_offsets);
1743 if (!signature_is_valid(contents, false))
1746 if (c->signature && c->signature[c->index]) {
1749 l = strlen(contents);
1751 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1752 !startswith(c->signature + c->index + 1, contents) ||
1753 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1756 nindex = c->index + 1 + l + 1;
1760 if (c->enclosing != 0)
1763 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1769 nindex = e - c->signature;
1772 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1775 alignment = bus_gvariant_get_alignment(contents);
1779 if (!message_extend_body(m, alignment, 0, false))
1782 r = bus_gvariant_is_fixed_size(contents);
1786 *begin = m->header->body_size;
1787 *need_offsets = r == 0;
1789 /* Align contents to 8 byte boundary */
1790 if (!message_extend_body(m, 8, 0, false))
1794 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1800 static int bus_message_open_dict_entry(
1802 struct bus_container *c,
1803 const char *contents,
1805 bool *need_offsets) {
1813 assert(need_offsets);
1815 if (!signature_is_pair(contents))
1818 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1821 if (c->signature && c->signature[c->index]) {
1824 l = strlen(contents);
1826 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1827 !startswith(c->signature + c->index + 1, contents) ||
1828 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1833 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1836 alignment = bus_gvariant_get_alignment(contents);
1840 if (!message_extend_body(m, alignment, 0, false))
1843 r = bus_gvariant_is_fixed_size(contents);
1847 *begin = m->header->body_size;
1848 *need_offsets = r == 0;
1850 /* Align contents to 8 byte boundary */
1851 if (!message_extend_body(m, 8, 0, false))
1858 _public_ int sd_bus_message_open_container(
1861 const char *contents) {
1863 struct bus_container *c, *w;
1864 uint32_t *array_size = NULL;
1866 size_t before, begin = 0;
1867 bool need_offsets = false;
1870 assert_return(m, -EINVAL);
1871 assert_return(!m->sealed, -EPERM);
1872 assert_return(contents, -EINVAL);
1873 assert_return(!m->poisoned, -ESTALE);
1875 /* Make sure we have space for one more container */
1876 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1881 c = message_get_container(m);
1883 signature = strdup(contents);
1889 /* Save old index in the parent container, in case we have to
1890 * abort this container */
1891 c->saved_index = c->index;
1892 before = m->header->body_size;
1894 if (type == SD_BUS_TYPE_ARRAY)
1895 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1896 else if (type == SD_BUS_TYPE_VARIANT)
1897 r = bus_message_open_variant(m, c, contents);
1898 else if (type == SD_BUS_TYPE_STRUCT)
1899 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1900 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1901 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1910 /* OK, let's fill it in */
1911 w = m->containers + m->n_containers++;
1912 w->enclosing = type;
1913 w->signature = signature;
1915 w->array_size = array_size;
1918 w->n_offsets = w->offsets_allocated = 0;
1920 w->need_offsets = need_offsets;
1925 static size_t determine_word_size(size_t sz, size_t extra) {
1926 if (sz + extra <= 0xFF)
1928 else if (sz + extra*2 <= 0xFFFF)
1930 else if (sz + extra*4 <= 0xFFFFFFFF)
1936 static size_t read_word_le(void *p, size_t sz) {
1946 return *(uint8_t*) p;
1951 return le16toh(x.u16);
1953 return le32toh(x.u32);
1955 return le64toh(x.u64);
1957 assert_not_reached("unknown word width");
1960 static void write_word_le(void *p, size_t sz, size_t value) {
1968 assert(sz == 8 || (value < (1ULL << (sz*8))));
1971 *(uint8_t*) p = value;
1974 x.u16 = htole16((uint16_t) value);
1976 x.u32 = htole32((uint32_t) value);
1978 x.u64 = htole64((uint64_t) value);
1980 assert_not_reached("unknown word width");
1985 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1990 if (!BUS_MESSAGE_IS_GVARIANT(m))
1993 if (c->need_offsets) {
1994 size_t payload, sz, i;
1997 /* Variable-width arrays */
1999 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2000 sz = determine_word_size(payload, c->n_offsets);
2002 a = message_extend_body(m, 1, sz * c->n_offsets, true);
2006 for (i = 0; i < c->n_offsets; i++)
2007 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2011 /* Fixed-width or empty arrays */
2013 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
2021 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2028 if (!BUS_MESSAGE_IS_GVARIANT(m))
2031 l = strlen(c->signature);
2033 a = message_extend_body(m, 1, 1 + l, true);
2038 memcpy(a+1, c->signature, l);
2043 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2044 size_t n_variable = 0;
2053 if (!BUS_MESSAGE_IS_GVARIANT(m))
2056 p = strempty(c->signature);
2060 r = signature_element_length(p, &n);
2069 r = bus_gvariant_is_fixed_size(t);
2074 assert(!c->need_offsets || i <= c->n_offsets);
2076 /* We need to add an offset for each item that has a
2077 * variable size and that is not the last one in the
2079 if (r == 0 && p[n] != 0)
2086 assert(!c->need_offsets || i == c->n_offsets);
2087 assert(c->need_offsets || n_variable == 0);
2089 if (n_variable <= 0) {
2090 a = message_extend_body(m, 1, 0, add_offset);
2097 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2099 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2101 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2105 p = strempty(c->signature);
2106 for (i = 0, j = 0; i < c->n_offsets; i++) {
2110 r = signature_element_length(p, &n);
2121 r = bus_gvariant_is_fixed_size(t);
2124 if (r > 0 || p[0] == 0)
2128 k = n_variable - 1 - j;
2130 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2139 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2140 struct bus_container *c;
2143 assert_return(m, -EINVAL);
2144 assert_return(!m->sealed, -EPERM);
2145 assert_return(m->n_containers > 0, -EINVAL);
2146 assert_return(!m->poisoned, -ESTALE);
2148 c = message_get_container(m);
2150 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2151 if (c->signature && c->signature[c->index] != 0)
2156 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2157 r = bus_message_close_array(m, c);
2158 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2159 r = bus_message_close_variant(m, c);
2160 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2161 r = bus_message_close_struct(m, c, true);
2163 assert_not_reached("Unknown container type");
2177 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2184 stack[*i].types = types;
2185 stack[*i].n_struct = n_struct;
2186 stack[*i].n_array = n_array;
2192 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2203 *types = stack[*i].types;
2204 *n_struct = stack[*i].n_struct;
2205 *n_array = stack[*i].n_array;
2210 int bus_message_append_ap(
2215 unsigned n_array, n_struct;
2216 TypeStack stack[BUS_CONTAINER_DEPTH];
2217 unsigned stack_ptr = 0;
2225 n_array = (unsigned) -1;
2226 n_struct = strlen(types);
2231 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2232 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2238 r = sd_bus_message_close_container(m);
2246 if (n_array != (unsigned) -1)
2255 case SD_BUS_TYPE_BYTE: {
2258 x = (uint8_t) va_arg(ap, int);
2259 r = sd_bus_message_append_basic(m, *t, &x);
2263 case SD_BUS_TYPE_BOOLEAN:
2264 case SD_BUS_TYPE_INT32:
2265 case SD_BUS_TYPE_UINT32:
2266 case SD_BUS_TYPE_UNIX_FD: {
2269 /* We assume a boolean is the same as int32_t */
2270 assert_cc(sizeof(int32_t) == sizeof(int));
2272 x = va_arg(ap, uint32_t);
2273 r = sd_bus_message_append_basic(m, *t, &x);
2277 case SD_BUS_TYPE_INT16:
2278 case SD_BUS_TYPE_UINT16: {
2281 x = (uint16_t) va_arg(ap, int);
2282 r = sd_bus_message_append_basic(m, *t, &x);
2286 case SD_BUS_TYPE_INT64:
2287 case SD_BUS_TYPE_UINT64:
2288 case SD_BUS_TYPE_DOUBLE: {
2291 x = va_arg(ap, uint64_t);
2292 r = sd_bus_message_append_basic(m, *t, &x);
2296 case SD_BUS_TYPE_STRING:
2297 case SD_BUS_TYPE_OBJECT_PATH:
2298 case SD_BUS_TYPE_SIGNATURE: {
2301 x = va_arg(ap, const char*);
2302 r = sd_bus_message_append_basic(m, *t, x);
2306 case SD_BUS_TYPE_ARRAY: {
2309 r = signature_element_length(t + 1, &k);
2315 memcpy(s, t + 1, k);
2318 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2323 if (n_array == (unsigned) -1) {
2328 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2334 n_array = va_arg(ap, unsigned);
2339 case SD_BUS_TYPE_VARIANT: {
2342 s = va_arg(ap, const char*);
2346 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2350 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2355 n_struct = strlen(s);
2356 n_array = (unsigned) -1;
2361 case SD_BUS_TYPE_STRUCT_BEGIN:
2362 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2365 r = signature_element_length(t, &k);
2372 memcpy(s, t + 1, k - 2);
2375 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2380 if (n_array == (unsigned) -1) {
2385 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2391 n_array = (unsigned) -1;
2407 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2411 assert_return(m, -EINVAL);
2412 assert_return(types, -EINVAL);
2413 assert_return(!m->sealed, -EPERM);
2414 assert_return(!m->poisoned, -ESTALE);
2416 va_start(ap, types);
2417 r = bus_message_append_ap(m, types, ap);
2423 _public_ int sd_bus_message_append_array_space(
2433 assert_return(m, -EINVAL);
2434 assert_return(!m->sealed, -EPERM);
2435 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2436 assert_return(ptr || size == 0, -EINVAL);
2437 assert_return(!m->poisoned, -ESTALE);
2439 /* alignment and size of the trivial types (except bool) is
2440 * identical for gvariant and dbus1 marshalling */
2441 align = bus_type_get_alignment(type);
2442 sz = bus_type_get_size(type);
2444 assert_se(align > 0);
2450 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2454 a = message_extend_body(m, align, size, false);
2458 r = sd_bus_message_close_container(m);
2466 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2473 assert_return(m, -EINVAL);
2474 assert_return(!m->sealed, -EPERM);
2475 assert_return(bus_type_is_trivial(type), -EINVAL);
2476 assert_return(ptr || size == 0, -EINVAL);
2477 assert_return(!m->poisoned, -ESTALE);
2479 r = sd_bus_message_append_array_space(m, type, size, &p);
2484 memcpy(p, ptr, size);
2489 _public_ int sd_bus_message_append_array_iovec(
2492 const struct iovec *iov,
2500 assert_return(m, -EINVAL);
2501 assert_return(!m->sealed, -EPERM);
2502 assert_return(bus_type_is_trivial(type), -EINVAL);
2503 assert_return(iov || n == 0, -EINVAL);
2504 assert_return(!m->poisoned, -ESTALE);
2506 size = IOVEC_TOTAL_SIZE(iov, n);
2508 r = sd_bus_message_append_array_space(m, type, size, &p);
2512 for (i = 0; i < n; i++) {
2514 if (iov[i].iov_base)
2515 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2517 memzero(p, iov[i].iov_len);
2519 p = (uint8_t*) p + iov[i].iov_len;
2525 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2528 _cleanup_close_ int copy_fd = -1;
2529 struct bus_body_part *part;
2541 if (!bus_type_is_trivial(type))
2546 r = sd_memfd_set_sealed(memfd, true);
2550 copy_fd = sd_memfd_dup_fd(memfd);
2554 r = sd_memfd_get_size(memfd, &size);
2558 align = bus_type_get_alignment(type);
2559 sz = bus_type_get_size(type);
2561 assert_se(align > 0);
2567 if (size > (uint64_t) (uint32_t) -1)
2570 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2574 a = message_extend_body(m, align, 0, false);
2578 part = message_append_part(m);
2582 part->memfd = copy_fd;
2583 part->sealed = true;
2587 m->header->body_size += size;
2588 message_extend_containers(m, size);
2590 return sd_bus_message_close_container(m);
2593 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
2594 _cleanup_close_ int copy_fd = -1;
2595 struct bus_body_part *part;
2596 struct bus_container *c;
2601 assert_return(m, -EINVAL);
2602 assert_return(memfd, -EINVAL);
2603 assert_return(!m->sealed, -EPERM);
2604 assert_return(!m->poisoned, -ESTALE);
2606 r = sd_memfd_set_sealed(memfd, true);
2610 copy_fd = sd_memfd_dup_fd(memfd);
2614 r = sd_memfd_get_size(memfd, &size);
2618 /* We require this to be NUL terminated */
2622 if (size > (uint64_t) (uint32_t) -1)
2625 c = message_get_container(m);
2626 if (c->signature && c->signature[c->index]) {
2627 /* Container signature is already set */
2629 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2634 /* Maybe we can append to the signature? But only if this is the top-level container*/
2635 if (c->enclosing != 0)
2638 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2645 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2646 a = message_extend_body(m, 4, 4, false);
2650 *(uint32_t*) a = size - 1;
2653 part = message_append_part(m);
2657 part->memfd = copy_fd;
2658 part->sealed = true;
2662 m->header->body_size += size;
2663 message_extend_containers(m, size);
2665 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2666 r = message_add_offset(m, m->header->body_size);
2673 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2679 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2683 assert_return(m, -EINVAL);
2684 assert_return(!m->sealed, -EPERM);
2685 assert_return(!m->poisoned, -ESTALE);
2687 r = sd_bus_message_open_container(m, 'a', "s");
2691 STRV_FOREACH(i, l) {
2692 r = sd_bus_message_append_basic(m, 's', *i);
2697 return sd_bus_message_close_container(m);
2700 static int bus_message_close_header(sd_bus_message *m) {
2706 if (!BUS_MESSAGE_IS_GVARIANT(m))
2709 if (m->n_header_offsets < 1)
2712 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2714 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2716 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2720 for (i = 0; i < m->n_header_offsets; i++)
2721 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2726 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2727 struct bus_body_part *part;
2737 if (m->n_containers > 0)
2743 /* In vtables the return signature of method calls is listed,
2744 * let's check if they match if this is a response */
2745 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2746 m->enforced_reply_signature &&
2747 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2750 /* If gvariant marshalling is used we need to close the body structure */
2751 r = bus_message_close_struct(m, &m->root_container, false);
2755 /* If there's a non-trivial signature set, then add it in here */
2756 if (!isempty(m->root_container.signature)) {
2757 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2763 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2768 r = bus_message_close_header(m);
2772 m->header->serial = (uint32_t) cookie;
2773 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2775 /* Add padding at the end of the fields part, since we know
2776 * the body needs to start at an 8 byte alignment. We made
2777 * sure we allocated enough space for this, so all we need to
2778 * do here is to zero it out. */
2779 l = BUS_MESSAGE_FIELDS_SIZE(m);
2782 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, a);
2784 /* If this is something we can send as memfd, then let's seal
2785 the memfd now. Note that we can send memfds as payload only
2786 for directed messages, and not for broadcasts. */
2787 if (m->destination && m->bus && m->bus->use_memfd) {
2788 MESSAGE_FOREACH_PART(part, i, m)
2789 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2792 /* Try to seal it if that makes
2793 * sense. First, unmap our own map to
2794 * make sure we don't keep it busy. */
2795 bus_body_part_unmap(part);
2797 /* Then, sync up real memfd size */
2799 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &sz) < 0)
2802 /* Finally, try to seal */
2803 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
2804 part->sealed = true;
2808 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2809 m->root_container.index = 0;
2810 m->root_container.offset_index = 0;
2811 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2818 int bus_body_part_map(struct bus_body_part *part) {
2827 if (part->size <= 0)
2830 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2831 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2832 static const uint8_t zeroes[7] = { };
2833 part->data = (void*) zeroes;
2837 psz = PAGE_ALIGN(part->size);
2839 if (part->memfd >= 0)
2840 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2841 else if (part->is_zero)
2842 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2846 if (p == MAP_FAILED)
2851 part->munmap_this = true;
2856 void bus_body_part_unmap(struct bus_body_part *part) {
2860 if (part->memfd < 0)
2866 if (!part->munmap_this)
2869 assert_se(munmap(part->data, part->mapped) == 0);
2873 part->munmap_this = false;
2878 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2879 size_t k, start, end;
2884 start = ALIGN_TO((size_t) *rindex, align);
2885 end = start + nbytes;
2890 /* Verify that padding is 0 */
2891 for (k = *rindex; k < start; k++)
2892 if (((const uint8_t*) p)[k] != 0)
2896 *r = (uint8_t*) p + start;
2903 static bool message_end_of_signature(sd_bus_message *m) {
2904 struct bus_container *c;
2908 c = message_get_container(m);
2909 return !c->signature || c->signature[c->index] == 0;
2912 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2913 struct bus_container *c;
2917 c = message_get_container(m);
2918 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2921 if (BUS_MESSAGE_IS_GVARIANT(m))
2922 return index >= c->end;
2924 assert(c->array_size);
2925 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2929 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2930 assert_return(m, -EINVAL);
2931 assert_return(m->sealed, -EPERM);
2933 if (complete && m->n_containers > 0)
2936 if (message_end_of_signature(m))
2939 if (message_end_of_array(m, m->rindex))
2945 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2946 struct bus_body_part *part;
2952 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2953 part = m->cached_rindex_part;
2954 begin = m->cached_rindex_part_begin;
2964 if (index + sz <= begin + part->size) {
2966 r = bus_body_part_map(part);
2971 *p = (uint8_t*) part->data + index - begin;
2973 m->cached_rindex_part = part;
2974 m->cached_rindex_part_begin = begin;
2979 begin += part->size;
2986 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2993 if (!BUS_MESSAGE_IS_GVARIANT(m))
2996 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2999 sz = bus_gvariant_get_size(c->signature);
3003 if (c->offset_index+1 >= c->n_offsets)
3006 /* Variable-size array */
3008 alignment = bus_gvariant_get_alignment(c->signature);
3009 assert(alignment > 0);
3011 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3012 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3015 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3018 /* Fixed-size array */
3019 *rindex = c->begin + (c->offset_index+1) * sz;
3025 } else if (c->enclosing == 0 ||
3026 c->enclosing == SD_BUS_TYPE_STRUCT ||
3027 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3032 if (c->offset_index+1 >= c->n_offsets)
3035 r = signature_element_length(c->signature + c->index, &n);
3039 r = signature_element_length(c->signature + c->index + n, &j);
3044 memcpy(t, c->signature + c->index + n, j);
3047 alignment = bus_gvariant_get_alignment(t);
3050 assert(alignment > 0);
3052 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3053 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3057 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3060 assert_not_reached("Unknown container type");
3065 /* Reached the end */
3072 static int message_peek_body(
3079 size_t k, start, end, padding;
3080 struct bus_body_part *part;
3087 start = ALIGN_TO((size_t) *rindex, align);
3088 padding = start - *rindex;
3089 end = start + nbytes;
3091 if (end > BUS_MESSAGE_BODY_SIZE(m))
3094 part = find_part(m, *rindex, padding, (void**) &q);
3099 /* Verify padding */
3100 for (k = 0; k < padding; k++)
3105 part = find_part(m, start, nbytes, (void**) &q);
3106 if (!part || (nbytes > 0 && !q))
3117 static bool validate_nul(const char *s, size_t l) {
3119 /* Check for NUL chars in the string */
3120 if (memchr(s, 0, l))
3123 /* Check for NUL termination */
3130 static bool validate_string(const char *s, size_t l) {
3132 if (!validate_nul(s, l))
3135 /* Check if valid UTF8 */
3136 if (!utf8_is_valid(s))
3142 static bool validate_signature(const char *s, size_t l) {
3144 if (!validate_nul(s, l))
3147 /* Check if valid signature */
3148 if (!signature_is_valid(s, true))
3154 static bool validate_object_path(const char *s, size_t l) {
3156 if (!validate_nul(s, l))
3159 if (!object_path_is_valid(s))
3165 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3166 struct bus_container *c;
3171 assert_return(m, -EINVAL);
3172 assert_return(m->sealed, -EPERM);
3173 assert_return(bus_type_is_basic(type), -EINVAL);
3175 if (message_end_of_signature(m))
3178 if (message_end_of_array(m, m->rindex))
3181 c = message_get_container(m);
3182 if (c->signature[c->index] != type)
3187 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3189 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3192 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3196 if (type == SD_BUS_TYPE_STRING)
3197 ok = validate_string(q, c->item_size-1);
3198 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3199 ok = validate_object_path(q, c->item_size-1);
3201 ok = validate_signature(q, c->item_size-1);
3207 *(const char**) p = q;
3211 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3213 if ((size_t) sz != c->item_size)
3216 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3219 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3225 case SD_BUS_TYPE_BYTE:
3227 *(uint8_t*) p = *(uint8_t*) q;
3230 case SD_BUS_TYPE_BOOLEAN:
3232 *(int*) p = !!*(uint8_t*) q;
3235 case SD_BUS_TYPE_INT16:
3236 case SD_BUS_TYPE_UINT16:
3238 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3241 case SD_BUS_TYPE_INT32:
3242 case SD_BUS_TYPE_UINT32:
3244 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3247 case SD_BUS_TYPE_INT64:
3248 case SD_BUS_TYPE_UINT64:
3249 case SD_BUS_TYPE_DOUBLE:
3251 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3254 case SD_BUS_TYPE_UNIX_FD: {
3257 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3262 *(int*) p = m->fds[j];
3268 assert_not_reached("unexpected type");
3272 r = container_next_item(m, c, &rindex);
3279 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3283 r = message_peek_body(m, &rindex, 4, 4, &q);
3287 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3288 r = message_peek_body(m, &rindex, 1, l+1, &q);
3292 if (type == SD_BUS_TYPE_OBJECT_PATH)
3293 ok = validate_object_path(q, l);
3295 ok = validate_string(q, l);
3300 *(const char**) p = q;
3302 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3305 r = message_peek_body(m, &rindex, 1, 1, &q);
3310 r = message_peek_body(m, &rindex, 1, l+1, &q);
3314 if (!validate_signature(q, l))
3318 *(const char**) p = q;
3323 align = bus_type_get_alignment(type);
3326 sz = bus_type_get_size(type);
3329 r = message_peek_body(m, &rindex, align, sz, &q);
3335 case SD_BUS_TYPE_BYTE:
3337 *(uint8_t*) p = *(uint8_t*) q;
3340 case SD_BUS_TYPE_BOOLEAN:
3342 *(int*) p = !!*(uint32_t*) q;
3345 case SD_BUS_TYPE_INT16:
3346 case SD_BUS_TYPE_UINT16:
3348 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3351 case SD_BUS_TYPE_INT32:
3352 case SD_BUS_TYPE_UINT32:
3354 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3357 case SD_BUS_TYPE_INT64:
3358 case SD_BUS_TYPE_UINT64:
3359 case SD_BUS_TYPE_DOUBLE:
3361 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3364 case SD_BUS_TYPE_UNIX_FD: {
3367 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3372 *(int*) p = m->fds[j];
3377 assert_not_reached("Unknown basic type...");
3384 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3390 static int bus_message_enter_array(
3392 struct bus_container *c,
3393 const char *contents,
3394 uint32_t **array_size,
3397 size_t *n_offsets) {
3411 if (!signature_is_single(contents, true))
3414 if (!c->signature || c->signature[c->index] == 0)
3417 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3420 if (!startswith(c->signature + c->index + 1, contents))
3425 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3428 r = message_peek_body(m, &rindex, 4, 4, &q);
3432 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3435 alignment = bus_type_get_alignment(contents[0]);
3439 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3443 *array_size = (uint32_t*) q;
3445 } else if (c->item_size <= 0) {
3447 /* gvariant: empty array */
3452 } else if (bus_gvariant_is_fixed_size(contents)) {
3454 /* gvariant: fixed length array */
3455 *item_size = bus_gvariant_get_size(contents);
3460 size_t where, p = 0, framing, sz;
3463 /* gvariant: variable length array */
3464 sz = determine_word_size(c->item_size, 0);
3466 where = rindex + c->item_size - sz;
3467 r = message_peek_body(m, &where, 1, sz, &q);
3471 framing = read_word_le(q, sz);
3472 if (framing > c->item_size - sz)
3474 if ((c->item_size - framing) % sz != 0)
3477 *n_offsets = (c->item_size - framing) / sz;
3479 where = rindex + framing;
3480 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3484 *offsets = new(size_t, *n_offsets);
3488 for (i = 0; i < *n_offsets; i++) {
3491 x = read_word_le((uint8_t*) q + i * sz, sz);
3492 if (x > c->item_size - sz)
3497 (*offsets)[i] = rindex + x;
3501 *item_size = (*offsets)[0] - rindex;
3506 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3507 c->index += 1 + strlen(contents);
3512 static int bus_message_enter_variant(
3514 struct bus_container *c,
3515 const char *contents,
3516 size_t *item_size) {
3528 if (!signature_is_single(contents, false))
3531 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3534 if (!c->signature || c->signature[c->index] == 0)
3537 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3542 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3545 k = strlen(contents);
3546 if (1+k > c->item_size)
3549 where = rindex + c->item_size - (1+k);
3550 r = message_peek_body(m, &where, 1, 1+k, &q);
3554 if (*(char*) q != 0)
3557 if (memcmp((uint8_t*) q+1, contents, k))
3560 *item_size = c->item_size - (1+k);
3563 r = message_peek_body(m, &rindex, 1, 1, &q);
3568 r = message_peek_body(m, &rindex, 1, l+1, &q);
3572 if (!validate_signature(q, l))
3575 if (!streq(q, contents))
3581 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3587 static int build_struct_offsets(
3589 const char *signature,
3593 size_t *n_offsets) {
3595 unsigned n_variable = 0, n_total = 0, v;
3596 size_t previous = 0, where;
3607 if (isempty(signature)) {
3614 sz = determine_word_size(size, 0);
3618 /* First, loop over signature and count variable elements and
3619 * elements in general. We use this to know how large the
3620 * offset array is at the end of the structure. Note that
3621 * GVariant only stores offsets for all variable size elements
3622 * that are not the last item. */
3628 r = signature_element_length(p, &n);
3637 r = bus_gvariant_is_fixed_size(t);
3642 if (r == 0 && p[n] != 0) /* except the last item */
3649 if (size < n_variable * sz)
3652 where = m->rindex + size - (n_variable * sz);
3653 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3659 *offsets = new(size_t, n_total);
3665 /* Second, loop again and build an offset table */
3671 r = signature_element_length(p, &n);
3680 k = bus_gvariant_get_size(t);
3688 x = read_word_le((uint8_t*) q + v*sz, sz);
3691 if (m->rindex + x < previous)
3694 /* The last item's end
3695 * is determined from
3698 x = size - (n_variable * sz);
3700 offset = m->rindex + x;
3706 align = bus_gvariant_get_alignment(t);
3709 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3713 previous = (*offsets)[(*n_offsets)++] = offset;
3718 assert(*n_offsets == n_total);
3720 *item_size = (*offsets)[0] - m->rindex;
3724 static int enter_struct_or_dict_entry(
3726 struct bus_container *c,
3727 const char *contents,
3730 size_t *n_offsets) {
3741 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3744 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3748 } else if (c->item_size <= 0) {
3750 /* gvariant empty struct */
3755 /* gvariant with contents */
3756 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3761 static int bus_message_enter_struct(
3763 struct bus_container *c,
3764 const char *contents,
3767 size_t *n_offsets) {
3779 if (!signature_is_valid(contents, false))
3782 if (!c->signature || c->signature[c->index] == 0)
3785 l = strlen(contents);
3787 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3788 !startswith(c->signature + c->index + 1, contents) ||
3789 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3792 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3796 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3797 c->index += 1 + l + 1;
3802 static int bus_message_enter_dict_entry(
3804 struct bus_container *c,
3805 const char *contents,
3808 size_t *n_offsets) {
3817 if (!signature_is_pair(contents))
3820 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3823 if (!c->signature || c->signature[c->index] == 0)
3826 l = strlen(contents);
3828 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3829 !startswith(c->signature + c->index + 1, contents) ||
3830 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3833 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3837 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3838 c->index += 1 + l + 1;
3843 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3845 const char *contents) {
3846 struct bus_container *c, *w;
3847 uint32_t *array_size = NULL;
3850 size_t *offsets = NULL;
3851 size_t n_offsets = 0, item_size = 0;
3854 assert_return(m, -EINVAL);
3855 assert_return(m->sealed, -EPERM);
3856 assert_return(type != 0 || !contents, -EINVAL);
3858 if (type == 0 || !contents) {
3862 /* Allow entering into anonymous containers */
3863 r = sd_bus_message_peek_type(m, &tt, &cc);
3867 if (type != 0 && type != tt)
3870 if (contents && !streq(contents, cc))
3878 * We enforce a global limit on container depth, that is much
3879 * higher than the 32 structs and 32 arrays the specification
3880 * mandates. This is simpler to implement for us, and we need
3881 * this only to ensure our container array doesn't grow
3882 * without bounds. We are happy to return any data from a
3883 * message as long as the data itself is valid, even if the
3884 * overall message might be not.
3886 * Note that the message signature is validated when
3887 * parsing the headers, and that validation does check the
3890 * Note that the specification defines no limits on the depth
3891 * of stacked variants, but we do.
3893 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3896 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3899 if (message_end_of_signature(m))
3902 if (message_end_of_array(m, m->rindex))
3905 c = message_get_container(m);
3907 signature = strdup(contents);
3911 c->saved_index = c->index;
3914 if (type == SD_BUS_TYPE_ARRAY)
3915 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3916 else if (type == SD_BUS_TYPE_VARIANT)
3917 r = bus_message_enter_variant(m, c, contents, &item_size);
3918 else if (type == SD_BUS_TYPE_STRUCT)
3919 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3920 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3921 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3931 /* OK, let's fill it in */
3932 w = m->containers + m->n_containers++;
3933 w->enclosing = type;
3934 w->signature = signature;
3935 w->peeked_signature = NULL;
3939 w->begin = m->rindex;
3940 w->end = m->rindex + c->item_size;
3942 w->array_size = array_size;
3943 w->item_size = item_size;
3944 w->offsets = offsets;
3945 w->n_offsets = n_offsets;
3946 w->offset_index = 0;
3951 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3952 struct bus_container *c;
3956 assert_return(m, -EINVAL);
3957 assert_return(m->sealed, -EPERM);
3958 assert_return(m->n_containers > 0, -ENXIO);
3960 c = message_get_container(m);
3962 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3963 if (c->signature && c->signature[c->index] != 0)
3967 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3968 if (m->rindex < c->end)
3971 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3974 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3975 if (c->begin + l != m->rindex)
3980 free(c->peeked_signature);
3984 c = message_get_container(m);
3987 c->index = c->saved_index;
3988 r = container_next_item(m, c, &m->rindex);
3996 static void message_quit_container(sd_bus_message *m) {
3997 struct bus_container *c;
4001 assert(m->n_containers > 0);
4003 c = message_get_container(m);
4006 assert(m->rindex >= c->before);
4007 m->rindex = c->before;
4009 /* Free container */
4014 /* Correct index of new top-level container */
4015 c = message_get_container(m);
4016 c->index = c->saved_index;
4019 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4020 struct bus_container *c;
4023 assert_return(m, -EINVAL);
4024 assert_return(m->sealed, -EPERM);
4026 if (message_end_of_signature(m))
4029 if (message_end_of_array(m, m->rindex))
4032 c = message_get_container(m);
4034 if (bus_type_is_basic(c->signature[c->index])) {
4038 *type = c->signature[c->index];
4042 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4048 r = signature_element_length(c->signature+c->index+1, &l);
4054 sig = strndup(c->signature + c->index + 1, l);
4058 free(c->peeked_signature);
4059 *contents = c->peeked_signature = sig;
4063 *type = SD_BUS_TYPE_ARRAY;
4068 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4069 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4075 r = signature_element_length(c->signature+c->index, &l);
4080 sig = strndup(c->signature + c->index + 1, l - 2);
4084 free(c->peeked_signature);
4085 *contents = c->peeked_signature = sig;
4089 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4094 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4098 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4101 if (c->item_size < 2)
4104 /* Look for the NUL delimiter that
4105 separates the payload from the
4106 signature. Since the body might be
4107 in a different part that then the
4108 signature we map byte by byte. */
4110 for (k = 2; k <= c->item_size; k++) {
4113 where = m->rindex + c->item_size - k;
4114 r = message_peek_body(m, &where, 1, k, &q);
4118 if (*(char*) q == 0)
4122 if (k > c->item_size)
4125 free(c->peeked_signature);
4126 c->peeked_signature = strndup((char*) q + 1, k - 1);
4127 if (!c->peeked_signature)
4130 if (!signature_is_valid(c->peeked_signature, true))
4133 *contents = c->peeked_signature;
4138 r = message_peek_body(m, &rindex, 1, 1, &q);
4143 r = message_peek_body(m, &rindex, 1, l+1, &q);
4147 if (!validate_signature(q, l))
4155 *type = SD_BUS_TYPE_VARIANT;
4170 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4171 struct bus_container *c;
4173 assert_return(m, -EINVAL);
4174 assert_return(m->sealed, -EPERM);
4177 message_reset_containers(m);
4180 c = message_get_container(m);
4182 c = message_get_container(m);
4184 c->offset_index = 0;
4186 m->rindex = c->begin;
4189 c->offset_index = 0;
4190 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4192 return !isempty(c->signature);
4195 static int message_read_ap(
4200 unsigned n_array, n_struct;
4201 TypeStack stack[BUS_CONTAINER_DEPTH];
4202 unsigned stack_ptr = 0;
4203 unsigned n_loop = 0;
4211 /* Ideally, we'd just call ourselves recursively on every
4212 * complex type. However, the state of a va_list that is
4213 * passed to a function is undefined after that function
4214 * returns. This means we need to docode the va_list linearly
4215 * in a single stackframe. We hence implement our own
4216 * home-grown stack in an array. */
4218 n_array = (unsigned) -1; /* length of current array entries */
4219 n_struct = strlen(types); /* length of current struct contents signature */
4226 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4227 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4233 r = sd_bus_message_exit_container(m);
4241 if (n_array != (unsigned) -1)
4250 case SD_BUS_TYPE_BYTE:
4251 case SD_BUS_TYPE_BOOLEAN:
4252 case SD_BUS_TYPE_INT16:
4253 case SD_BUS_TYPE_UINT16:
4254 case SD_BUS_TYPE_INT32:
4255 case SD_BUS_TYPE_UINT32:
4256 case SD_BUS_TYPE_INT64:
4257 case SD_BUS_TYPE_UINT64:
4258 case SD_BUS_TYPE_DOUBLE:
4259 case SD_BUS_TYPE_STRING:
4260 case SD_BUS_TYPE_OBJECT_PATH:
4261 case SD_BUS_TYPE_SIGNATURE:
4262 case SD_BUS_TYPE_UNIX_FD: {
4265 p = va_arg(ap, void*);
4266 r = sd_bus_message_read_basic(m, *t, p);
4279 case SD_BUS_TYPE_ARRAY: {
4282 r = signature_element_length(t + 1, &k);
4288 memcpy(s, t + 1, k);
4291 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4302 if (n_array == (unsigned) -1) {
4307 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4313 n_array = va_arg(ap, unsigned);
4318 case SD_BUS_TYPE_VARIANT: {
4321 s = va_arg(ap, const char *);
4325 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4335 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4340 n_struct = strlen(s);
4341 n_array = (unsigned) -1;
4346 case SD_BUS_TYPE_STRUCT_BEGIN:
4347 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4350 r = signature_element_length(t, &k);
4356 memcpy(s, t + 1, k - 2);
4359 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4369 if (n_array == (unsigned) -1) {
4374 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4380 n_array = (unsigned) -1;
4393 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4397 assert_return(m, -EINVAL);
4398 assert_return(m->sealed, -EPERM);
4399 assert_return(types, -EINVAL);
4401 va_start(ap, types);
4402 r = message_read_ap(m, types, ap);
4408 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4411 assert_return(m, -EINVAL);
4412 assert_return(m->sealed, -EPERM);
4413 assert_return(types, -EINVAL);
4420 case SD_BUS_TYPE_BYTE:
4421 case SD_BUS_TYPE_BOOLEAN:
4422 case SD_BUS_TYPE_INT16:
4423 case SD_BUS_TYPE_UINT16:
4424 case SD_BUS_TYPE_INT32:
4425 case SD_BUS_TYPE_UINT32:
4426 case SD_BUS_TYPE_INT64:
4427 case SD_BUS_TYPE_UINT64:
4428 case SD_BUS_TYPE_DOUBLE:
4429 case SD_BUS_TYPE_STRING:
4430 case SD_BUS_TYPE_OBJECT_PATH:
4431 case SD_BUS_TYPE_SIGNATURE:
4432 case SD_BUS_TYPE_UNIX_FD:
4434 r = sd_bus_message_read_basic(m, *types, NULL);
4438 r = sd_bus_message_skip(m, types + 1);
4444 case SD_BUS_TYPE_ARRAY: {
4447 r = signature_element_length(types + 1, &k);
4453 memcpy(s, types+1, k);
4456 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4461 r = sd_bus_message_skip(m, s);
4468 r = sd_bus_message_exit_container(m);
4473 r = sd_bus_message_skip(m, types + 1 + k);
4480 case SD_BUS_TYPE_VARIANT: {
4481 const char *contents;
4484 r = sd_bus_message_peek_type(m, &x, &contents);
4488 if (x != SD_BUS_TYPE_VARIANT)
4491 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4495 r = sd_bus_message_skip(m, contents);
4500 r = sd_bus_message_exit_container(m);
4504 r = sd_bus_message_skip(m, types + 1);
4511 case SD_BUS_TYPE_STRUCT_BEGIN:
4512 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4515 r = signature_element_length(types, &k);
4521 memcpy(s, types+1, k-2);
4524 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4528 r = sd_bus_message_skip(m, s);
4533 r = sd_bus_message_exit_container(m);
4538 r = sd_bus_message_skip(m, types + k);
4550 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4554 struct bus_container *c;
4560 assert_return(m, -EINVAL);
4561 assert_return(m->sealed, -EPERM);
4562 assert_return(bus_type_is_trivial(type), -EINVAL);
4563 assert_return(ptr, -EINVAL);
4564 assert_return(size, -EINVAL);
4565 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4567 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4571 c = message_get_container(m);
4573 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4574 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4578 sz = c->end - c->begin;
4580 align = bus_type_get_alignment(type);
4584 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4588 /* Zero length array, let's return some aligned
4589 * pointer that is not NULL */
4590 p = (uint8_t*) NULL + align;
4592 r = message_peek_body(m, &m->rindex, align, sz, &p);
4597 r = sd_bus_message_exit_container(m);
4601 *ptr = (const void*) p;
4607 message_quit_container(m);
4611 static int message_peek_fields(
4622 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4625 static int message_peek_field_uint32(
4637 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4640 /* identical for gvariant and dbus1 */
4642 r = message_peek_fields(m, ri, 4, 4, &q);
4647 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4652 static int message_peek_field_string(
4654 bool (*validate)(const char *p),
4666 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4671 r = message_peek_fields(m, ri, 1, item_size, &q);
4677 r = message_peek_field_uint32(m, ri, 4, &l);
4681 r = message_peek_fields(m, ri, 1, l+1, &q);
4687 if (!validate_nul(q, l))
4693 if (!validate_string(q, l))
4703 static int message_peek_field_signature(
4716 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4721 r = message_peek_fields(m, ri, 1, item_size, &q);
4727 r = message_peek_fields(m, ri, 1, 1, &q);
4732 r = message_peek_fields(m, ri, 1, l+1, &q);
4737 if (!validate_signature(q, l))
4746 static int message_skip_fields(
4749 uint32_t array_size,
4750 const char **signature) {
4752 size_t original_index;
4758 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4760 original_index = *ri;
4766 if (array_size != (uint32_t) -1 &&
4767 array_size <= *ri - original_index)
4774 if (t == SD_BUS_TYPE_STRING) {
4776 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4782 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4784 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4790 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4792 r = message_peek_field_signature(m, ri, 0, NULL);
4798 } else if (bus_type_is_basic(t)) {
4801 align = bus_type_get_alignment(t);
4802 k = bus_type_get_size(t);
4803 assert(align > 0 && k > 0);
4805 r = message_peek_fields(m, ri, align, k, NULL);
4811 } else if (t == SD_BUS_TYPE_ARRAY) {
4813 r = signature_element_length(*signature+1, &l);
4823 strncpy(sig, *signature + 1, l-1);
4826 alignment = bus_type_get_alignment(sig[0]);
4830 r = message_peek_field_uint32(m, ri, 0, &nas);
4833 if (nas > BUS_ARRAY_MAX_SIZE)
4836 r = message_peek_fields(m, ri, alignment, 0, NULL);
4840 r = message_skip_fields(m, ri, nas, (const char**) &s);
4845 (*signature) += 1 + l;
4847 } else if (t == SD_BUS_TYPE_VARIANT) {
4850 r = message_peek_field_signature(m, ri, 0, &s);
4854 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4860 } else if (t == SD_BUS_TYPE_STRUCT ||
4861 t == SD_BUS_TYPE_DICT_ENTRY) {
4863 r = signature_element_length(*signature, &l);
4870 strncpy(sig, *signature + 1, l-1);
4873 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4884 int bus_message_parse_fields(sd_bus_message *m) {
4887 uint32_t unix_fds = 0;
4888 bool unix_fds_set = false;
4889 void *offsets = NULL;
4890 unsigned n_offsets = 0;
4896 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4899 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4903 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4904 r = message_peek_fields(m, &ri, 1, sz, &q);
4908 framing = read_word_le(q, sz);
4909 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4911 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4915 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4919 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4924 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4925 _cleanup_free_ char *sig = NULL;
4926 const char *signature;
4928 size_t item_size = (size_t) -1;
4930 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4937 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4940 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4944 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4949 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4954 where = ri = ALIGN_TO(ri, 8);
4955 item_size = end - ri;
4956 r = message_peek_fields(m, &where, 1, item_size, &q);
4960 b = memrchr(q, 0, item_size);
4964 sig = strndup(b+1, item_size - (b+1-(char*) q));
4969 item_size = b - (char*) q;
4971 r = message_peek_field_signature(m, &ri, 0, &signature);
4977 case _BUS_MESSAGE_HEADER_INVALID:
4980 case BUS_MESSAGE_HEADER_PATH:
4985 if (!streq(signature, "o"))
4988 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
4991 case BUS_MESSAGE_HEADER_INTERFACE:
4996 if (!streq(signature, "s"))
4999 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5002 case BUS_MESSAGE_HEADER_MEMBER:
5007 if (!streq(signature, "s"))
5010 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5013 case BUS_MESSAGE_HEADER_ERROR_NAME:
5018 if (!streq(signature, "s"))
5021 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5023 m->error._need_free = -1;
5027 case BUS_MESSAGE_HEADER_DESTINATION:
5032 if (!streq(signature, "s"))
5035 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5038 case BUS_MESSAGE_HEADER_SENDER:
5043 if (!streq(signature, "s"))
5046 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5048 if (r >= 0 && m->sender[0] == ':' && m->bus && m->bus->bus_client && !m->bus->is_kernel) {
5049 m->creds.unique_name = (char*) m->sender;
5050 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5056 case BUS_MESSAGE_HEADER_SIGNATURE: {
5060 if (m->root_container.signature)
5063 if (!streq(signature, "g"))
5066 r = message_peek_field_signature(m, &ri, item_size, &s);
5074 free(m->root_container.signature);
5075 m->root_container.signature = c;
5079 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5082 if (m->reply_cookie != 0)
5085 if (!streq(signature, "u"))
5088 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5092 m->reply_cookie = serial;
5094 if (m->reply_cookie == 0)
5100 case BUS_MESSAGE_HEADER_UNIX_FDS:
5104 if (!streq(signature, "u"))
5107 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5111 unix_fds_set = true;
5115 if (!BUS_MESSAGE_IS_GVARIANT(m))
5116 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5125 if (m->n_fds != unix_fds)
5128 switch (m->header->type) {
5130 case SD_BUS_MESSAGE_SIGNAL:
5131 if (!m->path || !m->interface || !m->member)
5135 case SD_BUS_MESSAGE_METHOD_CALL:
5137 if (!m->path || !m->member)
5142 case SD_BUS_MESSAGE_METHOD_RETURN:
5144 if (m->reply_cookie == 0)
5148 case SD_BUS_MESSAGE_METHOD_ERROR:
5150 if (m->reply_cookie == 0 || !m->error.name)
5155 /* Refuse non-local messages that claim they are local */
5156 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5158 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5160 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5163 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5165 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5166 r = build_struct_offsets(
5168 m->root_container.signature,
5169 BUS_MESSAGE_BODY_SIZE(m),
5170 &m->root_container.item_size,
5171 &m->root_container.offsets,
5172 &m->root_container.n_offsets);
5177 /* Try to read the error message, but if we can't it's a non-issue */
5178 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5179 sd_bus_message_read(m, "s", &m->error.message);
5184 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5185 assert_return(m, -EINVAL);
5186 assert_return(destination, -EINVAL);
5187 assert_return(!m->sealed, -EPERM);
5188 assert_return(!m->destination, -EEXIST);
5190 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5193 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5197 struct bus_body_part *part;
5203 total = BUS_MESSAGE_SIZE(m);
5209 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5210 MESSAGE_FOREACH_PART(part, i, m)
5211 e = mempcpy(e, part->data, part->size);
5213 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5221 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5227 r = sd_bus_message_enter_container(m, 'a', "s");
5234 r = sd_bus_message_read_basic(m, 's', &s);
5240 r = strv_extend(l, s);
5245 r = sd_bus_message_exit_container(m);
5252 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5256 assert_return(m, -EINVAL);
5257 assert_return(m->sealed, -EPERM);
5258 assert_return(l, -EINVAL);
5260 r = bus_message_read_strv_extend(m, &strv);
5270 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5272 const char *t = NULL;
5277 r = sd_bus_message_rewind(m, true);
5281 for (j = 0; j <= i; j++) {
5284 r = sd_bus_message_peek_type(m, &type, NULL);
5288 if (type != SD_BUS_TYPE_STRING &&
5289 type != SD_BUS_TYPE_OBJECT_PATH &&
5290 type != SD_BUS_TYPE_SIGNATURE)
5293 r = sd_bus_message_read_basic(m, type, &t);
5301 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5307 if (size < sizeof(struct bus_header))
5310 full = sizeof(struct bus_header) +
5311 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5313 return size >= full;
5316 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5322 if (h->endian == BUS_NATIVE_ENDIAN) {
5323 fs = h->fields_size;
5325 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5326 fs = bswap_32(h->fields_size);
5327 bs = bswap_32(h->body_size);
5331 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5335 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5336 assert_return(m, -EINVAL);
5338 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5341 return sd_bus_error_get_errno(&m->error);
5344 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5345 struct bus_container *c;
5347 assert_return(m, NULL);
5349 c = complete ? &m->root_container : message_get_container(m);
5350 return strempty(c->signature);
5353 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5354 bool done_something = false;
5357 assert_return(m, -EINVAL);
5358 assert_return(source, -EINVAL);
5359 assert_return(!m->sealed, -EPERM);
5360 assert_return(source->sealed, -EPERM);
5363 const char *contents;
5378 r = sd_bus_message_peek_type(source, &type, &contents);
5384 done_something = true;
5386 if (bus_type_is_container(type) > 0) {
5388 r = sd_bus_message_enter_container(source, type, contents);
5392 r = sd_bus_message_open_container(m, type, contents);
5396 r = sd_bus_message_copy(m, source, true);
5400 r = sd_bus_message_close_container(m);
5404 r = sd_bus_message_exit_container(source);
5411 r = sd_bus_message_read_basic(source, type, &basic);
5417 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5418 type == SD_BUS_TYPE_SIGNATURE ||
5419 type == SD_BUS_TYPE_STRING)
5420 r = sd_bus_message_append_basic(m, type, basic.string);
5422 r = sd_bus_message_append_basic(m, type, &basic);
5429 return done_something;
5432 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5437 assert_return(m, -EINVAL);
5438 assert_return(m->sealed, -EPERM);
5439 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5440 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5441 assert_return(type || contents, -EINVAL);
5442 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5444 r = sd_bus_message_peek_type(m, &t, &c);
5448 if (type != 0 && type != t)
5451 if (contents && !streq_ptr(contents, c))
5457 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5458 assert_return(m, NULL);
5463 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5464 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5472 switch ((*m)->header->type) {
5474 case SD_BUS_MESSAGE_SIGNAL:
5475 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5481 case SD_BUS_MESSAGE_METHOD_CALL:
5482 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5488 case SD_BUS_MESSAGE_METHOD_RETURN:
5489 case SD_BUS_MESSAGE_METHOD_ERROR:
5491 n = message_new(bus, (*m)->header->type);
5495 n->reply_cookie = (*m)->reply_cookie;
5496 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5500 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5501 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5505 n->error._need_free = -1;
5514 if ((*m)->destination && !n->destination) {
5515 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5520 if ((*m)->sender && !n->sender) {
5521 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5526 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5528 r = sd_bus_message_copy(n, *m, true);
5532 timeout = (*m)->timeout;
5533 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5534 timeout = BUS_DEFAULT_TIMEOUT;
5536 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5540 sd_bus_message_unref(*m);
5547 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5551 assert_return(!m->sealed, -EPERM);
5552 assert_return(!m->sender, -EPERM);
5554 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5557 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5558 assert_return(m, -EINVAL);
5559 assert_return(priority, -EINVAL);
5561 *priority = m->priority;
5565 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5566 assert_return(m, -EINVAL);
5567 assert_return(!m->sealed, -EPERM);
5569 m->priority = priority;