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_usec(sd_bus_message *m, uint64_t *usec) {
884 assert_return(m, -EINVAL);
885 assert_return(usec, -EINVAL);
887 if (m->monotonic <= 0)
890 *usec = m->monotonic;
894 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
895 assert_return(m, -EINVAL);
896 assert_return(usec, -EINVAL);
898 if (m->realtime <= 0)
905 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
906 assert_return(m, -EINVAL);
907 assert_return(seqnum, -EINVAL);
916 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
917 assert_return(m, NULL);
919 if (m->creds.mask == 0)
925 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
926 const char *interface,
927 const char *member) {
928 assert_return(m, -EINVAL);
930 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
933 if (interface && (!m->interface || !streq(m->interface, interface)))
936 if (member && (!m->member || !streq(m->member, member)))
942 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
943 const char *interface,
944 const char *member) {
945 assert_return(m, -EINVAL);
947 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
950 if (interface && (!m->interface || !streq(m->interface, interface)))
953 if (member && (!m->member || !streq(m->member, member)))
959 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
960 assert_return(m, -EINVAL);
962 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
965 if (name && (!m->error.name || !streq(m->error.name, name)))
971 _public_ int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
972 assert_return(m, -EINVAL);
973 assert_return(!m->sealed, -EPERM);
974 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
977 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
979 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
984 _public_ int sd_bus_message_set_no_auto_start(sd_bus_message *m, int b) {
985 assert_return(m, -EINVAL);
986 assert_return(!m->sealed, -EPERM);
989 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
991 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
996 static struct bus_container *message_get_container(sd_bus_message *m) {
999 if (m->n_containers == 0)
1000 return &m->root_container;
1002 assert(m->containers);
1003 return m->containers + m->n_containers - 1;
1006 struct bus_body_part *message_append_part(sd_bus_message *m) {
1007 struct bus_body_part *part;
1014 if (m->n_body_parts <= 0) {
1018 assert(m->body_end);
1020 part = new0(struct bus_body_part, 1);
1026 m->body_end->next = part;
1036 static void part_zero(struct bus_body_part *part, size_t sz) {
1041 /* All other fields can be left in their defaults */
1042 assert(!part->data);
1043 assert(part->memfd < 0);
1046 part->is_zero = true;
1047 part->sealed = true;
1050 static int part_make_space(
1051 struct sd_bus_message *m,
1052 struct bus_body_part *part,
1061 assert(!part->sealed);
1066 if (!part->data && part->memfd < 0)
1067 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1069 if (part->memfd >= 0) {
1071 if (part->allocated == 0 || sz > part->allocated) {
1072 uint64_t new_allocated;
1074 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1075 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &new_allocated);
1081 part->allocated = new_allocated;
1084 if (!part->data || sz > part->mapped) {
1087 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1088 if (part->mapped <= 0)
1089 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1091 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1093 if (n == MAP_FAILED) {
1102 part->munmap_this = true;
1104 if (part->allocated == 0 || sz > part->allocated) {
1105 size_t new_allocated;
1107 new_allocated = sz > 0 ? 2 * sz : 64;
1108 n = realloc(part->data, new_allocated);
1115 part->allocated = new_allocated;
1116 part->free_this = true;
1121 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1127 static int message_add_offset(sd_bus_message *m, size_t offset) {
1128 struct bus_container *c;
1131 assert(BUS_MESSAGE_IS_GVARIANT(m));
1133 /* Add offset to current container, unless this is the first
1134 * item in it, which will have the 0 offset, which we can
1136 c = message_get_container(m);
1138 if (!c->need_offsets)
1141 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1144 c->offsets[c->n_offsets++] = offset;
1148 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1149 struct bus_container *c;
1156 /* Update counters */
1157 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1160 *c->array_size += expand;
1164 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1165 size_t start_body, end_body, padding, added;
1176 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1177 end_body = start_body + sz;
1179 padding = start_body - m->header->body_size;
1180 added = padding + sz;
1182 /* Check for 32bit overflows */
1183 if (end_body > (size_t) ((uint32_t) -1)) {
1189 struct bus_body_part *part = NULL;
1193 m->n_body_parts <= 0 ||
1194 m->body_end->sealed ||
1195 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1199 part = message_append_part(m);
1203 part_zero(part, padding);
1206 part = message_append_part(m);
1210 r = part_make_space(m, part, sz, &p);
1214 struct bus_container *c;
1216 size_t os, start_part, end_part;
1222 start_part = ALIGN_TO(part->size, align);
1223 end_part = start_part + sz;
1225 r = part_make_space(m, part, end_part, &p);
1230 memset(p, 0, padding);
1231 p = (uint8_t*) p + padding;
1234 /* Readjust pointers */
1235 for (c = m->containers; c < m->containers + m->n_containers; c++)
1236 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1238 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1241 /* Return something that is not NULL and is aligned */
1242 p = (uint8_t *) NULL + align;
1244 m->header->body_size = end_body;
1245 message_extend_containers(m, added);
1248 r = message_add_offset(m, end_body);
1258 static int message_push_fd(sd_bus_message *m, int fd) {
1269 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1273 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1276 close_nointr_nofail(copy);
1281 m->fds[m->n_fds] = copy;
1287 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1288 _cleanup_close_ int fd = -1;
1289 struct bus_container *c;
1293 assert_return(m, -EINVAL);
1294 assert_return(!m->sealed, -EPERM);
1295 assert_return(bus_type_is_basic(type), -EINVAL);
1296 assert_return(!m->poisoned, -ESTALE);
1298 c = message_get_container(m);
1300 if (c->signature && c->signature[c->index]) {
1301 /* Container signature is already set */
1303 if (c->signature[c->index] != type)
1308 /* Maybe we can append to the signature? But only if this is the top-level container*/
1309 if (c->enclosing != 0)
1312 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1319 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1325 case SD_BUS_TYPE_SIGNATURE:
1326 case SD_BUS_TYPE_STRING:
1329 /* Fall through... */
1330 case SD_BUS_TYPE_OBJECT_PATH:
1338 case SD_BUS_TYPE_BOOLEAN:
1340 u8 = p && *(int*) p;
1346 case SD_BUS_TYPE_UNIX_FD:
1351 fd = message_push_fd(m, *(int*) p);
1362 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1363 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1370 a = message_extend_body(m, align, sz, true);
1377 *stored = (const uint8_t*) a;
1384 case SD_BUS_TYPE_STRING:
1385 /* To make things easy we'll serialize a NULL string
1386 * into the empty string */
1389 /* Fall through... */
1390 case SD_BUS_TYPE_OBJECT_PATH:
1396 sz = 4 + strlen(p) + 1;
1399 case SD_BUS_TYPE_SIGNATURE:
1404 sz = 1 + strlen(p) + 1;
1407 case SD_BUS_TYPE_BOOLEAN:
1409 u32 = p && *(int*) p;
1415 case SD_BUS_TYPE_UNIX_FD:
1420 fd = message_push_fd(m, *(int*) p);
1431 align = bus_type_get_alignment(type);
1432 sz = bus_type_get_size(type);
1439 a = message_extend_body(m, align, sz, false);
1443 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1444 *(uint32_t*) a = sz - 5;
1445 memcpy((uint8_t*) a + 4, p, sz - 4);
1448 *stored = (const uint8_t*) a + 4;
1450 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1451 *(uint8_t*) a = sz - 2;
1452 memcpy((uint8_t*) a + 1, p, sz - 1);
1455 *stored = (const uint8_t*) a + 1;
1464 if (type == SD_BUS_TYPE_UNIX_FD)
1467 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1474 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1475 return message_append_basic(m, type, p, NULL);
1478 _public_ int sd_bus_message_append_string_space(
1483 struct bus_container *c;
1486 assert_return(m, -EINVAL);
1487 assert_return(s, -EINVAL);
1488 assert_return(!m->sealed, -EPERM);
1489 assert_return(!m->poisoned, -ESTALE);
1491 c = message_get_container(m);
1493 if (c->signature && c->signature[c->index]) {
1494 /* Container signature is already set */
1496 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1501 /* Maybe we can append to the signature? But only if this is the top-level container*/
1502 if (c->enclosing != 0)
1505 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1512 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1513 a = message_extend_body(m, 1, size + 1, true);
1519 a = message_extend_body(m, 4, 4 + size + 1, false);
1523 *(uint32_t*) a = size;
1529 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1535 _public_ int sd_bus_message_append_string_iovec(
1537 const struct iovec *iov,
1545 assert_return(m, -EINVAL);
1546 assert_return(!m->sealed, -EPERM);
1547 assert_return(iov || n == 0, -EINVAL);
1548 assert_return(!m->poisoned, -ESTALE);
1550 size = IOVEC_TOTAL_SIZE(iov, n);
1552 r = sd_bus_message_append_string_space(m, size, &p);
1556 for (i = 0; i < n; i++) {
1558 if (iov[i].iov_base)
1559 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1561 memset(p, ' ', iov[i].iov_len);
1563 p += iov[i].iov_len;
1569 static int bus_message_open_array(
1571 struct bus_container *c,
1572 const char *contents,
1573 uint32_t **array_size,
1575 bool *need_offsets) {
1585 assert(need_offsets);
1587 if (!signature_is_single(contents, true))
1590 if (c->signature && c->signature[c->index]) {
1592 /* Verify the existing signature */
1594 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1597 if (!startswith(c->signature + c->index + 1, contents))
1600 nindex = c->index + 1 + strlen(contents);
1604 if (c->enclosing != 0)
1607 /* Extend the existing signature */
1609 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1615 nindex = e - c->signature;
1618 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1619 alignment = bus_gvariant_get_alignment(contents);
1623 /* Add alignment padding and add to offset list */
1624 if (!message_extend_body(m, alignment, 0, false))
1627 r = bus_gvariant_is_fixed_size(contents);
1631 *begin = m->header->body_size;
1632 *need_offsets = r == 0;
1636 struct bus_body_part *o;
1638 alignment = bus_type_get_alignment(contents[0]);
1642 a = message_extend_body(m, 4, 4, false);
1647 op = m->body_end->data;
1648 os = m->body_end->size;
1650 /* Add alignment between size and first element */
1651 if (!message_extend_body(m, alignment, 0, false))
1654 /* location of array size might have changed so let's readjust a */
1655 if (o == m->body_end)
1656 a = adjust_pointer(a, op, os, m->body_end->data);
1662 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1668 static int bus_message_open_variant(
1670 struct bus_container *c,
1671 const char *contents) {
1677 if (!signature_is_single(contents, false))
1680 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1683 if (c->signature && c->signature[c->index]) {
1685 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1691 if (c->enclosing != 0)
1694 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1701 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1702 /* Variants are always aligned to 8 */
1704 if (!message_extend_body(m, 8, 0, false))
1711 l = strlen(contents);
1712 a = message_extend_body(m, 1, 1 + l + 1, false);
1717 memcpy((uint8_t*) a + 1, contents, l + 1);
1720 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1726 static int bus_message_open_struct(
1728 struct bus_container *c,
1729 const char *contents,
1731 bool *need_offsets) {
1740 assert(need_offsets);
1742 if (!signature_is_valid(contents, false))
1745 if (c->signature && c->signature[c->index]) {
1748 l = strlen(contents);
1750 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1751 !startswith(c->signature + c->index + 1, contents) ||
1752 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1755 nindex = c->index + 1 + l + 1;
1759 if (c->enclosing != 0)
1762 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1768 nindex = e - c->signature;
1771 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1774 alignment = bus_gvariant_get_alignment(contents);
1778 if (!message_extend_body(m, alignment, 0, false))
1781 r = bus_gvariant_is_fixed_size(contents);
1785 *begin = m->header->body_size;
1786 *need_offsets = r == 0;
1788 /* Align contents to 8 byte boundary */
1789 if (!message_extend_body(m, 8, 0, false))
1793 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1799 static int bus_message_open_dict_entry(
1801 struct bus_container *c,
1802 const char *contents,
1804 bool *need_offsets) {
1812 assert(need_offsets);
1814 if (!signature_is_pair(contents))
1817 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1820 if (c->signature && c->signature[c->index]) {
1823 l = strlen(contents);
1825 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1826 !startswith(c->signature + c->index + 1, contents) ||
1827 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1832 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1835 alignment = bus_gvariant_get_alignment(contents);
1839 if (!message_extend_body(m, alignment, 0, false))
1842 r = bus_gvariant_is_fixed_size(contents);
1846 *begin = m->header->body_size;
1847 *need_offsets = r == 0;
1849 /* Align contents to 8 byte boundary */
1850 if (!message_extend_body(m, 8, 0, false))
1857 _public_ int sd_bus_message_open_container(
1860 const char *contents) {
1862 struct bus_container *c, *w;
1863 uint32_t *array_size = NULL;
1865 size_t before, begin;
1866 bool need_offsets = false;
1869 assert_return(m, -EINVAL);
1870 assert_return(!m->sealed, -EPERM);
1871 assert_return(contents, -EINVAL);
1872 assert_return(!m->poisoned, -ESTALE);
1874 /* Make sure we have space for one more container */
1875 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1880 c = message_get_container(m);
1882 signature = strdup(contents);
1888 /* Save old index in the parent container, in case we have to
1889 * abort this container */
1890 c->saved_index = c->index;
1891 before = m->header->body_size;
1893 if (type == SD_BUS_TYPE_ARRAY)
1894 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1895 else if (type == SD_BUS_TYPE_VARIANT)
1896 r = bus_message_open_variant(m, c, contents);
1897 else if (type == SD_BUS_TYPE_STRUCT)
1898 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1899 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1900 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1909 /* OK, let's fill it in */
1910 w = m->containers + m->n_containers++;
1911 w->enclosing = type;
1912 w->signature = signature;
1914 w->array_size = array_size;
1917 w->n_offsets = w->offsets_allocated = 0;
1919 w->need_offsets = need_offsets;
1924 static size_t determine_word_size(size_t sz, size_t extra) {
1925 if (sz + extra <= 0xFF)
1927 else if (sz + extra*2 <= 0xFFFF)
1929 else if (sz + extra*4 <= 0xFFFFFFFF)
1935 static size_t read_word_le(void *p, size_t sz) {
1945 return *(uint8_t*) p;
1950 return le16toh(x.u16);
1952 return le32toh(x.u32);
1954 return le64toh(x.u64);
1956 assert_not_reached("unknown word width");
1959 static void write_word_le(void *p, size_t sz, size_t value) {
1967 assert(sz == 8 || (value < (1ULL << (sz*8))));
1970 *(uint8_t*) p = value;
1973 x.u16 = htole16((uint16_t) value);
1975 x.u32 = htole32((uint32_t) value);
1977 x.u64 = htole64((uint64_t) value);
1979 assert_not_reached("unknown word width");
1984 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1989 if (!BUS_MESSAGE_IS_GVARIANT(m))
1992 if (c->need_offsets) {
1993 size_t payload, sz, i;
1996 /* Variable-width arrays */
1998 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
1999 sz = determine_word_size(payload, c->n_offsets);
2001 a = message_extend_body(m, 1, sz * c->n_offsets, true);
2005 for (i = 0; i < c->n_offsets; i++)
2006 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2010 /* Fixed-width or empty arrays */
2012 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
2020 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2027 if (!BUS_MESSAGE_IS_GVARIANT(m))
2030 l = strlen(c->signature);
2032 a = message_extend_body(m, 1, 1 + l, true);
2037 memcpy(a+1, c->signature, l);
2042 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2043 size_t n_variable = 0;
2052 if (!BUS_MESSAGE_IS_GVARIANT(m))
2055 p = strempty(c->signature);
2059 r = signature_element_length(p, &n);
2068 r = bus_gvariant_is_fixed_size(t);
2073 assert(!c->need_offsets || i <= c->n_offsets);
2075 /* We need to add an offset for each item that has a
2076 * variable size and that is not the last one in the
2078 if (r == 0 && p[n] != 0)
2085 assert(!c->need_offsets || i == c->n_offsets);
2086 assert(c->need_offsets || n_variable == 0);
2088 if (n_variable <= 0) {
2089 a = message_extend_body(m, 1, 0, add_offset);
2096 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2098 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2100 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2104 p = strempty(c->signature);
2105 for (i = 0, j = 0; i < c->n_offsets; i++) {
2109 r = signature_element_length(p, &n);
2120 r = bus_gvariant_is_fixed_size(t);
2123 if (r > 0 || p[0] == 0)
2127 k = n_variable - 1 - j;
2129 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2138 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2139 struct bus_container *c;
2142 assert_return(m, -EINVAL);
2143 assert_return(!m->sealed, -EPERM);
2144 assert_return(m->n_containers > 0, -EINVAL);
2145 assert_return(!m->poisoned, -ESTALE);
2147 c = message_get_container(m);
2149 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2150 if (c->signature && c->signature[c->index] != 0)
2155 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2156 r = bus_message_close_array(m, c);
2157 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2158 r = bus_message_close_variant(m, c);
2159 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2160 r = bus_message_close_struct(m, c, true);
2162 assert_not_reached("Unknown container type");
2176 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2183 stack[*i].types = types;
2184 stack[*i].n_struct = n_struct;
2185 stack[*i].n_array = n_array;
2191 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2202 *types = stack[*i].types;
2203 *n_struct = stack[*i].n_struct;
2204 *n_array = stack[*i].n_array;
2209 int bus_message_append_ap(
2214 unsigned n_array, n_struct;
2215 TypeStack stack[BUS_CONTAINER_DEPTH];
2216 unsigned stack_ptr = 0;
2224 n_array = (unsigned) -1;
2225 n_struct = strlen(types);
2230 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2231 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2237 r = sd_bus_message_close_container(m);
2245 if (n_array != (unsigned) -1)
2254 case SD_BUS_TYPE_BYTE: {
2257 x = (uint8_t) va_arg(ap, int);
2258 r = sd_bus_message_append_basic(m, *t, &x);
2262 case SD_BUS_TYPE_BOOLEAN:
2263 case SD_BUS_TYPE_INT32:
2264 case SD_BUS_TYPE_UINT32:
2265 case SD_BUS_TYPE_UNIX_FD: {
2268 /* We assume a boolean is the same as int32_t */
2269 assert_cc(sizeof(int32_t) == sizeof(int));
2271 x = va_arg(ap, uint32_t);
2272 r = sd_bus_message_append_basic(m, *t, &x);
2276 case SD_BUS_TYPE_INT16:
2277 case SD_BUS_TYPE_UINT16: {
2280 x = (uint16_t) va_arg(ap, int);
2281 r = sd_bus_message_append_basic(m, *t, &x);
2285 case SD_BUS_TYPE_INT64:
2286 case SD_BUS_TYPE_UINT64:
2287 case SD_BUS_TYPE_DOUBLE: {
2290 x = va_arg(ap, uint64_t);
2291 r = sd_bus_message_append_basic(m, *t, &x);
2295 case SD_BUS_TYPE_STRING:
2296 case SD_BUS_TYPE_OBJECT_PATH:
2297 case SD_BUS_TYPE_SIGNATURE: {
2300 x = va_arg(ap, const char*);
2301 r = sd_bus_message_append_basic(m, *t, x);
2305 case SD_BUS_TYPE_ARRAY: {
2308 r = signature_element_length(t + 1, &k);
2314 memcpy(s, t + 1, k);
2317 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2322 if (n_array == (unsigned) -1) {
2327 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2333 n_array = va_arg(ap, unsigned);
2338 case SD_BUS_TYPE_VARIANT: {
2341 s = va_arg(ap, const char*);
2345 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2349 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2354 n_struct = strlen(s);
2355 n_array = (unsigned) -1;
2360 case SD_BUS_TYPE_STRUCT_BEGIN:
2361 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2364 r = signature_element_length(t, &k);
2371 memcpy(s, t + 1, k - 2);
2374 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2379 if (n_array == (unsigned) -1) {
2384 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2390 n_array = (unsigned) -1;
2406 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2410 assert_return(m, -EINVAL);
2411 assert_return(types, -EINVAL);
2412 assert_return(!m->sealed, -EPERM);
2413 assert_return(!m->poisoned, -ESTALE);
2415 va_start(ap, types);
2416 r = bus_message_append_ap(m, types, ap);
2422 _public_ int sd_bus_message_append_array_space(
2432 assert_return(m, -EINVAL);
2433 assert_return(!m->sealed, -EPERM);
2434 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2435 assert_return(ptr || size == 0, -EINVAL);
2436 assert_return(!m->poisoned, -ESTALE);
2438 /* alignment and size of the trivial types (except bool) is
2439 * identical for gvariant and dbus1 marshalling */
2440 align = bus_type_get_alignment(type);
2441 sz = bus_type_get_size(type);
2443 assert_se(align > 0);
2449 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2453 a = message_extend_body(m, align, size, false);
2457 r = sd_bus_message_close_container(m);
2465 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2472 assert_return(m, -EINVAL);
2473 assert_return(!m->sealed, -EPERM);
2474 assert_return(bus_type_is_trivial(type), -EINVAL);
2475 assert_return(ptr || size == 0, -EINVAL);
2476 assert_return(!m->poisoned, -ESTALE);
2478 r = sd_bus_message_append_array_space(m, type, size, &p);
2483 memcpy(p, ptr, size);
2488 _public_ int sd_bus_message_append_array_iovec(
2491 const struct iovec *iov,
2499 assert_return(m, -EINVAL);
2500 assert_return(!m->sealed, -EPERM);
2501 assert_return(bus_type_is_trivial(type), -EINVAL);
2502 assert_return(iov || n == 0, -EINVAL);
2503 assert_return(!m->poisoned, -ESTALE);
2505 size = IOVEC_TOTAL_SIZE(iov, n);
2507 r = sd_bus_message_append_array_space(m, type, size, &p);
2511 for (i = 0; i < n; i++) {
2513 if (iov[i].iov_base)
2514 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2516 memset(p, 0, iov[i].iov_len);
2518 p = (uint8_t*) p + iov[i].iov_len;
2524 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2527 _cleanup_close_ int copy_fd = -1;
2528 struct bus_body_part *part;
2540 if (!bus_type_is_trivial(type))
2545 r = sd_memfd_set_sealed(memfd, true);
2549 copy_fd = sd_memfd_dup_fd(memfd);
2553 r = sd_memfd_get_size(memfd, &size);
2557 align = bus_type_get_alignment(type);
2558 sz = bus_type_get_size(type);
2560 assert_se(align > 0);
2566 if (size > (uint64_t) (uint32_t) -1)
2569 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2573 a = message_extend_body(m, align, 0, false);
2577 part = message_append_part(m);
2581 part->memfd = copy_fd;
2582 part->sealed = true;
2586 m->header->body_size += size;
2587 message_extend_containers(m, size);
2589 return sd_bus_message_close_container(m);
2592 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
2593 _cleanup_close_ int copy_fd = -1;
2594 struct bus_body_part *part;
2595 struct bus_container *c;
2600 assert_return(m, -EINVAL);
2601 assert_return(memfd, -EINVAL);
2602 assert_return(!m->sealed, -EPERM);
2603 assert_return(!m->poisoned, -ESTALE);
2605 r = sd_memfd_set_sealed(memfd, true);
2609 copy_fd = sd_memfd_dup_fd(memfd);
2613 r = sd_memfd_get_size(memfd, &size);
2617 /* We require this to be NUL terminated */
2621 if (size > (uint64_t) (uint32_t) -1)
2624 c = message_get_container(m);
2625 if (c->signature && c->signature[c->index]) {
2626 /* Container signature is already set */
2628 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2633 /* Maybe we can append to the signature? But only if this is the top-level container*/
2634 if (c->enclosing != 0)
2637 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2644 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2645 a = message_extend_body(m, 4, 4, false);
2649 *(uint32_t*) a = size - 1;
2652 part = message_append_part(m);
2656 part->memfd = copy_fd;
2657 part->sealed = true;
2661 m->header->body_size += size;
2662 message_extend_containers(m, size);
2664 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2665 r = message_add_offset(m, m->header->body_size);
2672 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2678 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2682 assert_return(m, -EINVAL);
2683 assert_return(!m->sealed, -EPERM);
2684 assert_return(!m->poisoned, -ESTALE);
2686 r = sd_bus_message_open_container(m, 'a', "s");
2690 STRV_FOREACH(i, l) {
2691 r = sd_bus_message_append_basic(m, 's', *i);
2696 return sd_bus_message_close_container(m);
2699 static int bus_message_close_header(sd_bus_message *m) {
2705 if (!BUS_MESSAGE_IS_GVARIANT(m))
2708 if (m->n_header_offsets < 1)
2711 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2713 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2715 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2719 for (i = 0; i < m->n_header_offsets; i++)
2720 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2725 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2726 struct bus_body_part *part;
2736 if (m->n_containers > 0)
2742 /* In vtables the return signature of method calls is listed,
2743 * let's check if they match if this is a response */
2744 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2745 m->enforced_reply_signature &&
2746 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2749 /* If gvariant marshalling is used we need to close the body structure */
2750 r = bus_message_close_struct(m, &m->root_container, false);
2754 /* If there's a non-trivial signature set, then add it in here */
2755 if (!isempty(m->root_container.signature)) {
2756 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2762 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2767 r = bus_message_close_header(m);
2771 m->header->serial = (uint32_t) cookie;
2772 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2774 /* Add padding at the end of the fields part, since we know
2775 * the body needs to start at an 8 byte alignment. We made
2776 * sure we allocated enough space for this, so all we need to
2777 * do here is to zero it out. */
2778 l = BUS_MESSAGE_FIELDS_SIZE(m);
2781 memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
2783 /* If this is something we can send as memfd, then let's seal
2784 the memfd now. Note that we can send memfds as payload only
2785 for directed messages, and not for broadcasts. */
2786 if (m->destination && m->bus && m->bus->use_memfd) {
2787 MESSAGE_FOREACH_PART(part, i, m)
2788 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2791 /* Try to seal it if that makes
2792 * sense. First, unmap our own map to
2793 * make sure we don't keep it busy. */
2794 bus_body_part_unmap(part);
2796 /* Then, sync up real memfd size */
2798 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &sz) < 0)
2801 /* Finally, try to seal */
2802 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
2803 part->sealed = true;
2807 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2808 m->root_container.index = 0;
2809 m->root_container.offset_index = 0;
2810 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2817 int bus_body_part_map(struct bus_body_part *part) {
2826 if (part->size <= 0)
2829 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2830 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2831 static const uint8_t zeroes[7] = { };
2832 part->data = (void*) zeroes;
2836 psz = PAGE_ALIGN(part->size);
2838 if (part->memfd >= 0)
2839 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2840 else if (part->is_zero)
2841 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2845 if (p == MAP_FAILED)
2850 part->munmap_this = true;
2855 void bus_body_part_unmap(struct bus_body_part *part) {
2859 if (part->memfd < 0)
2865 if (!part->munmap_this)
2868 assert_se(munmap(part->data, part->mapped) == 0);
2872 part->munmap_this = false;
2877 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2878 size_t k, start, end;
2883 start = ALIGN_TO((size_t) *rindex, align);
2884 end = start + nbytes;
2889 /* Verify that padding is 0 */
2890 for (k = *rindex; k < start; k++)
2891 if (((const uint8_t*) p)[k] != 0)
2895 *r = (uint8_t*) p + start;
2902 static bool message_end_of_signature(sd_bus_message *m) {
2903 struct bus_container *c;
2907 c = message_get_container(m);
2908 return !c->signature || c->signature[c->index] == 0;
2911 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2912 struct bus_container *c;
2916 c = message_get_container(m);
2917 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2920 if (BUS_MESSAGE_IS_GVARIANT(m))
2921 return index >= c->end;
2923 assert(c->array_size);
2924 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2928 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2929 assert_return(m, -EINVAL);
2930 assert_return(m->sealed, -EPERM);
2932 if (complete && m->n_containers > 0)
2935 if (message_end_of_signature(m))
2938 if (message_end_of_array(m, m->rindex))
2944 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2945 struct bus_body_part *part;
2951 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2952 part = m->cached_rindex_part;
2953 begin = m->cached_rindex_part_begin;
2963 if (index + sz <= begin + part->size) {
2965 r = bus_body_part_map(part);
2970 *p = (uint8_t*) part->data + index - begin;
2972 m->cached_rindex_part = part;
2973 m->cached_rindex_part_begin = begin;
2978 begin += part->size;
2985 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2992 if (!BUS_MESSAGE_IS_GVARIANT(m))
2995 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2998 sz = bus_gvariant_get_size(c->signature);
3002 if (c->offset_index+1 >= c->n_offsets)
3005 /* Variable-size array */
3007 alignment = bus_gvariant_get_alignment(c->signature);
3008 assert(alignment > 0);
3010 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3011 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3014 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3017 /* Fixed-size array */
3018 *rindex = c->begin + (c->offset_index+1) * sz;
3024 } else if (c->enclosing == 0 ||
3025 c->enclosing == SD_BUS_TYPE_STRUCT ||
3026 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3031 if (c->offset_index+1 >= c->n_offsets)
3034 r = signature_element_length(c->signature + c->index, &n);
3038 r = signature_element_length(c->signature + c->index + n, &j);
3043 memcpy(t, c->signature + c->index + n, j);
3046 alignment = bus_gvariant_get_alignment(t);
3049 assert(alignment > 0);
3051 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3052 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3056 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3059 assert_not_reached("Unknown container type");
3064 /* Reached the end */
3071 static int message_peek_body(
3078 size_t k, start, end, padding;
3079 struct bus_body_part *part;
3086 start = ALIGN_TO((size_t) *rindex, align);
3087 padding = start - *rindex;
3088 end = start + nbytes;
3090 if (end > BUS_MESSAGE_BODY_SIZE(m))
3093 part = find_part(m, *rindex, padding, (void**) &q);
3098 /* Verify padding */
3099 for (k = 0; k < padding; k++)
3104 part = find_part(m, start, nbytes, (void**) &q);
3105 if (!part || (nbytes > 0 && !q))
3116 static bool validate_nul(const char *s, size_t l) {
3118 /* Check for NUL chars in the string */
3119 if (memchr(s, 0, l))
3122 /* Check for NUL termination */
3129 static bool validate_string(const char *s, size_t l) {
3131 if (!validate_nul(s, l))
3134 /* Check if valid UTF8 */
3135 if (!utf8_is_valid(s))
3141 static bool validate_signature(const char *s, size_t l) {
3143 if (!validate_nul(s, l))
3146 /* Check if valid signature */
3147 if (!signature_is_valid(s, true))
3153 static bool validate_object_path(const char *s, size_t l) {
3155 if (!validate_nul(s, l))
3158 if (!object_path_is_valid(s))
3164 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3165 struct bus_container *c;
3170 assert_return(m, -EINVAL);
3171 assert_return(m->sealed, -EPERM);
3172 assert_return(bus_type_is_basic(type), -EINVAL);
3174 if (message_end_of_signature(m))
3177 if (message_end_of_array(m, m->rindex))
3180 c = message_get_container(m);
3181 if (c->signature[c->index] != type)
3186 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3188 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3191 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3195 if (type == SD_BUS_TYPE_STRING)
3196 ok = validate_string(q, c->item_size-1);
3197 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3198 ok = validate_object_path(q, c->item_size-1);
3200 ok = validate_signature(q, c->item_size-1);
3206 *(const char**) p = q;
3210 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3212 if ((size_t) sz != c->item_size)
3215 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3218 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3224 case SD_BUS_TYPE_BYTE:
3226 *(uint8_t*) p = *(uint8_t*) q;
3229 case SD_BUS_TYPE_BOOLEAN:
3231 *(int*) p = !!*(uint8_t*) q;
3234 case SD_BUS_TYPE_INT16:
3235 case SD_BUS_TYPE_UINT16:
3237 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3240 case SD_BUS_TYPE_INT32:
3241 case SD_BUS_TYPE_UINT32:
3243 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3246 case SD_BUS_TYPE_INT64:
3247 case SD_BUS_TYPE_UINT64:
3248 case SD_BUS_TYPE_DOUBLE:
3250 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3253 case SD_BUS_TYPE_UNIX_FD: {
3256 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3261 *(int*) p = m->fds[j];
3267 assert_not_reached("unexpected type");
3271 r = container_next_item(m, c, &rindex);
3278 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3282 r = message_peek_body(m, &rindex, 4, 4, &q);
3286 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3287 r = message_peek_body(m, &rindex, 1, l+1, &q);
3291 if (type == SD_BUS_TYPE_OBJECT_PATH)
3292 ok = validate_object_path(q, l);
3294 ok = validate_string(q, l);
3299 *(const char**) p = q;
3301 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3304 r = message_peek_body(m, &rindex, 1, 1, &q);
3309 r = message_peek_body(m, &rindex, 1, l+1, &q);
3313 if (!validate_signature(q, l))
3317 *(const char**) p = q;
3322 align = bus_type_get_alignment(type);
3325 sz = bus_type_get_size(type);
3328 r = message_peek_body(m, &rindex, align, sz, &q);
3334 case SD_BUS_TYPE_BYTE:
3336 *(uint8_t*) p = *(uint8_t*) q;
3339 case SD_BUS_TYPE_BOOLEAN:
3341 *(int*) p = !!*(uint32_t*) q;
3344 case SD_BUS_TYPE_INT16:
3345 case SD_BUS_TYPE_UINT16:
3347 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3350 case SD_BUS_TYPE_INT32:
3351 case SD_BUS_TYPE_UINT32:
3353 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3356 case SD_BUS_TYPE_INT64:
3357 case SD_BUS_TYPE_UINT64:
3358 case SD_BUS_TYPE_DOUBLE:
3360 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3363 case SD_BUS_TYPE_UNIX_FD: {
3366 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3371 *(int*) p = m->fds[j];
3376 assert_not_reached("Unknown basic type...");
3383 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3389 static int bus_message_enter_array(
3391 struct bus_container *c,
3392 const char *contents,
3393 uint32_t **array_size,
3396 size_t *n_offsets) {
3410 if (!signature_is_single(contents, true))
3413 if (!c->signature || c->signature[c->index] == 0)
3416 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3419 if (!startswith(c->signature + c->index + 1, contents))
3424 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3427 r = message_peek_body(m, &rindex, 4, 4, &q);
3431 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3434 alignment = bus_type_get_alignment(contents[0]);
3438 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3442 *array_size = (uint32_t*) q;
3444 } else if (c->item_size <= 0) {
3446 /* gvariant: empty array */
3451 } else if (bus_gvariant_is_fixed_size(contents)) {
3453 /* gvariant: fixed length array */
3454 *item_size = bus_gvariant_get_size(contents);
3459 size_t where, p = 0, framing, sz;
3462 /* gvariant: variable length array */
3463 sz = determine_word_size(c->item_size, 0);
3465 where = rindex + c->item_size - sz;
3466 r = message_peek_body(m, &where, 1, sz, &q);
3470 framing = read_word_le(q, sz);
3471 if (framing > c->item_size - sz)
3473 if ((c->item_size - framing) % sz != 0)
3476 *n_offsets = (c->item_size - framing) / sz;
3478 where = rindex + framing;
3479 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3483 *offsets = new(size_t, *n_offsets);
3487 for (i = 0; i < *n_offsets; i++) {
3490 x = read_word_le((uint8_t*) q + i * sz, sz);
3491 if (x > c->item_size - sz)
3496 (*offsets)[i] = rindex + x;
3500 *item_size = (*offsets)[0] - rindex;
3505 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3506 c->index += 1 + strlen(contents);
3511 static int bus_message_enter_variant(
3513 struct bus_container *c,
3514 const char *contents,
3515 size_t *item_size) {
3527 if (!signature_is_single(contents, false))
3530 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3533 if (!c->signature || c->signature[c->index] == 0)
3536 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3541 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3544 k = strlen(contents);
3545 if (1+k > c->item_size)
3548 where = rindex + c->item_size - (1+k);
3549 r = message_peek_body(m, &where, 1, 1+k, &q);
3553 if (*(char*) q != 0)
3556 if (memcmp((uint8_t*) q+1, contents, k))
3559 *item_size = c->item_size - (1+k);
3562 r = message_peek_body(m, &rindex, 1, 1, &q);
3567 r = message_peek_body(m, &rindex, 1, l+1, &q);
3571 if (!validate_signature(q, l))
3574 if (!streq(q, contents))
3580 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3586 static int build_struct_offsets(
3588 const char *signature,
3592 size_t *n_offsets) {
3594 unsigned n_variable = 0, n_total = 0, v;
3595 size_t previous = 0, where;
3606 if (isempty(signature)) {
3613 sz = determine_word_size(size, 0);
3617 /* First, loop over signature and count variable elements and
3618 * elements in general. We use this to know how large the
3619 * offset array is at the end of the structure. Note that
3620 * GVariant only stores offsets for all variable size elements
3621 * that are not the last item. */
3627 r = signature_element_length(p, &n);
3636 r = bus_gvariant_is_fixed_size(t);
3641 if (r == 0 && p[n] != 0) /* except the last item */
3648 if (size < n_variable * sz)
3651 where = m->rindex + size - (n_variable * sz);
3652 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3658 *offsets = new(size_t, n_total);
3664 /* Second, loop again and build an offset table */
3670 r = signature_element_length(p, &n);
3679 k = bus_gvariant_get_size(t);
3687 x = read_word_le((uint8_t*) q + v*sz, sz);
3690 if (m->rindex + x < previous)
3693 /* The last item's end
3694 * is determined from
3697 x = size - (n_variable * sz);
3699 offset = m->rindex + x;
3705 align = bus_gvariant_get_alignment(t);
3708 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3712 previous = (*offsets)[(*n_offsets)++] = offset;
3717 assert(*n_offsets == n_total);
3719 *item_size = (*offsets)[0] - m->rindex;
3723 static int enter_struct_or_dict_entry(
3725 struct bus_container *c,
3726 const char *contents,
3729 size_t *n_offsets) {
3740 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3743 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3747 } else if (c->item_size <= 0) {
3749 /* gvariant empty struct */
3754 /* gvariant with contents */
3755 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3760 static int bus_message_enter_struct(
3762 struct bus_container *c,
3763 const char *contents,
3766 size_t *n_offsets) {
3778 if (!signature_is_valid(contents, false))
3781 if (!c->signature || c->signature[c->index] == 0)
3784 l = strlen(contents);
3786 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3787 !startswith(c->signature + c->index + 1, contents) ||
3788 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3791 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3795 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3796 c->index += 1 + l + 1;
3801 static int bus_message_enter_dict_entry(
3803 struct bus_container *c,
3804 const char *contents,
3807 size_t *n_offsets) {
3816 if (!signature_is_pair(contents))
3819 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3822 if (!c->signature || c->signature[c->index] == 0)
3825 l = strlen(contents);
3827 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3828 !startswith(c->signature + c->index + 1, contents) ||
3829 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3832 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3836 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3837 c->index += 1 + l + 1;
3842 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3844 const char *contents) {
3845 struct bus_container *c, *w;
3846 uint32_t *array_size = NULL;
3849 size_t *offsets = NULL;
3850 size_t n_offsets = 0, item_size = 0;
3853 assert_return(m, -EINVAL);
3854 assert_return(m->sealed, -EPERM);
3855 assert_return(type != 0 || !contents, -EINVAL);
3857 if (type == 0 || !contents) {
3861 /* Allow entering into anonymous containers */
3862 r = sd_bus_message_peek_type(m, &tt, &cc);
3866 if (type != 0 && type != tt)
3869 if (contents && !streq(contents, cc))
3877 * We enforce a global limit on container depth, that is much
3878 * higher than the 32 structs and 32 arrays the specification
3879 * mandates. This is simpler to implement for us, and we need
3880 * this only to ensure our container array doesn't grow
3881 * without bounds. We are happy to return any data from a
3882 * message as long as the data itself is valid, even if the
3883 * overall message might be not.
3885 * Note that the message signature is validated when
3886 * parsing the headers, and that validation does check the
3889 * Note that the specification defines no limits on the depth
3890 * of stacked variants, but we do.
3892 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3895 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3898 if (message_end_of_signature(m))
3901 if (message_end_of_array(m, m->rindex))
3904 c = message_get_container(m);
3906 signature = strdup(contents);
3910 c->saved_index = c->index;
3913 if (type == SD_BUS_TYPE_ARRAY)
3914 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3915 else if (type == SD_BUS_TYPE_VARIANT)
3916 r = bus_message_enter_variant(m, c, contents, &item_size);
3917 else if (type == SD_BUS_TYPE_STRUCT)
3918 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3919 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3920 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3930 /* OK, let's fill it in */
3931 w = m->containers + m->n_containers++;
3932 w->enclosing = type;
3933 w->signature = signature;
3934 w->peeked_signature = NULL;
3938 w->begin = m->rindex;
3939 w->end = m->rindex + c->item_size;
3941 w->array_size = array_size;
3942 w->item_size = item_size;
3943 w->offsets = offsets;
3944 w->n_offsets = n_offsets;
3945 w->offset_index = 0;
3950 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3951 struct bus_container *c;
3955 assert_return(m, -EINVAL);
3956 assert_return(m->sealed, -EPERM);
3957 assert_return(m->n_containers > 0, -ENXIO);
3959 c = message_get_container(m);
3961 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3962 if (c->signature && c->signature[c->index] != 0)
3966 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3967 if (m->rindex < c->end)
3970 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3973 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3974 if (c->begin + l != m->rindex)
3979 free(c->peeked_signature);
3983 c = message_get_container(m);
3986 c->index = c->saved_index;
3987 r = container_next_item(m, c, &m->rindex);
3995 static void message_quit_container(sd_bus_message *m) {
3996 struct bus_container *c;
4000 assert(m->n_containers > 0);
4002 c = message_get_container(m);
4005 assert(m->rindex >= c->before);
4006 m->rindex = c->before;
4008 /* Free container */
4013 /* Correct index of new top-level container */
4014 c = message_get_container(m);
4015 c->index = c->saved_index;
4018 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4019 struct bus_container *c;
4022 assert_return(m, -EINVAL);
4023 assert_return(m->sealed, -EPERM);
4025 if (message_end_of_signature(m))
4028 if (message_end_of_array(m, m->rindex))
4031 c = message_get_container(m);
4033 if (bus_type_is_basic(c->signature[c->index])) {
4037 *type = c->signature[c->index];
4041 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4047 r = signature_element_length(c->signature+c->index+1, &l);
4053 sig = strndup(c->signature + c->index + 1, l);
4057 free(c->peeked_signature);
4058 *contents = c->peeked_signature = sig;
4062 *type = SD_BUS_TYPE_ARRAY;
4067 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4068 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4074 r = signature_element_length(c->signature+c->index, &l);
4079 sig = strndup(c->signature + c->index + 1, l - 2);
4083 free(c->peeked_signature);
4084 *contents = c->peeked_signature = sig;
4088 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4093 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4097 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4100 if (c->item_size < 2)
4103 /* Look for the NUL delimiter that
4104 separates the payload from the
4105 signature. Since the body might be
4106 in a different part that then the
4107 signature we map byte by byte. */
4109 for (k = 2; k <= c->item_size; k++) {
4112 where = m->rindex + c->item_size - k;
4113 r = message_peek_body(m, &where, 1, k, &q);
4117 if (*(char*) q == 0)
4121 if (k > c->item_size)
4124 free(c->peeked_signature);
4125 c->peeked_signature = strndup((char*) q + 1, k - 1);
4126 if (!c->peeked_signature)
4129 if (!signature_is_valid(c->peeked_signature, true))
4132 *contents = c->peeked_signature;
4137 r = message_peek_body(m, &rindex, 1, 1, &q);
4142 r = message_peek_body(m, &rindex, 1, l+1, &q);
4146 if (!validate_signature(q, l))
4154 *type = SD_BUS_TYPE_VARIANT;
4169 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4170 struct bus_container *c;
4172 assert_return(m, -EINVAL);
4173 assert_return(m->sealed, -EPERM);
4176 message_reset_containers(m);
4179 c = message_get_container(m);
4181 c = message_get_container(m);
4183 c->offset_index = 0;
4185 m->rindex = c->begin;
4188 c->offset_index = 0;
4189 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4191 return !isempty(c->signature);
4194 static int message_read_ap(
4199 unsigned n_array, n_struct;
4200 TypeStack stack[BUS_CONTAINER_DEPTH];
4201 unsigned stack_ptr = 0;
4202 unsigned n_loop = 0;
4210 /* Ideally, we'd just call ourselves recursively on every
4211 * complex type. However, the state of a va_list that is
4212 * passed to a function is undefined after that function
4213 * returns. This means we need to docode the va_list linearly
4214 * in a single stackframe. We hence implement our own
4215 * home-grown stack in an array. */
4217 n_array = (unsigned) -1; /* lenght of current array entries */
4218 n_struct = strlen(types); /* length of current struct contents signature */
4225 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4226 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4232 r = sd_bus_message_exit_container(m);
4240 if (n_array != (unsigned) -1)
4249 case SD_BUS_TYPE_BYTE:
4250 case SD_BUS_TYPE_BOOLEAN:
4251 case SD_BUS_TYPE_INT16:
4252 case SD_BUS_TYPE_UINT16:
4253 case SD_BUS_TYPE_INT32:
4254 case SD_BUS_TYPE_UINT32:
4255 case SD_BUS_TYPE_INT64:
4256 case SD_BUS_TYPE_UINT64:
4257 case SD_BUS_TYPE_DOUBLE:
4258 case SD_BUS_TYPE_STRING:
4259 case SD_BUS_TYPE_OBJECT_PATH:
4260 case SD_BUS_TYPE_SIGNATURE:
4261 case SD_BUS_TYPE_UNIX_FD: {
4264 p = va_arg(ap, void*);
4265 r = sd_bus_message_read_basic(m, *t, p);
4278 case SD_BUS_TYPE_ARRAY: {
4281 r = signature_element_length(t + 1, &k);
4287 memcpy(s, t + 1, k);
4290 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4301 if (n_array == (unsigned) -1) {
4306 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4312 n_array = va_arg(ap, unsigned);
4317 case SD_BUS_TYPE_VARIANT: {
4320 s = va_arg(ap, const char *);
4324 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4334 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4339 n_struct = strlen(s);
4340 n_array = (unsigned) -1;
4345 case SD_BUS_TYPE_STRUCT_BEGIN:
4346 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4349 r = signature_element_length(t, &k);
4355 memcpy(s, t + 1, k - 2);
4358 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4368 if (n_array == (unsigned) -1) {
4373 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4379 n_array = (unsigned) -1;
4392 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4396 assert_return(m, -EINVAL);
4397 assert_return(m->sealed, -EPERM);
4398 assert_return(types, -EINVAL);
4400 va_start(ap, types);
4401 r = message_read_ap(m, types, ap);
4407 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4410 assert_return(m, -EINVAL);
4411 assert_return(m->sealed, -EPERM);
4412 assert_return(types, -EINVAL);
4419 case SD_BUS_TYPE_BYTE:
4420 case SD_BUS_TYPE_BOOLEAN:
4421 case SD_BUS_TYPE_INT16:
4422 case SD_BUS_TYPE_UINT16:
4423 case SD_BUS_TYPE_INT32:
4424 case SD_BUS_TYPE_UINT32:
4425 case SD_BUS_TYPE_INT64:
4426 case SD_BUS_TYPE_UINT64:
4427 case SD_BUS_TYPE_DOUBLE:
4428 case SD_BUS_TYPE_STRING:
4429 case SD_BUS_TYPE_OBJECT_PATH:
4430 case SD_BUS_TYPE_SIGNATURE:
4431 case SD_BUS_TYPE_UNIX_FD:
4433 r = sd_bus_message_read_basic(m, *types, NULL);
4437 r = sd_bus_message_skip(m, types + 1);
4443 case SD_BUS_TYPE_ARRAY: {
4446 r = signature_element_length(types + 1, &k);
4452 memcpy(s, types+1, k);
4455 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4460 r = sd_bus_message_skip(m, s);
4467 r = sd_bus_message_exit_container(m);
4472 r = sd_bus_message_skip(m, types + 1 + k);
4479 case SD_BUS_TYPE_VARIANT: {
4480 const char *contents;
4483 r = sd_bus_message_peek_type(m, &x, &contents);
4487 if (x != SD_BUS_TYPE_VARIANT)
4490 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4494 r = sd_bus_message_skip(m, contents);
4499 r = sd_bus_message_exit_container(m);
4503 r = sd_bus_message_skip(m, types + 1);
4510 case SD_BUS_TYPE_STRUCT_BEGIN:
4511 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4514 r = signature_element_length(types, &k);
4520 memcpy(s, types+1, k-2);
4523 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4527 r = sd_bus_message_skip(m, s);
4532 r = sd_bus_message_exit_container(m);
4537 r = sd_bus_message_skip(m, types + k);
4549 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4553 struct bus_container *c;
4559 assert_return(m, -EINVAL);
4560 assert_return(m->sealed, -EPERM);
4561 assert_return(bus_type_is_trivial(type), -EINVAL);
4562 assert_return(ptr, -EINVAL);
4563 assert_return(size, -EINVAL);
4564 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4566 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4570 c = message_get_container(m);
4572 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4573 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4577 sz = c->end - c->begin;
4579 align = bus_type_get_alignment(type);
4583 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4587 /* Zero length array, let's return some aligned
4588 * pointer that is not NULL */
4589 p = (uint8_t*) NULL + align;
4591 r = message_peek_body(m, &m->rindex, align, sz, &p);
4596 r = sd_bus_message_exit_container(m);
4600 *ptr = (const void*) p;
4606 message_quit_container(m);
4610 static int message_peek_fields(
4621 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4624 static int message_peek_field_uint32(
4636 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4639 /* identical for gvariant and dbus1 */
4641 r = message_peek_fields(m, ri, 4, 4, &q);
4646 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4651 static int message_peek_field_string(
4653 bool (*validate)(const char *p),
4665 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4670 r = message_peek_fields(m, ri, 1, item_size, &q);
4676 r = message_peek_field_uint32(m, ri, 4, &l);
4680 r = message_peek_fields(m, ri, 1, l+1, &q);
4686 if (!validate_nul(q, l))
4692 if (!validate_string(q, l))
4702 static int message_peek_field_signature(
4715 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4720 r = message_peek_fields(m, ri, 1, item_size, &q);
4726 r = message_peek_fields(m, ri, 1, 1, &q);
4731 r = message_peek_fields(m, ri, 1, l+1, &q);
4736 if (!validate_signature(q, l))
4745 static int message_skip_fields(
4748 uint32_t array_size,
4749 const char **signature) {
4751 size_t original_index;
4757 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4759 original_index = *ri;
4765 if (array_size != (uint32_t) -1 &&
4766 array_size <= *ri - original_index)
4773 if (t == SD_BUS_TYPE_STRING) {
4775 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4781 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4783 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4789 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4791 r = message_peek_field_signature(m, ri, 0, NULL);
4797 } else if (bus_type_is_basic(t)) {
4800 align = bus_type_get_alignment(t);
4801 k = bus_type_get_size(t);
4802 assert(align > 0 && k > 0);
4804 r = message_peek_fields(m, ri, align, k, NULL);
4810 } else if (t == SD_BUS_TYPE_ARRAY) {
4812 r = signature_element_length(*signature+1, &l);
4822 strncpy(sig, *signature + 1, l-1);
4825 alignment = bus_type_get_alignment(sig[0]);
4829 r = message_peek_field_uint32(m, ri, 0, &nas);
4832 if (nas > BUS_ARRAY_MAX_SIZE)
4835 r = message_peek_fields(m, ri, alignment, 0, NULL);
4839 r = message_skip_fields(m, ri, nas, (const char**) &s);
4844 (*signature) += 1 + l;
4846 } else if (t == SD_BUS_TYPE_VARIANT) {
4849 r = message_peek_field_signature(m, ri, 0, &s);
4853 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4859 } else if (t == SD_BUS_TYPE_STRUCT ||
4860 t == SD_BUS_TYPE_DICT_ENTRY) {
4862 r = signature_element_length(*signature, &l);
4869 strncpy(sig, *signature + 1, l-1);
4872 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4883 int bus_message_parse_fields(sd_bus_message *m) {
4886 uint32_t unix_fds = 0;
4887 void *offsets = NULL;
4888 unsigned n_offsets = 0;
4894 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4897 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4901 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4902 r = message_peek_fields(m, &ri, 1, sz, &q);
4906 framing = read_word_le(q, sz);
4907 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4909 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4913 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4917 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4922 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4923 _cleanup_free_ char *sig = NULL;
4924 const char *signature;
4926 size_t item_size = (size_t) -1;
4928 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4935 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4938 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4942 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4947 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4952 where = ri = ALIGN_TO(ri, 8);
4953 item_size = end - ri;
4954 r = message_peek_fields(m, &where, 1, item_size, &q);
4958 b = memrchr(q, 0, item_size);
4962 sig = strndup(b+1, item_size - (b+1-(char*) q));
4967 item_size = b - (char*) q;
4969 r = message_peek_field_signature(m, &ri, 0, &signature);
4975 case _BUS_MESSAGE_HEADER_INVALID:
4978 case BUS_MESSAGE_HEADER_PATH:
4983 if (!streq(signature, "o"))
4986 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
4989 case BUS_MESSAGE_HEADER_INTERFACE:
4994 if (!streq(signature, "s"))
4997 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5000 case BUS_MESSAGE_HEADER_MEMBER:
5005 if (!streq(signature, "s"))
5008 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5011 case BUS_MESSAGE_HEADER_ERROR_NAME:
5016 if (!streq(signature, "s"))
5019 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5021 m->error._need_free = -1;
5025 case BUS_MESSAGE_HEADER_DESTINATION:
5030 if (!streq(signature, "s"))
5033 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5036 case BUS_MESSAGE_HEADER_SENDER:
5041 if (!streq(signature, "s"))
5044 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5046 if (r >= 0 && m->sender[0] == ':' && m->bus && m->bus->bus_client && !m->bus->is_kernel) {
5047 m->creds.unique_name = (char*) m->sender;
5048 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5054 case BUS_MESSAGE_HEADER_SIGNATURE: {
5058 if (m->root_container.signature)
5061 if (!streq(signature, "g"))
5064 r = message_peek_field_signature(m, &ri, item_size, &s);
5072 free(m->root_container.signature);
5073 m->root_container.signature = c;
5077 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5078 if (m->reply_cookie != 0)
5081 if (!streq(signature, "u"))
5084 r = message_peek_field_uint32(m, &ri, item_size, &m->reply_cookie);
5088 if (m->reply_cookie == 0)
5093 case BUS_MESSAGE_HEADER_UNIX_FDS:
5097 if (!streq(signature, "u"))
5100 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5110 if (!BUS_MESSAGE_IS_GVARIANT(m))
5111 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5120 if (m->n_fds != unix_fds)
5123 switch (m->header->type) {
5125 case SD_BUS_MESSAGE_SIGNAL:
5126 if (!m->path || !m->interface || !m->member)
5130 case SD_BUS_MESSAGE_METHOD_CALL:
5132 if (!m->path || !m->member)
5137 case SD_BUS_MESSAGE_METHOD_RETURN:
5139 if (m->reply_cookie == 0)
5143 case SD_BUS_MESSAGE_METHOD_ERROR:
5145 if (m->reply_cookie == 0 || !m->error.name)
5150 /* Refuse non-local messages that claim they are local */
5151 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5153 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5155 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5158 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5160 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5161 r = build_struct_offsets(
5163 m->root_container.signature,
5164 BUS_MESSAGE_BODY_SIZE(m),
5165 &m->root_container.item_size,
5166 &m->root_container.offsets,
5167 &m->root_container.n_offsets);
5172 /* Try to read the error message, but if we can't it's a non-issue */
5173 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5174 sd_bus_message_read(m, "s", &m->error.message);
5179 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5180 assert_return(m, -EINVAL);
5181 assert_return(destination, -EINVAL);
5182 assert_return(!m->sealed, -EPERM);
5183 assert_return(!m->destination, -EEXIST);
5185 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5188 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5192 struct bus_body_part *part;
5198 total = BUS_MESSAGE_SIZE(m);
5204 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5205 MESSAGE_FOREACH_PART(part, i, m)
5206 e = mempcpy(e, part->data, part->size);
5208 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5216 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5222 r = sd_bus_message_enter_container(m, 'a', "s");
5229 r = sd_bus_message_read_basic(m, 's', &s);
5235 r = strv_extend(l, s);
5240 r = sd_bus_message_exit_container(m);
5247 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5251 assert_return(m, -EINVAL);
5252 assert_return(m->sealed, -EPERM);
5253 assert_return(l, -EINVAL);
5255 r = bus_message_read_strv_extend(m, &strv);
5265 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5267 const char *t = NULL;
5272 r = sd_bus_message_rewind(m, true);
5276 for (j = 0; j <= i; j++) {
5279 r = sd_bus_message_peek_type(m, &type, NULL);
5283 if (type != SD_BUS_TYPE_STRING &&
5284 type != SD_BUS_TYPE_OBJECT_PATH &&
5285 type != SD_BUS_TYPE_SIGNATURE)
5288 r = sd_bus_message_read_basic(m, type, &t);
5296 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5302 if (size < sizeof(struct bus_header))
5305 full = sizeof(struct bus_header) +
5306 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5308 return size >= full;
5311 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5317 if (h->endian == BUS_NATIVE_ENDIAN) {
5318 fs = h->fields_size;
5320 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5321 fs = bswap_32(h->fields_size);
5322 bs = bswap_32(h->body_size);
5326 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5330 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5331 assert_return(m, -EINVAL);
5333 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5336 return sd_bus_error_get_errno(&m->error);
5339 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5340 struct bus_container *c;
5342 assert_return(m, NULL);
5344 c = complete ? &m->root_container : message_get_container(m);
5345 return strempty(c->signature);
5348 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5349 bool done_something = false;
5352 assert_return(m, -EINVAL);
5353 assert_return(source, -EINVAL);
5354 assert_return(!m->sealed, -EPERM);
5355 assert_return(source->sealed, -EPERM);
5358 const char *contents;
5373 r = sd_bus_message_peek_type(source, &type, &contents);
5379 done_something = true;
5381 if (bus_type_is_container(type) > 0) {
5383 r = sd_bus_message_enter_container(source, type, contents);
5387 r = sd_bus_message_open_container(m, type, contents);
5391 r = sd_bus_message_copy(m, source, true);
5395 r = sd_bus_message_close_container(m);
5399 r = sd_bus_message_exit_container(source);
5406 r = sd_bus_message_read_basic(source, type, &basic);
5412 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5413 type == SD_BUS_TYPE_SIGNATURE ||
5414 type == SD_BUS_TYPE_STRING)
5415 r = sd_bus_message_append_basic(m, type, basic.string);
5417 r = sd_bus_message_append_basic(m, type, &basic);
5424 return done_something;
5427 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5432 assert_return(m, -EINVAL);
5433 assert_return(m->sealed, -EPERM);
5434 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5435 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5436 assert_return(type || contents, -EINVAL);
5437 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5439 r = sd_bus_message_peek_type(m, &t, &c);
5443 if (type != 0 && type != t)
5446 if (contents && !streq_ptr(contents, c))
5452 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5453 assert_return(m, NULL);
5458 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5459 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5467 switch ((*m)->header->type) {
5469 case SD_BUS_MESSAGE_SIGNAL:
5470 r = sd_bus_message_new_signal(bus, (*m)->path, (*m)->interface, (*m)->member, &n);
5476 case SD_BUS_MESSAGE_METHOD_CALL:
5477 r = sd_bus_message_new_method_call(bus, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member, &n);
5483 case SD_BUS_MESSAGE_METHOD_RETURN:
5484 case SD_BUS_MESSAGE_METHOD_ERROR:
5486 n = message_new(bus, (*m)->header->type);
5490 n->reply_cookie = (*m)->reply_cookie;
5491 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, n->reply_cookie);
5495 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5496 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5500 n->error._need_free = -1;
5509 if ((*m)->destination && !n->destination) {
5510 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5515 if ((*m)->sender && !n->sender) {
5516 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5521 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5523 r = sd_bus_message_copy(n, *m, true);
5527 timeout = (*m)->timeout;
5528 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5529 timeout = BUS_DEFAULT_TIMEOUT;
5531 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5535 sd_bus_message_unref(*m);
5542 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5546 assert_return(!m->sealed, -EPERM);
5547 assert_return(!m->sender, -EPERM);
5549 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);