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"
34 #include "bus-message.h"
35 #include "bus-internal.h"
37 #include "bus-signature.h"
38 #include "bus-gvariant.h"
41 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
43 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
48 if (old_base == new_base)
51 if ((uint8_t*) p < (uint8_t*) old_base)
54 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
57 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
60 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
64 if (part->memfd >= 0) {
65 /* If we can reuse the memfd, try that. For that it
66 * can't be sealed yet. */
69 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
72 assert_se(munmap(part->data, part->mapped) == 0);
74 safe_close(part->memfd);
77 } else if (part->munmap_this)
78 munmap(part->data, part->mapped);
79 else if (part->free_this)
86 static void message_reset_parts(sd_bus_message *m) {
87 struct bus_body_part *part;
92 while (m->n_body_parts > 0) {
93 struct bus_body_part *next = part->next;
94 message_free_part(m, part);
101 m->cached_rindex_part = NULL;
102 m->cached_rindex_part_begin = 0;
105 static void message_reset_containers(sd_bus_message *m) {
110 for (i = 0; i < m->n_containers; i++) {
111 free(m->containers[i].signature);
112 free(m->containers[i].offsets);
116 m->containers = NULL;
118 m->n_containers = m->containers_allocated = 0;
119 m->root_container.index = 0;
122 static void message_free(sd_bus_message *m) {
128 message_reset_parts(m);
130 if (m->release_kdbus) {
131 uint64_t off _alignas_(8);
133 off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
134 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;
377 assert(buffer || length <= 0);
378 assert(fds || n_fds <= 0);
381 if (length < sizeof(struct bus_header))
385 if (h->version != 1 &&
392 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
395 if (h->endian != BUS_LITTLE_ENDIAN &&
396 h->endian != BUS_BIG_ENDIAN)
399 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
402 label_sz = strlen(label);
417 m->creds.uid = ucred->uid;
418 m->creds.pid = ucred->pid;
419 m->creds.gid = ucred->gid;
420 m->creds.mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID;
424 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
425 memcpy(m->creds.label, label, label_sz + 1);
427 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) {
494 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
499 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
500 m->header->endian = BUS_NATIVE_ENDIAN;
501 m->header->type = type;
502 m->header->version = bus ? bus->message_version : 1;
503 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
504 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, -ENOTCONN);
521 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
522 assert_return(object_path_is_valid(path), -EINVAL);
523 assert_return(interface_name_is_valid(interface), -EINVAL);
524 assert_return(member_name_is_valid(member), -EINVAL);
525 assert_return(m, -EINVAL);
527 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
531 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
533 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
536 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
539 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
547 sd_bus_message_unref(t);
551 _public_ int sd_bus_message_new_method_call(
554 const char *destination,
556 const char *interface,
557 const char *member) {
562 assert_return(bus, -ENOTCONN);
563 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
564 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
565 assert_return(object_path_is_valid(path), -EINVAL);
566 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
567 assert_return(member_name_is_valid(member), -EINVAL);
568 assert_return(m, -EINVAL);
570 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
574 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
577 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
582 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
588 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
601 static int message_new_reply(
602 sd_bus_message *call,
604 sd_bus_message **m) {
609 assert_return(call, -EINVAL);
610 assert_return(call->sealed, -EPERM);
611 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
612 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
613 assert_return(m, -EINVAL);
615 t = message_new(call->bus, type);
619 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
620 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
622 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
627 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
632 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
633 t->enforced_reply_signature = call->enforced_reply_signature;
643 _public_ int sd_bus_message_new_method_return(
644 sd_bus_message *call,
645 sd_bus_message **m) {
647 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
650 _public_ int sd_bus_message_new_method_error(
651 sd_bus_message *call,
653 const sd_bus_error *e) {
658 assert_return(sd_bus_error_is_set(e), -EINVAL);
659 assert_return(m, -EINVAL);
661 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
665 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
670 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
675 t->error._need_free = -1;
685 _public_ int sd_bus_message_new_method_errorf(
686 sd_bus_message *call,
692 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
695 assert_return(name, -EINVAL);
696 assert_return(m, -EINVAL);
698 va_start(ap, format);
699 bus_error_setfv(&error, name, format, ap);
702 return sd_bus_message_new_method_error(call, m, &error);
705 _public_ int sd_bus_message_new_method_errno(
706 sd_bus_message *call,
709 const sd_bus_error *p) {
711 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
713 if (sd_bus_error_is_set(p))
714 return sd_bus_message_new_method_error(call, m, p);
716 sd_bus_error_set_errno(&berror, error);
718 return sd_bus_message_new_method_error(call, m, &berror);
721 _public_ int sd_bus_message_new_method_errnof(
722 sd_bus_message *call,
728 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
731 va_start(ap, format);
732 bus_error_set_errnofv(&berror, error, format, ap);
735 return sd_bus_message_new_method_error(call, m, &berror);
738 int bus_message_new_synthetic_error(
741 const sd_bus_error *e,
742 sd_bus_message **m) {
748 assert(sd_bus_error_is_set(e));
751 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
755 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
756 t->reply_cookie = cookie;
758 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
762 if (bus && bus->unique_name) {
763 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
768 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
773 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
778 t->error._need_free = -1;
788 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
789 assert_return(m, NULL);
791 assert(m->n_ref > 0);
797 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
802 assert(m->n_ref > 0);
812 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
813 assert_return(m, -EINVAL);
814 assert_return(type, -EINVAL);
816 *type = m->header->type;
820 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
821 assert_return(m, -EINVAL);
822 assert_return(cookie, -EINVAL);
823 assert_return(m->header->serial != 0, -ENODATA);
825 *cookie = BUS_MESSAGE_COOKIE(m);
829 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
830 assert_return(m, -EINVAL);
831 assert_return(cookie, -EINVAL);
832 assert_return(m->reply_cookie != 0, -ENODATA);
834 *cookie = m->reply_cookie;
838 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
839 assert_return(m, -EINVAL);
841 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
842 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
845 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
846 assert_return(m, -EINVAL);
848 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
851 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
852 assert_return(m, NULL);
857 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
858 assert_return(m, NULL);
863 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
864 assert_return(m, NULL);
869 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
870 assert_return(m, NULL);
872 return m->destination;
875 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
876 assert_return(m, NULL);
881 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
882 assert_return(m, NULL);
883 assert_return(sd_bus_error_is_set(&m->error), NULL);
888 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
889 assert_return(m, -EINVAL);
890 assert_return(usec, -EINVAL);
892 if (m->monotonic <= 0)
895 *usec = m->monotonic;
899 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
900 assert_return(m, -EINVAL);
901 assert_return(usec, -EINVAL);
903 if (m->realtime <= 0)
910 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
911 assert_return(m, -EINVAL);
912 assert_return(seqnum, -EINVAL);
921 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
922 assert_return(m, NULL);
924 if (m->creds.mask == 0)
930 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
931 const char *interface,
932 const char *member) {
933 assert_return(m, -EINVAL);
935 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
938 if (interface && (!m->interface || !streq(m->interface, interface)))
941 if (member && (!m->member || !streq(m->member, member)))
947 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
948 const char *interface,
949 const char *member) {
950 assert_return(m, -EINVAL);
952 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
955 if (interface && (!m->interface || !streq(m->interface, interface)))
958 if (member && (!m->member || !streq(m->member, member)))
964 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
965 assert_return(m, -EINVAL);
967 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
970 if (name && (!m->error.name || !streq(m->error.name, name)))
976 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
977 assert_return(m, -EINVAL);
978 assert_return(!m->sealed, -EPERM);
979 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
982 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
984 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
989 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
990 assert_return(m, -EINVAL);
991 assert_return(!m->sealed, -EPERM);
994 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
996 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1001 static struct bus_container *message_get_container(sd_bus_message *m) {
1004 if (m->n_containers == 0)
1005 return &m->root_container;
1007 assert(m->containers);
1008 return m->containers + m->n_containers - 1;
1011 struct bus_body_part *message_append_part(sd_bus_message *m) {
1012 struct bus_body_part *part;
1019 if (m->n_body_parts <= 0) {
1023 assert(m->body_end);
1025 part = new0(struct bus_body_part, 1);
1031 m->body_end->next = part;
1041 static void part_zero(struct bus_body_part *part, size_t sz) {
1046 /* All other fields can be left in their defaults */
1047 assert(!part->data);
1048 assert(part->memfd < 0);
1051 part->is_zero = true;
1052 part->sealed = true;
1055 static int part_make_space(
1056 struct sd_bus_message *m,
1057 struct bus_body_part *part,
1066 assert(!part->sealed);
1071 if (!part->data && part->memfd < 0)
1072 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1074 if (part->memfd >= 0) {
1076 if (part->allocated == 0 || sz > part->allocated) {
1077 uint64_t new_allocated;
1079 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1080 r = ftruncate(part->memfd, new_allocated);
1086 part->allocated = new_allocated;
1089 if (!part->data || sz > part->mapped) {
1092 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1093 if (part->mapped <= 0)
1094 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1096 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1098 if (n == MAP_FAILED) {
1107 part->munmap_this = true;
1109 if (part->allocated == 0 || sz > part->allocated) {
1110 size_t new_allocated;
1112 new_allocated = sz > 0 ? 2 * sz : 64;
1113 n = realloc(part->data, new_allocated);
1120 part->allocated = new_allocated;
1121 part->free_this = true;
1126 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1132 static int message_add_offset(sd_bus_message *m, size_t offset) {
1133 struct bus_container *c;
1136 assert(BUS_MESSAGE_IS_GVARIANT(m));
1138 /* Add offset to current container, unless this is the first
1139 * item in it, which will have the 0 offset, which we can
1141 c = message_get_container(m);
1143 if (!c->need_offsets)
1146 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1149 c->offsets[c->n_offsets++] = offset;
1153 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1154 struct bus_container *c;
1161 /* Update counters */
1162 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1165 *c->array_size += expand;
1169 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1170 size_t start_body, end_body, padding, added;
1181 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1182 end_body = start_body + sz;
1184 padding = start_body - m->header->body_size;
1185 added = padding + sz;
1187 /* Check for 32bit overflows */
1188 if (end_body > (size_t) ((uint32_t) -1)) {
1194 struct bus_body_part *part = NULL;
1198 m->n_body_parts <= 0 ||
1199 m->body_end->sealed ||
1200 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1204 part = message_append_part(m);
1208 part_zero(part, padding);
1211 part = message_append_part(m);
1215 r = part_make_space(m, part, sz, &p);
1219 struct bus_container *c;
1221 size_t os, start_part, end_part;
1227 start_part = ALIGN_TO(part->size, align);
1228 end_part = start_part + sz;
1230 r = part_make_space(m, part, end_part, &p);
1235 memzero(p, padding);
1236 p = (uint8_t*) p + padding;
1239 /* Readjust pointers */
1240 for (c = m->containers; c < m->containers + m->n_containers; c++)
1241 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1243 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1246 /* Return something that is not NULL and is aligned */
1247 p = (uint8_t *) NULL + align;
1249 m->header->body_size = end_body;
1250 message_extend_containers(m, added);
1253 r = message_add_offset(m, end_body);
1263 static int message_push_fd(sd_bus_message *m, int fd) {
1274 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1278 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1286 m->fds[m->n_fds] = copy;
1292 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1293 _cleanup_close_ int fd = -1;
1294 struct bus_container *c;
1298 assert_return(m, -EINVAL);
1299 assert_return(!m->sealed, -EPERM);
1300 assert_return(bus_type_is_basic(type), -EINVAL);
1301 assert_return(!m->poisoned, -ESTALE);
1303 c = message_get_container(m);
1305 if (c->signature && c->signature[c->index]) {
1306 /* Container signature is already set */
1308 if (c->signature[c->index] != type)
1313 /* Maybe we can append to the signature? But only if this is the top-level container*/
1314 if (c->enclosing != 0)
1317 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1324 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1330 case SD_BUS_TYPE_SIGNATURE:
1331 case SD_BUS_TYPE_STRING:
1334 /* Fall through... */
1335 case SD_BUS_TYPE_OBJECT_PATH:
1343 case SD_BUS_TYPE_BOOLEAN:
1345 u8 = p && *(int*) p;
1351 case SD_BUS_TYPE_UNIX_FD:
1356 fd = message_push_fd(m, *(int*) p);
1367 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1368 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1375 a = message_extend_body(m, align, sz, true);
1382 *stored = (const uint8_t*) a;
1389 case SD_BUS_TYPE_STRING:
1390 /* To make things easy we'll serialize a NULL string
1391 * into the empty string */
1394 /* Fall through... */
1395 case SD_BUS_TYPE_OBJECT_PATH:
1401 sz = 4 + strlen(p) + 1;
1404 case SD_BUS_TYPE_SIGNATURE:
1409 sz = 1 + strlen(p) + 1;
1412 case SD_BUS_TYPE_BOOLEAN:
1414 u32 = p && *(int*) p;
1420 case SD_BUS_TYPE_UNIX_FD:
1425 fd = message_push_fd(m, *(int*) p);
1436 align = bus_type_get_alignment(type);
1437 sz = bus_type_get_size(type);
1444 a = message_extend_body(m, align, sz, false);
1448 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1449 *(uint32_t*) a = sz - 5;
1450 memcpy((uint8_t*) a + 4, p, sz - 4);
1453 *stored = (const uint8_t*) a + 4;
1455 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1456 *(uint8_t*) a = sz - 2;
1457 memcpy((uint8_t*) a + 1, p, sz - 1);
1460 *stored = (const uint8_t*) a + 1;
1469 if (type == SD_BUS_TYPE_UNIX_FD)
1472 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1479 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1480 return message_append_basic(m, type, p, NULL);
1483 _public_ int sd_bus_message_append_string_space(
1488 struct bus_container *c;
1491 assert_return(m, -EINVAL);
1492 assert_return(s, -EINVAL);
1493 assert_return(!m->sealed, -EPERM);
1494 assert_return(!m->poisoned, -ESTALE);
1496 c = message_get_container(m);
1498 if (c->signature && c->signature[c->index]) {
1499 /* Container signature is already set */
1501 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1506 /* Maybe we can append to the signature? But only if this is the top-level container*/
1507 if (c->enclosing != 0)
1510 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1517 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1518 a = message_extend_body(m, 1, size + 1, true);
1524 a = message_extend_body(m, 4, 4 + size + 1, false);
1528 *(uint32_t*) a = size;
1534 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1540 _public_ int sd_bus_message_append_string_iovec(
1542 const struct iovec *iov,
1550 assert_return(m, -EINVAL);
1551 assert_return(!m->sealed, -EPERM);
1552 assert_return(iov || n == 0, -EINVAL);
1553 assert_return(!m->poisoned, -ESTALE);
1555 size = IOVEC_TOTAL_SIZE(iov, n);
1557 r = sd_bus_message_append_string_space(m, size, &p);
1561 for (i = 0; i < n; i++) {
1563 if (iov[i].iov_base)
1564 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1566 memset(p, ' ', iov[i].iov_len);
1568 p += iov[i].iov_len;
1574 static int bus_message_open_array(
1576 struct bus_container *c,
1577 const char *contents,
1578 uint32_t **array_size,
1580 bool *need_offsets) {
1590 assert(need_offsets);
1592 if (!signature_is_single(contents, true))
1595 if (c->signature && c->signature[c->index]) {
1597 /* Verify the existing signature */
1599 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1602 if (!startswith(c->signature + c->index + 1, contents))
1605 nindex = c->index + 1 + strlen(contents);
1609 if (c->enclosing != 0)
1612 /* Extend the existing signature */
1614 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1620 nindex = e - c->signature;
1623 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1624 alignment = bus_gvariant_get_alignment(contents);
1628 /* Add alignment padding and add to offset list */
1629 if (!message_extend_body(m, alignment, 0, false))
1632 r = bus_gvariant_is_fixed_size(contents);
1636 *begin = m->header->body_size;
1637 *need_offsets = r == 0;
1641 struct bus_body_part *o;
1643 alignment = bus_type_get_alignment(contents[0]);
1647 a = message_extend_body(m, 4, 4, false);
1652 op = m->body_end->data;
1653 os = m->body_end->size;
1655 /* Add alignment between size and first element */
1656 if (!message_extend_body(m, alignment, 0, false))
1659 /* location of array size might have changed so let's readjust a */
1660 if (o == m->body_end)
1661 a = adjust_pointer(a, op, os, m->body_end->data);
1667 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1673 static int bus_message_open_variant(
1675 struct bus_container *c,
1676 const char *contents) {
1682 if (!signature_is_single(contents, false))
1685 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1688 if (c->signature && c->signature[c->index]) {
1690 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1696 if (c->enclosing != 0)
1699 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1706 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1707 /* Variants are always aligned to 8 */
1709 if (!message_extend_body(m, 8, 0, false))
1716 l = strlen(contents);
1717 a = message_extend_body(m, 1, 1 + l + 1, false);
1722 memcpy((uint8_t*) a + 1, contents, l + 1);
1725 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1731 static int bus_message_open_struct(
1733 struct bus_container *c,
1734 const char *contents,
1736 bool *need_offsets) {
1745 assert(need_offsets);
1747 if (!signature_is_valid(contents, false))
1750 if (c->signature && c->signature[c->index]) {
1753 l = strlen(contents);
1755 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1756 !startswith(c->signature + c->index + 1, contents) ||
1757 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1760 nindex = c->index + 1 + l + 1;
1764 if (c->enclosing != 0)
1767 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1773 nindex = e - c->signature;
1776 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1779 alignment = bus_gvariant_get_alignment(contents);
1783 if (!message_extend_body(m, alignment, 0, false))
1786 r = bus_gvariant_is_fixed_size(contents);
1790 *begin = m->header->body_size;
1791 *need_offsets = r == 0;
1793 /* Align contents to 8 byte boundary */
1794 if (!message_extend_body(m, 8, 0, false))
1798 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1804 static int bus_message_open_dict_entry(
1806 struct bus_container *c,
1807 const char *contents,
1809 bool *need_offsets) {
1817 assert(need_offsets);
1819 if (!signature_is_pair(contents))
1822 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1825 if (c->signature && c->signature[c->index]) {
1828 l = strlen(contents);
1830 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1831 !startswith(c->signature + c->index + 1, contents) ||
1832 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1837 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1840 alignment = bus_gvariant_get_alignment(contents);
1844 if (!message_extend_body(m, alignment, 0, false))
1847 r = bus_gvariant_is_fixed_size(contents);
1851 *begin = m->header->body_size;
1852 *need_offsets = r == 0;
1854 /* Align contents to 8 byte boundary */
1855 if (!message_extend_body(m, 8, 0, false))
1862 _public_ int sd_bus_message_open_container(
1865 const char *contents) {
1867 struct bus_container *c, *w;
1868 uint32_t *array_size = NULL;
1870 size_t before, begin = 0;
1871 bool need_offsets = false;
1874 assert_return(m, -EINVAL);
1875 assert_return(!m->sealed, -EPERM);
1876 assert_return(contents, -EINVAL);
1877 assert_return(!m->poisoned, -ESTALE);
1879 /* Make sure we have space for one more container */
1880 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1885 c = message_get_container(m);
1887 signature = strdup(contents);
1893 /* Save old index in the parent container, in case we have to
1894 * abort this container */
1895 c->saved_index = c->index;
1896 before = m->header->body_size;
1898 if (type == SD_BUS_TYPE_ARRAY)
1899 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1900 else if (type == SD_BUS_TYPE_VARIANT)
1901 r = bus_message_open_variant(m, c, contents);
1902 else if (type == SD_BUS_TYPE_STRUCT)
1903 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1904 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1905 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1914 /* OK, let's fill it in */
1915 w = m->containers + m->n_containers++;
1916 w->enclosing = type;
1917 w->signature = signature;
1919 w->array_size = array_size;
1922 w->n_offsets = w->offsets_allocated = 0;
1924 w->need_offsets = need_offsets;
1929 static size_t determine_word_size(size_t sz, size_t extra) {
1930 if (sz + extra <= 0xFF)
1932 else if (sz + extra*2 <= 0xFFFF)
1934 else if (sz + extra*4 <= 0xFFFFFFFF)
1940 static size_t read_word_le(void *p, size_t sz) {
1950 return *(uint8_t*) p;
1955 return le16toh(x.u16);
1957 return le32toh(x.u32);
1959 return le64toh(x.u64);
1961 assert_not_reached("unknown word width");
1964 static void write_word_le(void *p, size_t sz, size_t value) {
1972 assert(sz == 8 || (value < (1ULL << (sz*8))));
1975 *(uint8_t*) p = value;
1978 x.u16 = htole16((uint16_t) value);
1980 x.u32 = htole32((uint32_t) value);
1982 x.u64 = htole64((uint64_t) value);
1984 assert_not_reached("unknown word width");
1989 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1994 if (!BUS_MESSAGE_IS_GVARIANT(m))
1997 if (c->need_offsets) {
1998 size_t payload, sz, i;
2001 /* Variable-width arrays */
2003 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2004 sz = determine_word_size(payload, c->n_offsets);
2006 a = message_extend_body(m, 1, sz * c->n_offsets, true);
2010 for (i = 0; i < c->n_offsets; i++)
2011 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2015 /* Fixed-width or empty arrays */
2017 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
2025 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2032 if (!BUS_MESSAGE_IS_GVARIANT(m))
2035 l = strlen(c->signature);
2037 a = message_extend_body(m, 1, 1 + l, true);
2042 memcpy(a+1, c->signature, l);
2047 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2048 size_t n_variable = 0;
2057 if (!BUS_MESSAGE_IS_GVARIANT(m))
2060 p = strempty(c->signature);
2064 r = signature_element_length(p, &n);
2073 r = bus_gvariant_is_fixed_size(t);
2078 assert(!c->need_offsets || i <= c->n_offsets);
2080 /* We need to add an offset for each item that has a
2081 * variable size and that is not the last one in the
2083 if (r == 0 && p[n] != 0)
2090 assert(!c->need_offsets || i == c->n_offsets);
2091 assert(c->need_offsets || n_variable == 0);
2093 if (n_variable <= 0) {
2094 a = message_extend_body(m, 1, 0, add_offset);
2101 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2103 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2105 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2109 p = strempty(c->signature);
2110 for (i = 0, j = 0; i < c->n_offsets; i++) {
2114 r = signature_element_length(p, &n);
2125 r = bus_gvariant_is_fixed_size(t);
2128 if (r > 0 || p[0] == 0)
2132 k = n_variable - 1 - j;
2134 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2143 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2144 struct bus_container *c;
2147 assert_return(m, -EINVAL);
2148 assert_return(!m->sealed, -EPERM);
2149 assert_return(m->n_containers > 0, -EINVAL);
2150 assert_return(!m->poisoned, -ESTALE);
2152 c = message_get_container(m);
2154 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2155 if (c->signature && c->signature[c->index] != 0)
2160 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2161 r = bus_message_close_array(m, c);
2162 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2163 r = bus_message_close_variant(m, c);
2164 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2165 r = bus_message_close_struct(m, c, true);
2167 assert_not_reached("Unknown container type");
2181 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2188 stack[*i].types = types;
2189 stack[*i].n_struct = n_struct;
2190 stack[*i].n_array = n_array;
2196 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2207 *types = stack[*i].types;
2208 *n_struct = stack[*i].n_struct;
2209 *n_array = stack[*i].n_array;
2214 int bus_message_append_ap(
2219 unsigned n_array, n_struct;
2220 TypeStack stack[BUS_CONTAINER_DEPTH];
2221 unsigned stack_ptr = 0;
2229 n_array = (unsigned) -1;
2230 n_struct = strlen(types);
2235 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2236 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2242 r = sd_bus_message_close_container(m);
2250 if (n_array != (unsigned) -1)
2259 case SD_BUS_TYPE_BYTE: {
2262 x = (uint8_t) va_arg(ap, int);
2263 r = sd_bus_message_append_basic(m, *t, &x);
2267 case SD_BUS_TYPE_BOOLEAN:
2268 case SD_BUS_TYPE_INT32:
2269 case SD_BUS_TYPE_UINT32:
2270 case SD_BUS_TYPE_UNIX_FD: {
2273 /* We assume a boolean is the same as int32_t */
2274 assert_cc(sizeof(int32_t) == sizeof(int));
2276 x = va_arg(ap, uint32_t);
2277 r = sd_bus_message_append_basic(m, *t, &x);
2281 case SD_BUS_TYPE_INT16:
2282 case SD_BUS_TYPE_UINT16: {
2285 x = (uint16_t) va_arg(ap, int);
2286 r = sd_bus_message_append_basic(m, *t, &x);
2290 case SD_BUS_TYPE_INT64:
2291 case SD_BUS_TYPE_UINT64:
2292 case SD_BUS_TYPE_DOUBLE: {
2295 x = va_arg(ap, uint64_t);
2296 r = sd_bus_message_append_basic(m, *t, &x);
2300 case SD_BUS_TYPE_STRING:
2301 case SD_BUS_TYPE_OBJECT_PATH:
2302 case SD_BUS_TYPE_SIGNATURE: {
2305 x = va_arg(ap, const char*);
2306 r = sd_bus_message_append_basic(m, *t, x);
2310 case SD_BUS_TYPE_ARRAY: {
2313 r = signature_element_length(t + 1, &k);
2319 memcpy(s, t + 1, k);
2322 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2327 if (n_array == (unsigned) -1) {
2332 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2338 n_array = va_arg(ap, unsigned);
2343 case SD_BUS_TYPE_VARIANT: {
2346 s = va_arg(ap, const char*);
2350 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2354 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2359 n_struct = strlen(s);
2360 n_array = (unsigned) -1;
2365 case SD_BUS_TYPE_STRUCT_BEGIN:
2366 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2369 r = signature_element_length(t, &k);
2376 memcpy(s, t + 1, k - 2);
2379 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2384 if (n_array == (unsigned) -1) {
2389 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2395 n_array = (unsigned) -1;
2411 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2415 assert_return(m, -EINVAL);
2416 assert_return(types, -EINVAL);
2417 assert_return(!m->sealed, -EPERM);
2418 assert_return(!m->poisoned, -ESTALE);
2420 va_start(ap, types);
2421 r = bus_message_append_ap(m, types, ap);
2427 _public_ int sd_bus_message_append_array_space(
2437 assert_return(m, -EINVAL);
2438 assert_return(!m->sealed, -EPERM);
2439 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2440 assert_return(ptr || size == 0, -EINVAL);
2441 assert_return(!m->poisoned, -ESTALE);
2443 /* alignment and size of the trivial types (except bool) is
2444 * identical for gvariant and dbus1 marshalling */
2445 align = bus_type_get_alignment(type);
2446 sz = bus_type_get_size(type);
2448 assert_se(align > 0);
2454 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2458 a = message_extend_body(m, align, size, false);
2462 r = sd_bus_message_close_container(m);
2470 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2477 assert_return(m, -EINVAL);
2478 assert_return(!m->sealed, -EPERM);
2479 assert_return(bus_type_is_trivial(type), -EINVAL);
2480 assert_return(ptr || size == 0, -EINVAL);
2481 assert_return(!m->poisoned, -ESTALE);
2483 r = sd_bus_message_append_array_space(m, type, size, &p);
2488 memcpy(p, ptr, size);
2493 _public_ int sd_bus_message_append_array_iovec(
2496 const struct iovec *iov,
2504 assert_return(m, -EINVAL);
2505 assert_return(!m->sealed, -EPERM);
2506 assert_return(bus_type_is_trivial(type), -EINVAL);
2507 assert_return(iov || n == 0, -EINVAL);
2508 assert_return(!m->poisoned, -ESTALE);
2510 size = IOVEC_TOTAL_SIZE(iov, n);
2512 r = sd_bus_message_append_array_space(m, type, size, &p);
2516 for (i = 0; i < n; i++) {
2518 if (iov[i].iov_base)
2519 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2521 memzero(p, iov[i].iov_len);
2523 p = (uint8_t*) p + iov[i].iov_len;
2529 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2532 _cleanup_close_ int copy_fd = -1;
2533 struct bus_body_part *part;
2545 if (!bus_type_is_trivial(type))
2550 r = memfd_set_sealed(memfd);
2554 copy_fd = dup(memfd);
2558 r = memfd_get_size(memfd, &size);
2562 align = bus_type_get_alignment(type);
2563 sz = bus_type_get_size(type);
2565 assert_se(align > 0);
2571 if (size > (uint64_t) (uint32_t) -1)
2574 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2578 a = message_extend_body(m, align, 0, false);
2582 part = message_append_part(m);
2586 part->memfd = copy_fd;
2587 part->sealed = true;
2591 m->header->body_size += size;
2592 message_extend_containers(m, size);
2594 return sd_bus_message_close_container(m);
2597 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) {
2598 _cleanup_close_ int copy_fd = -1;
2599 struct bus_body_part *part;
2600 struct bus_container *c;
2605 assert_return(m, -EINVAL);
2606 assert_return(memfd >= 0, -EINVAL);
2607 assert_return(!m->sealed, -EPERM);
2608 assert_return(!m->poisoned, -ESTALE);
2610 r = memfd_set_sealed(memfd);
2614 copy_fd = dup(memfd);
2618 r = memfd_get_size(memfd, &size);
2622 /* We require this to be NUL terminated */
2626 if (size > (uint64_t) (uint32_t) -1)
2629 c = message_get_container(m);
2630 if (c->signature && c->signature[c->index]) {
2631 /* Container signature is already set */
2633 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2638 /* Maybe we can append to the signature? But only if this is the top-level container*/
2639 if (c->enclosing != 0)
2642 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2649 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2650 a = message_extend_body(m, 4, 4, false);
2654 *(uint32_t*) a = size - 1;
2657 part = message_append_part(m);
2661 part->memfd = copy_fd;
2662 part->sealed = true;
2666 m->header->body_size += size;
2667 message_extend_containers(m, size);
2669 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2670 r = message_add_offset(m, m->header->body_size);
2677 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2683 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2687 assert_return(m, -EINVAL);
2688 assert_return(!m->sealed, -EPERM);
2689 assert_return(!m->poisoned, -ESTALE);
2691 r = sd_bus_message_open_container(m, 'a', "s");
2695 STRV_FOREACH(i, l) {
2696 r = sd_bus_message_append_basic(m, 's', *i);
2701 return sd_bus_message_close_container(m);
2704 static int bus_message_close_header(sd_bus_message *m) {
2710 if (!BUS_MESSAGE_IS_GVARIANT(m))
2713 if (m->n_header_offsets < 1)
2716 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2718 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2720 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2724 for (i = 0; i < m->n_header_offsets; i++)
2725 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2730 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2731 struct bus_body_part *part;
2741 if (m->n_containers > 0)
2747 /* In vtables the return signature of method calls is listed,
2748 * let's check if they match if this is a response */
2749 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2750 m->enforced_reply_signature &&
2751 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2754 /* If gvariant marshalling is used we need to close the body structure */
2755 r = bus_message_close_struct(m, &m->root_container, false);
2759 /* If there's a non-trivial signature set, then add it in here */
2760 if (!isempty(m->root_container.signature)) {
2761 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2767 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2772 r = bus_message_close_header(m);
2776 m->header->serial = (uint32_t) cookie;
2777 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2779 /* Add padding at the end of the fields part, since we know
2780 * the body needs to start at an 8 byte alignment. We made
2781 * sure we allocated enough space for this, so all we need to
2782 * do here is to zero it out. */
2783 l = BUS_MESSAGE_FIELDS_SIZE(m);
2786 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, a);
2788 /* If this is something we can send as memfd, then let's seal
2789 the memfd now. Note that we can send memfds as payload only
2790 for directed messages, and not for broadcasts. */
2791 if (m->destination && m->bus->use_memfd) {
2792 MESSAGE_FOREACH_PART(part, i, m)
2793 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2796 /* Try to seal it if that makes
2797 * sense. First, unmap our own map to
2798 * make sure we don't keep it busy. */
2799 bus_body_part_unmap(part);
2801 /* Then, sync up real memfd size */
2803 if (ftruncate(part->memfd, sz) < 0)
2806 /* Finally, try to seal */
2807 if (fcntl(part->memfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE) >= 0)
2808 part->sealed = true;
2812 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2813 m->root_container.index = 0;
2814 m->root_container.offset_index = 0;
2815 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2822 int bus_body_part_map(struct bus_body_part *part) {
2831 if (part->size <= 0)
2834 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2835 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2836 static const uint8_t zeroes[7] = { };
2837 part->data = (void*) zeroes;
2841 psz = PAGE_ALIGN(part->size);
2843 if (part->memfd >= 0)
2844 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, 0);
2845 else if (part->is_zero)
2846 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2850 if (p == MAP_FAILED)
2855 part->munmap_this = true;
2860 void bus_body_part_unmap(struct bus_body_part *part) {
2864 if (part->memfd < 0)
2870 if (!part->munmap_this)
2873 assert_se(munmap(part->data, part->mapped) == 0);
2877 part->munmap_this = false;
2882 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2883 size_t k, start, end;
2888 start = ALIGN_TO((size_t) *rindex, align);
2889 end = start + nbytes;
2894 /* Verify that padding is 0 */
2895 for (k = *rindex; k < start; k++)
2896 if (((const uint8_t*) p)[k] != 0)
2900 *r = (uint8_t*) p + start;
2907 static bool message_end_of_signature(sd_bus_message *m) {
2908 struct bus_container *c;
2912 c = message_get_container(m);
2913 return !c->signature || c->signature[c->index] == 0;
2916 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2917 struct bus_container *c;
2921 c = message_get_container(m);
2922 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2925 if (BUS_MESSAGE_IS_GVARIANT(m))
2926 return index >= c->end;
2928 assert(c->array_size);
2929 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2933 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2934 assert_return(m, -EINVAL);
2935 assert_return(m->sealed, -EPERM);
2937 if (complete && m->n_containers > 0)
2940 if (message_end_of_signature(m))
2943 if (message_end_of_array(m, m->rindex))
2949 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2950 struct bus_body_part *part;
2956 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2957 part = m->cached_rindex_part;
2958 begin = m->cached_rindex_part_begin;
2968 if (index + sz <= begin + part->size) {
2970 r = bus_body_part_map(part);
2975 *p = (uint8_t*) part->data + index - begin;
2977 m->cached_rindex_part = part;
2978 m->cached_rindex_part_begin = begin;
2983 begin += part->size;
2990 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2997 if (!BUS_MESSAGE_IS_GVARIANT(m))
3000 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3003 sz = bus_gvariant_get_size(c->signature);
3007 if (c->offset_index+1 >= c->n_offsets)
3010 /* Variable-size array */
3012 alignment = bus_gvariant_get_alignment(c->signature);
3013 assert(alignment > 0);
3015 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3016 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3019 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3022 /* Fixed-size array */
3023 *rindex = c->begin + (c->offset_index+1) * sz;
3029 } else if (c->enclosing == 0 ||
3030 c->enclosing == SD_BUS_TYPE_STRUCT ||
3031 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3036 if (c->offset_index+1 >= c->n_offsets)
3039 r = signature_element_length(c->signature + c->index, &n);
3043 r = signature_element_length(c->signature + c->index + n, &j);
3048 memcpy(t, c->signature + c->index + n, j);
3051 alignment = bus_gvariant_get_alignment(t);
3054 assert(alignment > 0);
3056 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3057 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3061 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3064 assert_not_reached("Unknown container type");
3069 /* Reached the end */
3076 static int message_peek_body(
3083 size_t k, start, end, padding;
3084 struct bus_body_part *part;
3091 start = ALIGN_TO((size_t) *rindex, align);
3092 padding = start - *rindex;
3093 end = start + nbytes;
3095 if (end > BUS_MESSAGE_BODY_SIZE(m))
3098 part = find_part(m, *rindex, padding, (void**) &q);
3103 /* Verify padding */
3104 for (k = 0; k < padding; k++)
3109 part = find_part(m, start, nbytes, (void**) &q);
3110 if (!part || (nbytes > 0 && !q))
3121 static bool validate_nul(const char *s, size_t l) {
3123 /* Check for NUL chars in the string */
3124 if (memchr(s, 0, l))
3127 /* Check for NUL termination */
3134 static bool validate_string(const char *s, size_t l) {
3136 if (!validate_nul(s, l))
3139 /* Check if valid UTF8 */
3140 if (!utf8_is_valid(s))
3146 static bool validate_signature(const char *s, size_t l) {
3148 if (!validate_nul(s, l))
3151 /* Check if valid signature */
3152 if (!signature_is_valid(s, true))
3158 static bool validate_object_path(const char *s, size_t l) {
3160 if (!validate_nul(s, l))
3163 if (!object_path_is_valid(s))
3169 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3170 struct bus_container *c;
3175 assert_return(m, -EINVAL);
3176 assert_return(m->sealed, -EPERM);
3177 assert_return(bus_type_is_basic(type), -EINVAL);
3179 if (message_end_of_signature(m))
3182 if (message_end_of_array(m, m->rindex))
3185 c = message_get_container(m);
3186 if (c->signature[c->index] != type)
3191 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3193 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3196 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3200 if (type == SD_BUS_TYPE_STRING)
3201 ok = validate_string(q, c->item_size-1);
3202 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3203 ok = validate_object_path(q, c->item_size-1);
3205 ok = validate_signature(q, c->item_size-1);
3211 *(const char**) p = q;
3215 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3217 if ((size_t) sz != c->item_size)
3220 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3223 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3229 case SD_BUS_TYPE_BYTE:
3231 *(uint8_t*) p = *(uint8_t*) q;
3234 case SD_BUS_TYPE_BOOLEAN:
3236 *(int*) p = !!*(uint8_t*) q;
3239 case SD_BUS_TYPE_INT16:
3240 case SD_BUS_TYPE_UINT16:
3242 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3245 case SD_BUS_TYPE_INT32:
3246 case SD_BUS_TYPE_UINT32:
3248 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3251 case SD_BUS_TYPE_INT64:
3252 case SD_BUS_TYPE_UINT64:
3253 case SD_BUS_TYPE_DOUBLE:
3255 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3258 case SD_BUS_TYPE_UNIX_FD: {
3261 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3266 *(int*) p = m->fds[j];
3272 assert_not_reached("unexpected type");
3276 r = container_next_item(m, c, &rindex);
3283 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3287 r = message_peek_body(m, &rindex, 4, 4, &q);
3291 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3292 r = message_peek_body(m, &rindex, 1, l+1, &q);
3296 if (type == SD_BUS_TYPE_OBJECT_PATH)
3297 ok = validate_object_path(q, l);
3299 ok = validate_string(q, l);
3304 *(const char**) p = q;
3306 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3309 r = message_peek_body(m, &rindex, 1, 1, &q);
3314 r = message_peek_body(m, &rindex, 1, l+1, &q);
3318 if (!validate_signature(q, l))
3322 *(const char**) p = q;
3327 align = bus_type_get_alignment(type);
3330 sz = bus_type_get_size(type);
3333 r = message_peek_body(m, &rindex, align, sz, &q);
3339 case SD_BUS_TYPE_BYTE:
3341 *(uint8_t*) p = *(uint8_t*) q;
3344 case SD_BUS_TYPE_BOOLEAN:
3346 *(int*) p = !!*(uint32_t*) q;
3349 case SD_BUS_TYPE_INT16:
3350 case SD_BUS_TYPE_UINT16:
3352 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3355 case SD_BUS_TYPE_INT32:
3356 case SD_BUS_TYPE_UINT32:
3358 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3361 case SD_BUS_TYPE_INT64:
3362 case SD_BUS_TYPE_UINT64:
3363 case SD_BUS_TYPE_DOUBLE:
3365 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3368 case SD_BUS_TYPE_UNIX_FD: {
3371 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3376 *(int*) p = m->fds[j];
3381 assert_not_reached("Unknown basic type...");
3388 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3394 static int bus_message_enter_array(
3396 struct bus_container *c,
3397 const char *contents,
3398 uint32_t **array_size,
3401 size_t *n_offsets) {
3415 if (!signature_is_single(contents, true))
3418 if (!c->signature || c->signature[c->index] == 0)
3421 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3424 if (!startswith(c->signature + c->index + 1, contents))
3429 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3432 r = message_peek_body(m, &rindex, 4, 4, &q);
3436 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3439 alignment = bus_type_get_alignment(contents[0]);
3443 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3447 *array_size = (uint32_t*) q;
3449 } else if (c->item_size <= 0) {
3451 /* gvariant: empty array */
3456 } else if (bus_gvariant_is_fixed_size(contents)) {
3458 /* gvariant: fixed length array */
3459 *item_size = bus_gvariant_get_size(contents);
3464 size_t where, p = 0, framing, sz;
3467 /* gvariant: variable length array */
3468 sz = determine_word_size(c->item_size, 0);
3470 where = rindex + c->item_size - sz;
3471 r = message_peek_body(m, &where, 1, sz, &q);
3475 framing = read_word_le(q, sz);
3476 if (framing > c->item_size - sz)
3478 if ((c->item_size - framing) % sz != 0)
3481 *n_offsets = (c->item_size - framing) / sz;
3483 where = rindex + framing;
3484 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3488 *offsets = new(size_t, *n_offsets);
3492 for (i = 0; i < *n_offsets; i++) {
3495 x = read_word_le((uint8_t*) q + i * sz, sz);
3496 if (x > c->item_size - sz)
3501 (*offsets)[i] = rindex + x;
3505 *item_size = (*offsets)[0] - rindex;
3510 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3511 c->index += 1 + strlen(contents);
3516 static int bus_message_enter_variant(
3518 struct bus_container *c,
3519 const char *contents,
3520 size_t *item_size) {
3532 if (!signature_is_single(contents, false))
3535 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3538 if (!c->signature || c->signature[c->index] == 0)
3541 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3546 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3549 k = strlen(contents);
3550 if (1+k > c->item_size)
3553 where = rindex + c->item_size - (1+k);
3554 r = message_peek_body(m, &where, 1, 1+k, &q);
3558 if (*(char*) q != 0)
3561 if (memcmp((uint8_t*) q+1, contents, k))
3564 *item_size = c->item_size - (1+k);
3567 r = message_peek_body(m, &rindex, 1, 1, &q);
3572 r = message_peek_body(m, &rindex, 1, l+1, &q);
3576 if (!validate_signature(q, l))
3579 if (!streq(q, contents))
3585 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3591 static int build_struct_offsets(
3593 const char *signature,
3597 size_t *n_offsets) {
3599 unsigned n_variable = 0, n_total = 0, v;
3600 size_t previous = 0, where;
3611 if (isempty(signature)) {
3618 sz = determine_word_size(size, 0);
3622 /* First, loop over signature and count variable elements and
3623 * elements in general. We use this to know how large the
3624 * offset array is at the end of the structure. Note that
3625 * GVariant only stores offsets for all variable size elements
3626 * that are not the last item. */
3632 r = signature_element_length(p, &n);
3641 r = bus_gvariant_is_fixed_size(t);
3646 if (r == 0 && p[n] != 0) /* except the last item */
3653 if (size < n_variable * sz)
3656 where = m->rindex + size - (n_variable * sz);
3657 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3663 *offsets = new(size_t, n_total);
3669 /* Second, loop again and build an offset table */
3675 r = signature_element_length(p, &n);
3684 k = bus_gvariant_get_size(t);
3692 x = read_word_le((uint8_t*) q + v*sz, sz);
3695 if (m->rindex + x < previous)
3698 /* The last item's end
3699 * is determined from
3702 x = size - (n_variable * sz);
3704 offset = m->rindex + x;
3710 align = bus_gvariant_get_alignment(t);
3713 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3717 previous = (*offsets)[(*n_offsets)++] = offset;
3722 assert(*n_offsets == n_total);
3724 *item_size = (*offsets)[0] - m->rindex;
3728 static int enter_struct_or_dict_entry(
3730 struct bus_container *c,
3731 const char *contents,
3734 size_t *n_offsets) {
3745 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3748 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3752 } else if (c->item_size <= 0) {
3754 /* gvariant empty struct */
3759 /* gvariant with contents */
3760 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3765 static int bus_message_enter_struct(
3767 struct bus_container *c,
3768 const char *contents,
3771 size_t *n_offsets) {
3783 if (!signature_is_valid(contents, false))
3786 if (!c->signature || c->signature[c->index] == 0)
3789 l = strlen(contents);
3791 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3792 !startswith(c->signature + c->index + 1, contents) ||
3793 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3796 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3800 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3801 c->index += 1 + l + 1;
3806 static int bus_message_enter_dict_entry(
3808 struct bus_container *c,
3809 const char *contents,
3812 size_t *n_offsets) {
3821 if (!signature_is_pair(contents))
3824 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3827 if (!c->signature || c->signature[c->index] == 0)
3830 l = strlen(contents);
3832 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3833 !startswith(c->signature + c->index + 1, contents) ||
3834 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3837 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3841 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3842 c->index += 1 + l + 1;
3847 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3849 const char *contents) {
3850 struct bus_container *c, *w;
3851 uint32_t *array_size = NULL;
3854 size_t *offsets = NULL;
3855 size_t n_offsets = 0, item_size = 0;
3858 assert_return(m, -EINVAL);
3859 assert_return(m->sealed, -EPERM);
3860 assert_return(type != 0 || !contents, -EINVAL);
3862 if (type == 0 || !contents) {
3866 /* Allow entering into anonymous containers */
3867 r = sd_bus_message_peek_type(m, &tt, &cc);
3871 if (type != 0 && type != tt)
3874 if (contents && !streq(contents, cc))
3882 * We enforce a global limit on container depth, that is much
3883 * higher than the 32 structs and 32 arrays the specification
3884 * mandates. This is simpler to implement for us, and we need
3885 * this only to ensure our container array doesn't grow
3886 * without bounds. We are happy to return any data from a
3887 * message as long as the data itself is valid, even if the
3888 * overall message might be not.
3890 * Note that the message signature is validated when
3891 * parsing the headers, and that validation does check the
3894 * Note that the specification defines no limits on the depth
3895 * of stacked variants, but we do.
3897 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3900 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3903 if (message_end_of_signature(m))
3906 if (message_end_of_array(m, m->rindex))
3909 c = message_get_container(m);
3911 signature = strdup(contents);
3915 c->saved_index = c->index;
3918 if (type == SD_BUS_TYPE_ARRAY)
3919 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3920 else if (type == SD_BUS_TYPE_VARIANT)
3921 r = bus_message_enter_variant(m, c, contents, &item_size);
3922 else if (type == SD_BUS_TYPE_STRUCT)
3923 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3924 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3925 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3935 /* OK, let's fill it in */
3936 w = m->containers + m->n_containers++;
3937 w->enclosing = type;
3938 w->signature = signature;
3939 w->peeked_signature = NULL;
3943 w->begin = m->rindex;
3944 w->end = m->rindex + c->item_size;
3946 w->array_size = array_size;
3947 w->item_size = item_size;
3948 w->offsets = offsets;
3949 w->n_offsets = n_offsets;
3950 w->offset_index = 0;
3955 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3956 struct bus_container *c;
3960 assert_return(m, -EINVAL);
3961 assert_return(m->sealed, -EPERM);
3962 assert_return(m->n_containers > 0, -ENXIO);
3964 c = message_get_container(m);
3966 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3967 if (c->signature && c->signature[c->index] != 0)
3971 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3972 if (m->rindex < c->end)
3975 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3978 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3979 if (c->begin + l != m->rindex)
3984 free(c->peeked_signature);
3988 c = message_get_container(m);
3991 c->index = c->saved_index;
3992 r = container_next_item(m, c, &m->rindex);
4000 static void message_quit_container(sd_bus_message *m) {
4001 struct bus_container *c;
4005 assert(m->n_containers > 0);
4007 c = message_get_container(m);
4010 assert(m->rindex >= c->before);
4011 m->rindex = c->before;
4013 /* Free container */
4018 /* Correct index of new top-level container */
4019 c = message_get_container(m);
4020 c->index = c->saved_index;
4023 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4024 struct bus_container *c;
4027 assert_return(m, -EINVAL);
4028 assert_return(m->sealed, -EPERM);
4030 if (message_end_of_signature(m))
4033 if (message_end_of_array(m, m->rindex))
4036 c = message_get_container(m);
4038 if (bus_type_is_basic(c->signature[c->index])) {
4042 *type = c->signature[c->index];
4046 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4052 r = signature_element_length(c->signature+c->index+1, &l);
4058 sig = strndup(c->signature + c->index + 1, l);
4062 free(c->peeked_signature);
4063 *contents = c->peeked_signature = sig;
4067 *type = SD_BUS_TYPE_ARRAY;
4072 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4073 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4079 r = signature_element_length(c->signature+c->index, &l);
4084 sig = strndup(c->signature + c->index + 1, l - 2);
4088 free(c->peeked_signature);
4089 *contents = c->peeked_signature = sig;
4093 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4098 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4102 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4105 if (c->item_size < 2)
4108 /* Look for the NUL delimiter that
4109 separates the payload from the
4110 signature. Since the body might be
4111 in a different part that then the
4112 signature we map byte by byte. */
4114 for (k = 2; k <= c->item_size; k++) {
4117 where = m->rindex + c->item_size - k;
4118 r = message_peek_body(m, &where, 1, k, &q);
4122 if (*(char*) q == 0)
4126 if (k > c->item_size)
4129 free(c->peeked_signature);
4130 c->peeked_signature = strndup((char*) q + 1, k - 1);
4131 if (!c->peeked_signature)
4134 if (!signature_is_valid(c->peeked_signature, true))
4137 *contents = c->peeked_signature;
4142 r = message_peek_body(m, &rindex, 1, 1, &q);
4147 r = message_peek_body(m, &rindex, 1, l+1, &q);
4151 if (!validate_signature(q, l))
4159 *type = SD_BUS_TYPE_VARIANT;
4174 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4175 struct bus_container *c;
4177 assert_return(m, -EINVAL);
4178 assert_return(m->sealed, -EPERM);
4181 message_reset_containers(m);
4184 c = message_get_container(m);
4186 c = message_get_container(m);
4188 c->offset_index = 0;
4190 m->rindex = c->begin;
4193 c->offset_index = 0;
4194 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4196 return !isempty(c->signature);
4199 static int message_read_ap(
4204 unsigned n_array, n_struct;
4205 TypeStack stack[BUS_CONTAINER_DEPTH];
4206 unsigned stack_ptr = 0;
4207 unsigned n_loop = 0;
4215 /* Ideally, we'd just call ourselves recursively on every
4216 * complex type. However, the state of a va_list that is
4217 * passed to a function is undefined after that function
4218 * returns. This means we need to docode the va_list linearly
4219 * in a single stackframe. We hence implement our own
4220 * home-grown stack in an array. */
4222 n_array = (unsigned) -1; /* length of current array entries */
4223 n_struct = strlen(types); /* length of current struct contents signature */
4230 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4231 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4237 r = sd_bus_message_exit_container(m);
4245 if (n_array != (unsigned) -1)
4254 case SD_BUS_TYPE_BYTE:
4255 case SD_BUS_TYPE_BOOLEAN:
4256 case SD_BUS_TYPE_INT16:
4257 case SD_BUS_TYPE_UINT16:
4258 case SD_BUS_TYPE_INT32:
4259 case SD_BUS_TYPE_UINT32:
4260 case SD_BUS_TYPE_INT64:
4261 case SD_BUS_TYPE_UINT64:
4262 case SD_BUS_TYPE_DOUBLE:
4263 case SD_BUS_TYPE_STRING:
4264 case SD_BUS_TYPE_OBJECT_PATH:
4265 case SD_BUS_TYPE_SIGNATURE:
4266 case SD_BUS_TYPE_UNIX_FD: {
4269 p = va_arg(ap, void*);
4270 r = sd_bus_message_read_basic(m, *t, p);
4283 case SD_BUS_TYPE_ARRAY: {
4286 r = signature_element_length(t + 1, &k);
4292 memcpy(s, t + 1, k);
4295 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4306 if (n_array == (unsigned) -1) {
4311 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4317 n_array = va_arg(ap, unsigned);
4322 case SD_BUS_TYPE_VARIANT: {
4325 s = va_arg(ap, const char *);
4329 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4339 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4344 n_struct = strlen(s);
4345 n_array = (unsigned) -1;
4350 case SD_BUS_TYPE_STRUCT_BEGIN:
4351 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4354 r = signature_element_length(t, &k);
4360 memcpy(s, t + 1, k - 2);
4363 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4373 if (n_array == (unsigned) -1) {
4378 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4384 n_array = (unsigned) -1;
4397 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4401 assert_return(m, -EINVAL);
4402 assert_return(m->sealed, -EPERM);
4403 assert_return(types, -EINVAL);
4405 va_start(ap, types);
4406 r = message_read_ap(m, types, ap);
4412 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4415 assert_return(m, -EINVAL);
4416 assert_return(m->sealed, -EPERM);
4417 assert_return(types, -EINVAL);
4424 case SD_BUS_TYPE_BYTE:
4425 case SD_BUS_TYPE_BOOLEAN:
4426 case SD_BUS_TYPE_INT16:
4427 case SD_BUS_TYPE_UINT16:
4428 case SD_BUS_TYPE_INT32:
4429 case SD_BUS_TYPE_UINT32:
4430 case SD_BUS_TYPE_INT64:
4431 case SD_BUS_TYPE_UINT64:
4432 case SD_BUS_TYPE_DOUBLE:
4433 case SD_BUS_TYPE_STRING:
4434 case SD_BUS_TYPE_OBJECT_PATH:
4435 case SD_BUS_TYPE_SIGNATURE:
4436 case SD_BUS_TYPE_UNIX_FD:
4438 r = sd_bus_message_read_basic(m, *types, NULL);
4442 r = sd_bus_message_skip(m, types + 1);
4448 case SD_BUS_TYPE_ARRAY: {
4451 r = signature_element_length(types + 1, &k);
4457 memcpy(s, types+1, k);
4460 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4465 r = sd_bus_message_skip(m, s);
4472 r = sd_bus_message_exit_container(m);
4477 r = sd_bus_message_skip(m, types + 1 + k);
4484 case SD_BUS_TYPE_VARIANT: {
4485 const char *contents;
4488 r = sd_bus_message_peek_type(m, &x, &contents);
4492 if (x != SD_BUS_TYPE_VARIANT)
4495 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4499 r = sd_bus_message_skip(m, contents);
4504 r = sd_bus_message_exit_container(m);
4508 r = sd_bus_message_skip(m, types + 1);
4515 case SD_BUS_TYPE_STRUCT_BEGIN:
4516 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4519 r = signature_element_length(types, &k);
4525 memcpy(s, types+1, k-2);
4528 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4532 r = sd_bus_message_skip(m, s);
4537 r = sd_bus_message_exit_container(m);
4542 r = sd_bus_message_skip(m, types + k);
4554 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4558 struct bus_container *c;
4564 assert_return(m, -EINVAL);
4565 assert_return(m->sealed, -EPERM);
4566 assert_return(bus_type_is_trivial(type), -EINVAL);
4567 assert_return(ptr, -EINVAL);
4568 assert_return(size, -EINVAL);
4569 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4571 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4575 c = message_get_container(m);
4577 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4578 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4582 sz = c->end - c->begin;
4584 align = bus_type_get_alignment(type);
4588 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4592 /* Zero length array, let's return some aligned
4593 * pointer that is not NULL */
4594 p = (uint8_t*) NULL + align;
4596 r = message_peek_body(m, &m->rindex, align, sz, &p);
4601 r = sd_bus_message_exit_container(m);
4605 *ptr = (const void*) p;
4611 message_quit_container(m);
4615 static int message_peek_fields(
4626 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4629 static int message_peek_field_uint32(
4641 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4644 /* identical for gvariant and dbus1 */
4646 r = message_peek_fields(m, ri, 4, 4, &q);
4651 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4656 static int message_peek_field_string(
4658 bool (*validate)(const char *p),
4670 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4675 r = message_peek_fields(m, ri, 1, item_size, &q);
4681 r = message_peek_field_uint32(m, ri, 4, &l);
4685 r = message_peek_fields(m, ri, 1, l+1, &q);
4691 if (!validate_nul(q, l))
4697 if (!validate_string(q, l))
4707 static int message_peek_field_signature(
4720 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4725 r = message_peek_fields(m, ri, 1, item_size, &q);
4731 r = message_peek_fields(m, ri, 1, 1, &q);
4736 r = message_peek_fields(m, ri, 1, l+1, &q);
4741 if (!validate_signature(q, l))
4750 static int message_skip_fields(
4753 uint32_t array_size,
4754 const char **signature) {
4756 size_t original_index;
4762 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4764 original_index = *ri;
4770 if (array_size != (uint32_t) -1 &&
4771 array_size <= *ri - original_index)
4778 if (t == SD_BUS_TYPE_STRING) {
4780 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4786 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4788 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4794 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4796 r = message_peek_field_signature(m, ri, 0, NULL);
4802 } else if (bus_type_is_basic(t)) {
4805 align = bus_type_get_alignment(t);
4806 k = bus_type_get_size(t);
4807 assert(align > 0 && k > 0);
4809 r = message_peek_fields(m, ri, align, k, NULL);
4815 } else if (t == SD_BUS_TYPE_ARRAY) {
4817 r = signature_element_length(*signature+1, &l);
4827 strncpy(sig, *signature + 1, l-1);
4830 alignment = bus_type_get_alignment(sig[0]);
4834 r = message_peek_field_uint32(m, ri, 0, &nas);
4837 if (nas > BUS_ARRAY_MAX_SIZE)
4840 r = message_peek_fields(m, ri, alignment, 0, NULL);
4844 r = message_skip_fields(m, ri, nas, (const char**) &s);
4849 (*signature) += 1 + l;
4851 } else if (t == SD_BUS_TYPE_VARIANT) {
4854 r = message_peek_field_signature(m, ri, 0, &s);
4858 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4864 } else if (t == SD_BUS_TYPE_STRUCT ||
4865 t == SD_BUS_TYPE_DICT_ENTRY) {
4867 r = signature_element_length(*signature, &l);
4874 strncpy(sig, *signature + 1, l-1);
4877 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4888 int bus_message_parse_fields(sd_bus_message *m) {
4891 uint32_t unix_fds = 0;
4892 bool unix_fds_set = false;
4893 void *offsets = NULL;
4894 unsigned n_offsets = 0;
4900 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4903 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4907 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4908 r = message_peek_fields(m, &ri, 1, sz, &q);
4912 framing = read_word_le(q, sz);
4913 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4915 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4919 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4923 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4928 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4929 _cleanup_free_ char *sig = NULL;
4930 const char *signature;
4932 size_t item_size = (size_t) -1;
4934 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4941 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4944 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4948 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4953 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4958 where = ri = ALIGN_TO(ri, 8);
4959 item_size = end - ri;
4960 r = message_peek_fields(m, &where, 1, item_size, &q);
4964 b = memrchr(q, 0, item_size);
4968 sig = strndup(b+1, item_size - (b+1-(char*) q));
4973 item_size = b - (char*) q;
4975 r = message_peek_field_signature(m, &ri, 0, &signature);
4981 case _BUS_MESSAGE_HEADER_INVALID:
4984 case BUS_MESSAGE_HEADER_PATH:
4989 if (!streq(signature, "o"))
4992 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
4995 case BUS_MESSAGE_HEADER_INTERFACE:
5000 if (!streq(signature, "s"))
5003 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5006 case BUS_MESSAGE_HEADER_MEMBER:
5011 if (!streq(signature, "s"))
5014 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5017 case BUS_MESSAGE_HEADER_ERROR_NAME:
5022 if (!streq(signature, "s"))
5025 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5027 m->error._need_free = -1;
5031 case BUS_MESSAGE_HEADER_DESTINATION:
5036 if (!streq(signature, "s"))
5039 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5042 case BUS_MESSAGE_HEADER_SENDER:
5047 if (!streq(signature, "s"))
5050 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5052 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5053 m->creds.unique_name = (char*) m->sender;
5054 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5060 case BUS_MESSAGE_HEADER_SIGNATURE: {
5064 if (m->root_container.signature)
5067 if (!streq(signature, "g"))
5070 r = message_peek_field_signature(m, &ri, item_size, &s);
5078 free(m->root_container.signature);
5079 m->root_container.signature = c;
5083 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5086 if (m->reply_cookie != 0)
5089 if (!streq(signature, "u"))
5092 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5096 m->reply_cookie = serial;
5098 if (m->reply_cookie == 0)
5104 case BUS_MESSAGE_HEADER_UNIX_FDS:
5108 if (!streq(signature, "u"))
5111 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5115 unix_fds_set = true;
5119 if (!BUS_MESSAGE_IS_GVARIANT(m))
5120 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5129 if (m->n_fds != unix_fds)
5132 switch (m->header->type) {
5134 case SD_BUS_MESSAGE_SIGNAL:
5135 if (!m->path || !m->interface || !m->member)
5139 case SD_BUS_MESSAGE_METHOD_CALL:
5141 if (!m->path || !m->member)
5146 case SD_BUS_MESSAGE_METHOD_RETURN:
5148 if (m->reply_cookie == 0)
5152 case SD_BUS_MESSAGE_METHOD_ERROR:
5154 if (m->reply_cookie == 0 || !m->error.name)
5159 /* Refuse non-local messages that claim they are local */
5160 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5162 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5164 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5167 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5169 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5170 r = build_struct_offsets(
5172 m->root_container.signature,
5173 BUS_MESSAGE_BODY_SIZE(m),
5174 &m->root_container.item_size,
5175 &m->root_container.offsets,
5176 &m->root_container.n_offsets);
5181 /* Try to read the error message, but if we can't it's a non-issue */
5182 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5183 sd_bus_message_read(m, "s", &m->error.message);
5188 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5189 assert_return(m, -EINVAL);
5190 assert_return(destination, -EINVAL);
5191 assert_return(!m->sealed, -EPERM);
5192 assert_return(!m->destination, -EEXIST);
5194 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5197 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5201 struct bus_body_part *part;
5207 total = BUS_MESSAGE_SIZE(m);
5213 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5214 MESSAGE_FOREACH_PART(part, i, m)
5215 e = mempcpy(e, part->data, part->size);
5217 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5225 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5231 r = sd_bus_message_enter_container(m, 'a', "s");
5238 r = sd_bus_message_read_basic(m, 's', &s);
5244 r = strv_extend(l, s);
5249 r = sd_bus_message_exit_container(m);
5256 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5260 assert_return(m, -EINVAL);
5261 assert_return(m->sealed, -EPERM);
5262 assert_return(l, -EINVAL);
5264 r = bus_message_read_strv_extend(m, &strv);
5274 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5276 const char *t = NULL;
5281 r = sd_bus_message_rewind(m, true);
5285 for (j = 0; j <= i; j++) {
5288 r = sd_bus_message_peek_type(m, &type, NULL);
5292 if (type != SD_BUS_TYPE_STRING &&
5293 type != SD_BUS_TYPE_OBJECT_PATH &&
5294 type != SD_BUS_TYPE_SIGNATURE)
5297 r = sd_bus_message_read_basic(m, type, &t);
5305 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5311 if (size < sizeof(struct bus_header))
5314 full = sizeof(struct bus_header) +
5315 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5317 return size >= full;
5320 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5326 if (h->endian == BUS_NATIVE_ENDIAN) {
5327 fs = h->fields_size;
5329 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5330 fs = bswap_32(h->fields_size);
5331 bs = bswap_32(h->body_size);
5335 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5339 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5340 assert_return(m, EINVAL);
5342 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5345 return sd_bus_error_get_errno(&m->error);
5348 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5349 struct bus_container *c;
5351 assert_return(m, NULL);
5353 c = complete ? &m->root_container : message_get_container(m);
5354 return strempty(c->signature);
5357 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5358 bool done_something = false;
5361 assert_return(m, -EINVAL);
5362 assert_return(source, -EINVAL);
5363 assert_return(!m->sealed, -EPERM);
5364 assert_return(source->sealed, -EPERM);
5367 const char *contents;
5382 r = sd_bus_message_peek_type(source, &type, &contents);
5388 done_something = true;
5390 if (bus_type_is_container(type) > 0) {
5392 r = sd_bus_message_enter_container(source, type, contents);
5396 r = sd_bus_message_open_container(m, type, contents);
5400 r = sd_bus_message_copy(m, source, true);
5404 r = sd_bus_message_close_container(m);
5408 r = sd_bus_message_exit_container(source);
5415 r = sd_bus_message_read_basic(source, type, &basic);
5421 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5422 type == SD_BUS_TYPE_SIGNATURE ||
5423 type == SD_BUS_TYPE_STRING)
5424 r = sd_bus_message_append_basic(m, type, basic.string);
5426 r = sd_bus_message_append_basic(m, type, &basic);
5433 return done_something;
5436 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5441 assert_return(m, -EINVAL);
5442 assert_return(m->sealed, -EPERM);
5443 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5444 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5445 assert_return(type || contents, -EINVAL);
5446 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5448 r = sd_bus_message_peek_type(m, &t, &c);
5452 if (type != 0 && type != t)
5455 if (contents && !streq_ptr(contents, c))
5461 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5462 assert_return(m, NULL);
5467 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5468 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5476 switch ((*m)->header->type) {
5478 case SD_BUS_MESSAGE_SIGNAL:
5479 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5485 case SD_BUS_MESSAGE_METHOD_CALL:
5486 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5492 case SD_BUS_MESSAGE_METHOD_RETURN:
5493 case SD_BUS_MESSAGE_METHOD_ERROR:
5495 n = message_new(bus, (*m)->header->type);
5499 n->reply_cookie = (*m)->reply_cookie;
5500 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5504 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5505 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5509 n->error._need_free = -1;
5518 if ((*m)->destination && !n->destination) {
5519 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5524 if ((*m)->sender && !n->sender) {
5525 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5530 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5532 r = sd_bus_message_copy(n, *m, true);
5536 timeout = (*m)->timeout;
5537 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5538 timeout = BUS_DEFAULT_TIMEOUT;
5540 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5544 sd_bus_message_unref(*m);
5551 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5555 assert_return(!m->sealed, -EPERM);
5556 assert_return(!m->sender, -EPERM);
5558 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5561 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5562 assert_return(m, -EINVAL);
5563 assert_return(priority, -EINVAL);
5565 *priority = m->priority;
5569 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5570 assert_return(m, -EINVAL);
5571 assert_return(!m->sealed, -EPERM);
5573 m->priority = priority;