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;
116 m->n_containers = m->containers_allocated = 0;
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;
168 old_size = sizeof(struct bus_header) + m->header->fields_size;
169 start = ALIGN_TO(old_size, align);
170 new_size = start + sz;
172 if (old_size == new_size)
173 return (uint8_t*) m->header + old_size;
175 if (new_size > (size_t) ((uint32_t) -1))
178 if (m->free_header) {
179 np = realloc(m->header, ALIGN8(new_size));
183 /* Initially, the header is allocated as part of of
184 * the sd_bus_message itself, let's replace it by
187 np = malloc(ALIGN8(new_size));
191 memcpy(np, m->header, sizeof(struct bus_header));
194 /* Zero out padding */
195 if (start > old_size)
196 memset((uint8_t*) np + old_size, 0, start - old_size);
200 m->header->fields_size = new_size - sizeof(struct bus_header);
202 /* Adjust quick access pointers */
203 m->path = adjust_pointer(m->path, op, old_size, m->header);
204 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
205 m->member = adjust_pointer(m->member, op, old_size, m->header);
206 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
207 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
208 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
210 m->free_header = true;
213 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
216 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
219 return (uint8_t*) np + start;
226 static int message_append_field_string(
238 /* dbus1 doesn't allow strings over 32bit, let's enforce this
239 * globally, to not risk convertability */
241 if (l > (size_t) (uint32_t) -1)
244 /* Signature "(yv)" where the variant contains "s" */
246 if (BUS_MESSAGE_IS_GVARIANT(m)) {
248 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
249 p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
261 *ret = (char*) p + 8;
264 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
265 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
274 ((uint32_t*) p)[1] = l;
275 memcpy(p + 8, s, l + 1);
278 *ret = (char*) p + 8;
284 static int message_append_field_signature(
295 /* dbus1 doesn't allow signatures over 32bit, let's enforce
296 * this globally, to not risk convertability */
301 /* Signature "(yv)" where the variant contains "g" */
303 if (BUS_MESSAGE_IS_GVARIANT(m))
304 /* For gvariant the serialization is the same as for normal strings */
305 return message_append_field_string(m, h, 'g', s, ret);
307 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
308 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
314 p[2] = SD_BUS_TYPE_SIGNATURE;
317 memcpy(p + 5, s, l + 1);
320 *ret = (const char*) p + 5;
326 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
331 if (BUS_MESSAGE_IS_GVARIANT(m)) {
332 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
334 p = message_extend_fields(m, 8, 1 + 7 + 4 + 1 + 1, true);
340 *((uint32_t*) (p + 8)) = x;
344 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
345 p = message_extend_fields(m, 8, 4 + 4, false);
351 p[2] = SD_BUS_TYPE_UINT32;
354 ((uint32_t*) p)[1] = x;
360 int bus_message_from_header(
366 const struct ucred *ucred,
369 sd_bus_message **ret) {
372 struct bus_header *h;
375 assert(buffer || length <= 0);
376 assert(fds || n_fds <= 0);
379 if (length < sizeof(struct bus_header))
383 if (h->version != 1 &&
390 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
393 if (h->endian != BUS_LITTLE_ENDIAN &&
394 h->endian != BUS_BIG_ENDIAN)
397 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
400 label_sz = strlen(label);
415 m->creds.uid = ucred->uid;
416 m->creds.pid = ucred->pid;
417 m->creds.gid = ucred->gid;
418 m->creds.mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID;
422 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
423 memcpy(m->creds.label, label, label_sz + 1);
425 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
429 m->bus = sd_bus_ref(bus);
435 int bus_message_from_malloc(
441 const struct ucred *ucred,
443 sd_bus_message **ret) {
449 r = bus_message_from_header(bus, buffer, length, fds, n_fds, ucred, label, 0, &m);
453 if (length != BUS_MESSAGE_SIZE(m)) {
458 sz = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
461 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
463 m->body.sealed = true;
468 m->iovec = m->iovec_fixed;
469 m->iovec[0].iov_base = buffer;
470 m->iovec[0].iov_len = length;
472 r = bus_message_parse_fields(m);
476 /* We take possession of the memory and fds now */
477 m->free_header = true;
488 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
491 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
496 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
497 m->header->endian = BUS_NATIVE_ENDIAN;
498 m->header->type = type;
499 m->header->version = bus ? bus->message_version : 1;
500 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
501 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
504 m->bus = sd_bus_ref(bus);
509 _public_ int sd_bus_message_new_signal(
512 const char *interface,
514 sd_bus_message **m) {
519 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
520 assert_return(object_path_is_valid(path), -EINVAL);
521 assert_return(interface_name_is_valid(interface), -EINVAL);
522 assert_return(member_name_is_valid(member), -EINVAL);
523 assert_return(m, -EINVAL);
525 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
529 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
531 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
534 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
537 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
545 sd_bus_message_unref(t);
549 _public_ int sd_bus_message_new_method_call(
551 const char *destination,
553 const char *interface,
555 sd_bus_message **m) {
560 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
561 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
562 assert_return(object_path_is_valid(path), -EINVAL);
563 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
564 assert_return(member_name_is_valid(member), -EINVAL);
565 assert_return(m, -EINVAL);
567 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
571 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
574 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
579 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
585 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
598 static int message_new_reply(
599 sd_bus_message *call,
601 sd_bus_message **m) {
606 assert_return(call, -EINVAL);
607 assert_return(call->sealed, -EPERM);
608 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
609 assert_return(!call->bus || call->bus->state != BUS_UNSET, -ENOTCONN);
610 assert_return(m, -EINVAL);
612 t = message_new(call->bus, type);
616 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
617 t->reply_serial = BUS_MESSAGE_SERIAL(call);
619 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
624 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
629 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
630 t->enforced_reply_signature = call->enforced_reply_signature;
640 _public_ int sd_bus_message_new_method_return(
641 sd_bus_message *call,
642 sd_bus_message **m) {
644 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
647 _public_ int sd_bus_message_new_method_error(
648 sd_bus_message *call,
649 const sd_bus_error *e,
650 sd_bus_message **m) {
655 assert_return(sd_bus_error_is_set(e), -EINVAL);
656 assert_return(m, -EINVAL);
658 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
662 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
667 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
672 t->error._need_free = -1;
682 _public_ int sd_bus_message_new_method_errorf(
683 sd_bus_message *call,
689 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
692 assert_return(name, -EINVAL);
693 assert_return(m, -EINVAL);
695 va_start(ap, format);
696 bus_error_setfv(&error, name, format, ap);
699 return sd_bus_message_new_method_error(call, &error, m);
702 _public_ int sd_bus_message_new_method_errno(
703 sd_bus_message *call,
705 const sd_bus_error *p,
706 sd_bus_message **m) {
708 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
710 if (sd_bus_error_is_set(p))
711 return sd_bus_message_new_method_error(call, p, m);
713 sd_bus_error_set_errno(&berror, error);
715 return sd_bus_message_new_method_error(call, &berror, m);
718 _public_ int sd_bus_message_new_method_errnof(
719 sd_bus_message *call,
725 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
728 va_start(ap, format);
729 bus_error_set_errnofv(&berror, error, format, ap);
732 return sd_bus_message_new_method_error(call, &berror, m);
735 int bus_message_new_synthetic_error(
738 const sd_bus_error *e,
739 sd_bus_message **m) {
744 assert(sd_bus_error_is_set(e));
747 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
751 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
752 t->reply_serial = serial;
754 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
758 if (bus && bus->unique_name) {
759 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
764 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
769 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
774 t->error._need_free = -1;
784 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
785 assert_return(m, NULL);
787 assert(m->n_ref > 0);
793 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
798 assert(m->n_ref > 0);
807 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
808 assert_return(m, -EINVAL);
809 assert_return(type, -EINVAL);
811 *type = m->header->type;
815 _public_ int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
816 assert_return(m, -EINVAL);
817 assert_return(serial, -EINVAL);
818 assert_return(m->header->serial != 0, -ENOENT);
820 *serial = BUS_MESSAGE_SERIAL(m);
824 _public_ int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
825 assert_return(m, -EINVAL);
826 assert_return(serial, -EINVAL);
827 assert_return(m->reply_serial != 0, -ENOENT);
829 *serial = m->reply_serial;
833 _public_ int sd_bus_message_get_no_reply(sd_bus_message *m) {
834 assert_return(m, -EINVAL);
836 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL ? !!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
839 _public_ int sd_bus_message_get_no_auto_start(sd_bus_message *m) {
840 assert_return(m, -EINVAL);
842 return !!(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
845 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
846 assert_return(m, NULL);
851 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
852 assert_return(m, NULL);
857 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
858 assert_return(m, NULL);
863 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
864 assert_return(m, NULL);
866 return m->destination;
869 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
870 assert_return(m, NULL);
875 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
876 assert_return(m, NULL);
877 assert_return(sd_bus_error_is_set(&m->error), NULL);
882 _public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
883 assert_return(m, -EINVAL);
884 assert_return(usec, -EINVAL);
885 assert_return(m->monotonic > 0, -ENODATA);
887 *usec = m->monotonic;
891 _public_ int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
892 assert_return(m, -EINVAL);
893 assert_return(usec, -EINVAL);
894 assert_return(m->realtime > 0, -ENODATA);
900 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
901 assert_return(m, NULL);
903 if (m->creds.mask == 0)
909 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
910 const char *interface,
911 const char *member) {
912 assert_return(m, -EINVAL);
914 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
917 if (interface && (!m->interface || !streq(m->interface, interface)))
920 if (member && (!m->member || !streq(m->member, member)))
926 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
927 const char *interface,
928 const char *member) {
929 assert_return(m, -EINVAL);
931 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
934 if (interface && (!m->interface || !streq(m->interface, interface)))
937 if (member && (!m->member || !streq(m->member, member)))
943 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
944 assert_return(m, -EINVAL);
946 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
949 if (name && (!m->error.name || !streq(m->error.name, name)))
955 _public_ int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
956 assert_return(m, -EINVAL);
957 assert_return(!m->sealed, -EPERM);
958 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
961 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
963 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
968 _public_ int sd_bus_message_set_no_auto_start(sd_bus_message *m, int b) {
969 assert_return(m, -EINVAL);
970 assert_return(!m->sealed, -EPERM);
973 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
975 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
980 static struct bus_container *message_get_container(sd_bus_message *m) {
983 if (m->n_containers == 0)
984 return &m->root_container;
986 assert(m->containers);
987 return m->containers + m->n_containers - 1;
990 struct bus_body_part *message_append_part(sd_bus_message *m) {
991 struct bus_body_part *part;
998 if (m->n_body_parts <= 0) {
1002 assert(m->body_end);
1004 part = new0(struct bus_body_part, 1);
1010 m->body_end->next = part;
1020 static void part_zero(struct bus_body_part *part, size_t sz) {
1025 /* All other fields can be left in their defaults */
1026 assert(!part->data);
1027 assert(part->memfd < 0);
1030 part->is_zero = true;
1031 part->sealed = true;
1034 static int part_make_space(
1035 struct sd_bus_message *m,
1036 struct bus_body_part *part,
1045 assert(!part->sealed);
1050 if (!part->data && part->memfd < 0)
1051 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped);
1053 if (part->memfd >= 0) {
1056 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &u);
1062 if (!part->data || sz > part->mapped) {
1063 size_t psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1065 if (part->mapped <= 0)
1066 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1068 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1070 if (n == MAP_FAILED) {
1079 part->munmap_this = true;
1081 n = realloc(part->data, MAX(sz, 1u));
1088 part->free_this = true;
1092 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1098 static int message_add_offset(sd_bus_message *m, size_t offset) {
1099 struct bus_container *c;
1102 assert(BUS_MESSAGE_IS_GVARIANT(m));
1104 /* Add offset to current container, unless this is the first
1105 * item in it, which will have the 0 offset, which we can
1107 c = message_get_container(m);
1109 if (!c->need_offsets)
1112 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1115 c->offsets[c->n_offsets++] = offset;
1119 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1120 struct bus_container *c;
1127 /* Update counters */
1128 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1131 *c->array_size += expand;
1135 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1136 size_t start_body, end_body, padding, added;
1147 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1148 end_body = start_body + sz;
1150 padding = start_body - m->header->body_size;
1151 added = padding + sz;
1153 /* Check for 32bit overflows */
1154 if (end_body > (size_t) ((uint32_t) -1)) {
1160 struct bus_body_part *part = NULL;
1164 m->n_body_parts <= 0 ||
1165 m->body_end->sealed ||
1166 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1170 part = message_append_part(m);
1174 part_zero(part, padding);
1177 part = message_append_part(m);
1181 r = part_make_space(m, part, sz, &p);
1185 struct bus_container *c;
1187 size_t os, start_part, end_part;
1193 start_part = ALIGN_TO(part->size, align);
1194 end_part = start_part + sz;
1196 r = part_make_space(m, part, end_part, &p);
1201 memset(p, 0, padding);
1202 p = (uint8_t*) p + padding;
1205 /* Readjust pointers */
1206 for (c = m->containers; c < m->containers + m->n_containers; c++)
1207 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1209 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1212 /* Return something that is not NULL and is aligned */
1213 p = (uint8_t *) NULL + align;
1215 m->header->body_size = end_body;
1216 message_extend_containers(m, added);
1219 r = message_add_offset(m, end_body);
1229 static int message_push_fd(sd_bus_message *m, int fd) {
1240 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1244 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1247 close_nointr_nofail(copy);
1252 m->fds[m->n_fds] = copy;
1258 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1259 _cleanup_close_ int fd = -1;
1260 struct bus_container *c;
1264 assert_return(m, -EINVAL);
1265 assert_return(!m->sealed, -EPERM);
1266 assert_return(bus_type_is_basic(type), -EINVAL);
1267 assert_return(!m->poisoned, -ESTALE);
1269 c = message_get_container(m);
1271 if (c->signature && c->signature[c->index]) {
1272 /* Container signature is already set */
1274 if (c->signature[c->index] != type)
1279 /* Maybe we can append to the signature? But only if this is the top-level container*/
1280 if (c->enclosing != 0)
1283 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1290 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1296 case SD_BUS_TYPE_SIGNATURE:
1297 case SD_BUS_TYPE_STRING:
1300 /* Fall through... */
1301 case SD_BUS_TYPE_OBJECT_PATH:
1309 case SD_BUS_TYPE_BOOLEAN:
1311 u8 = p && *(int*) p;
1317 case SD_BUS_TYPE_UNIX_FD:
1322 fd = message_push_fd(m, *(int*) p);
1333 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1334 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1341 a = message_extend_body(m, align, sz, true);
1348 *stored = (const uint8_t*) a;
1355 case SD_BUS_TYPE_STRING:
1356 /* To make things easy we'll serialize a NULL string
1357 * into the empty string */
1360 /* Fall through... */
1361 case SD_BUS_TYPE_OBJECT_PATH:
1367 sz = 4 + strlen(p) + 1;
1370 case SD_BUS_TYPE_SIGNATURE:
1375 sz = 1 + strlen(p) + 1;
1378 case SD_BUS_TYPE_BOOLEAN:
1380 u32 = p && *(int*) p;
1386 case SD_BUS_TYPE_UNIX_FD:
1391 fd = message_push_fd(m, *(int*) p);
1402 align = bus_type_get_alignment(type);
1403 sz = bus_type_get_size(type);
1410 a = message_extend_body(m, align, sz, false);
1414 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1415 *(uint32_t*) a = sz - 5;
1416 memcpy((uint8_t*) a + 4, p, sz - 4);
1419 *stored = (const uint8_t*) a + 4;
1421 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1422 *(uint8_t*) a = sz - 1;
1423 memcpy((uint8_t*) a + 1, p, sz - 1);
1426 *stored = (const uint8_t*) a + 1;
1435 if (type == SD_BUS_TYPE_UNIX_FD)
1438 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1445 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1446 return message_append_basic(m, type, p, NULL);
1449 _public_ int sd_bus_message_append_string_space(
1454 struct bus_container *c;
1457 assert_return(m, -EINVAL);
1458 assert_return(s, -EINVAL);
1459 assert_return(!m->sealed, -EPERM);
1460 assert_return(!m->poisoned, -ESTALE);
1462 c = message_get_container(m);
1464 if (c->signature && c->signature[c->index]) {
1465 /* Container signature is already set */
1467 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1472 /* Maybe we can append to the signature? But only if this is the top-level container*/
1473 if (c->enclosing != 0)
1476 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1483 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1484 a = message_extend_body(m, 1, size + 1, true);
1490 a = message_extend_body(m, 4, 4 + size + 1, false);
1494 *(uint32_t*) a = size;
1500 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1506 _public_ int sd_bus_message_append_string_iovec(
1508 const struct iovec *iov,
1516 assert_return(m, -EINVAL);
1517 assert_return(!m->sealed, -EPERM);
1518 assert_return(iov || n == 0, -EINVAL);
1519 assert_return(!m->poisoned, -ESTALE);
1521 size = IOVEC_TOTAL_SIZE(iov, n);
1523 r = sd_bus_message_append_string_space(m, size, &p);
1527 for (i = 0; i < n; i++) {
1529 if (iov[i].iov_base)
1530 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1532 memset(p, ' ', iov[i].iov_len);
1534 p += iov[i].iov_len;
1540 static int bus_message_open_array(
1542 struct bus_container *c,
1543 const char *contents,
1544 uint32_t **array_size,
1546 bool *need_offsets) {
1556 assert(need_offsets);
1558 if (!signature_is_single(contents, true))
1561 if (c->signature && c->signature[c->index]) {
1563 /* Verify the existing signature */
1565 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1568 if (!startswith(c->signature + c->index + 1, contents))
1571 nindex = c->index + 1 + strlen(contents);
1575 if (c->enclosing != 0)
1578 /* Extend the existing signature */
1580 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1586 nindex = e - c->signature;
1589 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1590 alignment = bus_gvariant_get_alignment(contents);
1594 /* Add alignment padding and add to offset list */
1595 if (!message_extend_body(m, alignment, 0, false))
1598 r = bus_gvariant_is_fixed_size(contents);
1602 *begin = m->header->body_size;
1603 *need_offsets = r == 0;
1607 struct bus_body_part *o;
1609 alignment = bus_type_get_alignment(contents[0]);
1613 a = message_extend_body(m, 4, 4, false);
1618 op = m->body_end->data;
1619 os = m->body_end->size;
1621 /* Add alignment between size and first element */
1622 if (!message_extend_body(m, alignment, 0, false))
1625 /* location of array size might have changed so let's readjust a */
1626 if (o == m->body_end)
1627 a = adjust_pointer(a, op, os, m->body_end->data);
1633 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1639 static int bus_message_open_variant(
1641 struct bus_container *c,
1642 const char *contents) {
1648 if (!signature_is_single(contents, false))
1651 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1654 if (c->signature && c->signature[c->index]) {
1656 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1662 if (c->enclosing != 0)
1665 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1672 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1673 /* Variants are always aligned to 8 */
1675 if (!message_extend_body(m, 8, 0, false))
1682 l = strlen(contents);
1683 a = message_extend_body(m, 1, 1 + l + 1, false);
1688 memcpy((uint8_t*) a + 1, contents, l + 1);
1691 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1697 static int bus_message_open_struct(
1699 struct bus_container *c,
1700 const char *contents,
1702 bool *need_offsets) {
1711 assert(need_offsets);
1713 if (!signature_is_valid(contents, false))
1716 if (c->signature && c->signature[c->index]) {
1719 l = strlen(contents);
1721 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1722 !startswith(c->signature + c->index + 1, contents) ||
1723 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1726 nindex = c->index + 1 + l + 1;
1730 if (c->enclosing != 0)
1733 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1739 nindex = e - c->signature;
1742 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1745 alignment = bus_gvariant_get_alignment(contents);
1749 if (!message_extend_body(m, alignment, 0, false))
1752 r = bus_gvariant_is_fixed_size(contents);
1756 *begin = m->header->body_size;
1757 *need_offsets = r == 0;
1759 /* Align contents to 8 byte boundary */
1760 if (!message_extend_body(m, 8, 0, false))
1764 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1770 static int bus_message_open_dict_entry(
1772 struct bus_container *c,
1773 const char *contents,
1775 bool *need_offsets) {
1783 assert(need_offsets);
1785 if (!signature_is_pair(contents))
1788 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1791 if (c->signature && c->signature[c->index]) {
1794 l = strlen(contents);
1796 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1797 !startswith(c->signature + c->index + 1, contents) ||
1798 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1803 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1806 alignment = bus_gvariant_get_alignment(contents);
1810 if (!message_extend_body(m, alignment, 0, false))
1813 r = bus_gvariant_is_fixed_size(contents);
1817 *begin = m->header->body_size;
1818 *need_offsets = r == 0;
1820 /* Align contents to 8 byte boundary */
1821 if (!message_extend_body(m, 8, 0, false))
1828 _public_ int sd_bus_message_open_container(
1831 const char *contents) {
1833 struct bus_container *c, *w;
1834 uint32_t *array_size = NULL;
1836 size_t before, begin;
1837 bool need_offsets = false;
1840 assert_return(m, -EINVAL);
1841 assert_return(!m->sealed, -EPERM);
1842 assert_return(contents, -EINVAL);
1843 assert_return(!m->poisoned, -ESTALE);
1845 /* Make sure we have space for one more container */
1846 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1851 c = message_get_container(m);
1853 signature = strdup(contents);
1859 /* Save old index in the parent container, in case we have to
1860 * abort this container */
1861 c->saved_index = c->index;
1862 before = m->header->body_size;
1864 if (type == SD_BUS_TYPE_ARRAY)
1865 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1866 else if (type == SD_BUS_TYPE_VARIANT)
1867 r = bus_message_open_variant(m, c, contents);
1868 else if (type == SD_BUS_TYPE_STRUCT)
1869 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1870 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1871 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1880 /* OK, let's fill it in */
1881 w = m->containers + m->n_containers++;
1882 w->enclosing = type;
1883 w->signature = signature;
1885 w->array_size = array_size;
1888 w->n_offsets = w->offsets_allocated = 0;
1890 w->need_offsets = need_offsets;
1895 static size_t determine_word_size(size_t sz, size_t extra) {
1896 if (sz + extra <= 0xFF)
1898 else if (sz + extra*2 <= 0xFFFF)
1900 else if (sz + extra*4 <= 0xFFFFFFFF)
1906 static size_t read_word_le(void *p, size_t sz) {
1916 return *(uint8_t*) p;
1921 return le16toh(x.u16);
1923 return le32toh(x.u32);
1925 return le64toh(x.u64);
1927 assert_not_reached("unknown word width");
1930 static void write_word_le(void *p, size_t sz, size_t value) {
1938 assert(sz == 8 || (value < (1ULL << (sz*8))));
1941 *(uint8_t*) p = value;
1944 x.u16 = htole16((uint16_t) value);
1946 x.u32 = htole32((uint32_t) value);
1948 x.u64 = htole64((uint64_t) value);
1950 assert_not_reached("unknown word width");
1955 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1960 if (!BUS_MESSAGE_IS_GVARIANT(m))
1963 if (c->need_offsets) {
1964 size_t payload, sz, i;
1967 /* Variable-width arrays */
1969 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
1970 sz = determine_word_size(payload, c->n_offsets);
1972 a = message_extend_body(m, 1, sz * c->n_offsets, true);
1976 for (i = 0; i < c->n_offsets; i++)
1977 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
1981 /* Fixed-width or empty arrays */
1983 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
1991 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
1998 if (!BUS_MESSAGE_IS_GVARIANT(m))
2001 l = strlen(c->signature);
2003 a = message_extend_body(m, 1, 1 + l, true);
2008 memcpy(a+1, c->signature, l);
2013 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2014 size_t n_variable = 0;
2023 if (!BUS_MESSAGE_IS_GVARIANT(m))
2026 p = strempty(c->signature);
2030 r = signature_element_length(p, &n);
2039 r = bus_gvariant_is_fixed_size(t);
2044 assert(i <= c->n_offsets);
2046 /* We need to add an offset for each item that has a
2047 * variable size and that is not the last one in the
2049 if (r == 0 && p[n] != 0)
2056 assert(i == c->n_offsets);
2058 if (n_variable <= 0) {
2059 a = message_extend_body(m, 1, 0, add_offset);
2066 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2068 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2070 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2074 p = strempty(c->signature);
2075 for (i = 0, j = 0; i < c->n_offsets; i++) {
2079 r = signature_element_length(p, &n);
2090 r = bus_gvariant_is_fixed_size(t);
2093 if (r > 0 || p[0] == 0)
2097 k = n_variable - 1 - j;
2099 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2108 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2109 struct bus_container *c;
2112 assert_return(m, -EINVAL);
2113 assert_return(!m->sealed, -EPERM);
2114 assert_return(m->n_containers > 0, -EINVAL);
2115 assert_return(!m->poisoned, -ESTALE);
2117 c = message_get_container(m);
2119 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2120 if (c->signature && c->signature[c->index] != 0)
2125 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2126 r = bus_message_close_array(m, c);
2127 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2128 r = bus_message_close_variant(m, c);
2129 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2130 r = bus_message_close_struct(m, c, true);
2132 assert_not_reached("Unknown container type");
2146 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2153 stack[*i].types = types;
2154 stack[*i].n_struct = n_struct;
2155 stack[*i].n_array = n_array;
2161 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2172 *types = stack[*i].types;
2173 *n_struct = stack[*i].n_struct;
2174 *n_array = stack[*i].n_array;
2179 int bus_message_append_ap(
2184 unsigned n_array, n_struct;
2185 TypeStack stack[BUS_CONTAINER_DEPTH];
2186 unsigned stack_ptr = 0;
2194 n_array = (unsigned) -1;
2195 n_struct = strlen(types);
2200 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2201 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2207 r = sd_bus_message_close_container(m);
2215 if (n_array != (unsigned) -1)
2224 case SD_BUS_TYPE_BYTE: {
2227 x = (uint8_t) va_arg(ap, int);
2228 r = sd_bus_message_append_basic(m, *t, &x);
2232 case SD_BUS_TYPE_BOOLEAN:
2233 case SD_BUS_TYPE_INT32:
2234 case SD_BUS_TYPE_UINT32:
2235 case SD_BUS_TYPE_UNIX_FD: {
2238 /* We assume a boolean is the same as int32_t */
2239 assert_cc(sizeof(int32_t) == sizeof(int));
2241 x = va_arg(ap, uint32_t);
2242 r = sd_bus_message_append_basic(m, *t, &x);
2246 case SD_BUS_TYPE_INT16:
2247 case SD_BUS_TYPE_UINT16: {
2250 x = (uint16_t) va_arg(ap, int);
2251 r = sd_bus_message_append_basic(m, *t, &x);
2255 case SD_BUS_TYPE_INT64:
2256 case SD_BUS_TYPE_UINT64:
2257 case SD_BUS_TYPE_DOUBLE: {
2260 x = va_arg(ap, uint64_t);
2261 r = sd_bus_message_append_basic(m, *t, &x);
2265 case SD_BUS_TYPE_STRING:
2266 case SD_BUS_TYPE_OBJECT_PATH:
2267 case SD_BUS_TYPE_SIGNATURE: {
2270 x = va_arg(ap, const char*);
2271 r = sd_bus_message_append_basic(m, *t, x);
2275 case SD_BUS_TYPE_ARRAY: {
2278 r = signature_element_length(t + 1, &k);
2284 memcpy(s, t + 1, k);
2287 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2292 if (n_array == (unsigned) -1) {
2297 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2303 n_array = va_arg(ap, unsigned);
2308 case SD_BUS_TYPE_VARIANT: {
2311 s = va_arg(ap, const char*);
2315 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2319 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2324 n_struct = strlen(s);
2325 n_array = (unsigned) -1;
2330 case SD_BUS_TYPE_STRUCT_BEGIN:
2331 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2334 r = signature_element_length(t, &k);
2341 memcpy(s, t + 1, k - 2);
2344 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2349 if (n_array == (unsigned) -1) {
2354 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2360 n_array = (unsigned) -1;
2376 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2380 assert_return(m, -EINVAL);
2381 assert_return(types, -EINVAL);
2382 assert_return(!m->sealed, -EPERM);
2383 assert_return(!m->poisoned, -ESTALE);
2385 va_start(ap, types);
2386 r = bus_message_append_ap(m, types, ap);
2392 _public_ int sd_bus_message_append_array_space(
2402 assert_return(m, -EINVAL);
2403 assert_return(!m->sealed, -EPERM);
2404 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2405 assert_return(ptr || size == 0, -EINVAL);
2406 assert_return(!m->poisoned, -ESTALE);
2408 /* alignment and size of the trivial types (except bool) is
2409 * identical for gvariant and dbus1 marshalling */
2410 align = bus_type_get_alignment(type);
2411 sz = bus_type_get_size(type);
2413 assert_se(align > 0);
2419 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2423 a = message_extend_body(m, align, size, false);
2427 r = sd_bus_message_close_container(m);
2435 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2442 assert_return(m, -EINVAL);
2443 assert_return(!m->sealed, -EPERM);
2444 assert_return(bus_type_is_trivial(type), -EINVAL);
2445 assert_return(ptr || size == 0, -EINVAL);
2446 assert_return(!m->poisoned, -ESTALE);
2448 r = sd_bus_message_append_array_space(m, type, size, &p);
2453 memcpy(p, ptr, size);
2458 _public_ int sd_bus_message_append_array_iovec(
2461 const struct iovec *iov,
2469 assert_return(m, -EINVAL);
2470 assert_return(!m->sealed, -EPERM);
2471 assert_return(bus_type_is_trivial(type), -EINVAL);
2472 assert_return(iov || n == 0, -EINVAL);
2473 assert_return(!m->poisoned, -ESTALE);
2475 size = IOVEC_TOTAL_SIZE(iov, n);
2477 r = sd_bus_message_append_array_space(m, type, size, &p);
2481 for (i = 0; i < n; i++) {
2483 if (iov[i].iov_base)
2484 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2486 memset(p, 0, iov[i].iov_len);
2488 p = (uint8_t*) p + iov[i].iov_len;
2494 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2497 _cleanup_close_ int copy_fd = -1;
2498 struct bus_body_part *part;
2510 if (!bus_type_is_trivial(type))
2515 r = sd_memfd_set_sealed(memfd, true);
2519 copy_fd = sd_memfd_dup_fd(memfd);
2523 r = sd_memfd_get_size(memfd, &size);
2527 align = bus_type_get_alignment(type);
2528 sz = bus_type_get_size(type);
2530 assert_se(align > 0);
2536 if (size > (uint64_t) (uint32_t) -1)
2539 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2543 a = message_extend_body(m, align, 0, false);
2547 part = message_append_part(m);
2551 part->memfd = copy_fd;
2552 part->sealed = true;
2556 m->header->body_size += size;
2557 message_extend_containers(m, size);
2559 return sd_bus_message_close_container(m);
2562 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
2563 _cleanup_close_ int copy_fd = -1;
2564 struct bus_body_part *part;
2565 struct bus_container *c;
2570 assert_return(m, -EINVAL);
2571 assert_return(memfd, -EINVAL);
2572 assert_return(!m->sealed, -EPERM);
2573 assert_return(!m->poisoned, -ESTALE);
2575 r = sd_memfd_set_sealed(memfd, true);
2579 copy_fd = sd_memfd_dup_fd(memfd);
2583 r = sd_memfd_get_size(memfd, &size);
2587 /* We require this to be NUL terminated */
2591 if (size > (uint64_t) (uint32_t) -1)
2594 c = message_get_container(m);
2595 if (c->signature && c->signature[c->index]) {
2596 /* Container signature is already set */
2598 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2603 /* Maybe we can append to the signature? But only if this is the top-level container*/
2604 if (c->enclosing != 0)
2607 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2614 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2615 a = message_extend_body(m, 4, 4, false);
2619 *(uint32_t*) a = size - 1;
2622 part = message_append_part(m);
2626 part->memfd = copy_fd;
2627 part->sealed = true;
2631 m->header->body_size += size;
2632 message_extend_containers(m, size);
2634 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2635 r = message_add_offset(m, m->header->body_size);
2642 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2648 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2652 assert_return(m, -EINVAL);
2653 assert_return(!m->sealed, -EPERM);
2654 assert_return(!m->poisoned, -ESTALE);
2656 r = sd_bus_message_open_container(m, 'a', "s");
2660 STRV_FOREACH(i, l) {
2661 r = sd_bus_message_append_basic(m, 's', *i);
2666 return sd_bus_message_close_container(m);
2669 static int bus_message_close_header(sd_bus_message *m) {
2675 if (!BUS_MESSAGE_IS_GVARIANT(m))
2678 if (m->n_header_offsets < 1)
2681 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2683 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2685 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2689 for (i = 0; i < m->n_header_offsets; i++)
2690 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2695 int bus_message_seal(sd_bus_message *m, uint64_t serial, usec_t timeout) {
2696 struct bus_body_part *part;
2706 if (m->n_containers > 0)
2712 /* In vtables the return signature of method calls is listed,
2713 * let's check if they match if this is a response */
2714 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2715 m->enforced_reply_signature &&
2716 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2719 /* If gvariant marshalling is used we need to close the body structure */
2720 r = bus_message_close_struct(m, &m->root_container, false);
2724 /* If there's a non-trivial signature set, then add it in here */
2725 if (!isempty(m->root_container.signature)) {
2726 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2732 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2737 r = bus_message_close_header(m);
2741 m->header->serial = serial;
2742 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2744 /* Add padding at the end of the fields part, since we know
2745 * the body needs to start at an 8 byte alignment. We made
2746 * sure we allocated enough space for this, so all we need to
2747 * do here is to zero it out. */
2748 l = BUS_MESSAGE_FIELDS_SIZE(m);
2751 memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
2753 /* If this is something we can send as memfd, then let's seal
2754 the memfd now. Note that we can send memfds as payload only
2755 for directed messages, and not for broadcasts. */
2756 if (m->destination && m->bus && m->bus->use_memfd) {
2757 MESSAGE_FOREACH_PART(part, i, m)
2758 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2759 bus_body_part_unmap(part);
2761 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
2762 part->sealed = true;
2766 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2767 m->root_container.index = 0;
2768 m->root_container.offset_index = 0;
2769 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2776 int bus_body_part_map(struct bus_body_part *part) {
2785 if (part->size <= 0)
2788 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2789 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2790 static const uint8_t zeroes[7] = { };
2791 part->data = (void*) zeroes;
2795 psz = PAGE_ALIGN(part->size);
2797 if (part->memfd >= 0)
2798 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2799 else if (part->is_zero)
2800 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2804 if (p == MAP_FAILED)
2809 part->munmap_this = true;
2814 void bus_body_part_unmap(struct bus_body_part *part) {
2818 if (part->memfd < 0)
2824 if (!part->munmap_this)
2827 assert_se(munmap(part->data, part->mapped) == 0);
2831 part->munmap_this = false;
2836 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2837 size_t k, start, end;
2842 start = ALIGN_TO((size_t) *rindex, align);
2843 end = start + nbytes;
2848 /* Verify that padding is 0 */
2849 for (k = *rindex; k < start; k++)
2850 if (((const uint8_t*) p)[k] != 0)
2854 *r = (uint8_t*) p + start;
2861 static bool message_end_of_signature(sd_bus_message *m) {
2862 struct bus_container *c;
2866 c = message_get_container(m);
2867 return !c->signature || c->signature[c->index] == 0;
2870 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2871 struct bus_container *c;
2875 c = message_get_container(m);
2876 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2879 if (BUS_MESSAGE_IS_GVARIANT(m))
2880 return index >= c->end;
2882 assert(c->array_size);
2883 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2887 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2888 assert_return(m, -EINVAL);
2889 assert_return(m->sealed, -EPERM);
2891 if (complete && m->n_containers > 0)
2894 if (message_end_of_signature(m))
2897 if (message_end_of_array(m, m->rindex))
2903 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2904 struct bus_body_part *part;
2910 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2911 part = m->cached_rindex_part;
2912 begin = m->cached_rindex_part_begin;
2922 if (index + sz <= begin + part->size) {
2924 r = bus_body_part_map(part);
2929 *p = (uint8_t*) part->data + index - begin;
2931 m->cached_rindex_part = part;
2932 m->cached_rindex_part_begin = begin;
2937 begin += part->size;
2944 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2951 if (!BUS_MESSAGE_IS_GVARIANT(m))
2954 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2957 sz = bus_gvariant_get_size(c->signature);
2961 if (c->offset_index+1 >= c->n_offsets)
2964 /* Variable-size array */
2966 alignment = bus_gvariant_get_alignment(c->signature);
2967 assert(alignment > 0);
2969 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
2970 c->item_size = c->offsets[c->offset_index+1] - *rindex;
2973 if (c->offset_index+1 >= (c->end-c->begin)/sz)
2976 /* Fixed-size array */
2977 *rindex = c->begin + (c->offset_index+1) * sz;
2983 } else if (c->enclosing == 0 ||
2984 c->enclosing == SD_BUS_TYPE_STRUCT ||
2985 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
2990 if (c->offset_index+1 >= c->n_offsets)
2993 r = signature_element_length(c->signature + c->index, &n);
2997 r = signature_element_length(c->signature + c->index + n, &j);
3002 memcpy(t, c->signature + c->index + n, j);
3005 alignment = bus_gvariant_get_alignment(t);
3008 assert(alignment > 0);
3010 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3011 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3015 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3018 assert_not_reached("Unknown container type");
3023 /* Reached the end */
3030 static int message_peek_body(
3037 size_t k, start, end, padding;
3038 struct bus_body_part *part;
3045 start = ALIGN_TO((size_t) *rindex, align);
3046 padding = start - *rindex;
3047 end = start + nbytes;
3049 if (end > BUS_MESSAGE_BODY_SIZE(m))
3052 part = find_part(m, *rindex, padding, (void**) &q);
3057 /* Verify padding */
3058 for (k = 0; k < padding; k++)
3063 part = find_part(m, start, nbytes, (void**) &q);
3064 if (!part || (nbytes > 0 && !q))
3075 static bool validate_nul(const char *s, size_t l) {
3077 /* Check for NUL chars in the string */
3078 if (memchr(s, 0, l))
3081 /* Check for NUL termination */
3088 static bool validate_string(const char *s, size_t l) {
3090 if (!validate_nul(s, l))
3093 /* Check if valid UTF8 */
3094 if (!utf8_is_valid(s))
3100 static bool validate_signature(const char *s, size_t l) {
3102 if (!validate_nul(s, l))
3105 /* Check if valid signature */
3106 if (!signature_is_valid(s, true))
3112 static bool validate_object_path(const char *s, size_t l) {
3114 if (!validate_nul(s, l))
3117 if (!object_path_is_valid(s))
3123 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3124 struct bus_container *c;
3129 assert_return(m, -EINVAL);
3130 assert_return(m->sealed, -EPERM);
3131 assert_return(bus_type_is_basic(type), -EINVAL);
3133 if (message_end_of_signature(m))
3136 if (message_end_of_array(m, m->rindex))
3139 c = message_get_container(m);
3140 if (c->signature[c->index] != type)
3145 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3147 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3150 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3154 if (type == SD_BUS_TYPE_STRING)
3155 ok = validate_string(q, c->item_size-1);
3156 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3157 ok = validate_object_path(q, c->item_size-1);
3159 ok = validate_signature(q, c->item_size-1);
3165 *(const char**) p = q;
3169 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3171 if ((size_t) sz != c->item_size)
3174 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3177 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3183 case SD_BUS_TYPE_BYTE:
3185 *(uint8_t*) p = *(uint8_t*) q;
3188 case SD_BUS_TYPE_BOOLEAN:
3190 *(int*) p = !!*(uint8_t*) q;
3193 case SD_BUS_TYPE_INT16:
3194 case SD_BUS_TYPE_UINT16:
3196 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3199 case SD_BUS_TYPE_INT32:
3200 case SD_BUS_TYPE_UINT32:
3202 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3205 case SD_BUS_TYPE_INT64:
3206 case SD_BUS_TYPE_UINT64:
3207 case SD_BUS_TYPE_DOUBLE:
3209 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3212 case SD_BUS_TYPE_UNIX_FD: {
3215 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3220 *(int*) p = m->fds[j];
3226 assert_not_reached("unexpected type");
3230 r = container_next_item(m, c, &rindex);
3237 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3241 r = message_peek_body(m, &rindex, 4, 4, &q);
3245 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3246 r = message_peek_body(m, &rindex, 1, l+1, &q);
3250 if (type == SD_BUS_TYPE_OBJECT_PATH)
3251 ok = validate_object_path(q, l);
3253 ok = validate_string(q, l);
3258 *(const char**) p = q;
3260 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3263 r = message_peek_body(m, &rindex, 1, 1, &q);
3268 r = message_peek_body(m, &rindex, 1, l+1, &q);
3272 if (!validate_signature(q, l))
3276 *(const char**) p = q;
3281 align = bus_type_get_alignment(type);
3284 sz = bus_type_get_size(type);
3287 r = message_peek_body(m, &rindex, align, sz, &q);
3293 case SD_BUS_TYPE_BYTE:
3295 *(uint8_t*) p = *(uint8_t*) q;
3298 case SD_BUS_TYPE_BOOLEAN:
3300 *(int*) p = !!*(uint32_t*) q;
3303 case SD_BUS_TYPE_INT16:
3304 case SD_BUS_TYPE_UINT16:
3306 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3309 case SD_BUS_TYPE_INT32:
3310 case SD_BUS_TYPE_UINT32:
3312 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3315 case SD_BUS_TYPE_INT64:
3316 case SD_BUS_TYPE_UINT64:
3317 case SD_BUS_TYPE_DOUBLE:
3319 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3322 case SD_BUS_TYPE_UNIX_FD: {
3325 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3330 *(int*) p = m->fds[j];
3335 assert_not_reached("Unknown basic type...");
3342 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3348 static int bus_message_enter_array(
3350 struct bus_container *c,
3351 const char *contents,
3352 uint32_t **array_size,
3355 size_t *n_offsets) {
3369 if (!signature_is_single(contents, true))
3372 if (!c->signature || c->signature[c->index] == 0)
3375 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3378 if (!startswith(c->signature + c->index + 1, contents))
3383 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3386 r = message_peek_body(m, &rindex, 4, 4, &q);
3390 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3393 alignment = bus_type_get_alignment(contents[0]);
3397 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3401 *array_size = (uint32_t*) q;
3403 } else if (c->item_size <= 0) {
3405 /* gvariant: empty array */
3410 } else if (bus_gvariant_is_fixed_size(contents)) {
3412 /* gvariant: fixed length array */
3413 *item_size = bus_gvariant_get_size(contents);
3418 size_t where, p = 0, framing, sz;
3421 /* gvariant: variable length array */
3422 sz = determine_word_size(c->item_size, 0);
3424 where = rindex + c->item_size - sz;
3425 r = message_peek_body(m, &where, 1, sz, &q);
3429 framing = read_word_le(q, sz);
3430 if (framing > c->item_size - sz)
3432 if ((c->item_size - framing) % sz != 0)
3435 *n_offsets = (c->item_size - framing) / sz;
3437 where = rindex + framing;
3438 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3442 *offsets = new(size_t, *n_offsets);
3446 for (i = 0; i < *n_offsets; i++) {
3449 x = read_word_le((uint8_t*) q + i * sz, sz);
3450 if (x > c->item_size - sz)
3455 (*offsets)[i] = rindex + x;
3459 *item_size = (*offsets)[0] - rindex;
3464 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3465 c->index += 1 + strlen(contents);
3470 static int bus_message_enter_variant(
3472 struct bus_container *c,
3473 const char *contents,
3474 size_t *item_size) {
3486 if (!signature_is_single(contents, false))
3489 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3492 if (!c->signature || c->signature[c->index] == 0)
3495 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3500 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3503 k = strlen(contents);
3504 if (1+k > c->item_size)
3507 where = rindex + c->item_size - (1+k);
3508 r = message_peek_body(m, &where, 1, 1+k, &q);
3512 if (*(char*) q != 0)
3515 if (memcmp((uint8_t*) q+1, contents, k))
3518 *item_size = c->item_size - (1+k);
3521 r = message_peek_body(m, &rindex, 1, 1, &q);
3526 r = message_peek_body(m, &rindex, 1, l+1, &q);
3530 if (!validate_signature(q, l))
3533 if (!streq(q, contents))
3539 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3545 static int build_struct_offsets(
3547 const char *signature,
3551 size_t *n_offsets) {
3553 unsigned n_variable = 0, n_total = 0, v;
3554 size_t previous = 0, where;
3565 if (isempty(signature)) {
3572 sz = determine_word_size(size, 0);
3576 /* First, loop over signature and count variable elements and
3577 * elements in general. We use this to know how large the
3578 * offset array is at the end of the structure. Note that
3579 * GVariant only stores offsets for all variable size elements
3580 * that are not the last item. */
3586 r = signature_element_length(p, &n);
3595 r = bus_gvariant_is_fixed_size(t);
3600 if (r == 0 && p[n] != 0) /* except the last item */
3607 if (size < n_variable * sz)
3610 where = m->rindex + size - (n_variable * sz);
3611 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3617 *offsets = new(size_t, n_total);
3623 /* Second, loop again and build an offset table */
3629 r = signature_element_length(p, &n);
3638 k = bus_gvariant_get_size(t);
3646 x = read_word_le((uint8_t*) q + v*sz, sz);
3649 if (m->rindex + x < previous)
3652 /* The last item's end
3653 * is determined from
3656 x = size - (n_variable * sz);
3658 offset = m->rindex + x;
3664 align = bus_gvariant_get_alignment(t);
3667 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3671 previous = (*offsets)[(*n_offsets)++] = offset;
3676 assert(*n_offsets == n_total);
3678 *item_size = (*offsets)[0] - m->rindex;
3682 static int enter_struct_or_dict_entry(
3684 struct bus_container *c,
3685 const char *contents,
3688 size_t *n_offsets) {
3699 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3702 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3706 } else if (c->item_size <= 0) {
3708 /* gvariant empty struct */
3713 /* gvariant with contents */
3714 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3719 static int bus_message_enter_struct(
3721 struct bus_container *c,
3722 const char *contents,
3725 size_t *n_offsets) {
3737 if (!signature_is_valid(contents, false))
3740 if (!c->signature || c->signature[c->index] == 0)
3743 l = strlen(contents);
3745 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3746 !startswith(c->signature + c->index + 1, contents) ||
3747 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3750 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3754 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3755 c->index += 1 + l + 1;
3760 static int bus_message_enter_dict_entry(
3762 struct bus_container *c,
3763 const char *contents,
3766 size_t *n_offsets) {
3775 if (!signature_is_pair(contents))
3778 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3781 if (!c->signature || c->signature[c->index] == 0)
3784 l = strlen(contents);
3786 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3787 !startswith(c->signature + c->index + 1, contents) ||
3788 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3791 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3795 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3796 c->index += 1 + l + 1;
3801 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3803 const char *contents) {
3804 struct bus_container *c, *w;
3805 uint32_t *array_size = NULL;
3808 size_t *offsets = NULL;
3809 size_t n_offsets = 0, item_size = 0;
3812 assert_return(m, -EINVAL);
3813 assert_return(m->sealed, -EPERM);
3814 assert_return(type != 0 || !contents, -EINVAL);
3816 if (type == 0 || !contents) {
3820 /* Allow entering into anonymous containers */
3821 r = sd_bus_message_peek_type(m, &tt, &cc);
3825 if (type != 0 && type != tt)
3828 if (contents && !streq(contents, cc))
3836 * We enforce a global limit on container depth, that is much
3837 * higher than the 32 structs and 32 arrays the specification
3838 * mandates. This is simpler to implement for us, and we need
3839 * this only to ensure our container array doesn't grow
3840 * without bounds. We are happy to return any data from a
3841 * message as long as the data itself is valid, even if the
3842 * overall message might be not.
3844 * Note that the message signature is validated when
3845 * parsing the headers, and that validation does check the
3848 * Note that the specification defines no limits on the depth
3849 * of stacked variants, but we do.
3851 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3854 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3857 if (message_end_of_signature(m))
3860 if (message_end_of_array(m, m->rindex))
3863 c = message_get_container(m);
3865 signature = strdup(contents);
3869 c->saved_index = c->index;
3872 if (type == SD_BUS_TYPE_ARRAY)
3873 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3874 else if (type == SD_BUS_TYPE_VARIANT)
3875 r = bus_message_enter_variant(m, c, contents, &item_size);
3876 else if (type == SD_BUS_TYPE_STRUCT)
3877 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3878 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3879 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3889 /* OK, let's fill it in */
3890 w = m->containers + m->n_containers++;
3891 w->enclosing = type;
3892 w->signature = signature;
3896 w->begin = m->rindex;
3897 w->end = m->rindex + c->item_size;
3899 w->array_size = array_size;
3900 w->item_size = item_size;
3901 w->offsets = offsets;
3902 w->n_offsets = n_offsets;
3903 w->offset_index = 0;
3908 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3909 struct bus_container *c;
3913 assert_return(m, -EINVAL);
3914 assert_return(m->sealed, -EPERM);
3915 assert_return(m->n_containers > 0, -ENXIO);
3917 c = message_get_container(m);
3919 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3920 if (c->signature && c->signature[c->index] != 0)
3924 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3925 if (m->rindex < c->end)
3928 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3931 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3932 if (c->begin + l != m->rindex)
3940 c = message_get_container(m);
3943 c->index = c->saved_index;
3944 r = container_next_item(m, c, &m->rindex);
3952 static void message_quit_container(sd_bus_message *m) {
3953 struct bus_container *c;
3957 assert(m->n_containers > 0);
3959 c = message_get_container(m);
3962 assert(m->rindex >= c->before);
3963 m->rindex = c->before;
3965 /* Free container */
3970 /* Correct index of new top-level container */
3971 c = message_get_container(m);
3972 c->index = c->saved_index;
3975 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
3976 struct bus_container *c;
3979 assert_return(m, -EINVAL);
3980 assert_return(m->sealed, -EPERM);
3982 if (message_end_of_signature(m))
3985 if (message_end_of_array(m, m->rindex))
3988 c = message_get_container(m);
3990 if (bus_type_is_basic(c->signature[c->index])) {
3994 *type = c->signature[c->index];
3998 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4004 r = signature_element_length(c->signature+c->index+1, &l);
4010 sig = strndup(c->signature + c->index + 1, l);
4014 free(m->peeked_signature);
4015 m->peeked_signature = sig;
4021 *type = SD_BUS_TYPE_ARRAY;
4026 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4027 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4033 r = signature_element_length(c->signature+c->index, &l);
4038 sig = strndup(c->signature + c->index + 1, l - 2);
4042 free(m->peeked_signature);
4043 m->peeked_signature = sig;
4049 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4054 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4058 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4061 if (c->item_size < 2)
4064 /* Look for the NUL delimiter that
4065 separates the payload from the
4066 signature. Since the body might be
4067 in a different part that then the
4068 signature we map byte by byte. */
4070 for (k = 2; k <= c->item_size; k++) {
4073 where = m->rindex + c->item_size - k;
4074 r = message_peek_body(m, &where, 1, k, &q);
4078 if (*(char*) q == 0)
4082 if (k > c->item_size)
4085 free(m->peeked_signature);
4086 m->peeked_signature = strndup((char*) q + 1, k - 1);
4087 if (!m->peeked_signature)
4090 if (!signature_is_valid(m->peeked_signature, true))
4093 *contents = m->peeked_signature;
4098 r = message_peek_body(m, &rindex, 1, 1, &q);
4103 r = message_peek_body(m, &rindex, 1, l+1, &q);
4107 if (!validate_signature(q, l))
4115 *type = SD_BUS_TYPE_VARIANT;
4130 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4131 struct bus_container *c;
4133 assert_return(m, -EINVAL);
4134 assert_return(m->sealed, -EPERM);
4137 message_reset_containers(m);
4140 c = message_get_container(m);
4142 c = message_get_container(m);
4144 c->offset_index = 0;
4146 m->rindex = c->begin;
4149 c->offset_index = 0;
4150 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4152 return !isempty(c->signature);
4155 static int message_read_ap(
4160 unsigned n_array, n_struct;
4161 TypeStack stack[BUS_CONTAINER_DEPTH];
4162 unsigned stack_ptr = 0;
4163 unsigned n_loop = 0;
4171 /* Ideally, we'd just call ourselves recursively on every
4172 * complex type. However, the state of a va_list that is
4173 * passed to a function is undefined after that function
4174 * returns. This means we need to docode the va_list linearly
4175 * in a single stackframe. We hence implement our own
4176 * home-grown stack in an array. */
4178 n_array = (unsigned) -1; /* lenght of current array entries */
4179 n_struct = strlen(types); /* length of current struct contents signature */
4186 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4187 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4193 r = sd_bus_message_exit_container(m);
4201 if (n_array != (unsigned) -1)
4210 case SD_BUS_TYPE_BYTE:
4211 case SD_BUS_TYPE_BOOLEAN:
4212 case SD_BUS_TYPE_INT16:
4213 case SD_BUS_TYPE_UINT16:
4214 case SD_BUS_TYPE_INT32:
4215 case SD_BUS_TYPE_UINT32:
4216 case SD_BUS_TYPE_INT64:
4217 case SD_BUS_TYPE_UINT64:
4218 case SD_BUS_TYPE_DOUBLE:
4219 case SD_BUS_TYPE_STRING:
4220 case SD_BUS_TYPE_OBJECT_PATH:
4221 case SD_BUS_TYPE_SIGNATURE:
4222 case SD_BUS_TYPE_UNIX_FD: {
4225 p = va_arg(ap, void*);
4226 r = sd_bus_message_read_basic(m, *t, p);
4239 case SD_BUS_TYPE_ARRAY: {
4242 r = signature_element_length(t + 1, &k);
4248 memcpy(s, t + 1, k);
4251 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4262 if (n_array == (unsigned) -1) {
4267 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4273 n_array = va_arg(ap, unsigned);
4278 case SD_BUS_TYPE_VARIANT: {
4281 s = va_arg(ap, const char *);
4285 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4295 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4300 n_struct = strlen(s);
4301 n_array = (unsigned) -1;
4306 case SD_BUS_TYPE_STRUCT_BEGIN:
4307 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4310 r = signature_element_length(t, &k);
4316 memcpy(s, t + 1, k - 2);
4319 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4329 if (n_array == (unsigned) -1) {
4334 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4340 n_array = (unsigned) -1;
4353 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4357 assert_return(m, -EINVAL);
4358 assert_return(m->sealed, -EPERM);
4359 assert_return(types, -EINVAL);
4361 va_start(ap, types);
4362 r = message_read_ap(m, types, ap);
4368 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4371 assert_return(m, -EINVAL);
4372 assert_return(m->sealed, -EPERM);
4373 assert_return(types, -EINVAL);
4380 case SD_BUS_TYPE_BYTE:
4381 case SD_BUS_TYPE_BOOLEAN:
4382 case SD_BUS_TYPE_INT16:
4383 case SD_BUS_TYPE_UINT16:
4384 case SD_BUS_TYPE_INT32:
4385 case SD_BUS_TYPE_UINT32:
4386 case SD_BUS_TYPE_INT64:
4387 case SD_BUS_TYPE_UINT64:
4388 case SD_BUS_TYPE_DOUBLE:
4389 case SD_BUS_TYPE_STRING:
4390 case SD_BUS_TYPE_OBJECT_PATH:
4391 case SD_BUS_TYPE_SIGNATURE:
4392 case SD_BUS_TYPE_UNIX_FD:
4394 r = sd_bus_message_read_basic(m, *types, NULL);
4398 r = sd_bus_message_skip(m, types + 1);
4404 case SD_BUS_TYPE_ARRAY: {
4407 r = signature_element_length(types + 1, &k);
4413 memcpy(s, types+1, k);
4416 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4421 r = sd_bus_message_skip(m, s);
4428 r = sd_bus_message_exit_container(m);
4433 r = sd_bus_message_skip(m, types + 1 + k);
4440 case SD_BUS_TYPE_VARIANT: {
4441 const char *contents;
4444 r = sd_bus_message_peek_type(m, &x, &contents);
4448 if (x != SD_BUS_TYPE_VARIANT)
4451 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4455 r = sd_bus_message_skip(m, contents);
4460 r = sd_bus_message_exit_container(m);
4464 r = sd_bus_message_skip(m, types + 1);
4471 case SD_BUS_TYPE_STRUCT_BEGIN:
4472 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4475 r = signature_element_length(types, &k);
4481 memcpy(s, types+1, k-2);
4484 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4488 r = sd_bus_message_skip(m, s);
4493 r = sd_bus_message_exit_container(m);
4498 r = sd_bus_message_skip(m, types + k);
4510 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4514 struct bus_container *c;
4520 assert_return(m, -EINVAL);
4521 assert_return(m->sealed, -EPERM);
4522 assert_return(bus_type_is_trivial(type), -EINVAL);
4523 assert_return(ptr, -EINVAL);
4524 assert_return(size, -EINVAL);
4525 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4527 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4531 c = message_get_container(m);
4533 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4534 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4538 sz = c->end - c->begin;
4540 align = bus_type_get_alignment(type);
4544 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4548 /* Zero length array, let's return some aligned
4549 * pointer that is not NULL */
4550 p = (uint8_t*) NULL + align;
4552 r = message_peek_body(m, &m->rindex, align, sz, &p);
4557 r = sd_bus_message_exit_container(m);
4561 *ptr = (const void*) p;
4567 message_quit_container(m);
4571 static int message_peek_fields(
4582 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4585 static int message_peek_field_uint32(
4597 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4600 /* identical for gvariant and dbus1 */
4602 r = message_peek_fields(m, ri, 4, 4, &q);
4607 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4612 static int message_peek_field_string(
4614 bool (*validate)(const char *p),
4626 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4631 r = message_peek_fields(m, ri, 1, item_size, &q);
4637 r = message_peek_field_uint32(m, ri, 4, &l);
4641 r = message_peek_fields(m, ri, 1, l+1, &q);
4647 if (!validate_nul(q, l))
4653 if (!validate_string(q, l))
4663 static int message_peek_field_signature(
4676 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4681 r = message_peek_fields(m, ri, 1, item_size, &q);
4687 r = message_peek_fields(m, ri, 1, 1, &q);
4692 r = message_peek_fields(m, ri, 1, l+1, &q);
4697 if (!validate_signature(q, l))
4706 static int message_skip_fields(
4709 uint32_t array_size,
4710 const char **signature) {
4712 size_t original_index;
4718 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4720 original_index = *ri;
4726 if (array_size != (uint32_t) -1 &&
4727 array_size <= *ri - original_index)
4734 if (t == SD_BUS_TYPE_STRING) {
4736 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4742 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4744 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4750 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4752 r = message_peek_field_signature(m, ri, 0, NULL);
4758 } else if (bus_type_is_basic(t)) {
4761 align = bus_type_get_alignment(t);
4762 k = bus_type_get_size(t);
4763 assert(align > 0 && k > 0);
4765 r = message_peek_fields(m, ri, align, k, NULL);
4771 } else if (t == SD_BUS_TYPE_ARRAY) {
4773 r = signature_element_length(*signature+1, &l);
4783 strncpy(sig, *signature + 1, l-1);
4786 alignment = bus_type_get_alignment(sig[0]);
4790 r = message_peek_field_uint32(m, ri, 0, &nas);
4793 if (nas > BUS_ARRAY_MAX_SIZE)
4796 r = message_peek_fields(m, ri, alignment, 0, NULL);
4800 r = message_skip_fields(m, ri, nas, (const char**) &s);
4805 (*signature) += 1 + l;
4807 } else if (t == SD_BUS_TYPE_VARIANT) {
4810 r = message_peek_field_signature(m, ri, 0, &s);
4814 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4820 } else if (t == SD_BUS_TYPE_STRUCT ||
4821 t == SD_BUS_TYPE_DICT_ENTRY) {
4823 r = signature_element_length(*signature, &l);
4830 strncpy(sig, *signature + 1, l-1);
4833 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4844 int bus_message_parse_fields(sd_bus_message *m) {
4847 uint32_t unix_fds = 0;
4848 void *offsets = NULL;
4849 unsigned n_offsets = 0;
4855 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4858 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4862 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4863 r = message_peek_fields(m, &ri, 1, sz, &q);
4867 framing = read_word_le(q, sz);
4868 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4870 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4874 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4878 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4883 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4884 _cleanup_free_ char *sig = NULL;
4885 const char *signature;
4887 size_t item_size = (size_t) -1;
4889 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4896 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4899 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4903 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4908 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4913 where = ri = ALIGN_TO(ri, 8);
4914 item_size = end - ri;
4915 r = message_peek_fields(m, &where, 1, item_size, &q);
4919 b = memrchr(q, 0, item_size);
4923 sig = strndup(b+1, item_size - (b+1-(char*) q));
4928 item_size = b - (char*) q;
4930 r = message_peek_field_signature(m, &ri, 0, &signature);
4936 case _BUS_MESSAGE_HEADER_INVALID:
4939 case BUS_MESSAGE_HEADER_PATH:
4944 if (!streq(signature, "o"))
4947 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
4950 case BUS_MESSAGE_HEADER_INTERFACE:
4955 if (!streq(signature, "s"))
4958 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
4961 case BUS_MESSAGE_HEADER_MEMBER:
4966 if (!streq(signature, "s"))
4969 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
4972 case BUS_MESSAGE_HEADER_ERROR_NAME:
4977 if (!streq(signature, "s"))
4980 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
4982 m->error._need_free = -1;
4986 case BUS_MESSAGE_HEADER_DESTINATION:
4991 if (!streq(signature, "s"))
4994 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
4997 case BUS_MESSAGE_HEADER_SENDER:
5002 if (!streq(signature, "s"))
5005 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5007 if (r >= 0 && m->sender[0] == ':' && m->bus && m->bus->bus_client && !m->bus->is_kernel) {
5008 m->creds.unique_name = (char*) m->sender;
5009 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5015 case BUS_MESSAGE_HEADER_SIGNATURE: {
5019 if (m->root_container.signature)
5022 if (!streq(signature, "g"))
5025 r = message_peek_field_signature(m, &ri, item_size, &s);
5033 free(m->root_container.signature);
5034 m->root_container.signature = c;
5038 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5039 if (m->reply_serial != 0)
5042 if (!streq(signature, "u"))
5045 r = message_peek_field_uint32(m, &ri, item_size, &m->reply_serial);
5049 if (m->reply_serial == 0)
5054 case BUS_MESSAGE_HEADER_UNIX_FDS:
5058 if (!streq(signature, "u"))
5061 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5071 if (!BUS_MESSAGE_IS_GVARIANT(m))
5072 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5081 if (m->n_fds != unix_fds)
5084 switch (m->header->type) {
5086 case SD_BUS_MESSAGE_SIGNAL:
5087 if (!m->path || !m->interface || !m->member)
5091 case SD_BUS_MESSAGE_METHOD_CALL:
5093 if (!m->path || !m->member)
5098 case SD_BUS_MESSAGE_METHOD_RETURN:
5100 if (m->reply_serial == 0)
5104 case SD_BUS_MESSAGE_METHOD_ERROR:
5106 if (m->reply_serial == 0 || !m->error.name)
5111 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5113 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5114 r = build_struct_offsets(
5116 m->root_container.signature,
5117 BUS_MESSAGE_BODY_SIZE(m),
5118 &m->root_container.item_size,
5119 &m->root_container.offsets,
5120 &m->root_container.n_offsets);
5125 /* Try to read the error message, but if we can't it's a non-issue */
5126 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5127 sd_bus_message_read(m, "s", &m->error.message);
5132 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5133 assert_return(m, -EINVAL);
5134 assert_return(destination, -EINVAL);
5135 assert_return(!m->sealed, -EPERM);
5136 assert_return(!m->destination, -EEXIST);
5138 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5141 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5145 struct bus_body_part *part;
5151 total = BUS_MESSAGE_SIZE(m);
5157 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5158 MESSAGE_FOREACH_PART(part, i, m)
5159 e = mempcpy(e, part->data, part->size);
5161 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5169 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5175 r = sd_bus_message_enter_container(m, 'a', "s");
5182 r = sd_bus_message_read_basic(m, 's', &s);
5188 r = strv_extend(l, s);
5193 r = sd_bus_message_exit_container(m);
5200 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5204 assert_return(m, -EINVAL);
5205 assert_return(m->sealed, -EPERM);
5206 assert_return(l, -EINVAL);
5208 r = bus_message_read_strv_extend(m, &strv);
5218 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5220 const char *t = NULL;
5225 r = sd_bus_message_rewind(m, true);
5229 for (j = 0; j <= i; j++) {
5232 r = sd_bus_message_peek_type(m, &type, NULL);
5236 if (type != SD_BUS_TYPE_STRING &&
5237 type != SD_BUS_TYPE_OBJECT_PATH &&
5238 type != SD_BUS_TYPE_SIGNATURE)
5241 r = sd_bus_message_read_basic(m, type, &t);
5249 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5255 if (size < sizeof(struct bus_header))
5258 full = sizeof(struct bus_header) +
5259 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5261 return size >= full;
5264 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5270 if (h->endian == BUS_NATIVE_ENDIAN) {
5271 fs = h->fields_size;
5273 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5274 fs = bswap_32(h->fields_size);
5275 bs = bswap_32(h->body_size);
5279 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5283 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5284 assert_return(m, -EINVAL);
5286 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5289 return sd_bus_error_get_errno(&m->error);
5292 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5293 struct bus_container *c;
5295 assert_return(m, NULL);
5297 c = complete ? &m->root_container : message_get_container(m);
5298 return strempty(c->signature);
5301 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5302 bool done_something = false;
5305 assert_return(m, -EINVAL);
5306 assert_return(source, -EINVAL);
5307 assert_return(!m->sealed, -EPERM);
5308 assert_return(source->sealed, -EPERM);
5311 const char *contents;
5326 r = sd_bus_message_peek_type(source, &type, &contents);
5332 done_something = true;
5334 if (bus_type_is_container(type) > 0) {
5336 r = sd_bus_message_enter_container(source, type, contents);
5340 r = sd_bus_message_open_container(m, type, contents);
5344 r = sd_bus_message_copy(m, source, true);
5348 r = sd_bus_message_close_container(m);
5352 r = sd_bus_message_exit_container(source);
5359 r = sd_bus_message_read_basic(source, type, &basic);
5365 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5366 type == SD_BUS_TYPE_SIGNATURE ||
5367 type == SD_BUS_TYPE_STRING)
5368 r = sd_bus_message_append_basic(m, type, basic.string);
5370 r = sd_bus_message_append_basic(m, type, &basic);
5377 return done_something;
5380 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5385 assert_return(m, -EINVAL);
5386 assert_return(m->sealed, -EPERM);
5387 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5388 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5389 assert_return(type || contents, -EINVAL);
5390 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5392 r = sd_bus_message_peek_type(m, &t, &c);
5396 if (type != 0 && type != t)
5399 if (contents && !streq_ptr(contents, c))
5405 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5406 assert_return(m, NULL);