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"
39 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
41 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
46 if (old_base == new_base)
49 if ((uint8_t*) p < (uint8_t*) old_base)
52 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
55 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
58 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
62 if (part->memfd >= 0) {
63 /* If we can reuse the memfd, try that. For that it
64 * can't be sealed yet. */
67 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped);
70 assert_se(munmap(part->data, part->mapped) == 0);
72 close_nointr_nofail(part->memfd);
75 } else if (part->munmap_this)
76 munmap(part->data, part->mapped);
77 else if (part->free_this)
84 static void message_reset_parts(sd_bus_message *m) {
85 struct bus_body_part *part;
90 while (m->n_body_parts > 0) {
91 struct bus_body_part *next = part->next;
92 message_free_part(m, part);
99 m->cached_rindex_part = NULL;
100 m->cached_rindex_part_begin = 0;
103 static void message_reset_containers(sd_bus_message *m) {
108 for (i = 0; i < m->n_containers; i++) {
109 free(m->containers[i].signature);
110 free(m->containers[i].offsets);
114 m->containers = NULL;
117 m->root_container.index = 0;
120 static void message_free(sd_bus_message *m) {
126 message_reset_parts(m);
131 if (m->release_kdbus) {
134 off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
135 ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &off);
139 sd_bus_unref(m->bus);
142 close_many(m->fds, m->n_fds);
146 if (m->iovec != m->iovec_fixed)
149 message_reset_containers(m);
150 free(m->root_container.signature);
151 free(m->root_container.offsets);
153 free(m->peeked_signature);
155 bus_creds_done(&m->creds);
159 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
161 size_t old_size, new_size, start;
164 assert_return(!m->poisoned, NULL);
166 old_size = sizeof(struct bus_header) + m->header->fields_size;
167 start = ALIGN_TO(old_size, align);
168 new_size = start + sz;
170 if (old_size == new_size)
171 return (uint8_t*) m->header + old_size;
173 if (new_size > (size_t) ((uint32_t) -1))
176 if (m->free_header) {
177 np = realloc(m->header, ALIGN8(new_size));
181 /* Initially, the header is allocated as part of of
182 * the sd_bus_message itself, let's replace it by
185 np = malloc(ALIGN8(new_size));
189 memcpy(np, m->header, sizeof(struct bus_header));
192 /* Zero out padding */
193 if (start > old_size)
194 memset((uint8_t*) np + old_size, 0, start - old_size);
198 m->header->fields_size = new_size - sizeof(struct bus_header);
200 /* Adjust quick access pointers */
201 m->path = adjust_pointer(m->path, op, old_size, m->header);
202 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
203 m->member = adjust_pointer(m->member, op, old_size, m->header);
204 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
205 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
206 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
208 m->free_header = true;
211 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
214 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
217 return (uint8_t*) np + start;
224 static int message_append_field_string(
236 /* dbus1 doesn't allow strings over 32bit, let's enforce this
237 * globally, to not risk convertability */
239 if (l > (size_t) (uint32_t) -1)
242 /* Signature "(yv)" where the variant contains "s" */
244 if (BUS_MESSAGE_IS_GVARIANT(m)) {
246 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
247 p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
259 *ret = (char*) p + 8;
262 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
263 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
272 ((uint32_t*) p)[1] = l;
273 memcpy(p + 8, s, l + 1);
276 *ret = (char*) p + 8;
282 static int message_append_field_signature(
293 /* dbus1 doesn't allow signatures over 32bit, let's enforce
294 * this globally, to not risk convertability */
299 /* Signature "(yv)" where the variant contains "g" */
301 if (BUS_MESSAGE_IS_GVARIANT(m))
302 /* For gvariant the serialization is the same as for normal strings */
303 return message_append_field_string(m, h, 'g', s, ret);
305 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
306 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
312 p[2] = SD_BUS_TYPE_SIGNATURE;
315 memcpy(p + 5, s, l + 1);
318 *ret = (const char*) p + 5;
324 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
329 if (BUS_MESSAGE_IS_GVARIANT(m)) {
330 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
332 p = message_extend_fields(m, 8, 1 + 7 + 4 + 1 + 1, true);
338 *((uint32_t*) (p + 8)) = x;
342 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
343 p = message_extend_fields(m, 8, 4 + 4, false);
349 p[2] = SD_BUS_TYPE_UINT32;
352 ((uint32_t*) p)[1] = x;
358 int bus_message_from_header(
364 const struct ucred *ucred,
367 sd_bus_message **ret) {
370 struct bus_header *h;
373 assert(buffer || length <= 0);
374 assert(fds || n_fds <= 0);
377 if (length < sizeof(struct bus_header))
381 if (h->version != 1 &&
388 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
391 if (h->endian != BUS_LITTLE_ENDIAN &&
392 h->endian != BUS_BIG_ENDIAN)
395 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
398 label_sz = strlen(label);
413 m->creds.uid = ucred->uid;
414 m->creds.pid = ucred->pid;
415 m->creds.gid = ucred->gid;
416 m->creds.mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID;
420 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
421 memcpy(m->creds.label, label, label_sz + 1);
423 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
427 m->bus = sd_bus_ref(bus);
433 int bus_message_from_malloc(
439 const struct ucred *ucred,
441 sd_bus_message **ret) {
447 r = bus_message_from_header(bus, buffer, length, fds, n_fds, ucred, label, 0, &m);
451 if (length != BUS_MESSAGE_SIZE(m)) {
456 sz = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
459 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
461 m->body.sealed = true;
466 m->iovec = m->iovec_fixed;
467 m->iovec[0].iov_base = buffer;
468 m->iovec[0].iov_len = length;
470 r = bus_message_parse_fields(m);
474 /* We take possession of the memory and fds now */
475 m->free_header = true;
486 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
489 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
494 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
495 m->header->endian = BUS_NATIVE_ENDIAN;
496 m->header->type = type;
497 m->header->version = bus ? bus->message_version : 1;
498 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
499 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
502 m->bus = sd_bus_ref(bus);
507 _public_ int sd_bus_message_new_signal(
510 const char *interface,
512 sd_bus_message **m) {
517 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
518 assert_return(object_path_is_valid(path), -EINVAL);
519 assert_return(interface_name_is_valid(interface), -EINVAL);
520 assert_return(member_name_is_valid(member), -EINVAL);
521 assert_return(m, -EINVAL);
523 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
527 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
529 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
532 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
535 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
543 sd_bus_message_unref(t);
547 _public_ int sd_bus_message_new_method_call(
549 const char *destination,
551 const char *interface,
553 sd_bus_message **m) {
558 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
559 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
560 assert_return(object_path_is_valid(path), -EINVAL);
561 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
562 assert_return(member_name_is_valid(member), -EINVAL);
563 assert_return(m, -EINVAL);
565 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
569 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
572 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
577 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
583 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
596 static int message_new_reply(
597 sd_bus_message *call,
599 sd_bus_message **m) {
604 assert_return(call, -EINVAL);
605 assert_return(call->sealed, -EPERM);
606 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
607 assert_return(!call->bus || call->bus->state != BUS_UNSET, -ENOTCONN);
608 assert_return(m, -EINVAL);
610 t = message_new(call->bus, type);
614 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
615 t->reply_serial = BUS_MESSAGE_SERIAL(call);
617 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
622 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
627 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
628 t->enforced_reply_signature = call->enforced_reply_signature;
638 _public_ int sd_bus_message_new_method_return(
639 sd_bus_message *call,
640 sd_bus_message **m) {
642 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
645 _public_ int sd_bus_message_new_method_error(
646 sd_bus_message *call,
647 const sd_bus_error *e,
648 sd_bus_message **m) {
653 assert_return(sd_bus_error_is_set(e), -EINVAL);
654 assert_return(m, -EINVAL);
656 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
660 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
665 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
670 t->error._need_free = -1;
680 _public_ int sd_bus_message_new_method_errorf(
681 sd_bus_message *call,
687 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
690 assert_return(name, -EINVAL);
691 assert_return(m, -EINVAL);
693 va_start(ap, format);
694 bus_error_setfv(&error, name, format, ap);
697 return sd_bus_message_new_method_error(call, &error, m);
700 _public_ int sd_bus_message_new_method_errno(
701 sd_bus_message *call,
703 const sd_bus_error *p,
704 sd_bus_message **m) {
706 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
708 if (sd_bus_error_is_set(p))
709 return sd_bus_message_new_method_error(call, p, m);
711 sd_bus_error_set_errno(&berror, error);
713 return sd_bus_message_new_method_error(call, &berror, m);
716 _public_ int sd_bus_message_new_method_errnof(
717 sd_bus_message *call,
723 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
726 va_start(ap, format);
727 bus_error_set_errnofv(&berror, error, format, ap);
730 return sd_bus_message_new_method_error(call, &berror, m);
733 int bus_message_new_synthetic_error(
736 const sd_bus_error *e,
737 sd_bus_message **m) {
742 assert(sd_bus_error_is_set(e));
745 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
749 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
750 t->reply_serial = serial;
752 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
756 if (bus && bus->unique_name) {
757 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
762 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
767 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
772 t->error._need_free = -1;
782 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
783 assert_return(m, NULL);
785 assert(m->n_ref > 0);
791 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
792 assert_return(m, NULL);
794 assert(m->n_ref > 0);
803 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
804 assert_return(m, -EINVAL);
805 assert_return(type, -EINVAL);
807 *type = m->header->type;
811 _public_ int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
812 assert_return(m, -EINVAL);
813 assert_return(serial, -EINVAL);
814 assert_return(m->header->serial != 0, -ENOENT);
816 *serial = BUS_MESSAGE_SERIAL(m);
820 _public_ int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
821 assert_return(m, -EINVAL);
822 assert_return(serial, -EINVAL);
823 assert_return(m->reply_serial != 0, -ENOENT);
825 *serial = m->reply_serial;
829 _public_ int sd_bus_message_get_no_reply(sd_bus_message *m) {
830 assert_return(m, -EINVAL);
832 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL ? !!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
835 _public_ int sd_bus_message_get_no_auto_start(sd_bus_message *m) {
836 assert_return(m, -EINVAL);
838 return !!(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
841 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
842 assert_return(m, NULL);
847 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
848 assert_return(m, NULL);
853 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
854 assert_return(m, NULL);
859 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
860 assert_return(m, NULL);
862 return m->destination;
865 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
866 assert_return(m, NULL);
871 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
872 assert_return(m, NULL);
873 assert_return(sd_bus_error_is_set(&m->error), NULL);
878 _public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
879 assert_return(m, -EINVAL);
880 assert_return(usec, -EINVAL);
881 assert_return(m->monotonic > 0, -ENODATA);
883 *usec = m->monotonic;
887 _public_ int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
888 assert_return(m, -EINVAL);
889 assert_return(usec, -EINVAL);
890 assert_return(m->realtime > 0, -ENODATA);
896 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
897 assert_return(m, NULL);
899 if (m->creds.mask == 0)
905 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
906 const char *interface,
907 const char *member) {
908 assert_return(m, -EINVAL);
910 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
913 if (interface && (!m->interface || !streq(m->interface, interface)))
916 if (member && (!m->member || !streq(m->member, member)))
922 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
923 const char *interface,
924 const char *member) {
925 assert_return(m, -EINVAL);
927 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
930 if (interface && (!m->interface || !streq(m->interface, interface)))
933 if (member && (!m->member || !streq(m->member, member)))
939 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
940 assert_return(m, -EINVAL);
942 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
945 if (name && (!m->error.name || !streq(m->error.name, name)))
951 _public_ int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
952 assert_return(m, -EINVAL);
953 assert_return(!m->sealed, -EPERM);
954 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
957 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
959 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
964 _public_ int sd_bus_message_set_no_auto_start(sd_bus_message *m, int b) {
965 assert_return(m, -EINVAL);
966 assert_return(!m->sealed, -EPERM);
969 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
971 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
976 static struct bus_container *message_get_container(sd_bus_message *m) {
979 if (m->n_containers == 0)
980 return &m->root_container;
982 assert(m->containers);
983 return m->containers + m->n_containers - 1;
986 struct bus_body_part *message_append_part(sd_bus_message *m) {
987 struct bus_body_part *part;
990 assert_return(!m->poisoned, NULL);
992 if (m->n_body_parts <= 0) {
998 part = new0(struct bus_body_part, 1);
1004 m->body_end->next = part;
1014 static void part_zero(struct bus_body_part *part, size_t sz) {
1019 /* All other fields can be left in their defaults */
1020 assert(!part->data);
1021 assert(part->memfd < 0);
1024 part->is_zero = true;
1025 part->sealed = true;
1028 static int part_make_space(
1029 struct sd_bus_message *m,
1030 struct bus_body_part *part,
1039 assert(!part->sealed);
1044 if (!part->data && part->memfd < 0)
1045 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped);
1047 if (part->memfd >= 0) {
1050 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &u);
1056 if (!part->data || sz > part->mapped) {
1057 size_t psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1059 if (part->mapped <= 0)
1060 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1062 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1064 if (n == MAP_FAILED) {
1073 part->munmap_this = true;
1075 n = realloc(part->data, MAX(sz, 1u));
1082 part->free_this = true;
1086 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1092 static int message_add_offset(sd_bus_message *m, size_t offset) {
1093 struct bus_container *c;
1096 assert(BUS_MESSAGE_IS_GVARIANT(m));
1098 /* Add offset to current container, unless this is the first
1099 * item in it, which will have the 0 offset, which we can
1101 c = message_get_container(m);
1103 if (!c->need_offsets)
1106 if (!GREEDY_REALLOC(c->offsets, c->n_offsets_allocated, c->n_offsets + 1))
1109 c->offsets[c->n_offsets++] = offset;
1113 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1114 struct bus_container *c;
1121 /* Update counters */
1122 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1125 *c->array_size += expand;
1129 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1130 size_t start_body, end_body, padding, added;
1137 assert_return(!m->poisoned, NULL);
1139 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1140 end_body = start_body + sz;
1142 padding = start_body - m->header->body_size;
1143 added = padding + sz;
1145 /* Check for 32bit overflows */
1146 if (end_body > (size_t) ((uint32_t) -1)) {
1152 struct bus_body_part *part = NULL;
1156 m->n_body_parts <= 0 ||
1157 m->body_end->sealed ||
1158 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1162 part = message_append_part(m);
1166 part_zero(part, padding);
1169 part = message_append_part(m);
1173 r = part_make_space(m, part, sz, &p);
1177 struct bus_container *c;
1179 size_t os, start_part, end_part;
1185 start_part = ALIGN_TO(part->size, align);
1186 end_part = start_part + sz;
1188 r = part_make_space(m, part, end_part, &p);
1193 memset(p, 0, padding);
1194 p = (uint8_t*) p + padding;
1197 /* Readjust pointers */
1198 for (c = m->containers; c < m->containers + m->n_containers; c++)
1199 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1201 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1204 /* Return something that is not NULL and is aligned */
1205 p = (uint8_t *) NULL + align;
1207 m->header->body_size = end_body;
1208 message_extend_containers(m, added);
1211 r = message_add_offset(m, end_body);
1221 static int message_push_fd(sd_bus_message *m, int fd) {
1232 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1236 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1239 close_nointr_nofail(copy);
1244 m->fds[m->n_fds] = copy;
1250 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1251 _cleanup_close_ int fd = -1;
1252 struct bus_container *c;
1256 assert_return(m, -EINVAL);
1257 assert_return(!m->sealed, -EPERM);
1258 assert_return(bus_type_is_basic(type), -EINVAL);
1259 assert_return(!m->poisoned, -ESTALE);
1261 c = message_get_container(m);
1263 if (c->signature && c->signature[c->index]) {
1264 /* Container signature is already set */
1266 if (c->signature[c->index] != type)
1271 /* Maybe we can append to the signature? But only if this is the top-level container*/
1272 if (c->enclosing != 0)
1275 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1282 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1288 case SD_BUS_TYPE_SIGNATURE:
1289 case SD_BUS_TYPE_STRING:
1292 /* Fall through... */
1293 case SD_BUS_TYPE_OBJECT_PATH:
1301 case SD_BUS_TYPE_BOOLEAN:
1303 u8 = p && *(int*) p;
1309 case SD_BUS_TYPE_UNIX_FD:
1314 fd = message_push_fd(m, *(int*) p);
1325 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1326 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1333 a = message_extend_body(m, align, sz, true);
1340 *stored = (const uint8_t*) a;
1347 case SD_BUS_TYPE_STRING:
1348 /* To make things easy we'll serialize a NULL string
1349 * into the empty string */
1352 /* Fall through... */
1353 case SD_BUS_TYPE_OBJECT_PATH:
1359 sz = 4 + strlen(p) + 1;
1362 case SD_BUS_TYPE_SIGNATURE:
1367 sz = 1 + strlen(p) + 1;
1370 case SD_BUS_TYPE_BOOLEAN:
1372 u32 = p && *(int*) p;
1378 case SD_BUS_TYPE_UNIX_FD:
1383 fd = message_push_fd(m, *(int*) p);
1394 align = bus_type_get_alignment(type);
1395 sz = bus_type_get_size(type);
1402 a = message_extend_body(m, align, sz, false);
1406 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1407 *(uint32_t*) a = sz - 5;
1408 memcpy((uint8_t*) a + 4, p, sz - 4);
1411 *stored = (const uint8_t*) a + 4;
1413 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1414 *(uint8_t*) a = sz - 1;
1415 memcpy((uint8_t*) a + 1, p, sz - 1);
1418 *stored = (const uint8_t*) a + 1;
1427 if (type == SD_BUS_TYPE_UNIX_FD)
1430 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1437 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1438 return message_append_basic(m, type, p, NULL);
1441 _public_ int sd_bus_message_append_string_space(
1446 struct bus_container *c;
1449 assert_return(m, -EINVAL);
1450 assert_return(s, -EINVAL);
1451 assert_return(!m->sealed, -EPERM);
1452 assert_return(!m->poisoned, -ESTALE);
1454 c = message_get_container(m);
1456 if (c->signature && c->signature[c->index]) {
1457 /* Container signature is already set */
1459 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1464 /* Maybe we can append to the signature? But only if this is the top-level container*/
1465 if (c->enclosing != 0)
1468 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1475 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1476 a = message_extend_body(m, 1, size + 1, true);
1482 a = message_extend_body(m, 4, 4 + size + 1, false);
1486 *(uint32_t*) a = size;
1492 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1498 _public_ int sd_bus_message_append_string_iovec(
1500 const struct iovec *iov,
1508 assert_return(m, -EINVAL);
1509 assert_return(!m->sealed, -EPERM);
1510 assert_return(iov || n == 0, -EINVAL);
1511 assert_return(!m->poisoned, -ESTALE);
1513 size = IOVEC_TOTAL_SIZE(iov, n);
1515 r = sd_bus_message_append_string_space(m, size, &p);
1519 for (i = 0; i < n; i++) {
1521 if (iov[i].iov_base)
1522 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1524 memset(p, ' ', iov[i].iov_len);
1526 p += iov[i].iov_len;
1532 static int bus_message_open_array(
1534 struct bus_container *c,
1535 const char *contents,
1536 uint32_t **array_size,
1538 bool *need_offsets) {
1548 assert(need_offsets);
1550 if (!signature_is_single(contents, true))
1553 if (c->signature && c->signature[c->index]) {
1555 /* Verify the existing signature */
1557 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1560 if (!startswith(c->signature + c->index + 1, contents))
1563 nindex = c->index + 1 + strlen(contents);
1567 if (c->enclosing != 0)
1570 /* Extend the existing signature */
1572 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1578 nindex = e - c->signature;
1581 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1582 alignment = bus_gvariant_get_alignment(contents);
1586 /* Add alignment padding and add to offset list */
1587 if (!message_extend_body(m, alignment, 0, false))
1590 r = bus_gvariant_is_fixed_size(contents);
1594 *begin = m->header->body_size;
1595 *need_offsets = r == 0;
1599 struct bus_body_part *o;
1601 alignment = bus_type_get_alignment(contents[0]);
1605 a = message_extend_body(m, 4, 4, false);
1610 op = m->body_end->data;
1611 os = m->body_end->size;
1613 /* Add alignment between size and first element */
1614 if (!message_extend_body(m, alignment, 0, false))
1617 /* location of array size might have changed so let's readjust a */
1618 if (o == m->body_end)
1619 a = adjust_pointer(a, op, os, m->body_end->data);
1625 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1631 static int bus_message_open_variant(
1633 struct bus_container *c,
1634 const char *contents) {
1640 if (!signature_is_single(contents, false))
1643 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1646 if (c->signature && c->signature[c->index]) {
1648 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1654 if (c->enclosing != 0)
1657 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1664 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1665 /* Variants are always aligned to 8 */
1667 if (!message_extend_body(m, 8, 0, false))
1674 l = strlen(contents);
1675 a = message_extend_body(m, 1, 1 + l + 1, false);
1680 memcpy((uint8_t*) a + 1, contents, l + 1);
1683 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1689 static int bus_message_open_struct(
1691 struct bus_container *c,
1692 const char *contents,
1694 bool *need_offsets) {
1703 assert(need_offsets);
1705 if (!signature_is_valid(contents, false))
1708 if (c->signature && c->signature[c->index]) {
1711 l = strlen(contents);
1713 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1714 !startswith(c->signature + c->index + 1, contents) ||
1715 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1718 nindex = c->index + 1 + l + 1;
1722 if (c->enclosing != 0)
1725 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1731 nindex = e - c->signature;
1734 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1737 alignment = bus_gvariant_get_alignment(contents);
1741 if (!message_extend_body(m, alignment, 0, false))
1744 r = bus_gvariant_is_fixed_size(contents);
1748 *begin = m->header->body_size;
1749 *need_offsets = r == 0;
1751 /* Align contents to 8 byte boundary */
1752 if (!message_extend_body(m, 8, 0, false))
1756 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1762 static int bus_message_open_dict_entry(
1764 struct bus_container *c,
1765 const char *contents,
1767 bool *need_offsets) {
1775 assert(need_offsets);
1777 if (!signature_is_pair(contents))
1780 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1783 if (c->signature && c->signature[c->index]) {
1786 l = strlen(contents);
1788 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1789 !startswith(c->signature + c->index + 1, contents) ||
1790 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1795 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1798 alignment = bus_gvariant_get_alignment(contents);
1802 if (!message_extend_body(m, alignment, 0, false))
1805 r = bus_gvariant_is_fixed_size(contents);
1809 *begin = m->header->body_size;
1810 *need_offsets = r == 0;
1812 /* Align contents to 8 byte boundary */
1813 if (!message_extend_body(m, 8, 0, false))
1820 _public_ int sd_bus_message_open_container(
1823 const char *contents) {
1825 struct bus_container *c, *w;
1826 uint32_t *array_size = NULL;
1828 size_t before, begin;
1829 bool need_offsets = false;
1832 assert_return(m, -EINVAL);
1833 assert_return(!m->sealed, -EPERM);
1834 assert_return(contents, -EINVAL);
1835 assert_return(!m->poisoned, -ESTALE);
1837 /* Make sure we have space for one more container */
1838 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1846 c = message_get_container(m);
1848 signature = strdup(contents);
1854 /* Save old index in the parent container, in case we have to
1855 * abort this container */
1856 c->saved_index = c->index;
1857 before = m->header->body_size;
1859 if (type == SD_BUS_TYPE_ARRAY)
1860 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1861 else if (type == SD_BUS_TYPE_VARIANT)
1862 r = bus_message_open_variant(m, c, contents);
1863 else if (type == SD_BUS_TYPE_STRUCT)
1864 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1865 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1866 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1875 /* OK, let's fill it in */
1876 w += m->n_containers++;
1877 w->enclosing = type;
1878 w->signature = signature;
1880 w->array_size = array_size;
1883 w->n_offsets = w->n_offsets_allocated = 0;
1885 w->need_offsets = need_offsets;
1890 static size_t determine_word_size(size_t sz, size_t extra) {
1891 if (sz + extra <= 0xFF)
1893 else if (sz + extra*2 <= 0xFFFF)
1895 else if (sz + extra*4 <= 0xFFFFFFFF)
1901 static size_t read_word_le(void *p, size_t sz) {
1911 return *(uint8_t*) p;
1916 return le16toh(x.u16);
1918 return le32toh(x.u32);
1920 return le64toh(x.u64);
1922 assert_not_reached("unknown word width");
1925 static void write_word_le(void *p, size_t sz, size_t value) {
1933 assert(sz == 8 || (value < (1ULL << (sz*8))));
1936 *(uint8_t*) p = value;
1939 x.u16 = htole16((uint16_t) value);
1941 x.u32 = htole32((uint32_t) value);
1943 x.u64 = htole64((uint64_t) value);
1945 assert_not_reached("unknown word width");
1950 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1955 if (!BUS_MESSAGE_IS_GVARIANT(m))
1958 if (c->need_offsets) {
1959 size_t payload, sz, i;
1962 /* Variable-width arrays */
1964 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
1965 sz = determine_word_size(payload, c->n_offsets);
1967 a = message_extend_body(m, 1, sz * c->n_offsets, true);
1971 for (i = 0; i < c->n_offsets; i++)
1972 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
1976 /* Fixed-width or empty arrays */
1978 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
1986 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
1993 if (!BUS_MESSAGE_IS_GVARIANT(m))
1996 l = strlen(c->signature);
1998 a = message_extend_body(m, 1, 1 + l, true);
2003 memcpy(a+1, c->signature, l);
2008 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2009 size_t n_variable = 0;
2018 if (!BUS_MESSAGE_IS_GVARIANT(m))
2021 p = strempty(c->signature);
2025 r = signature_element_length(p, &n);
2034 r = bus_gvariant_is_fixed_size(t);
2039 assert(i <= c->n_offsets);
2041 /* We need to add an offset for each item that has a
2042 * variable size and that is not the last one in the
2044 if (r == 0 && p[n] != 0)
2051 assert(i == c->n_offsets);
2053 if (n_variable <= 0) {
2054 a = message_extend_body(m, 1, 0, add_offset);
2061 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2063 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2065 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2069 p = strempty(c->signature);
2070 for (i = 0, j = 0; i < c->n_offsets; i++) {
2074 r = signature_element_length(p, &n);
2085 r = bus_gvariant_is_fixed_size(t);
2088 if (r > 0 || p[0] == 0)
2092 k = n_variable - 1 - j;
2094 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2103 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2104 struct bus_container *c;
2107 assert_return(m, -EINVAL);
2108 assert_return(!m->sealed, -EPERM);
2109 assert_return(m->n_containers > 0, -EINVAL);
2110 assert_return(!m->poisoned, -ESTALE);
2112 c = message_get_container(m);
2114 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2115 if (c->signature && c->signature[c->index] != 0)
2120 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2121 r = bus_message_close_array(m, c);
2122 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2123 r = bus_message_close_variant(m, c);
2124 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2125 r = bus_message_close_struct(m, c, true);
2127 assert_not_reached("Unknown container type");
2141 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2148 stack[*i].types = types;
2149 stack[*i].n_struct = n_struct;
2150 stack[*i].n_array = n_array;
2156 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2167 *types = stack[*i].types;
2168 *n_struct = stack[*i].n_struct;
2169 *n_array = stack[*i].n_array;
2174 int bus_message_append_ap(
2179 unsigned n_array, n_struct;
2180 TypeStack stack[BUS_CONTAINER_DEPTH];
2181 unsigned stack_ptr = 0;
2189 n_array = (unsigned) -1;
2190 n_struct = strlen(types);
2195 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2196 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2202 r = sd_bus_message_close_container(m);
2210 if (n_array != (unsigned) -1)
2219 case SD_BUS_TYPE_BYTE: {
2222 x = (uint8_t) va_arg(ap, int);
2223 r = sd_bus_message_append_basic(m, *t, &x);
2227 case SD_BUS_TYPE_BOOLEAN:
2228 case SD_BUS_TYPE_INT32:
2229 case SD_BUS_TYPE_UINT32:
2230 case SD_BUS_TYPE_UNIX_FD: {
2233 /* We assume a boolean is the same as int32_t */
2234 assert_cc(sizeof(int32_t) == sizeof(int));
2236 x = va_arg(ap, uint32_t);
2237 r = sd_bus_message_append_basic(m, *t, &x);
2241 case SD_BUS_TYPE_INT16:
2242 case SD_BUS_TYPE_UINT16: {
2245 x = (uint16_t) va_arg(ap, int);
2246 r = sd_bus_message_append_basic(m, *t, &x);
2250 case SD_BUS_TYPE_INT64:
2251 case SD_BUS_TYPE_UINT64:
2252 case SD_BUS_TYPE_DOUBLE: {
2255 x = va_arg(ap, uint64_t);
2256 r = sd_bus_message_append_basic(m, *t, &x);
2260 case SD_BUS_TYPE_STRING:
2261 case SD_BUS_TYPE_OBJECT_PATH:
2262 case SD_BUS_TYPE_SIGNATURE: {
2265 x = va_arg(ap, const char*);
2266 r = sd_bus_message_append_basic(m, *t, x);
2270 case SD_BUS_TYPE_ARRAY: {
2273 r = signature_element_length(t + 1, &k);
2279 memcpy(s, t + 1, k);
2282 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2287 if (n_array == (unsigned) -1) {
2292 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2298 n_array = va_arg(ap, unsigned);
2303 case SD_BUS_TYPE_VARIANT: {
2306 s = va_arg(ap, const char*);
2310 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2314 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2319 n_struct = strlen(s);
2320 n_array = (unsigned) -1;
2325 case SD_BUS_TYPE_STRUCT_BEGIN:
2326 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2329 r = signature_element_length(t, &k);
2336 memcpy(s, t + 1, k - 2);
2339 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2344 if (n_array == (unsigned) -1) {
2349 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2355 n_array = (unsigned) -1;
2371 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2375 assert_return(m, -EINVAL);
2376 assert_return(types, -EINVAL);
2377 assert_return(!m->sealed, -EPERM);
2378 assert_return(!m->poisoned, -ESTALE);
2380 va_start(ap, types);
2381 r = bus_message_append_ap(m, types, ap);
2387 _public_ int sd_bus_message_append_array_space(
2397 assert_return(m, -EINVAL);
2398 assert_return(!m->sealed, -EPERM);
2399 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2400 assert_return(ptr || size == 0, -EINVAL);
2401 assert_return(!m->poisoned, -ESTALE);
2403 /* alignment and size of the trivial types (except bool) is
2404 * identical for gvariant and dbus1 marshalling */
2405 align = bus_type_get_alignment(type);
2406 sz = bus_type_get_size(type);
2408 assert_se(align > 0);
2414 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2418 a = message_extend_body(m, align, size, false);
2422 r = sd_bus_message_close_container(m);
2430 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2437 assert_return(m, -EINVAL);
2438 assert_return(!m->sealed, -EPERM);
2439 assert_return(bus_type_is_trivial(type), -EINVAL);
2440 assert_return(ptr || size == 0, -EINVAL);
2441 assert_return(!m->poisoned, -ESTALE);
2443 r = sd_bus_message_append_array_space(m, type, size, &p);
2448 memcpy(p, ptr, size);
2453 _public_ int sd_bus_message_append_array_iovec(
2456 const struct iovec *iov,
2464 assert_return(m, -EINVAL);
2465 assert_return(!m->sealed, -EPERM);
2466 assert_return(bus_type_is_trivial(type), -EINVAL);
2467 assert_return(iov || n == 0, -EINVAL);
2468 assert_return(!m->poisoned, -ESTALE);
2470 size = IOVEC_TOTAL_SIZE(iov, n);
2472 r = sd_bus_message_append_array_space(m, type, size, &p);
2476 for (i = 0; i < n; i++) {
2478 if (iov[i].iov_base)
2479 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2481 memset(p, 0, iov[i].iov_len);
2483 p = (uint8_t*) p + iov[i].iov_len;
2489 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2492 _cleanup_close_ int copy_fd = -1;
2493 struct bus_body_part *part;
2505 if (!bus_type_is_trivial(type))
2510 r = sd_memfd_set_sealed(memfd, true);
2514 copy_fd = sd_memfd_dup_fd(memfd);
2518 r = sd_memfd_get_size(memfd, &size);
2522 align = bus_type_get_alignment(type);
2523 sz = bus_type_get_size(type);
2525 assert_se(align > 0);
2531 if (size > (uint64_t) (uint32_t) -1)
2534 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2538 a = message_extend_body(m, align, 0, false);
2542 part = message_append_part(m);
2546 part->memfd = copy_fd;
2547 part->sealed = true;
2551 m->header->body_size += size;
2552 message_extend_containers(m, size);
2554 return sd_bus_message_close_container(m);
2557 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
2558 _cleanup_close_ int copy_fd = -1;
2559 struct bus_body_part *part;
2560 struct bus_container *c;
2565 assert_return(m, -EINVAL);
2566 assert_return(memfd, -EINVAL);
2567 assert_return(!m->sealed, -EPERM);
2568 assert_return(!m->poisoned, -ESTALE);
2570 r = sd_memfd_set_sealed(memfd, true);
2574 copy_fd = sd_memfd_dup_fd(memfd);
2578 r = sd_memfd_get_size(memfd, &size);
2582 /* We require this to be NUL terminated */
2586 if (size > (uint64_t) (uint32_t) -1)
2589 c = message_get_container(m);
2590 if (c->signature && c->signature[c->index]) {
2591 /* Container signature is already set */
2593 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2598 /* Maybe we can append to the signature? But only if this is the top-level container*/
2599 if (c->enclosing != 0)
2602 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2609 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2610 a = message_extend_body(m, 4, 4, false);
2614 *(uint32_t*) a = size - 1;
2617 part = message_append_part(m);
2621 part->memfd = copy_fd;
2622 part->sealed = true;
2626 m->header->body_size += size;
2627 message_extend_containers(m, size);
2629 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2630 r = message_add_offset(m, m->header->body_size);
2637 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2643 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2647 assert_return(m, -EINVAL);
2648 assert_return(!m->sealed, -EPERM);
2649 assert_return(!m->poisoned, -ESTALE);
2651 r = sd_bus_message_open_container(m, 'a', "s");
2655 STRV_FOREACH(i, l) {
2656 r = sd_bus_message_append_basic(m, 's', *i);
2661 return sd_bus_message_close_container(m);
2664 static int bus_message_close_header(sd_bus_message *m) {
2670 if (!BUS_MESSAGE_IS_GVARIANT(m))
2673 if (m->n_header_offsets < 1)
2676 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2678 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2680 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2684 for (i = 0; i < m->n_header_offsets; i++)
2685 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2690 int bus_message_seal(sd_bus_message *m, uint64_t serial) {
2691 struct bus_body_part *part;
2701 if (m->n_containers > 0)
2707 /* In vtables the return signature of method calls is listed,
2708 * let's check if they match if this is a response */
2709 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2710 m->enforced_reply_signature &&
2711 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2714 /* If gvariant marshalling is used we need to close the body structure */
2715 r = bus_message_close_struct(m, &m->root_container, false);
2719 /* If there's a non-trivial signature set, then add it in here */
2720 if (!isempty(m->root_container.signature)) {
2721 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2727 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2732 r = bus_message_close_header(m);
2736 m->header->serial = serial;
2738 /* Add padding at the end of the fields part, since we know
2739 * the body needs to start at an 8 byte alignment. We made
2740 * sure we allocated enough space for this, so all we need to
2741 * do here is to zero it out. */
2742 l = BUS_MESSAGE_FIELDS_SIZE(m);
2745 memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
2747 /* If this is something we can send as memfd, then let's seal
2748 the memfd now. Note that we can send memfds as payload only
2749 for directed messages, and not for broadcasts. */
2750 if (m->destination && m->bus && m->bus->use_memfd) {
2751 MESSAGE_FOREACH_PART(part, i, m)
2752 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2753 bus_body_part_unmap(part);
2755 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
2756 part->sealed = true;
2760 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2761 m->root_container.index = 0;
2762 m->root_container.offset_index = 0;
2763 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2770 int bus_body_part_map(struct bus_body_part *part) {
2779 if (part->size <= 0)
2782 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2783 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2784 static const uint8_t zeroes[7] = { };
2785 part->data = (void*) zeroes;
2789 psz = PAGE_ALIGN(part->size);
2791 if (part->memfd >= 0)
2792 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2793 else if (part->is_zero)
2794 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2798 if (p == MAP_FAILED)
2803 part->munmap_this = true;
2808 void bus_body_part_unmap(struct bus_body_part *part) {
2812 if (part->memfd < 0)
2818 if (!part->munmap_this)
2821 assert_se(munmap(part->data, part->mapped) == 0);
2825 part->munmap_this = false;
2830 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2831 size_t k, start, end;
2836 start = ALIGN_TO((size_t) *rindex, align);
2837 end = start + nbytes;
2842 /* Verify that padding is 0 */
2843 for (k = *rindex; k < start; k++)
2844 if (((const uint8_t*) p)[k] != 0)
2848 *r = (uint8_t*) p + start;
2855 static bool message_end_of_signature(sd_bus_message *m) {
2856 struct bus_container *c;
2860 c = message_get_container(m);
2861 return !c->signature || c->signature[c->index] == 0;
2864 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2865 struct bus_container *c;
2869 c = message_get_container(m);
2870 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2873 if (BUS_MESSAGE_IS_GVARIANT(m))
2874 return index >= c->end;
2876 assert(c->array_size);
2877 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2881 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2882 assert_return(m, -EINVAL);
2883 assert_return(m->sealed, -EPERM);
2885 if (complete && m->n_containers > 0)
2888 if (message_end_of_signature(m))
2891 if (message_end_of_array(m, m->rindex))
2897 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2898 struct bus_body_part *part;
2904 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2905 part = m->cached_rindex_part;
2906 begin = m->cached_rindex_part_begin;
2916 if (index + sz <= begin + part->size) {
2918 r = bus_body_part_map(part);
2923 *p = (uint8_t*) part->data + index - begin;
2925 m->cached_rindex_part = part;
2926 m->cached_rindex_part_begin = begin;
2931 begin += part->size;
2938 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2945 if (!BUS_MESSAGE_IS_GVARIANT(m))
2948 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2951 sz = bus_gvariant_get_size(c->signature);
2955 if (c->offset_index+1 >= c->n_offsets)
2958 /* Variable-size array */
2960 alignment = bus_gvariant_get_alignment(c->signature);
2961 assert(alignment > 0);
2963 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
2964 c->item_size = c->offsets[c->offset_index+1] - *rindex;
2967 if (c->offset_index+1 >= (c->end-c->begin)/sz)
2970 /* Fixed-size array */
2971 *rindex = c->begin + (c->offset_index+1) * sz;
2977 } else if (c->enclosing == 0 ||
2978 c->enclosing == SD_BUS_TYPE_STRUCT ||
2979 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
2984 if (c->offset_index+1 >= c->n_offsets)
2987 r = signature_element_length(c->signature + c->index, &n);
2991 r = signature_element_length(c->signature + c->index + n, &j);
2996 memcpy(t, c->signature + c->index + n, j);
2999 alignment = bus_gvariant_get_alignment(t);
3002 assert(alignment > 0);
3004 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3005 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3009 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3012 assert_not_reached("Unknown container type");
3017 /* Reached the end */
3024 static int message_peek_body(
3031 size_t k, start, end, padding;
3032 struct bus_body_part *part;
3039 start = ALIGN_TO((size_t) *rindex, align);
3040 padding = start - *rindex;
3041 end = start + nbytes;
3043 if (end > BUS_MESSAGE_BODY_SIZE(m))
3046 part = find_part(m, *rindex, padding, (void**) &q);
3051 /* Verify padding */
3052 for (k = 0; k < padding; k++)
3057 part = find_part(m, start, nbytes, (void**) &q);
3058 if (!part || (nbytes > 0 && !q))
3069 static bool validate_nul(const char *s, size_t l) {
3071 /* Check for NUL chars in the string */
3072 if (memchr(s, 0, l))
3075 /* Check for NUL termination */
3082 static bool validate_string(const char *s, size_t l) {
3084 if (!validate_nul(s, l))
3087 /* Check if valid UTF8 */
3088 if (!utf8_is_valid(s))
3094 static bool validate_signature(const char *s, size_t l) {
3096 if (!validate_nul(s, l))
3099 /* Check if valid signature */
3100 if (!signature_is_valid(s, true))
3106 static bool validate_object_path(const char *s, size_t l) {
3108 if (!validate_nul(s, l))
3111 if (!object_path_is_valid(s))
3117 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3118 struct bus_container *c;
3123 assert_return(m, -EINVAL);
3124 assert_return(m->sealed, -EPERM);
3125 assert_return(bus_type_is_basic(type), -EINVAL);
3127 if (message_end_of_signature(m))
3130 if (message_end_of_array(m, m->rindex))
3133 c = message_get_container(m);
3134 if (c->signature[c->index] != type)
3139 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3141 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3144 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3148 if (type == SD_BUS_TYPE_STRING)
3149 ok = validate_string(q, c->item_size-1);
3150 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3151 ok = validate_object_path(q, c->item_size-1);
3153 ok = validate_signature(q, c->item_size-1);
3159 *(const char**) p = q;
3163 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3165 if ((size_t) sz != c->item_size)
3168 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3171 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3177 case SD_BUS_TYPE_BYTE:
3179 *(uint8_t*) p = *(uint8_t*) q;
3182 case SD_BUS_TYPE_BOOLEAN:
3184 *(int*) p = !!*(uint8_t*) q;
3187 case SD_BUS_TYPE_INT16:
3188 case SD_BUS_TYPE_UINT16:
3190 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3193 case SD_BUS_TYPE_INT32:
3194 case SD_BUS_TYPE_UINT32:
3196 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3199 case SD_BUS_TYPE_INT64:
3200 case SD_BUS_TYPE_UINT64:
3201 case SD_BUS_TYPE_DOUBLE:
3203 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3206 case SD_BUS_TYPE_UNIX_FD: {
3209 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3214 *(int*) p = m->fds[j];
3220 assert_not_reached("unexpected type");
3224 r = container_next_item(m, c, &rindex);
3231 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3235 r = message_peek_body(m, &rindex, 4, 4, &q);
3239 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3240 r = message_peek_body(m, &rindex, 1, l+1, &q);
3244 if (type == SD_BUS_TYPE_OBJECT_PATH)
3245 ok = validate_object_path(q, l);
3247 ok = validate_string(q, l);
3252 *(const char**) p = q;
3254 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3257 r = message_peek_body(m, &rindex, 1, 1, &q);
3262 r = message_peek_body(m, &rindex, 1, l+1, &q);
3266 if (!validate_signature(q, l))
3270 *(const char**) p = q;
3275 align = bus_type_get_alignment(type);
3278 sz = bus_type_get_size(type);
3281 r = message_peek_body(m, &rindex, align, sz, &q);
3287 case SD_BUS_TYPE_BYTE:
3289 *(uint8_t*) p = *(uint8_t*) q;
3292 case SD_BUS_TYPE_BOOLEAN:
3294 *(int*) p = !!*(uint32_t*) q;
3297 case SD_BUS_TYPE_INT16:
3298 case SD_BUS_TYPE_UINT16:
3300 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3303 case SD_BUS_TYPE_INT32:
3304 case SD_BUS_TYPE_UINT32:
3306 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3309 case SD_BUS_TYPE_INT64:
3310 case SD_BUS_TYPE_UINT64:
3311 case SD_BUS_TYPE_DOUBLE:
3313 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3316 case SD_BUS_TYPE_UNIX_FD: {
3319 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3324 *(int*) p = m->fds[j];
3329 assert_not_reached("Unknown basic type...");
3336 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3342 static int bus_message_enter_array(
3344 struct bus_container *c,
3345 const char *contents,
3346 uint32_t **array_size,
3349 size_t *n_offsets) {
3363 if (!signature_is_single(contents, true))
3366 if (!c->signature || c->signature[c->index] == 0)
3369 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3372 if (!startswith(c->signature + c->index + 1, contents))
3377 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3380 r = message_peek_body(m, &rindex, 4, 4, &q);
3384 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3387 alignment = bus_type_get_alignment(contents[0]);
3391 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3395 *array_size = (uint32_t*) q;
3397 } else if (c->item_size <= 0) {
3399 /* gvariant: empty array */
3404 } else if (bus_gvariant_is_fixed_size(contents)) {
3406 /* gvariant: fixed length array */
3407 *item_size = bus_gvariant_get_size(contents);
3412 size_t where, p = 0, framing, sz;
3415 /* gvariant: variable length array */
3416 sz = determine_word_size(c->item_size, 0);
3418 where = rindex + c->item_size - sz;
3419 r = message_peek_body(m, &where, 1, sz, &q);
3423 framing = read_word_le(q, sz);
3424 if (framing > c->item_size - sz)
3426 if ((c->item_size - framing) % sz != 0)
3429 *n_offsets = (c->item_size - framing) / sz;
3431 where = rindex + framing;
3432 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3436 *offsets = new(size_t, *n_offsets);
3440 for (i = 0; i < *n_offsets; i++) {
3443 x = read_word_le((uint8_t*) q + i * sz, sz);
3444 if (x > c->item_size - sz)
3449 (*offsets)[i] = rindex + x;
3453 *item_size = (*offsets)[0] - rindex;
3458 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3459 c->index += 1 + strlen(contents);
3464 static int bus_message_enter_variant(
3466 struct bus_container *c,
3467 const char *contents,
3468 size_t *item_size) {
3480 if (!signature_is_single(contents, false))
3483 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3486 if (!c->signature || c->signature[c->index] == 0)
3489 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3494 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3497 k = strlen(contents);
3498 if (1+k > c->item_size)
3501 where = rindex + c->item_size - (1+k);
3502 r = message_peek_body(m, &where, 1, 1+k, &q);
3506 if (*(char*) q != 0)
3509 if (memcmp((uint8_t*) q+1, contents, k))
3512 *item_size = c->item_size - (1+k);
3515 r = message_peek_body(m, &rindex, 1, 1, &q);
3520 r = message_peek_body(m, &rindex, 1, l+1, &q);
3524 if (!validate_signature(q, l))
3527 if (!streq(q, contents))
3533 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3539 static int build_struct_offsets(
3541 const char *signature,
3545 size_t *n_offsets) {
3547 unsigned n_variable = 0, n_total = 0, v;
3548 size_t previous = 0, where;
3559 if (isempty(signature)) {
3566 sz = determine_word_size(size, 0);
3570 /* First, loop over signature and count variable elements and
3571 * elements in general. We use this to know how large the
3572 * offset array is at the end of the structure. Note that
3573 * GVariant only stores offsets for all variable size elements
3574 * that are not the last item. */
3580 r = signature_element_length(p, &n);
3589 r = bus_gvariant_is_fixed_size(t);
3594 if (r == 0 && p[n] != 0) /* except the last item */
3601 if (size < n_variable * sz)
3604 where = m->rindex + size - (n_variable * sz);
3605 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3611 *offsets = new(size_t, n_total);
3617 /* Second, loop again and build an offset table */
3623 r = signature_element_length(p, &n);
3632 k = bus_gvariant_get_size(t);
3640 x = read_word_le((uint8_t*) q + v*sz, sz);
3643 if (m->rindex + x < previous)
3646 /* The last item's end
3647 * is determined from
3650 x = size - (n_variable * sz);
3652 offset = m->rindex + x;
3658 align = bus_gvariant_get_alignment(t);
3661 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3665 previous = (*offsets)[(*n_offsets)++] = offset;
3670 assert(*n_offsets == n_total);
3672 *item_size = (*offsets)[0] - m->rindex;
3676 static int enter_struct_or_dict_entry(
3678 struct bus_container *c,
3679 const char *contents,
3682 size_t *n_offsets) {
3693 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3696 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3700 } else if (c->item_size <= 0) {
3702 /* gvariant empty struct */
3707 /* gvariant with contents */
3708 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3713 static int bus_message_enter_struct(
3715 struct bus_container *c,
3716 const char *contents,
3719 size_t *n_offsets) {
3731 if (!signature_is_valid(contents, false))
3734 if (!c->signature || c->signature[c->index] == 0)
3737 l = strlen(contents);
3739 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3740 !startswith(c->signature + c->index + 1, contents) ||
3741 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3744 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3748 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3749 c->index += 1 + l + 1;
3754 static int bus_message_enter_dict_entry(
3756 struct bus_container *c,
3757 const char *contents,
3760 size_t *n_offsets) {
3769 if (!signature_is_pair(contents))
3772 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3775 if (!c->signature || c->signature[c->index] == 0)
3778 l = strlen(contents);
3780 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3781 !startswith(c->signature + c->index + 1, contents) ||
3782 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3785 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3789 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3790 c->index += 1 + l + 1;
3795 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3797 const char *contents) {
3798 struct bus_container *c, *w;
3799 uint32_t *array_size = NULL;
3802 size_t *offsets = NULL;
3803 size_t n_offsets = 0, item_size = 0;
3806 assert_return(m, -EINVAL);
3807 assert_return(m->sealed, -EPERM);
3808 assert_return(type != 0 || !contents, -EINVAL);
3810 if (type == 0 || !contents) {
3814 /* Allow entering into anonymous containers */
3815 r = sd_bus_message_peek_type(m, &tt, &cc);
3819 if (type != 0 && type != tt)
3822 if (contents && !streq(contents, cc))
3830 * We enforce a global limit on container depth, that is much
3831 * higher than the 32 structs and 32 arrays the specification
3832 * mandates. This is simpler to implement for us, and we need
3833 * this only to ensure our container array doesn't grow
3834 * without bounds. We are happy to return any data from a
3835 * message as long as the data itself is valid, even if the
3836 * overall message might be not.
3838 * Note that the message signature is validated when
3839 * parsing the headers, and that validation does check the
3842 * Note that the specification defines no limits on the depth
3843 * of stacked variants, but we do.
3845 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3848 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
3853 if (message_end_of_signature(m))
3856 if (message_end_of_array(m, m->rindex))
3859 c = message_get_container(m);
3861 signature = strdup(contents);
3865 c->saved_index = c->index;
3868 if (type == SD_BUS_TYPE_ARRAY)
3869 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3870 else if (type == SD_BUS_TYPE_VARIANT)
3871 r = bus_message_enter_variant(m, c, contents, &item_size);
3872 else if (type == SD_BUS_TYPE_STRUCT)
3873 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3874 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3875 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3885 /* OK, let's fill it in */
3886 w += m->n_containers++;
3887 w->enclosing = type;
3888 w->signature = signature;
3892 w->begin = m->rindex;
3893 w->end = m->rindex + c->item_size;
3895 w->array_size = array_size;
3896 w->item_size = item_size;
3897 w->offsets = offsets;
3898 w->n_offsets = n_offsets;
3899 w->offset_index = 0;
3904 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3905 struct bus_container *c;
3909 assert_return(m, -EINVAL);
3910 assert_return(m->sealed, -EPERM);
3911 assert_return(m->n_containers > 0, -ENXIO);
3913 c = message_get_container(m);
3915 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3916 if (c->signature && c->signature[c->index] != 0)
3920 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3921 if (m->rindex < c->end)
3924 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3927 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3928 if (c->begin + l != m->rindex)
3936 c = message_get_container(m);
3939 c->index = c->saved_index;
3940 r = container_next_item(m, c, &m->rindex);
3948 static void message_quit_container(sd_bus_message *m) {
3949 struct bus_container *c;
3953 assert(m->n_containers > 0);
3955 c = message_get_container(m);
3958 assert(m->rindex >= c->before);
3959 m->rindex = c->before;
3961 /* Free container */
3966 /* Correct index of new top-level container */
3967 c = message_get_container(m);
3968 c->index = c->saved_index;
3971 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
3972 struct bus_container *c;
3975 assert_return(m, -EINVAL);
3976 assert_return(m->sealed, -EPERM);
3978 if (message_end_of_signature(m))
3981 if (message_end_of_array(m, m->rindex))
3984 c = message_get_container(m);
3986 if (bus_type_is_basic(c->signature[c->index])) {
3990 *type = c->signature[c->index];
3994 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4000 r = signature_element_length(c->signature+c->index+1, &l);
4006 sig = strndup(c->signature + c->index + 1, l);
4010 free(m->peeked_signature);
4011 m->peeked_signature = sig;
4017 *type = SD_BUS_TYPE_ARRAY;
4022 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4023 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4029 r = signature_element_length(c->signature+c->index, &l);
4034 sig = strndup(c->signature + c->index + 1, l - 2);
4038 free(m->peeked_signature);
4039 m->peeked_signature = sig;
4045 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4050 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4054 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4057 if (c->item_size < 2)
4060 /* Look for the NUL delimiter that
4061 separates the payload from the
4062 signature. Since the body might be
4063 in a different part that then the
4064 signature we map byte by byte. */
4066 for (k = 2; k <= c->item_size; k++) {
4069 where = m->rindex + c->item_size - k;
4070 r = message_peek_body(m, &where, 1, k, &q);
4074 if (*(char*) q == 0)
4078 if (k > c->item_size)
4081 free(m->peeked_signature);
4082 m->peeked_signature = strndup((char*) q + 1, k - 1);
4083 if (!m->peeked_signature)
4086 if (!signature_is_valid(m->peeked_signature, true))
4089 *contents = m->peeked_signature;
4094 r = message_peek_body(m, &rindex, 1, 1, &q);
4099 r = message_peek_body(m, &rindex, 1, l+1, &q);
4103 if (!validate_signature(q, l))
4111 *type = SD_BUS_TYPE_VARIANT;
4126 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4127 struct bus_container *c;
4129 assert_return(m, -EINVAL);
4130 assert_return(m->sealed, -EPERM);
4133 message_reset_containers(m);
4136 c = message_get_container(m);
4138 c = message_get_container(m);
4140 c->offset_index = 0;
4142 m->rindex = c->begin;
4145 c->offset_index = 0;
4146 c->item_size = c->n_offsets > 0 ? c->offsets[0] : c->end;
4148 return !isempty(c->signature);
4151 static int message_read_ap(
4156 unsigned n_array, n_struct;
4157 TypeStack stack[BUS_CONTAINER_DEPTH];
4158 unsigned stack_ptr = 0;
4159 unsigned n_loop = 0;
4167 /* Ideally, we'd just call ourselves recursively on every
4168 * complex type. However, the state of a va_list that is
4169 * passed to a function is undefined after that function
4170 * returns. This means we need to docode the va_list linearly
4171 * in a single stackframe. We hence implement our own
4172 * home-grown stack in an array. */
4174 n_array = (unsigned) -1; /* lenght of current array entries */
4175 n_struct = strlen(types); /* length of current struct contents signature */
4182 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4183 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4189 r = sd_bus_message_exit_container(m);
4197 if (n_array != (unsigned) -1)
4206 case SD_BUS_TYPE_BYTE:
4207 case SD_BUS_TYPE_BOOLEAN:
4208 case SD_BUS_TYPE_INT16:
4209 case SD_BUS_TYPE_UINT16:
4210 case SD_BUS_TYPE_INT32:
4211 case SD_BUS_TYPE_UINT32:
4212 case SD_BUS_TYPE_INT64:
4213 case SD_BUS_TYPE_UINT64:
4214 case SD_BUS_TYPE_DOUBLE:
4215 case SD_BUS_TYPE_STRING:
4216 case SD_BUS_TYPE_OBJECT_PATH:
4217 case SD_BUS_TYPE_SIGNATURE:
4218 case SD_BUS_TYPE_UNIX_FD: {
4221 p = va_arg(ap, void*);
4222 r = sd_bus_message_read_basic(m, *t, p);
4235 case SD_BUS_TYPE_ARRAY: {
4238 r = signature_element_length(t + 1, &k);
4244 memcpy(s, t + 1, k);
4247 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4258 if (n_array == (unsigned) -1) {
4263 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4269 n_array = va_arg(ap, unsigned);
4274 case SD_BUS_TYPE_VARIANT: {
4277 s = va_arg(ap, const char *);
4281 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4291 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4296 n_struct = strlen(s);
4297 n_array = (unsigned) -1;
4302 case SD_BUS_TYPE_STRUCT_BEGIN:
4303 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4306 r = signature_element_length(t, &k);
4312 memcpy(s, t + 1, k - 2);
4315 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4325 if (n_array == (unsigned) -1) {
4330 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4336 n_array = (unsigned) -1;
4349 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4353 assert_return(m, -EINVAL);
4354 assert_return(m->sealed, -EPERM);
4355 assert_return(types, -EINVAL);
4357 va_start(ap, types);
4358 r = message_read_ap(m, types, ap);
4364 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4367 assert_return(m, -EINVAL);
4368 assert_return(m->sealed, -EPERM);
4369 assert_return(types, -EINVAL);
4376 case SD_BUS_TYPE_BYTE:
4377 case SD_BUS_TYPE_BOOLEAN:
4378 case SD_BUS_TYPE_INT16:
4379 case SD_BUS_TYPE_UINT16:
4380 case SD_BUS_TYPE_INT32:
4381 case SD_BUS_TYPE_UINT32:
4382 case SD_BUS_TYPE_INT64:
4383 case SD_BUS_TYPE_UINT64:
4384 case SD_BUS_TYPE_DOUBLE:
4385 case SD_BUS_TYPE_STRING:
4386 case SD_BUS_TYPE_OBJECT_PATH:
4387 case SD_BUS_TYPE_SIGNATURE:
4388 case SD_BUS_TYPE_UNIX_FD:
4390 r = sd_bus_message_read_basic(m, *types, NULL);
4394 r = sd_bus_message_skip(m, types + 1);
4400 case SD_BUS_TYPE_ARRAY: {
4403 r = signature_element_length(types + 1, &k);
4409 memcpy(s, types+1, k);
4412 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4417 r = sd_bus_message_skip(m, s);
4424 r = sd_bus_message_exit_container(m);
4429 r = sd_bus_message_skip(m, types + 1 + k);
4436 case SD_BUS_TYPE_VARIANT: {
4437 const char *contents;
4440 r = sd_bus_message_peek_type(m, &x, &contents);
4444 if (x != SD_BUS_TYPE_VARIANT)
4447 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4451 r = sd_bus_message_skip(m, contents);
4456 r = sd_bus_message_exit_container(m);
4460 r = sd_bus_message_skip(m, types + 1);
4467 case SD_BUS_TYPE_STRUCT_BEGIN:
4468 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4471 r = signature_element_length(types, &k);
4477 memcpy(s, types+1, k-2);
4480 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4484 r = sd_bus_message_skip(m, s);
4489 r = sd_bus_message_exit_container(m);
4494 r = sd_bus_message_skip(m, types + k);
4506 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4510 struct bus_container *c;
4516 assert_return(m, -EINVAL);
4517 assert_return(m->sealed, -EPERM);
4518 assert_return(bus_type_is_trivial(type), -EINVAL);
4519 assert_return(ptr, -EINVAL);
4520 assert_return(size, -EINVAL);
4521 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4523 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4527 c = message_get_container(m);
4529 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4530 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4534 sz = c->end - c->begin;
4536 align = bus_type_get_alignment(type);
4540 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4544 /* Zero length array, let's return some aligned
4545 * pointer that is not NULL */
4546 p = (uint8_t*) NULL + align;
4548 r = message_peek_body(m, &m->rindex, align, sz, &p);
4553 r = sd_bus_message_exit_container(m);
4557 *ptr = (const void*) p;
4563 message_quit_container(m);
4567 static int message_peek_fields(
4578 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4581 static int message_peek_field_uint32(
4593 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4596 /* identical for gvariant and dbus1 */
4598 r = message_peek_fields(m, ri, 4, 4, &q);
4603 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4608 static int message_peek_field_string(
4610 bool (*validate)(const char *p),
4622 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4627 r = message_peek_fields(m, ri, 1, item_size, &q);
4633 r = message_peek_field_uint32(m, ri, 4, &l);
4637 r = message_peek_fields(m, ri, 1, l+1, &q);
4643 if (!validate_nul(q, l))
4649 if (!validate_string(q, l))
4659 static int message_peek_field_signature(
4672 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4677 r = message_peek_fields(m, ri, 1, item_size, &q);
4683 r = message_peek_fields(m, ri, 1, 1, &q);
4688 r = message_peek_fields(m, ri, 1, l+1, &q);
4693 if (!validate_signature(q, l))
4702 static int message_skip_fields(
4705 uint32_t array_size,
4706 const char **signature) {
4708 size_t original_index;
4714 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4716 original_index = *ri;
4722 if (array_size != (uint32_t) -1 &&
4723 array_size <= *ri - original_index)
4730 if (t == SD_BUS_TYPE_STRING) {
4732 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4738 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4740 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4746 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4748 r = message_peek_field_signature(m, ri, 0, NULL);
4754 } else if (bus_type_is_basic(t)) {
4757 align = bus_type_get_alignment(t);
4758 k = bus_type_get_size(t);
4759 assert(align > 0 && k > 0);
4761 r = message_peek_fields(m, ri, align, k, NULL);
4767 } else if (t == SD_BUS_TYPE_ARRAY) {
4769 r = signature_element_length(*signature+1, &l);
4779 strncpy(sig, *signature + 1, l-1);
4782 alignment = bus_type_get_alignment(sig[0]);
4786 r = message_peek_field_uint32(m, ri, 0, &nas);
4789 if (nas > BUS_ARRAY_MAX_SIZE)
4792 r = message_peek_fields(m, ri, alignment, 0, NULL);
4796 r = message_skip_fields(m, ri, nas, (const char**) &s);
4801 (*signature) += 1 + l;
4803 } else if (t == SD_BUS_TYPE_VARIANT) {
4806 r = message_peek_field_signature(m, ri, 0, &s);
4810 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4816 } else if (t == SD_BUS_TYPE_STRUCT ||
4817 t == SD_BUS_TYPE_DICT_ENTRY) {
4819 r = signature_element_length(*signature, &l);
4826 strncpy(sig, *signature + 1, l-1);
4829 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4840 int bus_message_parse_fields(sd_bus_message *m) {
4843 uint32_t unix_fds = 0;
4844 void *offsets = NULL;
4845 unsigned n_offsets = 0;
4851 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4854 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4858 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4859 r = message_peek_fields(m, &ri, 1, sz, &q);
4863 framing = read_word_le(q, sz);
4864 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4866 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4870 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4874 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4879 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4880 _cleanup_free_ char *sig = NULL;
4881 const char *signature;
4883 size_t item_size = (size_t) -1;
4885 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4892 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4895 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4899 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4904 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4909 where = ri = ALIGN_TO(ri, 8);
4910 item_size = end - ri;
4911 r = message_peek_fields(m, &where, 1, item_size, &q);
4915 b = memrchr(q, 0, item_size);
4919 sig = strndup(b+1, item_size - (b+1-(char*) q));
4924 item_size = b - (char*) q;
4926 r = message_peek_field_signature(m, &ri, 0, &signature);
4932 case _BUS_MESSAGE_HEADER_INVALID:
4935 case BUS_MESSAGE_HEADER_PATH:
4940 if (!streq(signature, "o"))
4943 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
4946 case BUS_MESSAGE_HEADER_INTERFACE:
4951 if (!streq(signature, "s"))
4954 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
4957 case BUS_MESSAGE_HEADER_MEMBER:
4962 if (!streq(signature, "s"))
4965 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
4968 case BUS_MESSAGE_HEADER_ERROR_NAME:
4973 if (!streq(signature, "s"))
4976 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
4978 m->error._need_free = -1;
4982 case BUS_MESSAGE_HEADER_DESTINATION:
4987 if (!streq(signature, "s"))
4990 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
4993 case BUS_MESSAGE_HEADER_SENDER:
4998 if (!streq(signature, "s"))
5001 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5003 if (r >= 0 && m->sender[0] == ':' && m->bus && m->bus->bus_client && !m->bus->is_kernel) {
5004 m->creds.unique_name = (char*) m->sender;
5005 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5011 case BUS_MESSAGE_HEADER_SIGNATURE: {
5015 if (m->root_container.signature)
5018 if (!streq(signature, "g"))
5021 r = message_peek_field_signature(m, &ri, item_size, &s);
5029 free(m->root_container.signature);
5030 m->root_container.signature = c;
5034 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5035 if (m->reply_serial != 0)
5038 if (!streq(signature, "u"))
5041 r = message_peek_field_uint32(m, &ri, item_size, &m->reply_serial);
5045 if (m->reply_serial == 0)
5050 case BUS_MESSAGE_HEADER_UNIX_FDS:
5054 if (!streq(signature, "u"))
5057 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5067 if (!BUS_MESSAGE_IS_GVARIANT(m))
5068 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5077 if (m->n_fds != unix_fds)
5080 switch (m->header->type) {
5082 case SD_BUS_MESSAGE_SIGNAL:
5083 if (!m->path || !m->interface || !m->member)
5087 case SD_BUS_MESSAGE_METHOD_CALL:
5089 if (!m->path || !m->member)
5094 case SD_BUS_MESSAGE_METHOD_RETURN:
5096 if (m->reply_serial == 0)
5100 case SD_BUS_MESSAGE_METHOD_ERROR:
5102 if (m->reply_serial == 0 || !m->error.name)
5107 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5109 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5110 r = build_struct_offsets(
5112 m->root_container.signature,
5113 BUS_MESSAGE_BODY_SIZE(m),
5114 &m->root_container.item_size,
5115 &m->root_container.offsets,
5116 &m->root_container.n_offsets);
5121 /* Try to read the error message, but if we can't it's a non-issue */
5122 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5123 sd_bus_message_read(m, "s", &m->error.message);
5128 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5129 assert_return(m, -EINVAL);
5130 assert_return(destination, -EINVAL);
5131 assert_return(!m->sealed, -EPERM);
5132 assert_return(!m->destination, -EEXIST);
5134 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5137 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5141 struct bus_body_part *part;
5147 total = BUS_MESSAGE_SIZE(m);
5153 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5154 MESSAGE_FOREACH_PART(part, i, m)
5155 e = mempcpy(e, part->data, part->size);
5157 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5165 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5171 r = sd_bus_message_enter_container(m, 'a', "s");
5178 r = sd_bus_message_read_basic(m, 's', &s);
5184 r = strv_extend(l, s);
5189 r = sd_bus_message_exit_container(m);
5196 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5200 assert_return(m, -EINVAL);
5201 assert_return(m->sealed, -EPERM);
5202 assert_return(l, -EINVAL);
5204 r = bus_message_read_strv_extend(m, &strv);
5214 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5216 const char *t = NULL;
5221 r = sd_bus_message_rewind(m, true);
5225 for (j = 0; j <= i; j++) {
5228 r = sd_bus_message_peek_type(m, &type, NULL);
5232 if (type != SD_BUS_TYPE_STRING &&
5233 type != SD_BUS_TYPE_OBJECT_PATH &&
5234 type != SD_BUS_TYPE_SIGNATURE)
5237 r = sd_bus_message_read_basic(m, type, &t);
5245 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5251 if (size < sizeof(struct bus_header))
5254 full = sizeof(struct bus_header) +
5255 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5257 return size >= full;
5260 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5266 if (h->endian == BUS_NATIVE_ENDIAN) {
5267 fs = h->fields_size;
5269 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5270 fs = bswap_32(h->fields_size);
5271 bs = bswap_32(h->body_size);
5275 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5279 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5280 assert_return(m, -EINVAL);
5282 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5285 return sd_bus_error_get_errno(&m->error);
5288 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5289 struct bus_container *c;
5291 assert_return(m, NULL);
5293 c = complete ? &m->root_container : message_get_container(m);
5294 return strempty(c->signature);
5297 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5298 bool done_something = false;
5301 assert_return(m, -EINVAL);
5302 assert_return(source, -EINVAL);
5303 assert_return(!m->sealed, -EPERM);
5304 assert_return(source->sealed, -EPERM);
5307 const char *contents;
5322 r = sd_bus_message_peek_type(source, &type, &contents);
5328 done_something = true;
5330 if (bus_type_is_container(type) > 0) {
5332 r = sd_bus_message_enter_container(source, type, contents);
5336 r = sd_bus_message_open_container(m, type, contents);
5340 r = sd_bus_message_copy(m, source, true);
5344 r = sd_bus_message_close_container(m);
5348 r = sd_bus_message_exit_container(source);
5355 r = sd_bus_message_read_basic(source, type, &basic);
5361 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5362 type == SD_BUS_TYPE_SIGNATURE ||
5363 type == SD_BUS_TYPE_STRING)
5364 r = sd_bus_message_append_basic(m, type, basic.string);
5366 r = sd_bus_message_append_basic(m, type, &basic);
5373 return done_something;
5376 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5381 assert_return(m, -EINVAL);
5382 assert_return(m->sealed, -EPERM);
5383 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5384 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5385 assert_return(type || contents, -EINVAL);
5386 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5388 r = sd_bus_message_peek_type(m, &t, &c);
5392 if (type != 0 && type != t)
5395 if (contents && !streq_ptr(contents, c))
5401 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5402 assert_return(m, NULL);