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 safe_close(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);
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->root_container.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 memzero((uint8_t*) np + old_size, 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;
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;
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) {
493 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
498 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
499 m->header->endian = BUS_NATIVE_ENDIAN;
500 m->header->type = type;
501 m->header->version = bus ? bus->message_version : 1;
502 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
503 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(
513 const char *interface,
514 const char *member) {
519 assert_return(bus, -ENOTCONN);
520 assert_return(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(
553 const char *destination,
555 const char *interface,
556 const char *member) {
561 assert_return(bus, -ENOTCONN);
562 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
563 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
564 assert_return(object_path_is_valid(path), -EINVAL);
565 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
566 assert_return(member_name_is_valid(member), -EINVAL);
567 assert_return(m, -EINVAL);
569 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
573 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
576 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
581 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
587 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
600 static int message_new_reply(
601 sd_bus_message *call,
603 sd_bus_message **m) {
608 assert_return(call, -EINVAL);
609 assert_return(call->sealed, -EPERM);
610 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
611 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
612 assert_return(m, -EINVAL);
614 t = message_new(call->bus, type);
618 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
619 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
621 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
626 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
631 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
632 t->enforced_reply_signature = call->enforced_reply_signature;
642 _public_ int sd_bus_message_new_method_return(
643 sd_bus_message *call,
644 sd_bus_message **m) {
646 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
649 _public_ int sd_bus_message_new_method_error(
650 sd_bus_message *call,
652 const sd_bus_error *e) {
657 assert_return(sd_bus_error_is_set(e), -EINVAL);
658 assert_return(m, -EINVAL);
660 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
664 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
669 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
674 t->error._need_free = -1;
684 _public_ int sd_bus_message_new_method_errorf(
685 sd_bus_message *call,
691 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
694 assert_return(name, -EINVAL);
695 assert_return(m, -EINVAL);
697 va_start(ap, format);
698 bus_error_setfv(&error, name, format, ap);
701 return sd_bus_message_new_method_error(call, m, &error);
704 _public_ int sd_bus_message_new_method_errno(
705 sd_bus_message *call,
708 const sd_bus_error *p) {
710 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
712 if (sd_bus_error_is_set(p))
713 return sd_bus_message_new_method_error(call, m, p);
715 sd_bus_error_set_errno(&berror, error);
717 return sd_bus_message_new_method_error(call, m, &berror);
720 _public_ int sd_bus_message_new_method_errnof(
721 sd_bus_message *call,
727 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
730 va_start(ap, format);
731 bus_error_set_errnofv(&berror, error, format, ap);
734 return sd_bus_message_new_method_error(call, m, &berror);
737 int bus_message_new_synthetic_error(
740 const sd_bus_error *e,
741 sd_bus_message **m) {
747 assert(sd_bus_error_is_set(e));
750 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
754 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
755 t->reply_cookie = cookie;
757 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
761 if (bus && bus->unique_name) {
762 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
767 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
772 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
777 t->error._need_free = -1;
787 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
788 assert_return(m, NULL);
790 assert(m->n_ref > 0);
796 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
801 assert(m->n_ref > 0);
810 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
811 assert_return(m, -EINVAL);
812 assert_return(type, -EINVAL);
814 *type = m->header->type;
818 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
819 assert_return(m, -EINVAL);
820 assert_return(cookie, -EINVAL);
821 assert_return(m->header->serial != 0, -ENODATA);
823 *cookie = BUS_MESSAGE_COOKIE(m);
827 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
828 assert_return(m, -EINVAL);
829 assert_return(cookie, -EINVAL);
830 assert_return(m->reply_cookie != 0, -ENODATA);
832 *cookie = m->reply_cookie;
836 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
837 assert_return(m, -EINVAL);
839 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
840 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
843 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
844 assert_return(m, -EINVAL);
846 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
849 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
850 assert_return(m, NULL);
855 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
856 assert_return(m, NULL);
861 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
862 assert_return(m, NULL);
867 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
868 assert_return(m, NULL);
870 return m->destination;
873 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
874 assert_return(m, NULL);
879 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
880 assert_return(m, NULL);
881 assert_return(sd_bus_error_is_set(&m->error), NULL);
886 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
887 assert_return(m, -EINVAL);
888 assert_return(usec, -EINVAL);
890 if (m->monotonic <= 0)
893 *usec = m->monotonic;
897 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
898 assert_return(m, -EINVAL);
899 assert_return(usec, -EINVAL);
901 if (m->realtime <= 0)
908 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
909 assert_return(m, -EINVAL);
910 assert_return(seqnum, -EINVAL);
919 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
920 assert_return(m, NULL);
922 if (m->creds.mask == 0)
928 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
929 const char *interface,
930 const char *member) {
931 assert_return(m, -EINVAL);
933 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
936 if (interface && (!m->interface || !streq(m->interface, interface)))
939 if (member && (!m->member || !streq(m->member, member)))
945 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
946 const char *interface,
947 const char *member) {
948 assert_return(m, -EINVAL);
950 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
953 if (interface && (!m->interface || !streq(m->interface, interface)))
956 if (member && (!m->member || !streq(m->member, member)))
962 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
963 assert_return(m, -EINVAL);
965 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
968 if (name && (!m->error.name || !streq(m->error.name, name)))
974 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
975 assert_return(m, -EINVAL);
976 assert_return(!m->sealed, -EPERM);
977 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
980 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
982 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
987 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
988 assert_return(m, -EINVAL);
989 assert_return(!m->sealed, -EPERM);
992 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
994 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
999 static struct bus_container *message_get_container(sd_bus_message *m) {
1002 if (m->n_containers == 0)
1003 return &m->root_container;
1005 assert(m->containers);
1006 return m->containers + m->n_containers - 1;
1009 struct bus_body_part *message_append_part(sd_bus_message *m) {
1010 struct bus_body_part *part;
1017 if (m->n_body_parts <= 0) {
1021 assert(m->body_end);
1023 part = new0(struct bus_body_part, 1);
1029 m->body_end->next = part;
1039 static void part_zero(struct bus_body_part *part, size_t sz) {
1044 /* All other fields can be left in their defaults */
1045 assert(!part->data);
1046 assert(part->memfd < 0);
1049 part->is_zero = true;
1050 part->sealed = true;
1053 static int part_make_space(
1054 struct sd_bus_message *m,
1055 struct bus_body_part *part,
1064 assert(!part->sealed);
1069 if (!part->data && part->memfd < 0)
1070 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1072 if (part->memfd >= 0) {
1074 if (part->allocated == 0 || sz > part->allocated) {
1075 uint64_t new_allocated;
1077 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1078 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &new_allocated);
1084 part->allocated = new_allocated;
1087 if (!part->data || sz > part->mapped) {
1090 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1091 if (part->mapped <= 0)
1092 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1094 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1096 if (n == MAP_FAILED) {
1105 part->munmap_this = true;
1107 if (part->allocated == 0 || sz > part->allocated) {
1108 size_t new_allocated;
1110 new_allocated = sz > 0 ? 2 * sz : 64;
1111 n = realloc(part->data, new_allocated);
1118 part->allocated = new_allocated;
1119 part->free_this = true;
1124 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1130 static int message_add_offset(sd_bus_message *m, size_t offset) {
1131 struct bus_container *c;
1134 assert(BUS_MESSAGE_IS_GVARIANT(m));
1136 /* Add offset to current container, unless this is the first
1137 * item in it, which will have the 0 offset, which we can
1139 c = message_get_container(m);
1141 if (!c->need_offsets)
1144 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1147 c->offsets[c->n_offsets++] = offset;
1151 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1152 struct bus_container *c;
1159 /* Update counters */
1160 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1163 *c->array_size += expand;
1167 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1168 size_t start_body, end_body, padding, added;
1179 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1180 end_body = start_body + sz;
1182 padding = start_body - m->header->body_size;
1183 added = padding + sz;
1185 /* Check for 32bit overflows */
1186 if (end_body > (size_t) ((uint32_t) -1)) {
1192 struct bus_body_part *part = NULL;
1196 m->n_body_parts <= 0 ||
1197 m->body_end->sealed ||
1198 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1202 part = message_append_part(m);
1206 part_zero(part, padding);
1209 part = message_append_part(m);
1213 r = part_make_space(m, part, sz, &p);
1217 struct bus_container *c;
1219 size_t os, start_part, end_part;
1225 start_part = ALIGN_TO(part->size, align);
1226 end_part = start_part + sz;
1228 r = part_make_space(m, part, end_part, &p);
1233 memzero(p, padding);
1234 p = (uint8_t*) p + padding;
1237 /* Readjust pointers */
1238 for (c = m->containers; c < m->containers + m->n_containers; c++)
1239 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1241 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1244 /* Return something that is not NULL and is aligned */
1245 p = (uint8_t *) NULL + align;
1247 m->header->body_size = end_body;
1248 message_extend_containers(m, added);
1251 r = message_add_offset(m, end_body);
1261 static int message_push_fd(sd_bus_message *m, int fd) {
1272 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1276 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1284 m->fds[m->n_fds] = copy;
1290 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1291 _cleanup_close_ int fd = -1;
1292 struct bus_container *c;
1296 assert_return(m, -EINVAL);
1297 assert_return(!m->sealed, -EPERM);
1298 assert_return(bus_type_is_basic(type), -EINVAL);
1299 assert_return(!m->poisoned, -ESTALE);
1301 c = message_get_container(m);
1303 if (c->signature && c->signature[c->index]) {
1304 /* Container signature is already set */
1306 if (c->signature[c->index] != type)
1311 /* Maybe we can append to the signature? But only if this is the top-level container*/
1312 if (c->enclosing != 0)
1315 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1322 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1328 case SD_BUS_TYPE_SIGNATURE:
1329 case SD_BUS_TYPE_STRING:
1332 /* Fall through... */
1333 case SD_BUS_TYPE_OBJECT_PATH:
1341 case SD_BUS_TYPE_BOOLEAN:
1343 u8 = p && *(int*) p;
1349 case SD_BUS_TYPE_UNIX_FD:
1354 fd = message_push_fd(m, *(int*) p);
1365 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1366 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1373 a = message_extend_body(m, align, sz, true);
1380 *stored = (const uint8_t*) a;
1387 case SD_BUS_TYPE_STRING:
1388 /* To make things easy we'll serialize a NULL string
1389 * into the empty string */
1392 /* Fall through... */
1393 case SD_BUS_TYPE_OBJECT_PATH:
1399 sz = 4 + strlen(p) + 1;
1402 case SD_BUS_TYPE_SIGNATURE:
1407 sz = 1 + strlen(p) + 1;
1410 case SD_BUS_TYPE_BOOLEAN:
1412 u32 = p && *(int*) p;
1418 case SD_BUS_TYPE_UNIX_FD:
1423 fd = message_push_fd(m, *(int*) p);
1434 align = bus_type_get_alignment(type);
1435 sz = bus_type_get_size(type);
1442 a = message_extend_body(m, align, sz, false);
1446 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1447 *(uint32_t*) a = sz - 5;
1448 memcpy((uint8_t*) a + 4, p, sz - 4);
1451 *stored = (const uint8_t*) a + 4;
1453 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1454 *(uint8_t*) a = sz - 2;
1455 memcpy((uint8_t*) a + 1, p, sz - 1);
1458 *stored = (const uint8_t*) a + 1;
1467 if (type == SD_BUS_TYPE_UNIX_FD)
1470 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1477 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1478 return message_append_basic(m, type, p, NULL);
1481 _public_ int sd_bus_message_append_string_space(
1486 struct bus_container *c;
1489 assert_return(m, -EINVAL);
1490 assert_return(s, -EINVAL);
1491 assert_return(!m->sealed, -EPERM);
1492 assert_return(!m->poisoned, -ESTALE);
1494 c = message_get_container(m);
1496 if (c->signature && c->signature[c->index]) {
1497 /* Container signature is already set */
1499 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1504 /* Maybe we can append to the signature? But only if this is the top-level container*/
1505 if (c->enclosing != 0)
1508 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1515 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1516 a = message_extend_body(m, 1, size + 1, true);
1522 a = message_extend_body(m, 4, 4 + size + 1, false);
1526 *(uint32_t*) a = size;
1532 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1538 _public_ int sd_bus_message_append_string_iovec(
1540 const struct iovec *iov,
1548 assert_return(m, -EINVAL);
1549 assert_return(!m->sealed, -EPERM);
1550 assert_return(iov || n == 0, -EINVAL);
1551 assert_return(!m->poisoned, -ESTALE);
1553 size = IOVEC_TOTAL_SIZE(iov, n);
1555 r = sd_bus_message_append_string_space(m, size, &p);
1559 for (i = 0; i < n; i++) {
1561 if (iov[i].iov_base)
1562 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1564 memset(p, ' ', iov[i].iov_len);
1566 p += iov[i].iov_len;
1572 static int bus_message_open_array(
1574 struct bus_container *c,
1575 const char *contents,
1576 uint32_t **array_size,
1578 bool *need_offsets) {
1588 assert(need_offsets);
1590 if (!signature_is_single(contents, true))
1593 if (c->signature && c->signature[c->index]) {
1595 /* Verify the existing signature */
1597 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1600 if (!startswith(c->signature + c->index + 1, contents))
1603 nindex = c->index + 1 + strlen(contents);
1607 if (c->enclosing != 0)
1610 /* Extend the existing signature */
1612 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1618 nindex = e - c->signature;
1621 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1622 alignment = bus_gvariant_get_alignment(contents);
1626 /* Add alignment padding and add to offset list */
1627 if (!message_extend_body(m, alignment, 0, false))
1630 r = bus_gvariant_is_fixed_size(contents);
1634 *begin = m->header->body_size;
1635 *need_offsets = r == 0;
1639 struct bus_body_part *o;
1641 alignment = bus_type_get_alignment(contents[0]);
1645 a = message_extend_body(m, 4, 4, false);
1650 op = m->body_end->data;
1651 os = m->body_end->size;
1653 /* Add alignment between size and first element */
1654 if (!message_extend_body(m, alignment, 0, false))
1657 /* location of array size might have changed so let's readjust a */
1658 if (o == m->body_end)
1659 a = adjust_pointer(a, op, os, m->body_end->data);
1665 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1671 static int bus_message_open_variant(
1673 struct bus_container *c,
1674 const char *contents) {
1680 if (!signature_is_single(contents, false))
1683 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1686 if (c->signature && c->signature[c->index]) {
1688 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1694 if (c->enclosing != 0)
1697 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1704 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1705 /* Variants are always aligned to 8 */
1707 if (!message_extend_body(m, 8, 0, false))
1714 l = strlen(contents);
1715 a = message_extend_body(m, 1, 1 + l + 1, false);
1720 memcpy((uint8_t*) a + 1, contents, l + 1);
1723 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1729 static int bus_message_open_struct(
1731 struct bus_container *c,
1732 const char *contents,
1734 bool *need_offsets) {
1743 assert(need_offsets);
1745 if (!signature_is_valid(contents, false))
1748 if (c->signature && c->signature[c->index]) {
1751 l = strlen(contents);
1753 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1754 !startswith(c->signature + c->index + 1, contents) ||
1755 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1758 nindex = c->index + 1 + l + 1;
1762 if (c->enclosing != 0)
1765 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1771 nindex = e - c->signature;
1774 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1777 alignment = bus_gvariant_get_alignment(contents);
1781 if (!message_extend_body(m, alignment, 0, false))
1784 r = bus_gvariant_is_fixed_size(contents);
1788 *begin = m->header->body_size;
1789 *need_offsets = r == 0;
1791 /* Align contents to 8 byte boundary */
1792 if (!message_extend_body(m, 8, 0, false))
1796 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1802 static int bus_message_open_dict_entry(
1804 struct bus_container *c,
1805 const char *contents,
1807 bool *need_offsets) {
1815 assert(need_offsets);
1817 if (!signature_is_pair(contents))
1820 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1823 if (c->signature && c->signature[c->index]) {
1826 l = strlen(contents);
1828 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1829 !startswith(c->signature + c->index + 1, contents) ||
1830 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1835 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1838 alignment = bus_gvariant_get_alignment(contents);
1842 if (!message_extend_body(m, alignment, 0, false))
1845 r = bus_gvariant_is_fixed_size(contents);
1849 *begin = m->header->body_size;
1850 *need_offsets = r == 0;
1852 /* Align contents to 8 byte boundary */
1853 if (!message_extend_body(m, 8, 0, false))
1860 _public_ int sd_bus_message_open_container(
1863 const char *contents) {
1865 struct bus_container *c, *w;
1866 uint32_t *array_size = NULL;
1868 size_t before, begin = 0;
1869 bool need_offsets = false;
1872 assert_return(m, -EINVAL);
1873 assert_return(!m->sealed, -EPERM);
1874 assert_return(contents, -EINVAL);
1875 assert_return(!m->poisoned, -ESTALE);
1877 /* Make sure we have space for one more container */
1878 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1883 c = message_get_container(m);
1885 signature = strdup(contents);
1891 /* Save old index in the parent container, in case we have to
1892 * abort this container */
1893 c->saved_index = c->index;
1894 before = m->header->body_size;
1896 if (type == SD_BUS_TYPE_ARRAY)
1897 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1898 else if (type == SD_BUS_TYPE_VARIANT)
1899 r = bus_message_open_variant(m, c, contents);
1900 else if (type == SD_BUS_TYPE_STRUCT)
1901 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1902 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1903 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1912 /* OK, let's fill it in */
1913 w = m->containers + m->n_containers++;
1914 w->enclosing = type;
1915 w->signature = signature;
1917 w->array_size = array_size;
1920 w->n_offsets = w->offsets_allocated = 0;
1922 w->need_offsets = need_offsets;
1927 static size_t determine_word_size(size_t sz, size_t extra) {
1928 if (sz + extra <= 0xFF)
1930 else if (sz + extra*2 <= 0xFFFF)
1932 else if (sz + extra*4 <= 0xFFFFFFFF)
1938 static size_t read_word_le(void *p, size_t sz) {
1948 return *(uint8_t*) p;
1953 return le16toh(x.u16);
1955 return le32toh(x.u32);
1957 return le64toh(x.u64);
1959 assert_not_reached("unknown word width");
1962 static void write_word_le(void *p, size_t sz, size_t value) {
1970 assert(sz == 8 || (value < (1ULL << (sz*8))));
1973 *(uint8_t*) p = value;
1976 x.u16 = htole16((uint16_t) value);
1978 x.u32 = htole32((uint32_t) value);
1980 x.u64 = htole64((uint64_t) value);
1982 assert_not_reached("unknown word width");
1987 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1992 if (!BUS_MESSAGE_IS_GVARIANT(m))
1995 if (c->need_offsets) {
1996 size_t payload, sz, i;
1999 /* Variable-width arrays */
2001 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2002 sz = determine_word_size(payload, c->n_offsets);
2004 a = message_extend_body(m, 1, sz * c->n_offsets, true);
2008 for (i = 0; i < c->n_offsets; i++)
2009 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2013 /* Fixed-width or empty arrays */
2015 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
2023 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2030 if (!BUS_MESSAGE_IS_GVARIANT(m))
2033 l = strlen(c->signature);
2035 a = message_extend_body(m, 1, 1 + l, true);
2040 memcpy(a+1, c->signature, l);
2045 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2046 size_t n_variable = 0;
2055 if (!BUS_MESSAGE_IS_GVARIANT(m))
2058 p = strempty(c->signature);
2062 r = signature_element_length(p, &n);
2071 r = bus_gvariant_is_fixed_size(t);
2076 assert(!c->need_offsets || i <= c->n_offsets);
2078 /* We need to add an offset for each item that has a
2079 * variable size and that is not the last one in the
2081 if (r == 0 && p[n] != 0)
2088 assert(!c->need_offsets || i == c->n_offsets);
2089 assert(c->need_offsets || n_variable == 0);
2091 if (n_variable <= 0) {
2092 a = message_extend_body(m, 1, 0, add_offset);
2099 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2101 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2103 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2107 p = strempty(c->signature);
2108 for (i = 0, j = 0; i < c->n_offsets; i++) {
2112 r = signature_element_length(p, &n);
2123 r = bus_gvariant_is_fixed_size(t);
2126 if (r > 0 || p[0] == 0)
2130 k = n_variable - 1 - j;
2132 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2141 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2142 struct bus_container *c;
2145 assert_return(m, -EINVAL);
2146 assert_return(!m->sealed, -EPERM);
2147 assert_return(m->n_containers > 0, -EINVAL);
2148 assert_return(!m->poisoned, -ESTALE);
2150 c = message_get_container(m);
2152 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2153 if (c->signature && c->signature[c->index] != 0)
2158 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2159 r = bus_message_close_array(m, c);
2160 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2161 r = bus_message_close_variant(m, c);
2162 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2163 r = bus_message_close_struct(m, c, true);
2165 assert_not_reached("Unknown container type");
2179 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2186 stack[*i].types = types;
2187 stack[*i].n_struct = n_struct;
2188 stack[*i].n_array = n_array;
2194 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2205 *types = stack[*i].types;
2206 *n_struct = stack[*i].n_struct;
2207 *n_array = stack[*i].n_array;
2212 int bus_message_append_ap(
2217 unsigned n_array, n_struct;
2218 TypeStack stack[BUS_CONTAINER_DEPTH];
2219 unsigned stack_ptr = 0;
2227 n_array = (unsigned) -1;
2228 n_struct = strlen(types);
2233 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2234 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2240 r = sd_bus_message_close_container(m);
2248 if (n_array != (unsigned) -1)
2257 case SD_BUS_TYPE_BYTE: {
2260 x = (uint8_t) va_arg(ap, int);
2261 r = sd_bus_message_append_basic(m, *t, &x);
2265 case SD_BUS_TYPE_BOOLEAN:
2266 case SD_BUS_TYPE_INT32:
2267 case SD_BUS_TYPE_UINT32:
2268 case SD_BUS_TYPE_UNIX_FD: {
2271 /* We assume a boolean is the same as int32_t */
2272 assert_cc(sizeof(int32_t) == sizeof(int));
2274 x = va_arg(ap, uint32_t);
2275 r = sd_bus_message_append_basic(m, *t, &x);
2279 case SD_BUS_TYPE_INT16:
2280 case SD_BUS_TYPE_UINT16: {
2283 x = (uint16_t) va_arg(ap, int);
2284 r = sd_bus_message_append_basic(m, *t, &x);
2288 case SD_BUS_TYPE_INT64:
2289 case SD_BUS_TYPE_UINT64:
2290 case SD_BUS_TYPE_DOUBLE: {
2293 x = va_arg(ap, uint64_t);
2294 r = sd_bus_message_append_basic(m, *t, &x);
2298 case SD_BUS_TYPE_STRING:
2299 case SD_BUS_TYPE_OBJECT_PATH:
2300 case SD_BUS_TYPE_SIGNATURE: {
2303 x = va_arg(ap, const char*);
2304 r = sd_bus_message_append_basic(m, *t, x);
2308 case SD_BUS_TYPE_ARRAY: {
2311 r = signature_element_length(t + 1, &k);
2317 memcpy(s, t + 1, k);
2320 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2325 if (n_array == (unsigned) -1) {
2330 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2336 n_array = va_arg(ap, unsigned);
2341 case SD_BUS_TYPE_VARIANT: {
2344 s = va_arg(ap, const char*);
2348 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2352 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2357 n_struct = strlen(s);
2358 n_array = (unsigned) -1;
2363 case SD_BUS_TYPE_STRUCT_BEGIN:
2364 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2367 r = signature_element_length(t, &k);
2374 memcpy(s, t + 1, k - 2);
2377 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2382 if (n_array == (unsigned) -1) {
2387 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2393 n_array = (unsigned) -1;
2409 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2413 assert_return(m, -EINVAL);
2414 assert_return(types, -EINVAL);
2415 assert_return(!m->sealed, -EPERM);
2416 assert_return(!m->poisoned, -ESTALE);
2418 va_start(ap, types);
2419 r = bus_message_append_ap(m, types, ap);
2425 _public_ int sd_bus_message_append_array_space(
2435 assert_return(m, -EINVAL);
2436 assert_return(!m->sealed, -EPERM);
2437 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2438 assert_return(ptr || size == 0, -EINVAL);
2439 assert_return(!m->poisoned, -ESTALE);
2441 /* alignment and size of the trivial types (except bool) is
2442 * identical for gvariant and dbus1 marshalling */
2443 align = bus_type_get_alignment(type);
2444 sz = bus_type_get_size(type);
2446 assert_se(align > 0);
2452 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2456 a = message_extend_body(m, align, size, false);
2460 r = sd_bus_message_close_container(m);
2468 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2475 assert_return(m, -EINVAL);
2476 assert_return(!m->sealed, -EPERM);
2477 assert_return(bus_type_is_trivial(type), -EINVAL);
2478 assert_return(ptr || size == 0, -EINVAL);
2479 assert_return(!m->poisoned, -ESTALE);
2481 r = sd_bus_message_append_array_space(m, type, size, &p);
2486 memcpy(p, ptr, size);
2491 _public_ int sd_bus_message_append_array_iovec(
2494 const struct iovec *iov,
2502 assert_return(m, -EINVAL);
2503 assert_return(!m->sealed, -EPERM);
2504 assert_return(bus_type_is_trivial(type), -EINVAL);
2505 assert_return(iov || n == 0, -EINVAL);
2506 assert_return(!m->poisoned, -ESTALE);
2508 size = IOVEC_TOTAL_SIZE(iov, n);
2510 r = sd_bus_message_append_array_space(m, type, size, &p);
2514 for (i = 0; i < n; i++) {
2516 if (iov[i].iov_base)
2517 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2519 memzero(p, iov[i].iov_len);
2521 p = (uint8_t*) p + iov[i].iov_len;
2527 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2530 _cleanup_close_ int copy_fd = -1;
2531 struct bus_body_part *part;
2543 if (!bus_type_is_trivial(type))
2548 r = sd_memfd_set_sealed(memfd, true);
2552 copy_fd = sd_memfd_dup_fd(memfd);
2556 r = sd_memfd_get_size(memfd, &size);
2560 align = bus_type_get_alignment(type);
2561 sz = bus_type_get_size(type);
2563 assert_se(align > 0);
2569 if (size > (uint64_t) (uint32_t) -1)
2572 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2576 a = message_extend_body(m, align, 0, false);
2580 part = message_append_part(m);
2584 part->memfd = copy_fd;
2585 part->sealed = true;
2589 m->header->body_size += size;
2590 message_extend_containers(m, size);
2592 return sd_bus_message_close_container(m);
2595 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
2596 _cleanup_close_ int copy_fd = -1;
2597 struct bus_body_part *part;
2598 struct bus_container *c;
2603 assert_return(m, -EINVAL);
2604 assert_return(memfd, -EINVAL);
2605 assert_return(!m->sealed, -EPERM);
2606 assert_return(!m->poisoned, -ESTALE);
2608 r = sd_memfd_set_sealed(memfd, true);
2612 copy_fd = sd_memfd_dup_fd(memfd);
2616 r = sd_memfd_get_size(memfd, &size);
2620 /* We require this to be NUL terminated */
2624 if (size > (uint64_t) (uint32_t) -1)
2627 c = message_get_container(m);
2628 if (c->signature && c->signature[c->index]) {
2629 /* Container signature is already set */
2631 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2636 /* Maybe we can append to the signature? But only if this is the top-level container*/
2637 if (c->enclosing != 0)
2640 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2647 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2648 a = message_extend_body(m, 4, 4, false);
2652 *(uint32_t*) a = size - 1;
2655 part = message_append_part(m);
2659 part->memfd = copy_fd;
2660 part->sealed = true;
2664 m->header->body_size += size;
2665 message_extend_containers(m, size);
2667 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2668 r = message_add_offset(m, m->header->body_size);
2675 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2681 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2685 assert_return(m, -EINVAL);
2686 assert_return(!m->sealed, -EPERM);
2687 assert_return(!m->poisoned, -ESTALE);
2689 r = sd_bus_message_open_container(m, 'a', "s");
2693 STRV_FOREACH(i, l) {
2694 r = sd_bus_message_append_basic(m, 's', *i);
2699 return sd_bus_message_close_container(m);
2702 static int bus_message_close_header(sd_bus_message *m) {
2708 if (!BUS_MESSAGE_IS_GVARIANT(m))
2711 if (m->n_header_offsets < 1)
2714 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2716 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2718 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2722 for (i = 0; i < m->n_header_offsets; i++)
2723 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2728 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2729 struct bus_body_part *part;
2739 if (m->n_containers > 0)
2745 /* In vtables the return signature of method calls is listed,
2746 * let's check if they match if this is a response */
2747 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2748 m->enforced_reply_signature &&
2749 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2752 /* If gvariant marshalling is used we need to close the body structure */
2753 r = bus_message_close_struct(m, &m->root_container, false);
2757 /* If there's a non-trivial signature set, then add it in here */
2758 if (!isempty(m->root_container.signature)) {
2759 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2765 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2770 r = bus_message_close_header(m);
2774 m->header->serial = (uint32_t) cookie;
2775 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2777 /* Add padding at the end of the fields part, since we know
2778 * the body needs to start at an 8 byte alignment. We made
2779 * sure we allocated enough space for this, so all we need to
2780 * do here is to zero it out. */
2781 l = BUS_MESSAGE_FIELDS_SIZE(m);
2784 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, a);
2786 /* If this is something we can send as memfd, then let's seal
2787 the memfd now. Note that we can send memfds as payload only
2788 for directed messages, and not for broadcasts. */
2789 if (m->destination && m->bus->use_memfd) {
2790 MESSAGE_FOREACH_PART(part, i, m)
2791 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2794 /* Try to seal it if that makes
2795 * sense. First, unmap our own map to
2796 * make sure we don't keep it busy. */
2797 bus_body_part_unmap(part);
2799 /* Then, sync up real memfd size */
2801 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &sz) < 0)
2804 /* Finally, try to seal */
2805 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
2806 part->sealed = true;
2810 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2811 m->root_container.index = 0;
2812 m->root_container.offset_index = 0;
2813 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2820 int bus_body_part_map(struct bus_body_part *part) {
2829 if (part->size <= 0)
2832 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2833 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2834 static const uint8_t zeroes[7] = { };
2835 part->data = (void*) zeroes;
2839 psz = PAGE_ALIGN(part->size);
2841 if (part->memfd >= 0)
2842 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2843 else if (part->is_zero)
2844 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2848 if (p == MAP_FAILED)
2853 part->munmap_this = true;
2858 void bus_body_part_unmap(struct bus_body_part *part) {
2862 if (part->memfd < 0)
2868 if (!part->munmap_this)
2871 assert_se(munmap(part->data, part->mapped) == 0);
2875 part->munmap_this = false;
2880 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2881 size_t k, start, end;
2886 start = ALIGN_TO((size_t) *rindex, align);
2887 end = start + nbytes;
2892 /* Verify that padding is 0 */
2893 for (k = *rindex; k < start; k++)
2894 if (((const uint8_t*) p)[k] != 0)
2898 *r = (uint8_t*) p + start;
2905 static bool message_end_of_signature(sd_bus_message *m) {
2906 struct bus_container *c;
2910 c = message_get_container(m);
2911 return !c->signature || c->signature[c->index] == 0;
2914 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2915 struct bus_container *c;
2919 c = message_get_container(m);
2920 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2923 if (BUS_MESSAGE_IS_GVARIANT(m))
2924 return index >= c->end;
2926 assert(c->array_size);
2927 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2931 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2932 assert_return(m, -EINVAL);
2933 assert_return(m->sealed, -EPERM);
2935 if (complete && m->n_containers > 0)
2938 if (message_end_of_signature(m))
2941 if (message_end_of_array(m, m->rindex))
2947 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2948 struct bus_body_part *part;
2954 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2955 part = m->cached_rindex_part;
2956 begin = m->cached_rindex_part_begin;
2966 if (index + sz <= begin + part->size) {
2968 r = bus_body_part_map(part);
2973 *p = (uint8_t*) part->data + index - begin;
2975 m->cached_rindex_part = part;
2976 m->cached_rindex_part_begin = begin;
2981 begin += part->size;
2988 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2995 if (!BUS_MESSAGE_IS_GVARIANT(m))
2998 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3001 sz = bus_gvariant_get_size(c->signature);
3005 if (c->offset_index+1 >= c->n_offsets)
3008 /* Variable-size array */
3010 alignment = bus_gvariant_get_alignment(c->signature);
3011 assert(alignment > 0);
3013 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3014 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3017 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3020 /* Fixed-size array */
3021 *rindex = c->begin + (c->offset_index+1) * sz;
3027 } else if (c->enclosing == 0 ||
3028 c->enclosing == SD_BUS_TYPE_STRUCT ||
3029 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3034 if (c->offset_index+1 >= c->n_offsets)
3037 r = signature_element_length(c->signature + c->index, &n);
3041 r = signature_element_length(c->signature + c->index + n, &j);
3046 memcpy(t, c->signature + c->index + n, j);
3049 alignment = bus_gvariant_get_alignment(t);
3052 assert(alignment > 0);
3054 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3055 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3059 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3062 assert_not_reached("Unknown container type");
3067 /* Reached the end */
3074 static int message_peek_body(
3081 size_t k, start, end, padding;
3082 struct bus_body_part *part;
3089 start = ALIGN_TO((size_t) *rindex, align);
3090 padding = start - *rindex;
3091 end = start + nbytes;
3093 if (end > BUS_MESSAGE_BODY_SIZE(m))
3096 part = find_part(m, *rindex, padding, (void**) &q);
3101 /* Verify padding */
3102 for (k = 0; k < padding; k++)
3107 part = find_part(m, start, nbytes, (void**) &q);
3108 if (!part || (nbytes > 0 && !q))
3119 static bool validate_nul(const char *s, size_t l) {
3121 /* Check for NUL chars in the string */
3122 if (memchr(s, 0, l))
3125 /* Check for NUL termination */
3132 static bool validate_string(const char *s, size_t l) {
3134 if (!validate_nul(s, l))
3137 /* Check if valid UTF8 */
3138 if (!utf8_is_valid(s))
3144 static bool validate_signature(const char *s, size_t l) {
3146 if (!validate_nul(s, l))
3149 /* Check if valid signature */
3150 if (!signature_is_valid(s, true))
3156 static bool validate_object_path(const char *s, size_t l) {
3158 if (!validate_nul(s, l))
3161 if (!object_path_is_valid(s))
3167 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3168 struct bus_container *c;
3173 assert_return(m, -EINVAL);
3174 assert_return(m->sealed, -EPERM);
3175 assert_return(bus_type_is_basic(type), -EINVAL);
3177 if (message_end_of_signature(m))
3180 if (message_end_of_array(m, m->rindex))
3183 c = message_get_container(m);
3184 if (c->signature[c->index] != type)
3189 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3191 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3194 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3198 if (type == SD_BUS_TYPE_STRING)
3199 ok = validate_string(q, c->item_size-1);
3200 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3201 ok = validate_object_path(q, c->item_size-1);
3203 ok = validate_signature(q, c->item_size-1);
3209 *(const char**) p = q;
3213 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3215 if ((size_t) sz != c->item_size)
3218 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3221 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3227 case SD_BUS_TYPE_BYTE:
3229 *(uint8_t*) p = *(uint8_t*) q;
3232 case SD_BUS_TYPE_BOOLEAN:
3234 *(int*) p = !!*(uint8_t*) q;
3237 case SD_BUS_TYPE_INT16:
3238 case SD_BUS_TYPE_UINT16:
3240 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3243 case SD_BUS_TYPE_INT32:
3244 case SD_BUS_TYPE_UINT32:
3246 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3249 case SD_BUS_TYPE_INT64:
3250 case SD_BUS_TYPE_UINT64:
3251 case SD_BUS_TYPE_DOUBLE:
3253 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3256 case SD_BUS_TYPE_UNIX_FD: {
3259 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3264 *(int*) p = m->fds[j];
3270 assert_not_reached("unexpected type");
3274 r = container_next_item(m, c, &rindex);
3281 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3285 r = message_peek_body(m, &rindex, 4, 4, &q);
3289 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3290 r = message_peek_body(m, &rindex, 1, l+1, &q);
3294 if (type == SD_BUS_TYPE_OBJECT_PATH)
3295 ok = validate_object_path(q, l);
3297 ok = validate_string(q, l);
3302 *(const char**) p = q;
3304 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3307 r = message_peek_body(m, &rindex, 1, 1, &q);
3312 r = message_peek_body(m, &rindex, 1, l+1, &q);
3316 if (!validate_signature(q, l))
3320 *(const char**) p = q;
3325 align = bus_type_get_alignment(type);
3328 sz = bus_type_get_size(type);
3331 r = message_peek_body(m, &rindex, align, sz, &q);
3337 case SD_BUS_TYPE_BYTE:
3339 *(uint8_t*) p = *(uint8_t*) q;
3342 case SD_BUS_TYPE_BOOLEAN:
3344 *(int*) p = !!*(uint32_t*) q;
3347 case SD_BUS_TYPE_INT16:
3348 case SD_BUS_TYPE_UINT16:
3350 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3353 case SD_BUS_TYPE_INT32:
3354 case SD_BUS_TYPE_UINT32:
3356 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3359 case SD_BUS_TYPE_INT64:
3360 case SD_BUS_TYPE_UINT64:
3361 case SD_BUS_TYPE_DOUBLE:
3363 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3366 case SD_BUS_TYPE_UNIX_FD: {
3369 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3374 *(int*) p = m->fds[j];
3379 assert_not_reached("Unknown basic type...");
3386 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3392 static int bus_message_enter_array(
3394 struct bus_container *c,
3395 const char *contents,
3396 uint32_t **array_size,
3399 size_t *n_offsets) {
3413 if (!signature_is_single(contents, true))
3416 if (!c->signature || c->signature[c->index] == 0)
3419 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3422 if (!startswith(c->signature + c->index + 1, contents))
3427 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3430 r = message_peek_body(m, &rindex, 4, 4, &q);
3434 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3437 alignment = bus_type_get_alignment(contents[0]);
3441 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3445 *array_size = (uint32_t*) q;
3447 } else if (c->item_size <= 0) {
3449 /* gvariant: empty array */
3454 } else if (bus_gvariant_is_fixed_size(contents)) {
3456 /* gvariant: fixed length array */
3457 *item_size = bus_gvariant_get_size(contents);
3462 size_t where, p = 0, framing, sz;
3465 /* gvariant: variable length array */
3466 sz = determine_word_size(c->item_size, 0);
3468 where = rindex + c->item_size - sz;
3469 r = message_peek_body(m, &where, 1, sz, &q);
3473 framing = read_word_le(q, sz);
3474 if (framing > c->item_size - sz)
3476 if ((c->item_size - framing) % sz != 0)
3479 *n_offsets = (c->item_size - framing) / sz;
3481 where = rindex + framing;
3482 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3486 *offsets = new(size_t, *n_offsets);
3490 for (i = 0; i < *n_offsets; i++) {
3493 x = read_word_le((uint8_t*) q + i * sz, sz);
3494 if (x > c->item_size - sz)
3499 (*offsets)[i] = rindex + x;
3503 *item_size = (*offsets)[0] - rindex;
3508 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3509 c->index += 1 + strlen(contents);
3514 static int bus_message_enter_variant(
3516 struct bus_container *c,
3517 const char *contents,
3518 size_t *item_size) {
3530 if (!signature_is_single(contents, false))
3533 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3536 if (!c->signature || c->signature[c->index] == 0)
3539 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3544 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3547 k = strlen(contents);
3548 if (1+k > c->item_size)
3551 where = rindex + c->item_size - (1+k);
3552 r = message_peek_body(m, &where, 1, 1+k, &q);
3556 if (*(char*) q != 0)
3559 if (memcmp((uint8_t*) q+1, contents, k))
3562 *item_size = c->item_size - (1+k);
3565 r = message_peek_body(m, &rindex, 1, 1, &q);
3570 r = message_peek_body(m, &rindex, 1, l+1, &q);
3574 if (!validate_signature(q, l))
3577 if (!streq(q, contents))
3583 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3589 static int build_struct_offsets(
3591 const char *signature,
3595 size_t *n_offsets) {
3597 unsigned n_variable = 0, n_total = 0, v;
3598 size_t previous = 0, where;
3609 if (isempty(signature)) {
3616 sz = determine_word_size(size, 0);
3620 /* First, loop over signature and count variable elements and
3621 * elements in general. We use this to know how large the
3622 * offset array is at the end of the structure. Note that
3623 * GVariant only stores offsets for all variable size elements
3624 * that are not the last item. */
3630 r = signature_element_length(p, &n);
3639 r = bus_gvariant_is_fixed_size(t);
3644 if (r == 0 && p[n] != 0) /* except the last item */
3651 if (size < n_variable * sz)
3654 where = m->rindex + size - (n_variable * sz);
3655 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3661 *offsets = new(size_t, n_total);
3667 /* Second, loop again and build an offset table */
3673 r = signature_element_length(p, &n);
3682 k = bus_gvariant_get_size(t);
3690 x = read_word_le((uint8_t*) q + v*sz, sz);
3693 if (m->rindex + x < previous)
3696 /* The last item's end
3697 * is determined from
3700 x = size - (n_variable * sz);
3702 offset = m->rindex + x;
3708 align = bus_gvariant_get_alignment(t);
3711 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3715 previous = (*offsets)[(*n_offsets)++] = offset;
3720 assert(*n_offsets == n_total);
3722 *item_size = (*offsets)[0] - m->rindex;
3726 static int enter_struct_or_dict_entry(
3728 struct bus_container *c,
3729 const char *contents,
3732 size_t *n_offsets) {
3743 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3746 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3750 } else if (c->item_size <= 0) {
3752 /* gvariant empty struct */
3757 /* gvariant with contents */
3758 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3763 static int bus_message_enter_struct(
3765 struct bus_container *c,
3766 const char *contents,
3769 size_t *n_offsets) {
3781 if (!signature_is_valid(contents, false))
3784 if (!c->signature || c->signature[c->index] == 0)
3787 l = strlen(contents);
3789 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3790 !startswith(c->signature + c->index + 1, contents) ||
3791 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3794 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3798 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3799 c->index += 1 + l + 1;
3804 static int bus_message_enter_dict_entry(
3806 struct bus_container *c,
3807 const char *contents,
3810 size_t *n_offsets) {
3819 if (!signature_is_pair(contents))
3822 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3825 if (!c->signature || c->signature[c->index] == 0)
3828 l = strlen(contents);
3830 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3831 !startswith(c->signature + c->index + 1, contents) ||
3832 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3835 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3839 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3840 c->index += 1 + l + 1;
3845 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3847 const char *contents) {
3848 struct bus_container *c, *w;
3849 uint32_t *array_size = NULL;
3852 size_t *offsets = NULL;
3853 size_t n_offsets = 0, item_size = 0;
3856 assert_return(m, -EINVAL);
3857 assert_return(m->sealed, -EPERM);
3858 assert_return(type != 0 || !contents, -EINVAL);
3860 if (type == 0 || !contents) {
3864 /* Allow entering into anonymous containers */
3865 r = sd_bus_message_peek_type(m, &tt, &cc);
3869 if (type != 0 && type != tt)
3872 if (contents && !streq(contents, cc))
3880 * We enforce a global limit on container depth, that is much
3881 * higher than the 32 structs and 32 arrays the specification
3882 * mandates. This is simpler to implement for us, and we need
3883 * this only to ensure our container array doesn't grow
3884 * without bounds. We are happy to return any data from a
3885 * message as long as the data itself is valid, even if the
3886 * overall message might be not.
3888 * Note that the message signature is validated when
3889 * parsing the headers, and that validation does check the
3892 * Note that the specification defines no limits on the depth
3893 * of stacked variants, but we do.
3895 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3898 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3901 if (message_end_of_signature(m))
3904 if (message_end_of_array(m, m->rindex))
3907 c = message_get_container(m);
3909 signature = strdup(contents);
3913 c->saved_index = c->index;
3916 if (type == SD_BUS_TYPE_ARRAY)
3917 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3918 else if (type == SD_BUS_TYPE_VARIANT)
3919 r = bus_message_enter_variant(m, c, contents, &item_size);
3920 else if (type == SD_BUS_TYPE_STRUCT)
3921 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3922 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3923 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
3933 /* OK, let's fill it in */
3934 w = m->containers + m->n_containers++;
3935 w->enclosing = type;
3936 w->signature = signature;
3937 w->peeked_signature = NULL;
3941 w->begin = m->rindex;
3942 w->end = m->rindex + c->item_size;
3944 w->array_size = array_size;
3945 w->item_size = item_size;
3946 w->offsets = offsets;
3947 w->n_offsets = n_offsets;
3948 w->offset_index = 0;
3953 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
3954 struct bus_container *c;
3958 assert_return(m, -EINVAL);
3959 assert_return(m->sealed, -EPERM);
3960 assert_return(m->n_containers > 0, -ENXIO);
3962 c = message_get_container(m);
3964 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
3965 if (c->signature && c->signature[c->index] != 0)
3969 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3970 if (m->rindex < c->end)
3973 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3976 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3977 if (c->begin + l != m->rindex)
3982 free(c->peeked_signature);
3986 c = message_get_container(m);
3989 c->index = c->saved_index;
3990 r = container_next_item(m, c, &m->rindex);
3998 static void message_quit_container(sd_bus_message *m) {
3999 struct bus_container *c;
4003 assert(m->n_containers > 0);
4005 c = message_get_container(m);
4008 assert(m->rindex >= c->before);
4009 m->rindex = c->before;
4011 /* Free container */
4016 /* Correct index of new top-level container */
4017 c = message_get_container(m);
4018 c->index = c->saved_index;
4021 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4022 struct bus_container *c;
4025 assert_return(m, -EINVAL);
4026 assert_return(m->sealed, -EPERM);
4028 if (message_end_of_signature(m))
4031 if (message_end_of_array(m, m->rindex))
4034 c = message_get_container(m);
4036 if (bus_type_is_basic(c->signature[c->index])) {
4040 *type = c->signature[c->index];
4044 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4050 r = signature_element_length(c->signature+c->index+1, &l);
4056 sig = strndup(c->signature + c->index + 1, l);
4060 free(c->peeked_signature);
4061 *contents = c->peeked_signature = sig;
4065 *type = SD_BUS_TYPE_ARRAY;
4070 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4071 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4077 r = signature_element_length(c->signature+c->index, &l);
4082 sig = strndup(c->signature + c->index + 1, l - 2);
4086 free(c->peeked_signature);
4087 *contents = c->peeked_signature = sig;
4091 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4096 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4100 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4103 if (c->item_size < 2)
4106 /* Look for the NUL delimiter that
4107 separates the payload from the
4108 signature. Since the body might be
4109 in a different part that then the
4110 signature we map byte by byte. */
4112 for (k = 2; k <= c->item_size; k++) {
4115 where = m->rindex + c->item_size - k;
4116 r = message_peek_body(m, &where, 1, k, &q);
4120 if (*(char*) q == 0)
4124 if (k > c->item_size)
4127 free(c->peeked_signature);
4128 c->peeked_signature = strndup((char*) q + 1, k - 1);
4129 if (!c->peeked_signature)
4132 if (!signature_is_valid(c->peeked_signature, true))
4135 *contents = c->peeked_signature;
4140 r = message_peek_body(m, &rindex, 1, 1, &q);
4145 r = message_peek_body(m, &rindex, 1, l+1, &q);
4149 if (!validate_signature(q, l))
4157 *type = SD_BUS_TYPE_VARIANT;
4172 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4173 struct bus_container *c;
4175 assert_return(m, -EINVAL);
4176 assert_return(m->sealed, -EPERM);
4179 message_reset_containers(m);
4182 c = message_get_container(m);
4184 c = message_get_container(m);
4186 c->offset_index = 0;
4188 m->rindex = c->begin;
4191 c->offset_index = 0;
4192 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4194 return !isempty(c->signature);
4197 static int message_read_ap(
4202 unsigned n_array, n_struct;
4203 TypeStack stack[BUS_CONTAINER_DEPTH];
4204 unsigned stack_ptr = 0;
4205 unsigned n_loop = 0;
4213 /* Ideally, we'd just call ourselves recursively on every
4214 * complex type. However, the state of a va_list that is
4215 * passed to a function is undefined after that function
4216 * returns. This means we need to docode the va_list linearly
4217 * in a single stackframe. We hence implement our own
4218 * home-grown stack in an array. */
4220 n_array = (unsigned) -1; /* length of current array entries */
4221 n_struct = strlen(types); /* length of current struct contents signature */
4228 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4229 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4235 r = sd_bus_message_exit_container(m);
4243 if (n_array != (unsigned) -1)
4252 case SD_BUS_TYPE_BYTE:
4253 case SD_BUS_TYPE_BOOLEAN:
4254 case SD_BUS_TYPE_INT16:
4255 case SD_BUS_TYPE_UINT16:
4256 case SD_BUS_TYPE_INT32:
4257 case SD_BUS_TYPE_UINT32:
4258 case SD_BUS_TYPE_INT64:
4259 case SD_BUS_TYPE_UINT64:
4260 case SD_BUS_TYPE_DOUBLE:
4261 case SD_BUS_TYPE_STRING:
4262 case SD_BUS_TYPE_OBJECT_PATH:
4263 case SD_BUS_TYPE_SIGNATURE:
4264 case SD_BUS_TYPE_UNIX_FD: {
4267 p = va_arg(ap, void*);
4268 r = sd_bus_message_read_basic(m, *t, p);
4281 case SD_BUS_TYPE_ARRAY: {
4284 r = signature_element_length(t + 1, &k);
4290 memcpy(s, t + 1, k);
4293 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4304 if (n_array == (unsigned) -1) {
4309 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4315 n_array = va_arg(ap, unsigned);
4320 case SD_BUS_TYPE_VARIANT: {
4323 s = va_arg(ap, const char *);
4327 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4337 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4342 n_struct = strlen(s);
4343 n_array = (unsigned) -1;
4348 case SD_BUS_TYPE_STRUCT_BEGIN:
4349 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4352 r = signature_element_length(t, &k);
4358 memcpy(s, t + 1, k - 2);
4361 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4371 if (n_array == (unsigned) -1) {
4376 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4382 n_array = (unsigned) -1;
4395 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4399 assert_return(m, -EINVAL);
4400 assert_return(m->sealed, -EPERM);
4401 assert_return(types, -EINVAL);
4403 va_start(ap, types);
4404 r = message_read_ap(m, types, ap);
4410 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4413 assert_return(m, -EINVAL);
4414 assert_return(m->sealed, -EPERM);
4415 assert_return(types, -EINVAL);
4422 case SD_BUS_TYPE_BYTE:
4423 case SD_BUS_TYPE_BOOLEAN:
4424 case SD_BUS_TYPE_INT16:
4425 case SD_BUS_TYPE_UINT16:
4426 case SD_BUS_TYPE_INT32:
4427 case SD_BUS_TYPE_UINT32:
4428 case SD_BUS_TYPE_INT64:
4429 case SD_BUS_TYPE_UINT64:
4430 case SD_BUS_TYPE_DOUBLE:
4431 case SD_BUS_TYPE_STRING:
4432 case SD_BUS_TYPE_OBJECT_PATH:
4433 case SD_BUS_TYPE_SIGNATURE:
4434 case SD_BUS_TYPE_UNIX_FD:
4436 r = sd_bus_message_read_basic(m, *types, NULL);
4440 r = sd_bus_message_skip(m, types + 1);
4446 case SD_BUS_TYPE_ARRAY: {
4449 r = signature_element_length(types + 1, &k);
4455 memcpy(s, types+1, k);
4458 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4463 r = sd_bus_message_skip(m, s);
4470 r = sd_bus_message_exit_container(m);
4475 r = sd_bus_message_skip(m, types + 1 + k);
4482 case SD_BUS_TYPE_VARIANT: {
4483 const char *contents;
4486 r = sd_bus_message_peek_type(m, &x, &contents);
4490 if (x != SD_BUS_TYPE_VARIANT)
4493 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4497 r = sd_bus_message_skip(m, contents);
4502 r = sd_bus_message_exit_container(m);
4506 r = sd_bus_message_skip(m, types + 1);
4513 case SD_BUS_TYPE_STRUCT_BEGIN:
4514 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4517 r = signature_element_length(types, &k);
4523 memcpy(s, types+1, k-2);
4526 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4530 r = sd_bus_message_skip(m, s);
4535 r = sd_bus_message_exit_container(m);
4540 r = sd_bus_message_skip(m, types + k);
4552 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4556 struct bus_container *c;
4562 assert_return(m, -EINVAL);
4563 assert_return(m->sealed, -EPERM);
4564 assert_return(bus_type_is_trivial(type), -EINVAL);
4565 assert_return(ptr, -EINVAL);
4566 assert_return(size, -EINVAL);
4567 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4569 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4573 c = message_get_container(m);
4575 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4576 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4580 sz = c->end - c->begin;
4582 align = bus_type_get_alignment(type);
4586 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4590 /* Zero length array, let's return some aligned
4591 * pointer that is not NULL */
4592 p = (uint8_t*) NULL + align;
4594 r = message_peek_body(m, &m->rindex, align, sz, &p);
4599 r = sd_bus_message_exit_container(m);
4603 *ptr = (const void*) p;
4609 message_quit_container(m);
4613 static int message_peek_fields(
4624 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4627 static int message_peek_field_uint32(
4639 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4642 /* identical for gvariant and dbus1 */
4644 r = message_peek_fields(m, ri, 4, 4, &q);
4649 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4654 static int message_peek_field_string(
4656 bool (*validate)(const char *p),
4668 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4673 r = message_peek_fields(m, ri, 1, item_size, &q);
4679 r = message_peek_field_uint32(m, ri, 4, &l);
4683 r = message_peek_fields(m, ri, 1, l+1, &q);
4689 if (!validate_nul(q, l))
4695 if (!validate_string(q, l))
4705 static int message_peek_field_signature(
4718 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4723 r = message_peek_fields(m, ri, 1, item_size, &q);
4729 r = message_peek_fields(m, ri, 1, 1, &q);
4734 r = message_peek_fields(m, ri, 1, l+1, &q);
4739 if (!validate_signature(q, l))
4748 static int message_skip_fields(
4751 uint32_t array_size,
4752 const char **signature) {
4754 size_t original_index;
4760 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4762 original_index = *ri;
4768 if (array_size != (uint32_t) -1 &&
4769 array_size <= *ri - original_index)
4776 if (t == SD_BUS_TYPE_STRING) {
4778 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4784 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4786 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4792 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4794 r = message_peek_field_signature(m, ri, 0, NULL);
4800 } else if (bus_type_is_basic(t)) {
4803 align = bus_type_get_alignment(t);
4804 k = bus_type_get_size(t);
4805 assert(align > 0 && k > 0);
4807 r = message_peek_fields(m, ri, align, k, NULL);
4813 } else if (t == SD_BUS_TYPE_ARRAY) {
4815 r = signature_element_length(*signature+1, &l);
4825 strncpy(sig, *signature + 1, l-1);
4828 alignment = bus_type_get_alignment(sig[0]);
4832 r = message_peek_field_uint32(m, ri, 0, &nas);
4835 if (nas > BUS_ARRAY_MAX_SIZE)
4838 r = message_peek_fields(m, ri, alignment, 0, NULL);
4842 r = message_skip_fields(m, ri, nas, (const char**) &s);
4847 (*signature) += 1 + l;
4849 } else if (t == SD_BUS_TYPE_VARIANT) {
4852 r = message_peek_field_signature(m, ri, 0, &s);
4856 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4862 } else if (t == SD_BUS_TYPE_STRUCT ||
4863 t == SD_BUS_TYPE_DICT_ENTRY) {
4865 r = signature_element_length(*signature, &l);
4872 strncpy(sig, *signature + 1, l-1);
4875 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4886 int bus_message_parse_fields(sd_bus_message *m) {
4889 uint32_t unix_fds = 0;
4890 bool unix_fds_set = false;
4891 void *offsets = NULL;
4892 unsigned n_offsets = 0;
4898 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4901 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4905 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4906 r = message_peek_fields(m, &ri, 1, sz, &q);
4910 framing = read_word_le(q, sz);
4911 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
4913 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
4917 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
4921 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
4926 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
4927 _cleanup_free_ char *sig = NULL;
4928 const char *signature;
4930 size_t item_size = (size_t) -1;
4932 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4939 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
4942 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
4946 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4951 end = read_word_le((uint8_t*) offsets + i*sz, sz);
4956 where = ri = ALIGN_TO(ri, 8);
4957 item_size = end - ri;
4958 r = message_peek_fields(m, &where, 1, item_size, &q);
4962 b = memrchr(q, 0, item_size);
4966 sig = strndup(b+1, item_size - (b+1-(char*) q));
4971 item_size = b - (char*) q;
4973 r = message_peek_field_signature(m, &ri, 0, &signature);
4979 case _BUS_MESSAGE_HEADER_INVALID:
4982 case BUS_MESSAGE_HEADER_PATH:
4987 if (!streq(signature, "o"))
4990 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
4993 case BUS_MESSAGE_HEADER_INTERFACE:
4998 if (!streq(signature, "s"))
5001 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5004 case BUS_MESSAGE_HEADER_MEMBER:
5009 if (!streq(signature, "s"))
5012 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5015 case BUS_MESSAGE_HEADER_ERROR_NAME:
5020 if (!streq(signature, "s"))
5023 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5025 m->error._need_free = -1;
5029 case BUS_MESSAGE_HEADER_DESTINATION:
5034 if (!streq(signature, "s"))
5037 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5040 case BUS_MESSAGE_HEADER_SENDER:
5045 if (!streq(signature, "s"))
5048 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5050 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5051 m->creds.unique_name = (char*) m->sender;
5052 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5058 case BUS_MESSAGE_HEADER_SIGNATURE: {
5062 if (m->root_container.signature)
5065 if (!streq(signature, "g"))
5068 r = message_peek_field_signature(m, &ri, item_size, &s);
5076 free(m->root_container.signature);
5077 m->root_container.signature = c;
5081 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5084 if (m->reply_cookie != 0)
5087 if (!streq(signature, "u"))
5090 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5094 m->reply_cookie = serial;
5096 if (m->reply_cookie == 0)
5102 case BUS_MESSAGE_HEADER_UNIX_FDS:
5106 if (!streq(signature, "u"))
5109 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5113 unix_fds_set = true;
5117 if (!BUS_MESSAGE_IS_GVARIANT(m))
5118 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5127 if (m->n_fds != unix_fds)
5130 switch (m->header->type) {
5132 case SD_BUS_MESSAGE_SIGNAL:
5133 if (!m->path || !m->interface || !m->member)
5137 case SD_BUS_MESSAGE_METHOD_CALL:
5139 if (!m->path || !m->member)
5144 case SD_BUS_MESSAGE_METHOD_RETURN:
5146 if (m->reply_cookie == 0)
5150 case SD_BUS_MESSAGE_METHOD_ERROR:
5152 if (m->reply_cookie == 0 || !m->error.name)
5157 /* Refuse non-local messages that claim they are local */
5158 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5160 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5162 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5165 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5167 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5168 r = build_struct_offsets(
5170 m->root_container.signature,
5171 BUS_MESSAGE_BODY_SIZE(m),
5172 &m->root_container.item_size,
5173 &m->root_container.offsets,
5174 &m->root_container.n_offsets);
5179 /* Try to read the error message, but if we can't it's a non-issue */
5180 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5181 sd_bus_message_read(m, "s", &m->error.message);
5186 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5187 assert_return(m, -EINVAL);
5188 assert_return(destination, -EINVAL);
5189 assert_return(!m->sealed, -EPERM);
5190 assert_return(!m->destination, -EEXIST);
5192 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5195 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5199 struct bus_body_part *part;
5205 total = BUS_MESSAGE_SIZE(m);
5211 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5212 MESSAGE_FOREACH_PART(part, i, m)
5213 e = mempcpy(e, part->data, part->size);
5215 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5223 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5229 r = sd_bus_message_enter_container(m, 'a', "s");
5236 r = sd_bus_message_read_basic(m, 's', &s);
5242 r = strv_extend(l, s);
5247 r = sd_bus_message_exit_container(m);
5254 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5258 assert_return(m, -EINVAL);
5259 assert_return(m->sealed, -EPERM);
5260 assert_return(l, -EINVAL);
5262 r = bus_message_read_strv_extend(m, &strv);
5272 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
5274 const char *t = NULL;
5279 r = sd_bus_message_rewind(m, true);
5283 for (j = 0; j <= i; j++) {
5286 r = sd_bus_message_peek_type(m, &type, NULL);
5290 if (type != SD_BUS_TYPE_STRING &&
5291 type != SD_BUS_TYPE_OBJECT_PATH &&
5292 type != SD_BUS_TYPE_SIGNATURE)
5295 r = sd_bus_message_read_basic(m, type, &t);
5303 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5309 if (size < sizeof(struct bus_header))
5312 full = sizeof(struct bus_header) +
5313 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5315 return size >= full;
5318 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5324 if (h->endian == BUS_NATIVE_ENDIAN) {
5325 fs = h->fields_size;
5327 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5328 fs = bswap_32(h->fields_size);
5329 bs = bswap_32(h->body_size);
5333 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5337 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5338 assert_return(m, -EINVAL);
5340 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5343 return sd_bus_error_get_errno(&m->error);
5346 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5347 struct bus_container *c;
5349 assert_return(m, NULL);
5351 c = complete ? &m->root_container : message_get_container(m);
5352 return strempty(c->signature);
5355 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5356 bool done_something = false;
5359 assert_return(m, -EINVAL);
5360 assert_return(source, -EINVAL);
5361 assert_return(!m->sealed, -EPERM);
5362 assert_return(source->sealed, -EPERM);
5365 const char *contents;
5380 r = sd_bus_message_peek_type(source, &type, &contents);
5386 done_something = true;
5388 if (bus_type_is_container(type) > 0) {
5390 r = sd_bus_message_enter_container(source, type, contents);
5394 r = sd_bus_message_open_container(m, type, contents);
5398 r = sd_bus_message_copy(m, source, true);
5402 r = sd_bus_message_close_container(m);
5406 r = sd_bus_message_exit_container(source);
5413 r = sd_bus_message_read_basic(source, type, &basic);
5419 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5420 type == SD_BUS_TYPE_SIGNATURE ||
5421 type == SD_BUS_TYPE_STRING)
5422 r = sd_bus_message_append_basic(m, type, basic.string);
5424 r = sd_bus_message_append_basic(m, type, &basic);
5431 return done_something;
5434 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5439 assert_return(m, -EINVAL);
5440 assert_return(m->sealed, -EPERM);
5441 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5442 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5443 assert_return(type || contents, -EINVAL);
5444 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5446 r = sd_bus_message_peek_type(m, &t, &c);
5450 if (type != 0 && type != t)
5453 if (contents && !streq_ptr(contents, c))
5459 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5460 assert_return(m, NULL);
5465 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5466 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5474 switch ((*m)->header->type) {
5476 case SD_BUS_MESSAGE_SIGNAL:
5477 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5483 case SD_BUS_MESSAGE_METHOD_CALL:
5484 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5490 case SD_BUS_MESSAGE_METHOD_RETURN:
5491 case SD_BUS_MESSAGE_METHOD_ERROR:
5493 n = message_new(bus, (*m)->header->type);
5497 n->reply_cookie = (*m)->reply_cookie;
5498 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5502 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5503 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5507 n->error._need_free = -1;
5516 if ((*m)->destination && !n->destination) {
5517 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5522 if ((*m)->sender && !n->sender) {
5523 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5528 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5530 r = sd_bus_message_copy(n, *m, true);
5534 timeout = (*m)->timeout;
5535 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5536 timeout = BUS_DEFAULT_TIMEOUT;
5538 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5542 sd_bus_message_unref(*m);
5549 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5553 assert_return(!m->sealed, -EPERM);
5554 assert_return(!m->sender, -EPERM);
5556 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5559 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5560 assert_return(m, -EINVAL);
5561 assert_return(priority, -EINVAL);
5563 *priority = m->priority;
5567 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5568 assert_return(m, -EINVAL);
5569 assert_return(!m->sealed, -EPERM);
5571 m->priority = priority;