1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include "time-util.h"
30 #include "cgroup-util.h"
33 #include "bus-message.h"
34 #include "bus-internal.h"
36 #include "bus-signature.h"
37 #include "bus-gvariant.h"
40 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
42 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
47 if (old_base == new_base)
50 if ((uint8_t*) p < (uint8_t*) old_base)
53 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
56 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
59 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
63 if (part->memfd >= 0) {
64 /* If we can reuse the memfd, try that. For that it
65 * can't be sealed yet. */
68 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
71 assert_se(munmap(part->data, part->mapped) == 0);
73 close_nointr_nofail(part->memfd);
76 } else if (part->munmap_this)
77 munmap(part->data, part->mapped);
78 else if (part->free_this)
85 static void message_reset_parts(sd_bus_message *m) {
86 struct bus_body_part *part;
91 while (m->n_body_parts > 0) {
92 struct bus_body_part *next = part->next;
93 message_free_part(m, part);
100 m->cached_rindex_part = NULL;
101 m->cached_rindex_part_begin = 0;
104 static void message_reset_containers(sd_bus_message *m) {
109 for (i = 0; i < m->n_containers; i++) {
110 free(m->containers[i].signature);
111 free(m->containers[i].offsets);
115 m->containers = NULL;
117 m->n_containers = m->containers_allocated = 0;
118 m->root_container.index = 0;
121 static void message_free(sd_bus_message *m) {
127 message_reset_parts(m);
132 if (m->release_kdbus) {
135 off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
136 ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &off);
140 sd_bus_unref(m->bus);
143 close_many(m->fds, m->n_fds);
147 if (m->iovec != m->iovec_fixed)
150 message_reset_containers(m);
151 free(m->root_container.signature);
152 free(m->root_container.offsets);
154 free(m->peeked_signature);
156 bus_creds_done(&m->creds);
160 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
162 size_t old_size, new_size, start;
169 old_size = sizeof(struct bus_header) + m->header->fields_size;
170 start = ALIGN_TO(old_size, align);
171 new_size = start + sz;
173 if (old_size == new_size)
174 return (uint8_t*) m->header + old_size;
176 if (new_size > (size_t) ((uint32_t) -1))
179 if (m->free_header) {
180 np = realloc(m->header, ALIGN8(new_size));
184 /* Initially, the header is allocated as part of of
185 * the sd_bus_message itself, let's replace it by
188 np = malloc(ALIGN8(new_size));
192 memcpy(np, m->header, sizeof(struct bus_header));
195 /* Zero out padding */
196 if (start > old_size)
197 memset((uint8_t*) np + old_size, 0, start - old_size);
201 m->header->fields_size = new_size - sizeof(struct bus_header);
203 /* Adjust quick access pointers */
204 m->path = adjust_pointer(m->path, op, old_size, m->header);
205 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
206 m->member = adjust_pointer(m->member, op, old_size, m->header);
207 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
208 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
209 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
211 m->free_header = true;
214 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
217 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
220 return (uint8_t*) np + start;
227 static int message_append_field_string(
239 /* dbus1 doesn't allow strings over 32bit, let's enforce this
240 * globally, to not risk convertability */
242 if (l > (size_t) (uint32_t) -1)
245 /* Signature "(yv)" where the variant contains "s" */
247 if (BUS_MESSAGE_IS_GVARIANT(m)) {
249 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
250 p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
262 *ret = (char*) p + 8;
265 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
266 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
275 ((uint32_t*) p)[1] = l;
276 memcpy(p + 8, s, l + 1);
279 *ret = (char*) p + 8;
285 static int message_append_field_signature(
296 /* dbus1 doesn't allow signatures over 32bit, let's enforce
297 * this globally, to not risk convertability */
302 /* Signature "(yv)" where the variant contains "g" */
304 if (BUS_MESSAGE_IS_GVARIANT(m))
305 /* For gvariant the serialization is the same as for normal strings */
306 return message_append_field_string(m, h, 'g', s, ret);
308 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
309 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
315 p[2] = SD_BUS_TYPE_SIGNATURE;
318 memcpy(p + 5, s, l + 1);
321 *ret = (const char*) p + 5;
327 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
332 if (BUS_MESSAGE_IS_GVARIANT(m)) {
333 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
335 p = message_extend_fields(m, 8, 1 + 7 + 4 + 1 + 1, true);
341 *((uint32_t*) (p + 8)) = x;
345 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
346 p = message_extend_fields(m, 8, 4 + 4, false);
352 p[2] = SD_BUS_TYPE_UINT32;
355 ((uint32_t*) p)[1] = x;
361 int bus_message_from_header(
367 const struct ucred *ucred,
370 sd_bus_message **ret) {
373 struct bus_header *h;
376 assert(buffer || length <= 0);
377 assert(fds || n_fds <= 0);
380 if (length < sizeof(struct bus_header))
384 if (h->version != 1 &&
391 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
394 if (h->endian != BUS_LITTLE_ENDIAN &&
395 h->endian != BUS_BIG_ENDIAN)
398 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
401 label_sz = strlen(label);
416 m->creds.uid = ucred->uid;
417 m->creds.pid = ucred->pid;
418 m->creds.gid = ucred->gid;
419 m->creds.mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID;
423 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
424 memcpy(m->creds.label, label, label_sz + 1);
426 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
430 m->bus = sd_bus_ref(bus);
436 int bus_message_from_malloc(
442 const struct ucred *ucred,
444 sd_bus_message **ret) {
450 r = bus_message_from_header(bus, buffer, length, fds, n_fds, ucred, label, 0, &m);
454 if (length != BUS_MESSAGE_SIZE(m)) {
459 sz = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
462 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
464 m->body.sealed = true;
469 m->iovec = m->iovec_fixed;
470 m->iovec[0].iov_base = buffer;
471 m->iovec[0].iov_len = length;
473 r = bus_message_parse_fields(m);
477 /* We take possession of the memory and fds now */
478 m->free_header = true;
489 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
492 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
497 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
498 m->header->endian = BUS_NATIVE_ENDIAN;
499 m->header->type = type;
500 m->header->version = bus ? bus->message_version : 1;
501 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
502 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
505 m->bus = sd_bus_ref(bus);
510 _public_ int sd_bus_message_new_signal(
513 const char *interface,
515 sd_bus_message **m) {
520 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
521 assert_return(object_path_is_valid(path), -EINVAL);
522 assert_return(interface_name_is_valid(interface), -EINVAL);
523 assert_return(member_name_is_valid(member), -EINVAL);
524 assert_return(m, -EINVAL);
526 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
530 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
532 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
535 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
538 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
546 sd_bus_message_unref(t);
550 _public_ int sd_bus_message_new_method_call(
552 const char *destination,
554 const char *interface,
556 sd_bus_message **m) {
561 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
562 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
563 assert_return(object_path_is_valid(path), -EINVAL);
564 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
565 assert_return(member_name_is_valid(member), -EINVAL);
566 assert_return(m, -EINVAL);
568 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
572 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
575 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
580 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
586 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
599 static int message_new_reply(
600 sd_bus_message *call,
602 sd_bus_message **m) {
607 assert_return(call, -EINVAL);
608 assert_return(call->sealed, -EPERM);
609 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
610 assert_return(!call->bus || call->bus->state != BUS_UNSET, -ENOTCONN);
611 assert_return(m, -EINVAL);
613 t = message_new(call->bus, type);
617 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
618 t->reply_serial = BUS_MESSAGE_SERIAL(call);
620 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
625 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
630 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
631 t->enforced_reply_signature = call->enforced_reply_signature;
641 _public_ int sd_bus_message_new_method_return(
642 sd_bus_message *call,
643 sd_bus_message **m) {
645 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
648 _public_ int sd_bus_message_new_method_error(
649 sd_bus_message *call,
650 const sd_bus_error *e,
651 sd_bus_message **m) {
656 assert_return(sd_bus_error_is_set(e), -EINVAL);
657 assert_return(m, -EINVAL);
659 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
663 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
668 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
673 t->error._need_free = -1;
683 _public_ int sd_bus_message_new_method_errorf(
684 sd_bus_message *call,
690 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
693 assert_return(name, -EINVAL);
694 assert_return(m, -EINVAL);
696 va_start(ap, format);
697 bus_error_setfv(&error, name, format, ap);
700 return sd_bus_message_new_method_error(call, &error, m);
703 _public_ int sd_bus_message_new_method_errno(
704 sd_bus_message *call,
706 const sd_bus_error *p,
707 sd_bus_message **m) {
709 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
711 if (sd_bus_error_is_set(p))
712 return sd_bus_message_new_method_error(call, p, m);
714 sd_bus_error_set_errno(&berror, error);
716 return sd_bus_message_new_method_error(call, &berror, m);
719 _public_ int sd_bus_message_new_method_errnof(
720 sd_bus_message *call,
726 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
729 va_start(ap, format);
730 bus_error_set_errnofv(&berror, error, format, ap);
733 return sd_bus_message_new_method_error(call, &berror, m);
736 int bus_message_new_synthetic_error(
739 const sd_bus_error *e,
740 sd_bus_message **m) {
745 assert(sd_bus_error_is_set(e));
748 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
752 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
753 t->reply_serial = serial;
755 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
759 if (bus && bus->unique_name) {
760 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
765 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
770 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
775 t->error._need_free = -1;
785 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
786 assert_return(m, NULL);
788 assert(m->n_ref > 0);
794 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
799 assert(m->n_ref > 0);
808 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
809 assert_return(m, -EINVAL);
810 assert_return(type, -EINVAL);
812 *type = m->header->type;
816 _public_ int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
817 assert_return(m, -EINVAL);
818 assert_return(serial, -EINVAL);
819 assert_return(m->header->serial != 0, -ENOENT);
821 *serial = BUS_MESSAGE_SERIAL(m);
825 _public_ int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
826 assert_return(m, -EINVAL);
827 assert_return(serial, -EINVAL);
828 assert_return(m->reply_serial != 0, -ENOENT);
830 *serial = m->reply_serial;
834 _public_ int sd_bus_message_get_no_reply(sd_bus_message *m) {
835 assert_return(m, -EINVAL);
837 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL ? !!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
840 _public_ int sd_bus_message_get_no_auto_start(sd_bus_message *m) {
841 assert_return(m, -EINVAL);
843 return !!(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
846 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
847 assert_return(m, NULL);
852 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
853 assert_return(m, NULL);
858 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
859 assert_return(m, NULL);
864 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
865 assert_return(m, NULL);
867 return m->destination;
870 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
871 assert_return(m, NULL);
876 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
877 assert_return(m, NULL);
878 assert_return(sd_bus_error_is_set(&m->error), NULL);
883 _public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
884 assert_return(m, -EINVAL);
885 assert_return(usec, -EINVAL);
886 assert_return(m->monotonic > 0, -ENODATA);
888 *usec = m->monotonic;
892 _public_ int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
893 assert_return(m, -EINVAL);
894 assert_return(usec, -EINVAL);
895 assert_return(m->realtime > 0, -ENODATA);
901 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
902 assert_return(m, NULL);
904 if (m->creds.mask == 0)
910 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
911 const char *interface,
912 const char *member) {
913 assert_return(m, -EINVAL);
915 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
918 if (interface && (!m->interface || !streq(m->interface, interface)))
921 if (member && (!m->member || !streq(m->member, member)))
927 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
928 const char *interface,
929 const char *member) {
930 assert_return(m, -EINVAL);
932 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
935 if (interface && (!m->interface || !streq(m->interface, interface)))
938 if (member && (!m->member || !streq(m->member, member)))
944 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
945 assert_return(m, -EINVAL);
947 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
950 if (name && (!m->error.name || !streq(m->error.name, name)))
956 _public_ int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
957 assert_return(m, -EINVAL);
958 assert_return(!m->sealed, -EPERM);
959 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
962 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
964 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
969 _public_ int sd_bus_message_set_no_auto_start(sd_bus_message *m, int b) {
970 assert_return(m, -EINVAL);
971 assert_return(!m->sealed, -EPERM);
974 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
976 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
981 static struct bus_container *message_get_container(sd_bus_message *m) {
984 if (m->n_containers == 0)
985 return &m->root_container;
987 assert(m->containers);
988 return m->containers + m->n_containers - 1;
991 struct bus_body_part *message_append_part(sd_bus_message *m) {
992 struct bus_body_part *part;
999 if (m->n_body_parts <= 0) {
1003 assert(m->body_end);
1005 part = new0(struct bus_body_part, 1);
1011 m->body_end->next = part;
1021 static void part_zero(struct bus_body_part *part, size_t sz) {
1026 /* All other fields can be left in their defaults */
1027 assert(!part->data);
1028 assert(part->memfd < 0);
1031 part->is_zero = true;
1032 part->sealed = true;
1035 static int part_make_space(
1036 struct sd_bus_message *m,
1037 struct bus_body_part *part,
1046 assert(!part->sealed);
1051 if (!part->data && part->memfd < 0)
1052 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1054 if (part->memfd >= 0) {
1056 if (part->allocated == 0 || sz > part->allocated) {
1057 uint64_t new_allocated;
1059 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1060 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &new_allocated);
1066 part->allocated = new_allocated;
1069 if (!part->data || sz > part->mapped) {
1072 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1073 if (part->mapped <= 0)
1074 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1076 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1078 if (n == MAP_FAILED) {
1087 part->munmap_this = true;
1089 if (part->allocated == 0 || sz > part->allocated) {
1090 size_t new_allocated;
1092 new_allocated = sz > 0 ? 2 * sz : 64;
1093 n = realloc(part->data, new_allocated);
1100 part->allocated = new_allocated;
1101 part->free_this = true;
1106 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1112 static int message_add_offset(sd_bus_message *m, size_t offset) {
1113 struct bus_container *c;
1116 assert(BUS_MESSAGE_IS_GVARIANT(m));
1118 /* Add offset to current container, unless this is the first
1119 * item in it, which will have the 0 offset, which we can
1121 c = message_get_container(m);
1123 if (!c->need_offsets)
1126 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1129 c->offsets[c->n_offsets++] = offset;
1133 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1134 struct bus_container *c;
1141 /* Update counters */
1142 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1145 *c->array_size += expand;
1149 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1150 size_t start_body, end_body, padding, added;
1161 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1162 end_body = start_body + sz;
1164 padding = start_body - m->header->body_size;
1165 added = padding + sz;
1167 /* Check for 32bit overflows */
1168 if (end_body > (size_t) ((uint32_t) -1)) {
1174 struct bus_body_part *part = NULL;
1178 m->n_body_parts <= 0 ||
1179 m->body_end->sealed ||
1180 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1184 part = message_append_part(m);
1188 part_zero(part, padding);
1191 part = message_append_part(m);
1195 r = part_make_space(m, part, sz, &p);
1199 struct bus_container *c;
1201 size_t os, start_part, end_part;
1207 start_part = ALIGN_TO(part->size, align);
1208 end_part = start_part + sz;
1210 r = part_make_space(m, part, end_part, &p);
1215 memset(p, 0, padding);
1216 p = (uint8_t*) p + padding;
1219 /* Readjust pointers */
1220 for (c = m->containers; c < m->containers + m->n_containers; c++)
1221 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1223 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1226 /* Return something that is not NULL and is aligned */
1227 p = (uint8_t *) NULL + align;
1229 m->header->body_size = end_body;
1230 message_extend_containers(m, added);
1233 r = message_add_offset(m, end_body);
1243 static int message_push_fd(sd_bus_message *m, int fd) {
1254 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1258 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1261 close_nointr_nofail(copy);
1266 m->fds[m->n_fds] = copy;
1272 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1273 _cleanup_close_ int fd = -1;
1274 struct bus_container *c;
1278 assert_return(m, -EINVAL);
1279 assert_return(!m->sealed, -EPERM);
1280 assert_return(bus_type_is_basic(type), -EINVAL);
1281 assert_return(!m->poisoned, -ESTALE);
1283 c = message_get_container(m);
1285 if (c->signature && c->signature[c->index]) {
1286 /* Container signature is already set */
1288 if (c->signature[c->index] != type)
1293 /* Maybe we can append to the signature? But only if this is the top-level container*/
1294 if (c->enclosing != 0)
1297 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1304 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1310 case SD_BUS_TYPE_SIGNATURE:
1311 case SD_BUS_TYPE_STRING:
1314 /* Fall through... */
1315 case SD_BUS_TYPE_OBJECT_PATH:
1323 case SD_BUS_TYPE_BOOLEAN:
1325 u8 = p && *(int*) p;
1331 case SD_BUS_TYPE_UNIX_FD:
1336 fd = message_push_fd(m, *(int*) p);
1347 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1348 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1355 a = message_extend_body(m, align, sz, true);
1362 *stored = (const uint8_t*) a;
1369 case SD_BUS_TYPE_STRING:
1370 /* To make things easy we'll serialize a NULL string
1371 * into the empty string */
1374 /* Fall through... */
1375 case SD_BUS_TYPE_OBJECT_PATH:
1381 sz = 4 + strlen(p) + 1;
1384 case SD_BUS_TYPE_SIGNATURE:
1389 sz = 1 + strlen(p) + 1;
1392 case SD_BUS_TYPE_BOOLEAN:
1394 u32 = p && *(int*) p;
1400 case SD_BUS_TYPE_UNIX_FD:
1405 fd = message_push_fd(m, *(int*) p);
1416 align = bus_type_get_alignment(type);
1417 sz = bus_type_get_size(type);
1424 a = message_extend_body(m, align, sz, false);
1428 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1429 *(uint32_t*) a = sz - 5;
1430 memcpy((uint8_t*) a + 4, p, sz - 4);
1433 *stored = (const uint8_t*) a + 4;
1435 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1436 *(uint8_t*) a = sz - 1;
1437 memcpy((uint8_t*) a + 1, p, sz - 1);
1440 *stored = (const uint8_t*) a + 1;
1449 if (type == SD_BUS_TYPE_UNIX_FD)
1452 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1459 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1460 return message_append_basic(m, type, p, NULL);
1463 _public_ int sd_bus_message_append_string_space(
1468 struct bus_container *c;
1471 assert_return(m, -EINVAL);
1472 assert_return(s, -EINVAL);
1473 assert_return(!m->sealed, -EPERM);
1474 assert_return(!m->poisoned, -ESTALE);
1476 c = message_get_container(m);
1478 if (c->signature && c->signature[c->index]) {
1479 /* Container signature is already set */
1481 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1486 /* Maybe we can append to the signature? But only if this is the top-level container*/
1487 if (c->enclosing != 0)
1490 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1497 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1498 a = message_extend_body(m, 1, size + 1, true);
1504 a = message_extend_body(m, 4, 4 + size + 1, false);
1508 *(uint32_t*) a = size;
1514 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1520 _public_ int sd_bus_message_append_string_iovec(
1522 const struct iovec *iov,
1530 assert_return(m, -EINVAL);
1531 assert_return(!m->sealed, -EPERM);
1532 assert_return(iov || n == 0, -EINVAL);
1533 assert_return(!m->poisoned, -ESTALE);
1535 size = IOVEC_TOTAL_SIZE(iov, n);
1537 r = sd_bus_message_append_string_space(m, size, &p);
1541 for (i = 0; i < n; i++) {
1543 if (iov[i].iov_base)
1544 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1546 memset(p, ' ', iov[i].iov_len);
1548 p += iov[i].iov_len;
1554 static int bus_message_open_array(
1556 struct bus_container *c,
1557 const char *contents,
1558 uint32_t **array_size,
1560 bool *need_offsets) {
1570 assert(need_offsets);
1572 if (!signature_is_single(contents, true))
1575 if (c->signature && c->signature[c->index]) {
1577 /* Verify the existing signature */
1579 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1582 if (!startswith(c->signature + c->index + 1, contents))
1585 nindex = c->index + 1 + strlen(contents);
1589 if (c->enclosing != 0)
1592 /* Extend the existing signature */
1594 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1600 nindex = e - c->signature;
1603 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1604 alignment = bus_gvariant_get_alignment(contents);
1608 /* Add alignment padding and add to offset list */
1609 if (!message_extend_body(m, alignment, 0, false))
1612 r = bus_gvariant_is_fixed_size(contents);
1616 *begin = m->header->body_size;
1617 *need_offsets = r == 0;
1621 struct bus_body_part *o;
1623 alignment = bus_type_get_alignment(contents[0]);
1627 a = message_extend_body(m, 4, 4, false);
1632 op = m->body_end->data;
1633 os = m->body_end->size;
1635 /* Add alignment between size and first element */
1636 if (!message_extend_body(m, alignment, 0, false))
1639 /* location of array size might have changed so let's readjust a */
1640 if (o == m->body_end)
1641 a = adjust_pointer(a, op, os, m->body_end->data);
1647 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1653 static int bus_message_open_variant(
1655 struct bus_container *c,
1656 const char *contents) {
1662 if (!signature_is_single(contents, false))
1665 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1668 if (c->signature && c->signature[c->index]) {
1670 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1676 if (c->enclosing != 0)
1679 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1686 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1687 /* Variants are always aligned to 8 */
1689 if (!message_extend_body(m, 8, 0, false))
1696 l = strlen(contents);
1697 a = message_extend_body(m, 1, 1 + l + 1, false);
1702 memcpy((uint8_t*) a + 1, contents, l + 1);
1705 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1711 static int bus_message_open_struct(
1713 struct bus_container *c,
1714 const char *contents,
1716 bool *need_offsets) {
1725 assert(need_offsets);
1727 if (!signature_is_valid(contents, false))
1730 if (c->signature && c->signature[c->index]) {
1733 l = strlen(contents);
1735 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1736 !startswith(c->signature + c->index + 1, contents) ||
1737 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1740 nindex = c->index + 1 + l + 1;
1744 if (c->enclosing != 0)
1747 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1753 nindex = e - c->signature;
1756 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1759 alignment = bus_gvariant_get_alignment(contents);
1763 if (!message_extend_body(m, alignment, 0, false))
1766 r = bus_gvariant_is_fixed_size(contents);
1770 *begin = m->header->body_size;
1771 *need_offsets = r == 0;
1773 /* Align contents to 8 byte boundary */
1774 if (!message_extend_body(m, 8, 0, false))
1778 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1784 static int bus_message_open_dict_entry(
1786 struct bus_container *c,
1787 const char *contents,
1789 bool *need_offsets) {
1797 assert(need_offsets);
1799 if (!signature_is_pair(contents))
1802 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1805 if (c->signature && c->signature[c->index]) {
1808 l = strlen(contents);
1810 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1811 !startswith(c->signature + c->index + 1, contents) ||
1812 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1817 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1820 alignment = bus_gvariant_get_alignment(contents);
1824 if (!message_extend_body(m, alignment, 0, false))
1827 r = bus_gvariant_is_fixed_size(contents);
1831 *begin = m->header->body_size;
1832 *need_offsets = r == 0;
1834 /* Align contents to 8 byte boundary */
1835 if (!message_extend_body(m, 8, 0, false))
1842 _public_ int sd_bus_message_open_container(
1845 const char *contents) {
1847 struct bus_container *c, *w;
1848 uint32_t *array_size = NULL;
1850 size_t before, begin;
1851 bool need_offsets = false;
1854 assert_return(m, -EINVAL);
1855 assert_return(!m->sealed, -EPERM);
1856 assert_return(contents, -EINVAL);
1857 assert_return(!m->poisoned, -ESTALE);
1859 /* Make sure we have space for one more container */
1860 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1865 c = message_get_container(m);
1867 signature = strdup(contents);
1873 /* Save old index in the parent container, in case we have to
1874 * abort this container */
1875 c->saved_index = c->index;
1876 before = m->header->body_size;
1878 if (type == SD_BUS_TYPE_ARRAY)
1879 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1880 else if (type == SD_BUS_TYPE_VARIANT)
1881 r = bus_message_open_variant(m, c, contents);
1882 else if (type == SD_BUS_TYPE_STRUCT)
1883 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1884 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1885 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1894 /* OK, let's fill it in */
1895 w = m->containers + m->n_containers++;
1896 w->enclosing = type;
1897 w->signature = signature;
1899 w->array_size = array_size;
1902 w->n_offsets = w->offsets_allocated = 0;
1904 w->need_offsets = need_offsets;
1909 static size_t determine_word_size(size_t sz, size_t extra) {
1910 if (sz + extra <= 0xFF)
1912 else if (sz + extra*2 <= 0xFFFF)
1914 else if (sz + extra*4 <= 0xFFFFFFFF)
1920 static size_t read_word_le(void *p, size_t sz) {
1930 return *(uint8_t*) p;
1935 return le16toh(x.u16);
1937 return le32toh(x.u32);
1939 return le64toh(x.u64);
1941 assert_not_reached("unknown word width");
1944 static void write_word_le(void *p, size_t sz, size_t value) {
1952 assert(sz == 8 || (value < (1ULL << (sz*8))));
1955 *(uint8_t*) p = value;
1958 x.u16 = htole16((uint16_t) value);
1960 x.u32 = htole32((uint32_t) value);
1962 x.u64 = htole64((uint64_t) value);
1964 assert_not_reached("unknown word width");
1969 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1974 if (!BUS_MESSAGE_IS_GVARIANT(m))
1977 if (c->need_offsets) {
1978 size_t payload, sz, i;
1981 /* Variable-width arrays */
1983 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
1984 sz = determine_word_size(payload, c->n_offsets);
1986 a = message_extend_body(m, 1, sz * c->n_offsets, true);
1990 for (i = 0; i < c->n_offsets; i++)
1991 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
1995 /* Fixed-width or empty arrays */
1997 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
2005 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2012 if (!BUS_MESSAGE_IS_GVARIANT(m))
2015 l = strlen(c->signature);
2017 a = message_extend_body(m, 1, 1 + l, true);
2022 memcpy(a+1, c->signature, l);
2027 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2028 size_t n_variable = 0;
2037 if (!BUS_MESSAGE_IS_GVARIANT(m))
2040 p = strempty(c->signature);
2044 r = signature_element_length(p, &n);
2053 r = bus_gvariant_is_fixed_size(t);
2058 assert(i <= c->n_offsets);
2060 /* We need to add an offset for each item that has a
2061 * variable size and that is not the last one in the
2063 if (r == 0 && p[n] != 0)
2070 assert(i == c->n_offsets);
2072 if (n_variable <= 0) {
2073 a = message_extend_body(m, 1, 0, add_offset);
2080 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2082 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2084 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2088 p = strempty(c->signature);
2089 for (i = 0, j = 0; i < c->n_offsets; i++) {
2093 r = signature_element_length(p, &n);
2104 r = bus_gvariant_is_fixed_size(t);
2107 if (r > 0 || p[0] == 0)
2111 k = n_variable - 1 - j;
2113 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2122 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2123 struct bus_container *c;
2126 assert_return(m, -EINVAL);
2127 assert_return(!m->sealed, -EPERM);
2128 assert_return(m->n_containers > 0, -EINVAL);
2129 assert_return(!m->poisoned, -ESTALE);
2131 c = message_get_container(m);
2133 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2134 if (c->signature && c->signature[c->index] != 0)
2139 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2140 r = bus_message_close_array(m, c);
2141 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2142 r = bus_message_close_variant(m, c);
2143 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2144 r = bus_message_close_struct(m, c, true);
2146 assert_not_reached("Unknown container type");
2160 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2167 stack[*i].types = types;
2168 stack[*i].n_struct = n_struct;
2169 stack[*i].n_array = n_array;
2175 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2186 *types = stack[*i].types;
2187 *n_struct = stack[*i].n_struct;
2188 *n_array = stack[*i].n_array;
2193 int bus_message_append_ap(
2198 unsigned n_array, n_struct;
2199 TypeStack stack[BUS_CONTAINER_DEPTH];
2200 unsigned stack_ptr = 0;
2208 n_array = (unsigned) -1;
2209 n_struct = strlen(types);
2214 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2215 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2221 r = sd_bus_message_close_container(m);
2229 if (n_array != (unsigned) -1)
2238 case SD_BUS_TYPE_BYTE: {
2241 x = (uint8_t) va_arg(ap, int);
2242 r = sd_bus_message_append_basic(m, *t, &x);
2246 case SD_BUS_TYPE_BOOLEAN:
2247 case SD_BUS_TYPE_INT32:
2248 case SD_BUS_TYPE_UINT32:
2249 case SD_BUS_TYPE_UNIX_FD: {
2252 /* We assume a boolean is the same as int32_t */
2253 assert_cc(sizeof(int32_t) == sizeof(int));
2255 x = va_arg(ap, uint32_t);
2256 r = sd_bus_message_append_basic(m, *t, &x);
2260 case SD_BUS_TYPE_INT16:
2261 case SD_BUS_TYPE_UINT16: {
2264 x = (uint16_t) va_arg(ap, int);
2265 r = sd_bus_message_append_basic(m, *t, &x);
2269 case SD_BUS_TYPE_INT64:
2270 case SD_BUS_TYPE_UINT64:
2271 case SD_BUS_TYPE_DOUBLE: {
2274 x = va_arg(ap, uint64_t);
2275 r = sd_bus_message_append_basic(m, *t, &x);
2279 case SD_BUS_TYPE_STRING:
2280 case SD_BUS_TYPE_OBJECT_PATH:
2281 case SD_BUS_TYPE_SIGNATURE: {
2284 x = va_arg(ap, const char*);
2285 r = sd_bus_message_append_basic(m, *t, x);
2289 case SD_BUS_TYPE_ARRAY: {
2292 r = signature_element_length(t + 1, &k);
2298 memcpy(s, t + 1, k);
2301 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2306 if (n_array == (unsigned) -1) {
2311 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2317 n_array = va_arg(ap, unsigned);
2322 case SD_BUS_TYPE_VARIANT: {
2325 s = va_arg(ap, const char*);
2329 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2333 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2338 n_struct = strlen(s);
2339 n_array = (unsigned) -1;
2344 case SD_BUS_TYPE_STRUCT_BEGIN:
2345 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2348 r = signature_element_length(t, &k);
2355 memcpy(s, t + 1, k - 2);
2358 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2363 if (n_array == (unsigned) -1) {
2368 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2374 n_array = (unsigned) -1;
2390 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2394 assert_return(m, -EINVAL);
2395 assert_return(types, -EINVAL);
2396 assert_return(!m->sealed, -EPERM);
2397 assert_return(!m->poisoned, -ESTALE);
2399 va_start(ap, types);
2400 r = bus_message_append_ap(m, types, ap);
2406 _public_ int sd_bus_message_append_array_space(
2416 assert_return(m, -EINVAL);
2417 assert_return(!m->sealed, -EPERM);
2418 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2419 assert_return(ptr || size == 0, -EINVAL);
2420 assert_return(!m->poisoned, -ESTALE);
2422 /* alignment and size of the trivial types (except bool) is
2423 * identical for gvariant and dbus1 marshalling */
2424 align = bus_type_get_alignment(type);
2425 sz = bus_type_get_size(type);
2427 assert_se(align > 0);
2433 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2437 a = message_extend_body(m, align, size, false);
2441 r = sd_bus_message_close_container(m);
2449 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2456 assert_return(m, -EINVAL);
2457 assert_return(!m->sealed, -EPERM);
2458 assert_return(bus_type_is_trivial(type), -EINVAL);
2459 assert_return(ptr || size == 0, -EINVAL);
2460 assert_return(!m->poisoned, -ESTALE);
2462 r = sd_bus_message_append_array_space(m, type, size, &p);
2467 memcpy(p, ptr, size);
2472 _public_ int sd_bus_message_append_array_iovec(
2475 const struct iovec *iov,
2483 assert_return(m, -EINVAL);
2484 assert_return(!m->sealed, -EPERM);
2485 assert_return(bus_type_is_trivial(type), -EINVAL);
2486 assert_return(iov || n == 0, -EINVAL);
2487 assert_return(!m->poisoned, -ESTALE);
2489 size = IOVEC_TOTAL_SIZE(iov, n);
2491 r = sd_bus_message_append_array_space(m, type, size, &p);
2495 for (i = 0; i < n; i++) {
2497 if (iov[i].iov_base)
2498 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2500 memset(p, 0, iov[i].iov_len);
2502 p = (uint8_t*) p + iov[i].iov_len;
2508 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2511 _cleanup_close_ int copy_fd = -1;
2512 struct bus_body_part *part;
2524 if (!bus_type_is_trivial(type))
2529 r = sd_memfd_set_sealed(memfd, true);
2533 copy_fd = sd_memfd_dup_fd(memfd);
2537 r = sd_memfd_get_size(memfd, &size);
2541 align = bus_type_get_alignment(type);
2542 sz = bus_type_get_size(type);
2544 assert_se(align > 0);
2550 if (size > (uint64_t) (uint32_t) -1)
2553 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2557 a = message_extend_body(m, align, 0, false);
2561 part = message_append_part(m);
2565 part->memfd = copy_fd;
2566 part->sealed = true;
2570 m->header->body_size += size;
2571 message_extend_containers(m, size);
2573 return sd_bus_message_close_container(m);
2576 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
2577 _cleanup_close_ int copy_fd = -1;
2578 struct bus_body_part *part;
2579 struct bus_container *c;
2584 assert_return(m, -EINVAL);
2585 assert_return(memfd, -EINVAL);
2586 assert_return(!m->sealed, -EPERM);
2587 assert_return(!m->poisoned, -ESTALE);
2589 r = sd_memfd_set_sealed(memfd, true);
2593 copy_fd = sd_memfd_dup_fd(memfd);
2597 r = sd_memfd_get_size(memfd, &size);
2601 /* We require this to be NUL terminated */
2605 if (size > (uint64_t) (uint32_t) -1)
2608 c = message_get_container(m);
2609 if (c->signature && c->signature[c->index]) {
2610 /* Container signature is already set */
2612 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2617 /* Maybe we can append to the signature? But only if this is the top-level container*/
2618 if (c->enclosing != 0)
2621 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2628 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2629 a = message_extend_body(m, 4, 4, false);
2633 *(uint32_t*) a = size - 1;
2636 part = message_append_part(m);
2640 part->memfd = copy_fd;
2641 part->sealed = true;
2645 m->header->body_size += size;
2646 message_extend_containers(m, size);
2648 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2649 r = message_add_offset(m, m->header->body_size);
2656 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2662 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2666 assert_return(m, -EINVAL);
2667 assert_return(!m->sealed, -EPERM);
2668 assert_return(!m->poisoned, -ESTALE);
2670 r = sd_bus_message_open_container(m, 'a', "s");
2674 STRV_FOREACH(i, l) {
2675 r = sd_bus_message_append_basic(m, 's', *i);
2680 return sd_bus_message_close_container(m);
2683 static int bus_message_close_header(sd_bus_message *m) {
2689 if (!BUS_MESSAGE_IS_GVARIANT(m))
2692 if (m->n_header_offsets < 1)
2695 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2697 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2699 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2703 for (i = 0; i < m->n_header_offsets; i++)
2704 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2709 int bus_message_seal(sd_bus_message *m, uint64_t serial, usec_t timeout) {
2710 struct bus_body_part *part;
2720 if (m->n_containers > 0)
2726 /* In vtables the return signature of method calls is listed,
2727 * let's check if they match if this is a response */
2728 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2729 m->enforced_reply_signature &&
2730 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2733 /* If gvariant marshalling is used we need to close the body structure */
2734 r = bus_message_close_struct(m, &m->root_container, false);
2738 /* If there's a non-trivial signature set, then add it in here */
2739 if (!isempty(m->root_container.signature)) {
2740 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2746 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2751 r = bus_message_close_header(m);
2755 m->header->serial = serial;
2756 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2758 /* Add padding at the end of the fields part, since we know
2759 * the body needs to start at an 8 byte alignment. We made
2760 * sure we allocated enough space for this, so all we need to
2761 * do here is to zero it out. */
2762 l = BUS_MESSAGE_FIELDS_SIZE(m);
2765 memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
2767 /* If this is something we can send as memfd, then let's seal
2768 the memfd now. Note that we can send memfds as payload only
2769 for directed messages, and not for broadcasts. */
2770 if (m->destination && m->bus && m->bus->use_memfd) {
2771 MESSAGE_FOREACH_PART(part, i, m)
2772 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2775 /* Try to seal it if that makes
2776 * sense. First, unmap our own map to
2777 * make sure we don't keep it busy. */
2778 bus_body_part_unmap(part);
2780 /* Then, sync up real memfd size */
2782 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &sz) < 0)
2785 /* Finally, try to seal */
2786 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
2787 part->sealed = true;
2791 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2792 m->root_container.index = 0;
2793 m->root_container.offset_index = 0;
2794 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2801 int bus_body_part_map(struct bus_body_part *part) {
2810 if (part->size <= 0)
2813 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2814 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2815 static const uint8_t zeroes[7] = { };
2816 part->data = (void*) zeroes;
2820 psz = PAGE_ALIGN(part->size);
2822 if (part->memfd >= 0)
2823 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2824 else if (part->is_zero)
2825 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2829 if (p == MAP_FAILED)
2834 part->munmap_this = true;
2839 void bus_body_part_unmap(struct bus_body_part *part) {
2843 if (part->memfd < 0)
2849 if (!part->munmap_this)
2852 assert_se(munmap(part->data, part->mapped) == 0);
2856 part->munmap_this = false;
2861 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2862 size_t k, start, end;
2867 start = ALIGN_TO((size_t) *rindex, align);
2868 end = start + nbytes;
2873 /* Verify that padding is 0 */
2874 for (k = *rindex; k < start; k++)
2875 if (((const uint8_t*) p)[k] != 0)
2879 *r = (uint8_t*) p + start;
2886 static bool message_end_of_signature(sd_bus_message *m) {
2887 struct bus_container *c;
2891 c = message_get_container(m);
2892 return !c->signature || c->signature[c->index] == 0;
2895 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2896 struct bus_container *c;
2900 c = message_get_container(m);
2901 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2904 if (BUS_MESSAGE_IS_GVARIANT(m))
2905 return index >= c->end;
2907 assert(c->array_size);
2908 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2912 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2913 assert_return(m, -EINVAL);
2914 assert_return(m->sealed, -EPERM);
2916 if (complete && m->n_containers > 0)
2919 if (message_end_of_signature(m))
2922 if (message_end_of_array(m, m->rindex))
2928 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2929 struct bus_body_part *part;
2935 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2936 part = m->cached_rindex_part;
2937 begin = m->cached_rindex_part_begin;
2947 if (index + sz <= begin + part->size) {
2949 r = bus_body_part_map(part);
2954 *p = (uint8_t*) part->data + index - begin;
2956 m->cached_rindex_part = part;
2957 m->cached_rindex_part_begin = begin;
2962 begin += part->size;
2969 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2976 if (!BUS_MESSAGE_IS_GVARIANT(m))
2979 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2982 sz = bus_gvariant_get_size(c->signature);
2986 if (c->offset_index+1 >= c->n_offsets)
2989 /* Variable-size array */
2991 alignment = bus_gvariant_get_alignment(c->signature);
2992 assert(alignment > 0);
2994 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
2995 c->item_size = c->offsets[c->offset_index+1] - *rindex;
2998 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3001 /* Fixed-size array */
3002 *rindex = c->begin + (c->offset_index+1) * sz;
3008 } else if (c->enclosing == 0 ||
3009 c->enclosing == SD_BUS_TYPE_STRUCT ||
3010 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3015 if (c->offset_index+1 >= c->n_offsets)
3018 r = signature_element_length(c->signature + c->index, &n);
3022 r = signature_element_length(c->signature + c->index + n, &j);
3027 memcpy(t, c->signature + c->index + n, j);
3030 alignment = bus_gvariant_get_alignment(t);
3033 assert(alignment > 0);
3035 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3036 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3040 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3043 assert_not_reached("Unknown container type");
3048 /* Reached the end */
3055 static int message_peek_body(
3062 size_t k, start, end, padding;
3063 struct bus_body_part *part;
3070 start = ALIGN_TO((size_t) *rindex, align);
3071 padding = start - *rindex;
3072 end = start + nbytes;
3074 if (end > BUS_MESSAGE_BODY_SIZE(m))
3077 part = find_part(m, *rindex, padding, (void**) &q);
3082 /* Verify padding */
3083 for (k = 0; k < padding; k++)
3088 part = find_part(m, start, nbytes, (void**) &q);
3089 if (!part || (nbytes > 0 && !q))
3100 static bool validate_nul(const char *s, size_t l) {
3102 /* Check for NUL chars in the string */
3103 if (memchr(s, 0, l))
3106 /* Check for NUL termination */
3113 static bool validate_string(const char *s, size_t l) {
3115 if (!validate_nul(s, l))
3118 /* Check if valid UTF8 */
3119 if (!utf8_is_valid(s))
3125 static bool validate_signature(const char *s, size_t l) {
3127 if (!validate_nul(s, l))
3130 /* Check if valid signature */
3131 if (!signature_is_valid(s, true))
3137 static bool validate_object_path(const char *s, size_t l) {
3139 if (!validate_nul(s, l))
3142 if (!object_path_is_valid(s))
3148 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3149 struct bus_container *c;
3154 assert_return(m, -EINVAL);
3155 assert_return(m->sealed, -EPERM);
3156 assert_return(bus_type_is_basic(type), -EINVAL);
3158 if (message_end_of_signature(m))
3161 if (message_end_of_array(m, m->rindex))
3164 c = message_get_container(m);
3165 if (c->signature[c->index] != type)
3170 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3172 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3175 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3179 if (type == SD_BUS_TYPE_STRING)
3180 ok = validate_string(q, c->item_size-1);
3181 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3182 ok = validate_object_path(q, c->item_size-1);
3184 ok = validate_signature(q, c->item_size-1);
3190 *(const char**) p = q;
3194 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3196 if ((size_t) sz != c->item_size)
3199 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3202 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3208 case SD_BUS_TYPE_BYTE:
3210 *(uint8_t*) p = *(uint8_t*) q;
3213 case SD_BUS_TYPE_BOOLEAN:
3215 *(int*) p = !!*(uint8_t*) q;
3218 case SD_BUS_TYPE_INT16:
3219 case SD_BUS_TYPE_UINT16:
3221 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3224 case SD_BUS_TYPE_INT32:
3225 case SD_BUS_TYPE_UINT32:
3227 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3230 case SD_BUS_TYPE_INT64:
3231 case SD_BUS_TYPE_UINT64:
3232 case SD_BUS_TYPE_DOUBLE:
3234 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3237 case SD_BUS_TYPE_UNIX_FD: {
3240 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3245 *(int*) p = m->fds[j];
3251 assert_not_reached("unexpected type");
3255 r = container_next_item(m, c, &rindex);
3262 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3266 r = message_peek_body(m, &rindex, 4, 4, &q);
3270 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3271 r = message_peek_body(m, &rindex, 1, l+1, &q);
3275 if (type == SD_BUS_TYPE_OBJECT_PATH)
3276 ok = validate_object_path(q, l);
3278 ok = validate_string(q, l);
3283 *(const char**) p = q;
3285 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3288 r = message_peek_body(m, &rindex, 1, 1, &q);
3293 r = message_peek_body(m, &rindex, 1, l+1, &q);
3297 if (!validate_signature(q, l))
3301 *(const char**) p = q;
3306 align = bus_type_get_alignment(type);
3309 sz = bus_type_get_size(type);
3312 r = message_peek_body(m, &rindex, align, sz, &q);
3318 case SD_BUS_TYPE_BYTE:
3320 *(uint8_t*) p = *(uint8_t*) q;
3323 case SD_BUS_TYPE_BOOLEAN:
3325 *(int*) p = !!*(uint32_t*) q;
3328 case SD_BUS_TYPE_INT16:
3329 case SD_BUS_TYPE_UINT16:
3331 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3334 case SD_BUS_TYPE_INT32:
3335 case SD_BUS_TYPE_UINT32:
3337 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3340 case SD_BUS_TYPE_INT64:
3341 case SD_BUS_TYPE_UINT64:
3342 case SD_BUS_TYPE_DOUBLE:
3344 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3347 case SD_BUS_TYPE_UNIX_FD: {
3350 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3355 *(int*) p = m->fds[j];
3360 assert_not_reached("Unknown basic type...");
3367 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3373 static int bus_message_enter_array(
3375 struct bus_container *c,
3376 const char *contents,
3377 uint32_t **array_size,
3380 size_t *n_offsets) {
3394 if (!signature_is_single(contents, true))
3397 if (!c->signature || c->signature[c->index] == 0)
3400 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3403 if (!startswith(c->signature + c->index + 1, contents))
3408 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3411 r = message_peek_body(m, &rindex, 4, 4, &q);
3415 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3418 alignment = bus_type_get_alignment(contents[0]);
3422 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3426 *array_size = (uint32_t*) q;
3428 } else if (c->item_size <= 0) {
3430 /* gvariant: empty array */
3435 } else if (bus_gvariant_is_fixed_size(contents)) {
3437 /* gvariant: fixed length array */
3438 *item_size = bus_gvariant_get_size(contents);
3443 size_t where, p = 0, framing, sz;
3446 /* gvariant: variable length array */
3447 sz = determine_word_size(c->item_size, 0);
3449 where = rindex + c->item_size - sz;
3450 r = message_peek_body(m, &where, 1, sz, &q);
3454 framing = read_word_le(q, sz);
3455 if (framing > c->item_size - sz)
3457 if ((c->item_size - framing) % sz != 0)
3460 *n_offsets = (c->item_size - framing) / sz;
3462 where = rindex + framing;
3463 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3467 *offsets = new(size_t, *n_offsets);
3471 for (i = 0; i < *n_offsets; i++) {
3474 x = read_word_le((uint8_t*) q + i * sz, sz);
3475 if (x > c->item_size - sz)
3480 (*offsets)[i] = rindex + x;
3484 *item_size = (*offsets)[0] - rindex;
3489 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3490 c->index += 1 + strlen(contents);
3495 static int bus_message_enter_variant(
3497 struct bus_container *c,
3498 const char *contents,
3499 size_t *item_size) {
3511 if (!signature_is_single(contents, false))
3514 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3517 if (!c->signature || c->signature[c->index] == 0)
3520 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3525 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3528 k = strlen(contents);
3529 if (1+k > c->item_size)
3532 where = rindex + c->item_size - (1+k);
3533 r = message_peek_body(m, &where, 1, 1+k, &q);
3537 if (*(char*) q != 0)
3540 if (memcmp((uint8_t*) q+1, contents, k))
3543 *item_size = c->item_size - (1+k);
3546 r = message_peek_body(m, &rindex, 1, 1, &q);
3551 r = message_peek_body(m, &rindex, 1, l+1, &q);
3555 if (!validate_signature(q, l))
3558 if (!streq(q, contents))
3564 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3570 static int build_struct_offsets(
3572 const char *signature,
3576 size_t *n_offsets) {
3578 unsigned n_variable = 0, n_total = 0, v;
3579 size_t previous = 0, where;
3590 if (isempty(signature)) {
3597 sz = determine_word_size(size, 0);
3601 /* First, loop over signature and count variable elements and
3602 * elements in general. We use this to know how large the
3603 * offset array is at the end of the structure. Note that
3604 * GVariant only stores offsets for all variable size elements
3605 * that are not the last item. */
3611 r = signature_element_length(p, &n);
3620 r = bus_gvariant_is_fixed_size(t);
3625 if (r == 0 && p[n] != 0) /* except the last item */
3632 if (size < n_variable * sz)
3635 where = m->rindex + size - (n_variable * sz);
3636 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3642 *offsets = new(size_t, n_total);
3648 /* Second, loop again and build an offset table */
3654 r = signature_element_length(p, &n);
3663 k = bus_gvariant_get_size(t);
3671 x = read_word_le((uint8_t*) q + v*sz, sz);
3674 if (m->rindex + x < previous)
3677 /* The last item's end
3678 * is determined from
3681 x = size - (n_variable * sz);
3683 offset = m->rindex + x;
3689 align = bus_gvariant_get_alignment(t);
3692 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3696 previous = (*offsets)[(*n_offsets)++] = offset;
3701 assert(*n_offsets == n_total);
3703 *item_size = (*offsets)[0] - m->rindex;
3707 static int enter_struct_or_dict_entry(
3709 struct bus_container *c,
3710 const char *contents,
3713 size_t *n_offsets) {
3724 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3727 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3731 } else if (c->item_size <= 0) {
3733 /* gvariant empty struct */
3738 /* gvariant with contents */
3739 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3744 static int bus_message_enter_struct(
3746 struct bus_container *c,
3747 const char *contents,
3750 size_t *n_offsets) {
3762 if (!signature_is_valid(contents, false))
3765 if (!c->signature || c->signature[c->index] == 0)
3768 l = strlen(contents);
3770 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3771 !startswith(c->signature + c->index + 1, contents) ||
3772 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3775 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3779 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3780 c->index += 1 + l + 1;
3785 static int bus_message_enter_dict_entry(
3787 struct bus_container *c,
3788 const char *contents,
3791 size_t *n_offsets) {
3800 if (!signature_is_pair(contents))
3803 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3806 if (!c->signature || c->signature[c->index] == 0)
3809 l = strlen(contents);
3811 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3812 !startswith(c->signature + c->index + 1, contents) ||
3813 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3816 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3820 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3821 c->index += 1 + l + 1;
3826 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3828 const char *contents) {
3829 struct bus_container *c, *w;
3830 uint32_t *array_size = NULL;
3833 size_t *offsets = NULL;
3834 size_t n_offsets = 0, item_size = 0;
3837 assert_return(m, -EINVAL);
3838 assert_return(m->sealed, -EPERM);
3839 assert_return(type != 0 || !contents, -EINVAL);
3841 if (type == 0 || !contents) {
3845 /* Allow entering into anonymous containers */
3846 r = sd_bus_message_peek_type(m, &tt, &cc);
3850 if (type != 0 && type != tt)
3853 if (contents && !streq(contents, cc))
3861 * We enforce a global limit on container depth, that is much
3862 * higher than the 32 structs and 32 arrays the specification
3863 * mandates. This is simpler to implement for us, and we need
3864 * this only to ensure our container array doesn't grow
3865 * without bounds. We are happy to return any data from a
3866 * message as long as the data itself is valid, even if the
3867 * overall message might be not.
3869 * Note that the message signature is validated when
3870 * parsing the headers, and that validation does check the
3873 * Note that the specification defines no limits on the depth
3874 * of stacked variants, but we do.
3876 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3879 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3882 if (message_end_of_signature(m))
3885 if (message_end_of_array(m, m->rindex))
3888 c = message_get_container(m);
3890 signature = strdup(contents);
3894 c->saved_index = c->index;
3897 if (type == SD_BUS_TYPE_ARRAY)
3898 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3899 else if (type == SD_BUS_TYPE_VARIANT)
3900 r = bus_message_enter_variant(m, c, contents, &item_size);
3901 else if (type == SD_BUS_TYPE_STRUCT)
3902 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3903 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3904 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3914 /* OK, let's fill it in */
3915 w = m->containers + m->n_containers++;
3916 w->enclosing = type;
3917 w->signature = signature;
3921 w->begin = m->rindex;
3922 w->end = m->rindex + c->item_size;
3924 w->array_size = array_size;
3925 w->item_size = item_size;
3926 w->offsets = offsets;
3927 w->n_offsets = n_offsets;
3928 w->offset_index = 0;
3933 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3934 struct bus_container *c;
3938 assert_return(m, -EINVAL);
3939 assert_return(m->sealed, -EPERM);
3940 assert_return(m->n_containers > 0, -ENXIO);
3942 c = message_get_container(m);
3944 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3945 if (c->signature && c->signature[c->index] != 0)
3949 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3950 if (m->rindex < c->end)
3953 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3956 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3957 if (c->begin + l != m->rindex)
3965 c = message_get_container(m);
3968 c->index = c->saved_index;
3969 r = container_next_item(m, c, &m->rindex);
3977 static void message_quit_container(sd_bus_message *m) {
3978 struct bus_container *c;
3982 assert(m->n_containers > 0);
3984 c = message_get_container(m);
3987 assert(m->rindex >= c->before);
3988 m->rindex = c->before;
3990 /* Free container */
3995 /* Correct index of new top-level container */
3996 c = message_get_container(m);
3997 c->index = c->saved_index;
4000 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4001 struct bus_container *c;
4004 assert_return(m, -EINVAL);
4005 assert_return(m->sealed, -EPERM);
4007 if (message_end_of_signature(m))
4010 if (message_end_of_array(m, m->rindex))
4013 c = message_get_container(m);
4015 if (bus_type_is_basic(c->signature[c->index])) {
4019 *type = c->signature[c->index];
4023 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4029 r = signature_element_length(c->signature+c->index+1, &l);
4035 sig = strndup(c->signature + c->index + 1, l);
4039 free(m->peeked_signature);
4040 m->peeked_signature = sig;
4046 *type = SD_BUS_TYPE_ARRAY;
4051 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4052 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4058 r = signature_element_length(c->signature+c->index, &l);
4063 sig = strndup(c->signature + c->index + 1, l - 2);
4067 free(m->peeked_signature);
4068 m->peeked_signature = sig;
4074 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4079 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4083 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4086 if (c->item_size < 2)
4089 /* Look for the NUL delimiter that
4090 separates the payload from the
4091 signature. Since the body might be
4092 in a different part that then the
4093 signature we map byte by byte. */
4095 for (k = 2; k <= c->item_size; k++) {
4098 where = m->rindex + c->item_size - k;
4099 r = message_peek_body(m, &where, 1, k, &q);
4103 if (*(char*) q == 0)
4107 if (k > c->item_size)
4110 free(m->peeked_signature);
4111 m->peeked_signature = strndup((char*) q + 1, k - 1);
4112 if (!m->peeked_signature)
4115 if (!signature_is_valid(m->peeked_signature, true))
4118 *contents = m->peeked_signature;
4123 r = message_peek_body(m, &rindex, 1, 1, &q);
4128 r = message_peek_body(m, &rindex, 1, l+1, &q);
4132 if (!validate_signature(q, l))
4140 *type = SD_BUS_TYPE_VARIANT;
4155 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4156 struct bus_container *c;
4158 assert_return(m, -EINVAL);
4159 assert_return(m->sealed, -EPERM);
4162 message_reset_containers(m);
4165 c = message_get_container(m);
4167 c = message_get_container(m);
4169 c->offset_index = 0;
4171 m->rindex = c->begin;
4174 c->offset_index = 0;
4175 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4177 return !isempty(c->signature);
4180 static int message_read_ap(
4185 unsigned n_array, n_struct;
4186 TypeStack stack[BUS_CONTAINER_DEPTH];
4187 unsigned stack_ptr = 0;
4188 unsigned n_loop = 0;
4196 /* Ideally, we'd just call ourselves recursively on every
4197 * complex type. However, the state of a va_list that is
4198 * passed to a function is undefined after that function
4199 * returns. This means we need to docode the va_list linearly
4200 * in a single stackframe. We hence implement our own
4201 * home-grown stack in an array. */
4203 n_array = (unsigned) -1; /* lenght of current array entries */
4204 n_struct = strlen(types); /* length of current struct contents signature */
4211 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4212 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4218 r = sd_bus_message_exit_container(m);
4226 if (n_array != (unsigned) -1)
4235 case SD_BUS_TYPE_BYTE:
4236 case SD_BUS_TYPE_BOOLEAN:
4237 case SD_BUS_TYPE_INT16:
4238 case SD_BUS_TYPE_UINT16:
4239 case SD_BUS_TYPE_INT32:
4240 case SD_BUS_TYPE_UINT32:
4241 case SD_BUS_TYPE_INT64:
4242 case SD_BUS_TYPE_UINT64:
4243 case SD_BUS_TYPE_DOUBLE:
4244 case SD_BUS_TYPE_STRING:
4245 case SD_BUS_TYPE_OBJECT_PATH:
4246 case SD_BUS_TYPE_SIGNATURE:
4247 case SD_BUS_TYPE_UNIX_FD: {
4250 p = va_arg(ap, void*);
4251 r = sd_bus_message_read_basic(m, *t, p);
4264 case SD_BUS_TYPE_ARRAY: {
4267 r = signature_element_length(t + 1, &k);
4273 memcpy(s, t + 1, k);
4276 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4287 if (n_array == (unsigned) -1) {
4292 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4298 n_array = va_arg(ap, unsigned);
4303 case SD_BUS_TYPE_VARIANT: {
4306 s = va_arg(ap, const char *);
4310 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4320 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4325 n_struct = strlen(s);
4326 n_array = (unsigned) -1;
4331 case SD_BUS_TYPE_STRUCT_BEGIN:
4332 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4335 r = signature_element_length(t, &k);
4341 memcpy(s, t + 1, k - 2);
4344 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4354 if (n_array == (unsigned) -1) {
4359 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4365 n_array = (unsigned) -1;
4378 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4382 assert_return(m, -EINVAL);
4383 assert_return(m->sealed, -EPERM);
4384 assert_return(types, -EINVAL);
4386 va_start(ap, types);
4387 r = message_read_ap(m, types, ap);
4393 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4396 assert_return(m, -EINVAL);
4397 assert_return(m->sealed, -EPERM);
4398 assert_return(types, -EINVAL);
4405 case SD_BUS_TYPE_BYTE:
4406 case SD_BUS_TYPE_BOOLEAN:
4407 case SD_BUS_TYPE_INT16:
4408 case SD_BUS_TYPE_UINT16:
4409 case SD_BUS_TYPE_INT32:
4410 case SD_BUS_TYPE_UINT32:
4411 case SD_BUS_TYPE_INT64:
4412 case SD_BUS_TYPE_UINT64:
4413 case SD_BUS_TYPE_DOUBLE:
4414 case SD_BUS_TYPE_STRING:
4415 case SD_BUS_TYPE_OBJECT_PATH:
4416 case SD_BUS_TYPE_SIGNATURE:
4417 case SD_BUS_TYPE_UNIX_FD:
4419 r = sd_bus_message_read_basic(m, *types, NULL);
4423 r = sd_bus_message_skip(m, types + 1);
4429 case SD_BUS_TYPE_ARRAY: {
4432 r = signature_element_length(types + 1, &k);
4438 memcpy(s, types+1, k);
4441 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4446 r = sd_bus_message_skip(m, s);
4453 r = sd_bus_message_exit_container(m);
4458 r = sd_bus_message_skip(m, types + 1 + k);
4465 case SD_BUS_TYPE_VARIANT: {
4466 const char *contents;
4469 r = sd_bus_message_peek_type(m, &x, &contents);
4473 if (x != SD_BUS_TYPE_VARIANT)
4476 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4480 r = sd_bus_message_skip(m, contents);
4485 r = sd_bus_message_exit_container(m);
4489 r = sd_bus_message_skip(m, types + 1);
4496 case SD_BUS_TYPE_STRUCT_BEGIN:
4497 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4500 r = signature_element_length(types, &k);
4506 memcpy(s, types+1, k-2);
4509 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4513 r = sd_bus_message_skip(m, s);
4518 r = sd_bus_message_exit_container(m);
4523 r = sd_bus_message_skip(m, types + k);
4535 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4539 struct bus_container *c;
4545 assert_return(m, -EINVAL);
4546 assert_return(m->sealed, -EPERM);
4547 assert_return(bus_type_is_trivial(type), -EINVAL);
4548 assert_return(ptr, -EINVAL);
4549 assert_return(size, -EINVAL);
4550 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4552 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4556 c = message_get_container(m);
4558 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4559 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4563 sz = c->end - c->begin;
4565 align = bus_type_get_alignment(type);
4569 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4573 /* Zero length array, let's return some aligned
4574 * pointer that is not NULL */
4575 p = (uint8_t*) NULL + align;
4577 r = message_peek_body(m, &m->rindex, align, sz, &p);
4582 r = sd_bus_message_exit_container(m);
4586 *ptr = (const void*) p;
4592 message_quit_container(m);
4596 static int message_peek_fields(
4607 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4610 static int message_peek_field_uint32(
4622 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4625 /* identical for gvariant and dbus1 */
4627 r = message_peek_fields(m, ri, 4, 4, &q);
4632 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4637 static int message_peek_field_string(
4639 bool (*validate)(const char *p),
4651 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4656 r = message_peek_fields(m, ri, 1, item_size, &q);
4662 r = message_peek_field_uint32(m, ri, 4, &l);
4666 r = message_peek_fields(m, ri, 1, l+1, &q);
4672 if (!validate_nul(q, l))
4678 if (!validate_string(q, l))
4688 static int message_peek_field_signature(
4701 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4706 r = message_peek_fields(m, ri, 1, item_size, &q);
4712 r = message_peek_fields(m, ri, 1, 1, &q);
4717 r = message_peek_fields(m, ri, 1, l+1, &q);
4722 if (!validate_signature(q, l))
4731 static int message_skip_fields(
4734 uint32_t array_size,
4735 const char **signature) {
4737 size_t original_index;
4743 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4745 original_index = *ri;
4751 if (array_size != (uint32_t) -1 &&
4752 array_size <= *ri - original_index)
4759 if (t == SD_BUS_TYPE_STRING) {
4761 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4767 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4769 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4775 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4777 r = message_peek_field_signature(m, ri, 0, NULL);
4783 } else if (bus_type_is_basic(t)) {
4786 align = bus_type_get_alignment(t);
4787 k = bus_type_get_size(t);
4788 assert(align > 0 && k > 0);
4790 r = message_peek_fields(m, ri, align, k, NULL);
4796 } else if (t == SD_BUS_TYPE_ARRAY) {
4798 r = signature_element_length(*signature+1, &l);
4808 strncpy(sig, *signature + 1, l-1);
4811 alignment = bus_type_get_alignment(sig[0]);
4815 r = message_peek_field_uint32(m, ri, 0, &nas);
4818 if (nas > BUS_ARRAY_MAX_SIZE)
4821 r = message_peek_fields(m, ri, alignment, 0, NULL);
4825 r = message_skip_fields(m, ri, nas, (const char**) &s);
4830 (*signature) += 1 + l;
4832 } else if (t == SD_BUS_TYPE_VARIANT) {
4835 r = message_peek_field_signature(m, ri, 0, &s);
4839 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4845 } else if (t == SD_BUS_TYPE_STRUCT ||
4846 t == SD_BUS_TYPE_DICT_ENTRY) {
4848 r = signature_element_length(*signature, &l);
4855 strncpy(sig, *signature + 1, l-1);
4858 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4869 int bus_message_parse_fields(sd_bus_message *m) {
4872 uint32_t unix_fds = 0;
4873 void *offsets = NULL;
4874 unsigned n_offsets = 0;
4880 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4883 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4887 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4888 r = message_peek_fields(m, &ri, 1, sz, &q);
4892 framing = read_word_le(q, sz);
4893 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4895 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4899 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4903 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4908 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4909 _cleanup_free_ char *sig = NULL;
4910 const char *signature;
4912 size_t item_size = (size_t) -1;
4914 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4921 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4924 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4928 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4933 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4938 where = ri = ALIGN_TO(ri, 8);
4939 item_size = end - ri;
4940 r = message_peek_fields(m, &where, 1, item_size, &q);
4944 b = memrchr(q, 0, item_size);
4948 sig = strndup(b+1, item_size - (b+1-(char*) q));
4953 item_size = b - (char*) q;
4955 r = message_peek_field_signature(m, &ri, 0, &signature);
4961 case _BUS_MESSAGE_HEADER_INVALID:
4964 case BUS_MESSAGE_HEADER_PATH:
4969 if (!streq(signature, "o"))
4972 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
4975 case BUS_MESSAGE_HEADER_INTERFACE:
4980 if (!streq(signature, "s"))
4983 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
4986 case BUS_MESSAGE_HEADER_MEMBER:
4991 if (!streq(signature, "s"))
4994 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
4997 case BUS_MESSAGE_HEADER_ERROR_NAME:
5002 if (!streq(signature, "s"))
5005 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5007 m->error._need_free = -1;
5011 case BUS_MESSAGE_HEADER_DESTINATION:
5016 if (!streq(signature, "s"))
5019 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5022 case BUS_MESSAGE_HEADER_SENDER:
5027 if (!streq(signature, "s"))
5030 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5032 if (r >= 0 && m->sender[0] == ':' && m->bus && m->bus->bus_client && !m->bus->is_kernel) {
5033 m->creds.unique_name = (char*) m->sender;
5034 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5040 case BUS_MESSAGE_HEADER_SIGNATURE: {
5044 if (m->root_container.signature)
5047 if (!streq(signature, "g"))
5050 r = message_peek_field_signature(m, &ri, item_size, &s);
5058 free(m->root_container.signature);
5059 m->root_container.signature = c;
5063 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5064 if (m->reply_serial != 0)
5067 if (!streq(signature, "u"))
5070 r = message_peek_field_uint32(m, &ri, item_size, &m->reply_serial);
5074 if (m->reply_serial == 0)
5079 case BUS_MESSAGE_HEADER_UNIX_FDS:
5083 if (!streq(signature, "u"))
5086 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5096 if (!BUS_MESSAGE_IS_GVARIANT(m))
5097 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5106 if (m->n_fds != unix_fds)
5109 switch (m->header->type) {
5111 case SD_BUS_MESSAGE_SIGNAL:
5112 if (!m->path || !m->interface || !m->member)
5116 case SD_BUS_MESSAGE_METHOD_CALL:
5118 if (!m->path || !m->member)
5123 case SD_BUS_MESSAGE_METHOD_RETURN:
5125 if (m->reply_serial == 0)
5129 case SD_BUS_MESSAGE_METHOD_ERROR:
5131 if (m->reply_serial == 0 || !m->error.name)
5136 /* Refuse non-local messages that claim they are local */
5137 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5139 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5141 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5144 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5146 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5147 r = build_struct_offsets(
5149 m->root_container.signature,
5150 BUS_MESSAGE_BODY_SIZE(m),
5151 &m->root_container.item_size,
5152 &m->root_container.offsets,
5153 &m->root_container.n_offsets);
5158 /* Try to read the error message, but if we can't it's a non-issue */
5159 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5160 sd_bus_message_read(m, "s", &m->error.message);
5165 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5166 assert_return(m, -EINVAL);
5167 assert_return(destination, -EINVAL);
5168 assert_return(!m->sealed, -EPERM);
5169 assert_return(!m->destination, -EEXIST);
5171 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5174 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5178 struct bus_body_part *part;
5184 total = BUS_MESSAGE_SIZE(m);
5190 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5191 MESSAGE_FOREACH_PART(part, i, m)
5192 e = mempcpy(e, part->data, part->size);
5194 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5202 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5208 r = sd_bus_message_enter_container(m, 'a', "s");
5215 r = sd_bus_message_read_basic(m, 's', &s);
5221 r = strv_extend(l, s);
5226 r = sd_bus_message_exit_container(m);
5233 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5237 assert_return(m, -EINVAL);
5238 assert_return(m->sealed, -EPERM);
5239 assert_return(l, -EINVAL);
5241 r = bus_message_read_strv_extend(m, &strv);
5251 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5253 const char *t = NULL;
5258 r = sd_bus_message_rewind(m, true);
5262 for (j = 0; j <= i; j++) {
5265 r = sd_bus_message_peek_type(m, &type, NULL);
5269 if (type != SD_BUS_TYPE_STRING &&
5270 type != SD_BUS_TYPE_OBJECT_PATH &&
5271 type != SD_BUS_TYPE_SIGNATURE)
5274 r = sd_bus_message_read_basic(m, type, &t);
5282 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5288 if (size < sizeof(struct bus_header))
5291 full = sizeof(struct bus_header) +
5292 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5294 return size >= full;
5297 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5303 if (h->endian == BUS_NATIVE_ENDIAN) {
5304 fs = h->fields_size;
5306 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5307 fs = bswap_32(h->fields_size);
5308 bs = bswap_32(h->body_size);
5312 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5316 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5317 assert_return(m, -EINVAL);
5319 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5322 return sd_bus_error_get_errno(&m->error);
5325 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5326 struct bus_container *c;
5328 assert_return(m, NULL);
5330 c = complete ? &m->root_container : message_get_container(m);
5331 return strempty(c->signature);
5334 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5335 bool done_something = false;
5338 assert_return(m, -EINVAL);
5339 assert_return(source, -EINVAL);
5340 assert_return(!m->sealed, -EPERM);
5341 assert_return(source->sealed, -EPERM);
5344 const char *contents;
5359 r = sd_bus_message_peek_type(source, &type, &contents);
5365 done_something = true;
5367 if (bus_type_is_container(type) > 0) {
5369 r = sd_bus_message_enter_container(source, type, contents);
5373 r = sd_bus_message_open_container(m, type, contents);
5377 r = sd_bus_message_copy(m, source, true);
5381 r = sd_bus_message_close_container(m);
5385 r = sd_bus_message_exit_container(source);
5392 r = sd_bus_message_read_basic(source, type, &basic);
5398 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5399 type == SD_BUS_TYPE_SIGNATURE ||
5400 type == SD_BUS_TYPE_STRING)
5401 r = sd_bus_message_append_basic(m, type, basic.string);
5403 r = sd_bus_message_append_basic(m, type, &basic);
5410 return done_something;
5413 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5418 assert_return(m, -EINVAL);
5419 assert_return(m->sealed, -EPERM);
5420 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5421 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5422 assert_return(type || contents, -EINVAL);
5423 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5425 r = sd_bus_message_peek_type(m, &t, &c);
5429 if (type != 0 && type != t)
5432 if (contents && !streq_ptr(contents, c))
5438 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5439 assert_return(m, NULL);
5444 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5445 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5453 switch ((*m)->header->type) {
5455 case SD_BUS_MESSAGE_SIGNAL:
5456 r = sd_bus_message_new_signal(bus, (*m)->path, (*m)->interface, (*m)->member, &n);
5462 case SD_BUS_MESSAGE_METHOD_CALL:
5463 r = sd_bus_message_new_method_call(bus, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member, &n);
5469 case SD_BUS_MESSAGE_METHOD_RETURN:
5470 case SD_BUS_MESSAGE_METHOD_ERROR:
5472 n = message_new(bus, (*m)->header->type);
5476 n->reply_serial = (*m)->reply_serial;
5477 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, n->reply_serial);
5481 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5482 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5486 n->error._need_free = -1;
5495 if ((*m)->destination && !n->destination) {
5496 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5501 if ((*m)->sender && !n->sender) {
5502 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5507 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5509 r = sd_bus_message_copy(n, *m, true);
5513 timeout = (*m)->timeout;
5514 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5515 timeout = BUS_DEFAULT_TIMEOUT;
5517 r = bus_message_seal(n, (*m)->header->serial, timeout);
5521 sd_bus_message_unref(*m);