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"
31 #include "memfd-util.h"
34 #include "bus-message.h"
35 #include "bus-internal.h"
37 #include "bus-signature.h"
38 #include "bus-gvariant.h"
41 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
43 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
48 if (old_base == new_base)
51 if ((uint8_t*) p < (uint8_t*) old_base)
54 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
57 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
60 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
64 if (part->memfd >= 0) {
65 /* If we can reuse the memfd, try that. For that it
66 * can't be sealed yet. */
69 assert(part->memfd_offset == 0);
70 assert(part->data == part->mmap_begin);
71 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
74 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
76 safe_close(part->memfd);
79 } else if (part->munmap_this)
80 munmap(part->mmap_begin, part->mapped);
81 else if (part->free_this)
88 static void message_reset_parts(sd_bus_message *m) {
89 struct bus_body_part *part;
94 while (m->n_body_parts > 0) {
95 struct bus_body_part *next = part->next;
96 message_free_part(m, part);
103 m->cached_rindex_part = NULL;
104 m->cached_rindex_part_begin = 0;
107 static void message_reset_containers(sd_bus_message *m) {
112 for (i = 0; i < m->n_containers; i++) {
113 free(m->containers[i].signature);
114 free(m->containers[i].offsets);
118 m->containers = NULL;
120 m->n_containers = m->containers_allocated = 0;
121 m->root_container.index = 0;
124 static void message_free(sd_bus_message *m) {
130 message_reset_parts(m);
132 if (m->release_kdbus) {
133 struct kdbus_cmd_free cmd_free = { };
135 cmd_free.size = sizeof(cmd_free);
137 cmd_free.offset = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
138 (void) ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &cmd_free);
144 sd_bus_unref(m->bus);
147 close_many(m->fds, m->n_fds);
151 if (m->iovec != m->iovec_fixed)
154 if (m->destination_ptr) {
155 free(m->destination_ptr);
156 m->destination_ptr = NULL;
159 message_reset_containers(m);
160 free(m->root_container.signature);
161 free(m->root_container.offsets);
163 free(m->root_container.peeked_signature);
165 bus_creds_done(&m->creds);
169 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
171 size_t old_size, new_size, start;
178 old_size = sizeof(struct bus_header) + m->header->fields_size;
179 start = ALIGN_TO(old_size, align);
180 new_size = start + sz;
182 if (old_size == new_size)
183 return (uint8_t*) m->header + old_size;
185 if (new_size > (size_t) ((uint32_t) -1))
188 if (m->free_header) {
189 np = realloc(m->header, ALIGN8(new_size));
193 /* Initially, the header is allocated as part of of
194 * the sd_bus_message itself, let's replace it by
197 np = malloc(ALIGN8(new_size));
201 memcpy(np, m->header, sizeof(struct bus_header));
204 /* Zero out padding */
205 if (start > old_size)
206 memzero((uint8_t*) np + old_size, start - old_size);
210 m->header->fields_size = new_size - sizeof(struct bus_header);
212 /* Adjust quick access pointers */
213 m->path = adjust_pointer(m->path, op, old_size, m->header);
214 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
215 m->member = adjust_pointer(m->member, op, old_size, m->header);
216 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
217 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
218 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
220 m->free_header = true;
223 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
226 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
229 return (uint8_t*) np + start;
236 static int message_append_field_string(
248 /* dbus1 doesn't allow strings over 32bit, let's enforce this
249 * globally, to not risk convertability */
251 if (l > (size_t) (uint32_t) -1)
254 /* Signature "(yv)" where the variant contains "s" */
256 if (BUS_MESSAGE_IS_GVARIANT(m)) {
258 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
259 p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
271 *ret = (char*) p + 8;
274 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
275 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
284 ((uint32_t*) p)[1] = l;
285 memcpy(p + 8, s, l + 1);
288 *ret = (char*) p + 8;
294 static int message_append_field_signature(
305 /* dbus1 doesn't allow signatures over 32bit, let's enforce
306 * this globally, to not risk convertability */
311 /* Signature "(yv)" where the variant contains "g" */
313 if (BUS_MESSAGE_IS_GVARIANT(m))
314 /* For gvariant the serialization is the same as for normal strings */
315 return message_append_field_string(m, h, 'g', s, ret);
317 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
318 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
324 p[2] = SD_BUS_TYPE_SIGNATURE;
327 memcpy(p + 5, s, l + 1);
330 *ret = (const char*) p + 5;
336 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
341 if (BUS_MESSAGE_IS_GVARIANT(m)) {
342 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
344 p = message_extend_fields(m, 8, 1 + 7 + 4 + 1 + 1, true);
350 *((uint32_t*) (p + 8)) = x;
354 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
355 p = message_extend_fields(m, 8, 4 + 4, false);
361 p[2] = SD_BUS_TYPE_UINT32;
364 ((uint32_t*) p)[1] = x;
370 int bus_message_from_header(
376 const struct ucred *ucred,
379 sd_bus_message **ret) {
382 struct bus_header *h;
386 assert(buffer || length <= 0);
387 assert(fds || n_fds <= 0);
390 if (length < sizeof(struct bus_header))
394 if (h->version != 1 &&
401 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
404 if (h->endian != BUS_LITTLE_ENDIAN &&
405 h->endian != BUS_BIG_ENDIAN)
408 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
411 label_sz = strlen(label);
426 m->creds.pid = ucred->pid;
427 m->creds.uid = ucred->uid;
428 m->creds.gid = ucred->gid;
430 /* Due to namespace translations some data might be
431 * missing from this ucred record. */
432 if (m->creds.pid > 0)
433 m->creds.mask |= SD_BUS_CREDS_PID;
435 if (m->creds.uid != UID_INVALID)
436 m->creds.mask |= SD_BUS_CREDS_UID;
438 if (m->creds.gid != GID_INVALID)
439 m->creds.mask |= SD_BUS_CREDS_GID;
443 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
444 memcpy(m->creds.label, label, label_sz + 1);
446 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
449 m->bus = sd_bus_ref(bus);
455 int bus_message_from_malloc(
461 const struct ucred *ucred,
463 sd_bus_message **ret) {
469 r = bus_message_from_header(bus, buffer, length, fds, n_fds, ucred, label, 0, &m);
473 if (length != BUS_MESSAGE_SIZE(m)) {
478 sz = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
481 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
483 m->body.sealed = true;
488 m->iovec = m->iovec_fixed;
489 m->iovec[0].iov_base = buffer;
490 m->iovec[0].iov_len = length;
492 r = bus_message_parse_fields(m);
496 /* We take possession of the memory and fds now */
497 m->free_header = true;
508 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
513 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
518 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
519 m->header->endian = BUS_NATIVE_ENDIAN;
520 m->header->type = type;
521 m->header->version = bus ? bus->message_version : 1;
522 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
523 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
524 m->bus = sd_bus_ref(bus);
529 _public_ int sd_bus_message_new_signal(
533 const char *interface,
534 const char *member) {
539 assert_return(bus, -ENOTCONN);
540 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
541 assert_return(object_path_is_valid(path), -EINVAL);
542 assert_return(interface_name_is_valid(interface), -EINVAL);
543 assert_return(member_name_is_valid(member), -EINVAL);
544 assert_return(m, -EINVAL);
546 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
550 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
552 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
555 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
558 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
566 sd_bus_message_unref(t);
570 _public_ int sd_bus_message_new_method_call(
573 const char *destination,
575 const char *interface,
576 const char *member) {
581 assert_return(bus, -ENOTCONN);
582 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
583 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
584 assert_return(object_path_is_valid(path), -EINVAL);
585 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
586 assert_return(member_name_is_valid(member), -EINVAL);
587 assert_return(m, -EINVAL);
589 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
593 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
596 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
601 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
607 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
620 static int message_new_reply(
621 sd_bus_message *call,
623 sd_bus_message **m) {
628 assert_return(call, -EINVAL);
629 assert_return(call->sealed, -EPERM);
630 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
631 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
632 assert_return(m, -EINVAL);
634 t = message_new(call->bus, type);
638 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
639 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
641 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
646 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
651 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
652 t->enforced_reply_signature = call->enforced_reply_signature;
662 _public_ int sd_bus_message_new_method_return(
663 sd_bus_message *call,
664 sd_bus_message **m) {
666 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
669 _public_ int sd_bus_message_new_method_error(
670 sd_bus_message *call,
672 const sd_bus_error *e) {
677 assert_return(sd_bus_error_is_set(e), -EINVAL);
678 assert_return(m, -EINVAL);
680 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
684 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
689 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
694 t->error._need_free = -1;
704 _public_ int sd_bus_message_new_method_errorf(
705 sd_bus_message *call,
711 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
714 assert_return(name, -EINVAL);
715 assert_return(m, -EINVAL);
717 va_start(ap, format);
718 bus_error_setfv(&error, name, format, ap);
721 return sd_bus_message_new_method_error(call, m, &error);
724 _public_ int sd_bus_message_new_method_errno(
725 sd_bus_message *call,
728 const sd_bus_error *p) {
730 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
732 if (sd_bus_error_is_set(p))
733 return sd_bus_message_new_method_error(call, m, p);
735 sd_bus_error_set_errno(&berror, error);
737 return sd_bus_message_new_method_error(call, m, &berror);
740 _public_ int sd_bus_message_new_method_errnof(
741 sd_bus_message *call,
747 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
750 va_start(ap, format);
751 bus_error_set_errnofv(&berror, error, format, ap);
754 return sd_bus_message_new_method_error(call, m, &berror);
757 int bus_message_new_synthetic_error(
760 const sd_bus_error *e,
761 sd_bus_message **m) {
767 assert(sd_bus_error_is_set(e));
770 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
774 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
775 t->reply_cookie = cookie;
777 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
781 if (bus && bus->unique_name) {
782 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
787 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
792 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
797 t->error._need_free = -1;
807 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
808 assert_return(m, NULL);
810 assert(m->n_ref > 0);
816 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
821 assert(m->n_ref > 0);
831 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
832 assert_return(m, -EINVAL);
833 assert_return(type, -EINVAL);
835 *type = m->header->type;
839 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
840 assert_return(m, -EINVAL);
841 assert_return(cookie, -EINVAL);
842 assert_return(m->header->serial != 0, -ENODATA);
844 *cookie = BUS_MESSAGE_COOKIE(m);
848 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
849 assert_return(m, -EINVAL);
850 assert_return(cookie, -EINVAL);
851 assert_return(m->reply_cookie != 0, -ENODATA);
853 *cookie = m->reply_cookie;
857 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
858 assert_return(m, -EINVAL);
860 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
861 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
864 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
865 assert_return(m, -EINVAL);
867 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
870 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
871 assert_return(m, -EINVAL);
873 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
874 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
877 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
878 assert_return(m, NULL);
883 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
884 assert_return(m, NULL);
889 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
890 assert_return(m, NULL);
895 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
896 assert_return(m, NULL);
898 return m->destination;
901 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
902 assert_return(m, NULL);
907 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
908 assert_return(m, NULL);
909 assert_return(sd_bus_error_is_set(&m->error), NULL);
914 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
915 assert_return(m, -EINVAL);
916 assert_return(usec, -EINVAL);
918 if (m->monotonic <= 0)
921 *usec = m->monotonic;
925 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
926 assert_return(m, -EINVAL);
927 assert_return(usec, -EINVAL);
929 if (m->realtime <= 0)
936 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
937 assert_return(m, -EINVAL);
938 assert_return(seqnum, -EINVAL);
947 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
948 assert_return(m, NULL);
950 if (m->creds.mask == 0)
956 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
957 const char *interface,
958 const char *member) {
959 assert_return(m, -EINVAL);
961 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
964 if (interface && (!m->interface || !streq(m->interface, interface)))
967 if (member && (!m->member || !streq(m->member, member)))
973 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
974 const char *interface,
975 const char *member) {
976 assert_return(m, -EINVAL);
978 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
981 if (interface && (!m->interface || !streq(m->interface, interface)))
984 if (member && (!m->member || !streq(m->member, member)))
990 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
991 assert_return(m, -EINVAL);
993 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
996 if (name && (!m->error.name || !streq(m->error.name, name)))
1002 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1003 assert_return(m, -EINVAL);
1004 assert_return(!m->sealed, -EPERM);
1005 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1008 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1010 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1015 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1016 assert_return(m, -EINVAL);
1017 assert_return(!m->sealed, -EPERM);
1020 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1022 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1027 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1028 assert_return(m, -EINVAL);
1029 assert_return(!m->sealed, -EPERM);
1032 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1034 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1039 static struct bus_container *message_get_container(sd_bus_message *m) {
1042 if (m->n_containers == 0)
1043 return &m->root_container;
1045 assert(m->containers);
1046 return m->containers + m->n_containers - 1;
1049 struct bus_body_part *message_append_part(sd_bus_message *m) {
1050 struct bus_body_part *part;
1057 if (m->n_body_parts <= 0) {
1061 assert(m->body_end);
1063 part = new0(struct bus_body_part, 1);
1069 m->body_end->next = part;
1079 static void part_zero(struct bus_body_part *part, size_t sz) {
1084 /* All other fields can be left in their defaults */
1085 assert(!part->data);
1086 assert(part->memfd < 0);
1089 part->is_zero = true;
1090 part->sealed = true;
1093 static int part_make_space(
1094 struct sd_bus_message *m,
1095 struct bus_body_part *part,
1104 assert(!part->sealed);
1109 if (!part->data && part->memfd < 0) {
1110 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1111 part->mmap_begin = part->data;
1114 if (part->memfd >= 0) {
1116 if (part->allocated == 0 || sz > part->allocated) {
1117 uint64_t new_allocated;
1119 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1120 r = memfd_set_size(part->memfd, new_allocated);
1126 part->allocated = new_allocated;
1129 if (!part->data || sz > part->mapped) {
1132 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1133 if (part->mapped <= 0)
1134 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1136 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1138 if (n == MAP_FAILED) {
1143 part->mmap_begin = part->data = n;
1145 part->memfd_offset = 0;
1148 part->munmap_this = true;
1150 if (part->allocated == 0 || sz > part->allocated) {
1151 size_t new_allocated;
1153 new_allocated = sz > 0 ? 2 * sz : 64;
1154 n = realloc(part->data, new_allocated);
1161 part->allocated = new_allocated;
1162 part->free_this = true;
1167 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1173 static int message_add_offset(sd_bus_message *m, size_t offset) {
1174 struct bus_container *c;
1177 assert(BUS_MESSAGE_IS_GVARIANT(m));
1179 /* Add offset to current container, unless this is the first
1180 * item in it, which will have the 0 offset, which we can
1182 c = message_get_container(m);
1184 if (!c->need_offsets)
1187 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1190 c->offsets[c->n_offsets++] = offset;
1194 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1195 struct bus_container *c;
1202 /* Update counters */
1203 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1206 *c->array_size += expand;
1210 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1211 size_t start_body, end_body, padding, added;
1222 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1223 end_body = start_body + sz;
1225 padding = start_body - m->header->body_size;
1226 added = padding + sz;
1228 /* Check for 32bit overflows */
1229 if (end_body > (size_t) ((uint32_t) -1)) {
1235 struct bus_body_part *part = NULL;
1239 m->n_body_parts <= 0 ||
1240 m->body_end->sealed ||
1241 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1245 part = message_append_part(m);
1249 part_zero(part, padding);
1252 part = message_append_part(m);
1256 r = part_make_space(m, part, sz, &p);
1260 struct bus_container *c;
1262 size_t os, start_part, end_part;
1268 start_part = ALIGN_TO(part->size, align);
1269 end_part = start_part + sz;
1271 r = part_make_space(m, part, end_part, &p);
1276 memzero(p, padding);
1277 p = (uint8_t*) p + padding;
1280 /* Readjust pointers */
1281 for (c = m->containers; c < m->containers + m->n_containers; c++)
1282 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1284 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1287 /* Return something that is not NULL and is aligned */
1288 p = (uint8_t *) NULL + align;
1290 m->header->body_size = end_body;
1291 message_extend_containers(m, added);
1294 r = message_add_offset(m, end_body);
1304 static int message_push_fd(sd_bus_message *m, int fd) {
1315 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1319 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1327 m->fds[m->n_fds] = copy;
1333 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1334 _cleanup_close_ int fd = -1;
1335 struct bus_container *c;
1339 assert_return(m, -EINVAL);
1340 assert_return(!m->sealed, -EPERM);
1341 assert_return(bus_type_is_basic(type), -EINVAL);
1342 assert_return(!m->poisoned, -ESTALE);
1344 c = message_get_container(m);
1346 if (c->signature && c->signature[c->index]) {
1347 /* Container signature is already set */
1349 if (c->signature[c->index] != type)
1354 /* Maybe we can append to the signature? But only if this is the top-level container */
1355 if (c->enclosing != 0)
1358 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1365 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1371 case SD_BUS_TYPE_SIGNATURE:
1372 case SD_BUS_TYPE_STRING:
1375 /* Fall through... */
1376 case SD_BUS_TYPE_OBJECT_PATH:
1384 case SD_BUS_TYPE_BOOLEAN:
1386 u8 = p && *(int*) p;
1392 case SD_BUS_TYPE_UNIX_FD:
1397 fd = message_push_fd(m, *(int*) p);
1408 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1409 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1416 a = message_extend_body(m, align, sz, true);
1423 *stored = (const uint8_t*) a;
1430 case SD_BUS_TYPE_STRING:
1431 /* To make things easy we'll serialize a NULL string
1432 * into the empty string */
1435 /* Fall through... */
1436 case SD_BUS_TYPE_OBJECT_PATH:
1442 sz = 4 + strlen(p) + 1;
1445 case SD_BUS_TYPE_SIGNATURE:
1450 sz = 1 + strlen(p) + 1;
1453 case SD_BUS_TYPE_BOOLEAN:
1455 u32 = p && *(int*) p;
1461 case SD_BUS_TYPE_UNIX_FD:
1466 fd = message_push_fd(m, *(int*) p);
1477 align = bus_type_get_alignment(type);
1478 sz = bus_type_get_size(type);
1485 a = message_extend_body(m, align, sz, false);
1489 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1490 *(uint32_t*) a = sz - 5;
1491 memcpy((uint8_t*) a + 4, p, sz - 4);
1494 *stored = (const uint8_t*) a + 4;
1496 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1497 *(uint8_t*) a = sz - 2;
1498 memcpy((uint8_t*) a + 1, p, sz - 1);
1501 *stored = (const uint8_t*) a + 1;
1510 if (type == SD_BUS_TYPE_UNIX_FD)
1513 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1520 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1521 return message_append_basic(m, type, p, NULL);
1524 _public_ int sd_bus_message_append_string_space(
1529 struct bus_container *c;
1532 assert_return(m, -EINVAL);
1533 assert_return(s, -EINVAL);
1534 assert_return(!m->sealed, -EPERM);
1535 assert_return(!m->poisoned, -ESTALE);
1537 c = message_get_container(m);
1539 if (c->signature && c->signature[c->index]) {
1540 /* Container signature is already set */
1542 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1547 /* Maybe we can append to the signature? But only if this is the top-level container */
1548 if (c->enclosing != 0)
1551 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1558 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1559 a = message_extend_body(m, 1, size + 1, true);
1565 a = message_extend_body(m, 4, 4 + size + 1, false);
1569 *(uint32_t*) a = size;
1575 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1581 _public_ int sd_bus_message_append_string_iovec(
1583 const struct iovec *iov,
1591 assert_return(m, -EINVAL);
1592 assert_return(!m->sealed, -EPERM);
1593 assert_return(iov || n == 0, -EINVAL);
1594 assert_return(!m->poisoned, -ESTALE);
1596 size = IOVEC_TOTAL_SIZE(iov, n);
1598 r = sd_bus_message_append_string_space(m, size, &p);
1602 for (i = 0; i < n; i++) {
1604 if (iov[i].iov_base)
1605 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1607 memset(p, ' ', iov[i].iov_len);
1609 p += iov[i].iov_len;
1615 static int bus_message_open_array(
1617 struct bus_container *c,
1618 const char *contents,
1619 uint32_t **array_size,
1621 bool *need_offsets) {
1631 assert(need_offsets);
1633 if (!signature_is_single(contents, true))
1636 if (c->signature && c->signature[c->index]) {
1638 /* Verify the existing signature */
1640 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1643 if (!startswith(c->signature + c->index + 1, contents))
1646 nindex = c->index + 1 + strlen(contents);
1650 if (c->enclosing != 0)
1653 /* Extend the existing signature */
1655 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1661 nindex = e - c->signature;
1664 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1665 alignment = bus_gvariant_get_alignment(contents);
1669 /* Add alignment padding and add to offset list */
1670 if (!message_extend_body(m, alignment, 0, false))
1673 r = bus_gvariant_is_fixed_size(contents);
1677 *begin = m->header->body_size;
1678 *need_offsets = r == 0;
1682 struct bus_body_part *o;
1684 alignment = bus_type_get_alignment(contents[0]);
1688 a = message_extend_body(m, 4, 4, false);
1693 op = m->body_end->data;
1694 os = m->body_end->size;
1696 /* Add alignment between size and first element */
1697 if (!message_extend_body(m, alignment, 0, false))
1700 /* location of array size might have changed so let's readjust a */
1701 if (o == m->body_end)
1702 a = adjust_pointer(a, op, os, m->body_end->data);
1708 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1714 static int bus_message_open_variant(
1716 struct bus_container *c,
1717 const char *contents) {
1723 if (!signature_is_single(contents, false))
1726 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1729 if (c->signature && c->signature[c->index]) {
1731 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1737 if (c->enclosing != 0)
1740 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1747 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1748 /* Variants are always aligned to 8 */
1750 if (!message_extend_body(m, 8, 0, false))
1757 l = strlen(contents);
1758 a = message_extend_body(m, 1, 1 + l + 1, false);
1763 memcpy((uint8_t*) a + 1, contents, l + 1);
1766 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1772 static int bus_message_open_struct(
1774 struct bus_container *c,
1775 const char *contents,
1777 bool *need_offsets) {
1786 assert(need_offsets);
1788 if (!signature_is_valid(contents, false))
1791 if (c->signature && c->signature[c->index]) {
1794 l = strlen(contents);
1796 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1797 !startswith(c->signature + c->index + 1, contents) ||
1798 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1801 nindex = c->index + 1 + l + 1;
1805 if (c->enclosing != 0)
1808 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1814 nindex = e - c->signature;
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))
1839 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1845 static int bus_message_open_dict_entry(
1847 struct bus_container *c,
1848 const char *contents,
1850 bool *need_offsets) {
1858 assert(need_offsets);
1860 if (!signature_is_pair(contents))
1863 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1866 if (c->signature && c->signature[c->index]) {
1869 l = strlen(contents);
1871 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1872 !startswith(c->signature + c->index + 1, contents) ||
1873 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1878 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1881 alignment = bus_gvariant_get_alignment(contents);
1885 if (!message_extend_body(m, alignment, 0, false))
1888 r = bus_gvariant_is_fixed_size(contents);
1892 *begin = m->header->body_size;
1893 *need_offsets = r == 0;
1895 /* Align contents to 8 byte boundary */
1896 if (!message_extend_body(m, 8, 0, false))
1903 _public_ int sd_bus_message_open_container(
1906 const char *contents) {
1908 struct bus_container *c, *w;
1909 uint32_t *array_size = NULL;
1911 size_t before, begin = 0;
1912 bool need_offsets = false;
1915 assert_return(m, -EINVAL);
1916 assert_return(!m->sealed, -EPERM);
1917 assert_return(contents, -EINVAL);
1918 assert_return(!m->poisoned, -ESTALE);
1920 /* Make sure we have space for one more container */
1921 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1926 c = message_get_container(m);
1928 signature = strdup(contents);
1934 /* Save old index in the parent container, in case we have to
1935 * abort this container */
1936 c->saved_index = c->index;
1937 before = m->header->body_size;
1939 if (type == SD_BUS_TYPE_ARRAY)
1940 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1941 else if (type == SD_BUS_TYPE_VARIANT)
1942 r = bus_message_open_variant(m, c, contents);
1943 else if (type == SD_BUS_TYPE_STRUCT)
1944 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1945 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1946 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1955 /* OK, let's fill it in */
1956 w = m->containers + m->n_containers++;
1957 w->enclosing = type;
1958 w->signature = signature;
1960 w->array_size = array_size;
1963 w->n_offsets = w->offsets_allocated = 0;
1965 w->need_offsets = need_offsets;
1970 static size_t determine_word_size(size_t sz, size_t extra) {
1971 if (sz + extra <= 0xFF)
1973 else if (sz + extra*2 <= 0xFFFF)
1975 else if (sz + extra*4 <= 0xFFFFFFFF)
1981 static size_t read_word_le(void *p, size_t sz) {
1991 return *(uint8_t*) p;
1996 return le16toh(x.u16);
1998 return le32toh(x.u32);
2000 return le64toh(x.u64);
2002 assert_not_reached("unknown word width");
2005 static void write_word_le(void *p, size_t sz, size_t value) {
2013 assert(sz == 8 || (value < (1ULL << (sz*8))));
2016 *(uint8_t*) p = value;
2019 x.u16 = htole16((uint16_t) value);
2021 x.u32 = htole32((uint32_t) value);
2023 x.u64 = htole64((uint64_t) value);
2025 assert_not_reached("unknown word width");
2030 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2035 if (!BUS_MESSAGE_IS_GVARIANT(m))
2038 if (c->need_offsets) {
2039 size_t payload, sz, i;
2042 /* Variable-width arrays */
2044 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2045 sz = determine_word_size(payload, c->n_offsets);
2047 a = message_extend_body(m, 1, sz * c->n_offsets, true);
2051 for (i = 0; i < c->n_offsets; i++)
2052 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2056 /* Fixed-width or empty arrays */
2058 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
2066 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2072 assert(c->signature);
2074 if (!BUS_MESSAGE_IS_GVARIANT(m))
2077 l = strlen(c->signature);
2079 a = message_extend_body(m, 1, 1 + l, true);
2084 memcpy(a+1, c->signature, l);
2089 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2090 size_t n_variable = 0;
2099 if (!BUS_MESSAGE_IS_GVARIANT(m))
2102 p = strempty(c->signature);
2106 r = signature_element_length(p, &n);
2115 r = bus_gvariant_is_fixed_size(t);
2120 assert(!c->need_offsets || i <= c->n_offsets);
2122 /* We need to add an offset for each item that has a
2123 * variable size and that is not the last one in the
2125 if (r == 0 && p[n] != 0)
2132 assert(!c->need_offsets || i == c->n_offsets);
2133 assert(c->need_offsets || n_variable == 0);
2135 if (n_variable <= 0) {
2136 a = message_extend_body(m, 1, 0, add_offset);
2143 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2145 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2147 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2151 p = strempty(c->signature);
2152 for (i = 0, j = 0; i < c->n_offsets; i++) {
2156 r = signature_element_length(p, &n);
2167 r = bus_gvariant_is_fixed_size(t);
2170 if (r > 0 || p[0] == 0)
2174 k = n_variable - 1 - j;
2176 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2185 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2186 struct bus_container *c;
2189 assert_return(m, -EINVAL);
2190 assert_return(!m->sealed, -EPERM);
2191 assert_return(m->n_containers > 0, -EINVAL);
2192 assert_return(!m->poisoned, -ESTALE);
2194 c = message_get_container(m);
2196 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2197 if (c->signature && c->signature[c->index] != 0)
2202 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2203 r = bus_message_close_array(m, c);
2204 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2205 r = bus_message_close_variant(m, c);
2206 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2207 r = bus_message_close_struct(m, c, true);
2209 assert_not_reached("Unknown container type");
2223 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2230 stack[*i].types = types;
2231 stack[*i].n_struct = n_struct;
2232 stack[*i].n_array = n_array;
2238 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2249 *types = stack[*i].types;
2250 *n_struct = stack[*i].n_struct;
2251 *n_array = stack[*i].n_array;
2256 int bus_message_append_ap(
2261 unsigned n_array, n_struct;
2262 TypeStack stack[BUS_CONTAINER_DEPTH];
2263 unsigned stack_ptr = 0;
2271 n_array = (unsigned) -1;
2272 n_struct = strlen(types);
2277 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2278 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2284 r = sd_bus_message_close_container(m);
2292 if (n_array != (unsigned) -1)
2301 case SD_BUS_TYPE_BYTE: {
2304 x = (uint8_t) va_arg(ap, int);
2305 r = sd_bus_message_append_basic(m, *t, &x);
2309 case SD_BUS_TYPE_BOOLEAN:
2310 case SD_BUS_TYPE_INT32:
2311 case SD_BUS_TYPE_UINT32:
2312 case SD_BUS_TYPE_UNIX_FD: {
2315 /* We assume a boolean is the same as int32_t */
2316 assert_cc(sizeof(int32_t) == sizeof(int));
2318 x = va_arg(ap, uint32_t);
2319 r = sd_bus_message_append_basic(m, *t, &x);
2323 case SD_BUS_TYPE_INT16:
2324 case SD_BUS_TYPE_UINT16: {
2327 x = (uint16_t) va_arg(ap, int);
2328 r = sd_bus_message_append_basic(m, *t, &x);
2332 case SD_BUS_TYPE_INT64:
2333 case SD_BUS_TYPE_UINT64:
2334 case SD_BUS_TYPE_DOUBLE: {
2337 x = va_arg(ap, uint64_t);
2338 r = sd_bus_message_append_basic(m, *t, &x);
2342 case SD_BUS_TYPE_STRING:
2343 case SD_BUS_TYPE_OBJECT_PATH:
2344 case SD_BUS_TYPE_SIGNATURE: {
2347 x = va_arg(ap, const char*);
2348 r = sd_bus_message_append_basic(m, *t, x);
2352 case SD_BUS_TYPE_ARRAY: {
2355 r = signature_element_length(t + 1, &k);
2361 memcpy(s, t + 1, k);
2364 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2369 if (n_array == (unsigned) -1) {
2374 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2380 n_array = va_arg(ap, unsigned);
2385 case SD_BUS_TYPE_VARIANT: {
2388 s = va_arg(ap, const char*);
2392 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2396 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2401 n_struct = strlen(s);
2402 n_array = (unsigned) -1;
2407 case SD_BUS_TYPE_STRUCT_BEGIN:
2408 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2411 r = signature_element_length(t, &k);
2418 memcpy(s, t + 1, k - 2);
2421 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2426 if (n_array == (unsigned) -1) {
2431 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2437 n_array = (unsigned) -1;
2453 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2457 assert_return(m, -EINVAL);
2458 assert_return(types, -EINVAL);
2459 assert_return(!m->sealed, -EPERM);
2460 assert_return(!m->poisoned, -ESTALE);
2462 va_start(ap, types);
2463 r = bus_message_append_ap(m, types, ap);
2469 _public_ int sd_bus_message_append_array_space(
2479 assert_return(m, -EINVAL);
2480 assert_return(!m->sealed, -EPERM);
2481 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2482 assert_return(ptr || size == 0, -EINVAL);
2483 assert_return(!m->poisoned, -ESTALE);
2485 /* alignment and size of the trivial types (except bool) is
2486 * identical for gvariant and dbus1 marshalling */
2487 align = bus_type_get_alignment(type);
2488 sz = bus_type_get_size(type);
2490 assert_se(align > 0);
2496 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2500 a = message_extend_body(m, align, size, false);
2504 r = sd_bus_message_close_container(m);
2512 _public_ int sd_bus_message_append_array(
2520 assert_return(m, -EINVAL);
2521 assert_return(!m->sealed, -EPERM);
2522 assert_return(bus_type_is_trivial(type), -EINVAL);
2523 assert_return(ptr || size == 0, -EINVAL);
2524 assert_return(!m->poisoned, -ESTALE);
2526 r = sd_bus_message_append_array_space(m, type, size, &p);
2531 memcpy(p, ptr, size);
2536 _public_ int sd_bus_message_append_array_iovec(
2539 const struct iovec *iov,
2547 assert_return(m, -EINVAL);
2548 assert_return(!m->sealed, -EPERM);
2549 assert_return(bus_type_is_trivial(type), -EINVAL);
2550 assert_return(iov || n == 0, -EINVAL);
2551 assert_return(!m->poisoned, -ESTALE);
2553 size = IOVEC_TOTAL_SIZE(iov, n);
2555 r = sd_bus_message_append_array_space(m, type, size, &p);
2559 for (i = 0; i < n; i++) {
2561 if (iov[i].iov_base)
2562 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2564 memzero(p, iov[i].iov_len);
2566 p = (uint8_t*) p + iov[i].iov_len;
2572 _public_ int sd_bus_message_append_array_memfd(
2579 _cleanup_close_ int copy_fd = -1;
2580 struct bus_body_part *part;
2586 assert_return(m, -EINVAL);
2587 assert_return(memfd >= 0, -EINVAL);
2588 assert_return(bus_type_is_trivial(type), -EINVAL);
2589 assert_return(size > 0, -EINVAL);
2590 assert_return(!m->sealed, -EPERM);
2591 assert_return(!m->poisoned, -ESTALE);
2593 r = memfd_set_sealed(memfd);
2597 copy_fd = dup(memfd);
2601 r = memfd_get_size(memfd, &real_size);
2605 if (offset == 0 && size == (uint64_t) -1)
2607 else if (offset + size > real_size)
2610 align = bus_type_get_alignment(type);
2611 sz = bus_type_get_size(type);
2613 assert_se(align > 0);
2616 if (offset % align != 0)
2622 if (size > (uint64_t) (uint32_t) -1)
2625 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2629 a = message_extend_body(m, align, 0, false);
2633 part = message_append_part(m);
2637 part->memfd = copy_fd;
2638 part->memfd_offset = offset;
2639 part->sealed = true;
2643 m->header->body_size += size;
2644 message_extend_containers(m, size);
2646 return sd_bus_message_close_container(m);
2649 _public_ int sd_bus_message_append_string_memfd(
2655 _cleanup_close_ int copy_fd = -1;
2656 struct bus_body_part *part;
2657 struct bus_container *c;
2662 assert_return(m, -EINVAL);
2663 assert_return(memfd >= 0, -EINVAL);
2664 assert_return(size > 0, -EINVAL);
2665 assert_return(!m->sealed, -EPERM);
2666 assert_return(!m->poisoned, -ESTALE);
2668 r = memfd_set_sealed(memfd);
2672 copy_fd = dup(memfd);
2676 r = memfd_get_size(memfd, &real_size);
2680 if (offset == 0 && size == (uint64_t) -1)
2682 else if (offset + size > real_size)
2685 /* We require this to be NUL terminated */
2689 if (size > (uint64_t) (uint32_t) -1)
2692 c = message_get_container(m);
2693 if (c->signature && c->signature[c->index]) {
2694 /* Container signature is already set */
2696 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2701 /* Maybe we can append to the signature? But only if this is the top-level container */
2702 if (c->enclosing != 0)
2705 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2712 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2713 a = message_extend_body(m, 4, 4, false);
2717 *(uint32_t*) a = size - 1;
2720 part = message_append_part(m);
2724 part->memfd = copy_fd;
2725 part->memfd_offset = offset;
2726 part->sealed = true;
2730 m->header->body_size += size;
2731 message_extend_containers(m, size);
2733 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2734 r = message_add_offset(m, m->header->body_size);
2741 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2747 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2751 assert_return(m, -EINVAL);
2752 assert_return(!m->sealed, -EPERM);
2753 assert_return(!m->poisoned, -ESTALE);
2755 r = sd_bus_message_open_container(m, 'a', "s");
2759 STRV_FOREACH(i, l) {
2760 r = sd_bus_message_append_basic(m, 's', *i);
2765 return sd_bus_message_close_container(m);
2768 static int bus_message_close_header(sd_bus_message *m) {
2774 if (!BUS_MESSAGE_IS_GVARIANT(m))
2777 if (m->n_header_offsets < 1)
2780 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2782 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2784 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2788 for (i = 0; i < m->n_header_offsets; i++)
2789 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2794 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2795 struct bus_body_part *part;
2805 if (m->n_containers > 0)
2811 /* In vtables the return signature of method calls is listed,
2812 * let's check if they match if this is a response */
2813 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2814 m->enforced_reply_signature &&
2815 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2818 /* If gvariant marshalling is used we need to close the body structure */
2819 r = bus_message_close_struct(m, &m->root_container, false);
2823 /* If there's a non-trivial signature set, then add it in here */
2824 if (!isempty(m->root_container.signature)) {
2825 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2831 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2836 r = bus_message_close_header(m);
2840 m->header->serial = (uint32_t) cookie;
2841 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2843 /* Add padding at the end of the fields part, since we know
2844 * the body needs to start at an 8 byte alignment. We made
2845 * sure we allocated enough space for this, so all we need to
2846 * do here is to zero it out. */
2847 l = BUS_MESSAGE_FIELDS_SIZE(m);
2850 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, a);
2852 /* If this is something we can send as memfd, then let's seal
2853 the memfd now. Note that we can send memfds as payload only
2854 for directed messages, and not for broadcasts. */
2855 if (m->destination && m->bus->use_memfd) {
2856 MESSAGE_FOREACH_PART(part, i, m)
2857 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2860 /* Try to seal it if that makes
2861 * sense. First, unmap our own map to
2862 * make sure we don't keep it busy. */
2863 bus_body_part_unmap(part);
2865 /* Then, sync up real memfd size */
2867 r = memfd_set_size(part->memfd, sz);
2871 /* Finally, try to seal */
2872 if (memfd_set_sealed(part->memfd) >= 0)
2873 part->sealed = true;
2877 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2878 m->root_container.index = 0;
2879 m->root_container.offset_index = 0;
2880 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2887 int bus_body_part_map(struct bus_body_part *part) {
2896 if (part->size <= 0)
2899 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2900 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2901 static const uint8_t zeroes[7] = { };
2902 part->data = (void*) zeroes;
2906 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
2907 psz = PAGE_ALIGN(part->size + shift);
2909 if (part->memfd >= 0)
2910 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
2911 else if (part->is_zero)
2912 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2916 if (p == MAP_FAILED)
2920 part->mmap_begin = p;
2921 part->data = (uint8_t*) p + shift;
2922 part->munmap_this = true;
2927 void bus_body_part_unmap(struct bus_body_part *part) {
2931 if (part->memfd < 0)
2934 if (!part->mmap_begin)
2937 if (!part->munmap_this)
2940 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
2942 part->mmap_begin = NULL;
2945 part->munmap_this = false;
2950 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2951 size_t k, start, end;
2956 start = ALIGN_TO((size_t) *rindex, align);
2957 end = start + nbytes;
2962 /* Verify that padding is 0 */
2963 for (k = *rindex; k < start; k++)
2964 if (((const uint8_t*) p)[k] != 0)
2968 *r = (uint8_t*) p + start;
2975 static bool message_end_of_signature(sd_bus_message *m) {
2976 struct bus_container *c;
2980 c = message_get_container(m);
2981 return !c->signature || c->signature[c->index] == 0;
2984 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2985 struct bus_container *c;
2989 c = message_get_container(m);
2990 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2993 if (BUS_MESSAGE_IS_GVARIANT(m))
2994 return index >= c->end;
2996 assert(c->array_size);
2997 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3001 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3002 assert_return(m, -EINVAL);
3003 assert_return(m->sealed, -EPERM);
3005 if (complete && m->n_containers > 0)
3008 if (message_end_of_signature(m))
3011 if (message_end_of_array(m, m->rindex))
3017 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3018 struct bus_body_part *part;
3024 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3025 part = m->cached_rindex_part;
3026 begin = m->cached_rindex_part_begin;
3036 if (index + sz <= begin + part->size) {
3038 r = bus_body_part_map(part);
3043 *p = (uint8_t*) part->data + index - begin;
3045 m->cached_rindex_part = part;
3046 m->cached_rindex_part_begin = begin;
3051 begin += part->size;
3058 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3065 if (!BUS_MESSAGE_IS_GVARIANT(m))
3068 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3071 sz = bus_gvariant_get_size(c->signature);
3075 if (c->offset_index+1 >= c->n_offsets)
3078 /* Variable-size array */
3080 alignment = bus_gvariant_get_alignment(c->signature);
3081 assert(alignment > 0);
3083 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3084 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3087 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3090 /* Fixed-size array */
3091 *rindex = c->begin + (c->offset_index+1) * sz;
3097 } else if (c->enclosing == 0 ||
3098 c->enclosing == SD_BUS_TYPE_STRUCT ||
3099 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3104 if (c->offset_index+1 >= c->n_offsets)
3107 r = signature_element_length(c->signature + c->index, &n);
3111 r = signature_element_length(c->signature + c->index + n, &j);
3116 memcpy(t, c->signature + c->index + n, j);
3119 alignment = bus_gvariant_get_alignment(t);
3122 assert(alignment > 0);
3124 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3125 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3129 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3132 assert_not_reached("Unknown container type");
3137 /* Reached the end */
3144 static int message_peek_body(
3151 size_t k, start, end, padding;
3152 struct bus_body_part *part;
3159 start = ALIGN_TO((size_t) *rindex, align);
3160 padding = start - *rindex;
3161 end = start + nbytes;
3163 if (end > BUS_MESSAGE_BODY_SIZE(m))
3166 part = find_part(m, *rindex, padding, (void**) &q);
3171 /* Verify padding */
3172 for (k = 0; k < padding; k++)
3177 part = find_part(m, start, nbytes, (void**) &q);
3178 if (!part || (nbytes > 0 && !q))
3189 static bool validate_nul(const char *s, size_t l) {
3191 /* Check for NUL chars in the string */
3192 if (memchr(s, 0, l))
3195 /* Check for NUL termination */
3202 static bool validate_string(const char *s, size_t l) {
3204 if (!validate_nul(s, l))
3207 /* Check if valid UTF8 */
3208 if (!utf8_is_valid(s))
3214 static bool validate_signature(const char *s, size_t l) {
3216 if (!validate_nul(s, l))
3219 /* Check if valid signature */
3220 if (!signature_is_valid(s, true))
3226 static bool validate_object_path(const char *s, size_t l) {
3228 if (!validate_nul(s, l))
3231 if (!object_path_is_valid(s))
3237 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3238 struct bus_container *c;
3243 assert_return(m, -EINVAL);
3244 assert_return(m->sealed, -EPERM);
3245 assert_return(bus_type_is_basic(type), -EINVAL);
3247 if (message_end_of_signature(m))
3250 if (message_end_of_array(m, m->rindex))
3253 c = message_get_container(m);
3254 if (c->signature[c->index] != type)
3259 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3261 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3264 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3268 if (type == SD_BUS_TYPE_STRING)
3269 ok = validate_string(q, c->item_size-1);
3270 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3271 ok = validate_object_path(q, c->item_size-1);
3273 ok = validate_signature(q, c->item_size-1);
3279 *(const char**) p = q;
3283 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3285 if ((size_t) sz != c->item_size)
3288 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3291 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3297 case SD_BUS_TYPE_BYTE:
3299 *(uint8_t*) p = *(uint8_t*) q;
3302 case SD_BUS_TYPE_BOOLEAN:
3304 *(int*) p = !!*(uint8_t*) q;
3307 case SD_BUS_TYPE_INT16:
3308 case SD_BUS_TYPE_UINT16:
3310 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3313 case SD_BUS_TYPE_INT32:
3314 case SD_BUS_TYPE_UINT32:
3316 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3319 case SD_BUS_TYPE_INT64:
3320 case SD_BUS_TYPE_UINT64:
3321 case SD_BUS_TYPE_DOUBLE:
3323 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3326 case SD_BUS_TYPE_UNIX_FD: {
3329 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3334 *(int*) p = m->fds[j];
3340 assert_not_reached("unexpected type");
3344 r = container_next_item(m, c, &rindex);
3351 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3355 r = message_peek_body(m, &rindex, 4, 4, &q);
3359 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3360 r = message_peek_body(m, &rindex, 1, l+1, &q);
3364 if (type == SD_BUS_TYPE_OBJECT_PATH)
3365 ok = validate_object_path(q, l);
3367 ok = validate_string(q, l);
3372 *(const char**) p = q;
3374 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3377 r = message_peek_body(m, &rindex, 1, 1, &q);
3382 r = message_peek_body(m, &rindex, 1, l+1, &q);
3386 if (!validate_signature(q, l))
3390 *(const char**) p = q;
3395 align = bus_type_get_alignment(type);
3398 sz = bus_type_get_size(type);
3401 r = message_peek_body(m, &rindex, align, sz, &q);
3407 case SD_BUS_TYPE_BYTE:
3409 *(uint8_t*) p = *(uint8_t*) q;
3412 case SD_BUS_TYPE_BOOLEAN:
3414 *(int*) p = !!*(uint32_t*) q;
3417 case SD_BUS_TYPE_INT16:
3418 case SD_BUS_TYPE_UINT16:
3420 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3423 case SD_BUS_TYPE_INT32:
3424 case SD_BUS_TYPE_UINT32:
3426 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3429 case SD_BUS_TYPE_INT64:
3430 case SD_BUS_TYPE_UINT64:
3431 case SD_BUS_TYPE_DOUBLE:
3433 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3436 case SD_BUS_TYPE_UNIX_FD: {
3439 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3444 *(int*) p = m->fds[j];
3449 assert_not_reached("Unknown basic type...");
3456 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3462 static int bus_message_enter_array(
3464 struct bus_container *c,
3465 const char *contents,
3466 uint32_t **array_size,
3469 size_t *n_offsets) {
3483 if (!signature_is_single(contents, true))
3486 if (!c->signature || c->signature[c->index] == 0)
3489 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3492 if (!startswith(c->signature + c->index + 1, contents))
3497 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3500 r = message_peek_body(m, &rindex, 4, 4, &q);
3504 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3507 alignment = bus_type_get_alignment(contents[0]);
3511 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3515 *array_size = (uint32_t*) q;
3517 } else if (c->item_size <= 0) {
3519 /* gvariant: empty array */
3524 } else if (bus_gvariant_is_fixed_size(contents)) {
3526 /* gvariant: fixed length array */
3527 *item_size = bus_gvariant_get_size(contents);
3532 size_t where, p = 0, framing, sz;
3535 /* gvariant: variable length array */
3536 sz = determine_word_size(c->item_size, 0);
3538 where = rindex + c->item_size - sz;
3539 r = message_peek_body(m, &where, 1, sz, &q);
3543 framing = read_word_le(q, sz);
3544 if (framing > c->item_size - sz)
3546 if ((c->item_size - framing) % sz != 0)
3549 *n_offsets = (c->item_size - framing) / sz;
3551 where = rindex + framing;
3552 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3556 *offsets = new(size_t, *n_offsets);
3560 for (i = 0; i < *n_offsets; i++) {
3563 x = read_word_le((uint8_t*) q + i * sz, sz);
3564 if (x > c->item_size - sz)
3569 (*offsets)[i] = rindex + x;
3573 *item_size = (*offsets)[0] - rindex;
3578 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3579 c->index += 1 + strlen(contents);
3584 static int bus_message_enter_variant(
3586 struct bus_container *c,
3587 const char *contents,
3588 size_t *item_size) {
3600 if (!signature_is_single(contents, false))
3603 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3606 if (!c->signature || c->signature[c->index] == 0)
3609 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3614 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3617 k = strlen(contents);
3618 if (1+k > c->item_size)
3621 where = rindex + c->item_size - (1+k);
3622 r = message_peek_body(m, &where, 1, 1+k, &q);
3626 if (*(char*) q != 0)
3629 if (memcmp((uint8_t*) q+1, contents, k))
3632 *item_size = c->item_size - (1+k);
3635 r = message_peek_body(m, &rindex, 1, 1, &q);
3640 r = message_peek_body(m, &rindex, 1, l+1, &q);
3644 if (!validate_signature(q, l))
3647 if (!streq(q, contents))
3653 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3659 static int build_struct_offsets(
3661 const char *signature,
3665 size_t *n_offsets) {
3667 unsigned n_variable = 0, n_total = 0, v;
3668 size_t previous = 0, where;
3679 if (isempty(signature)) {
3686 sz = determine_word_size(size, 0);
3690 /* First, loop over signature and count variable elements and
3691 * elements in general. We use this to know how large the
3692 * offset array is at the end of the structure. Note that
3693 * GVariant only stores offsets for all variable size elements
3694 * that are not the last item. */
3700 r = signature_element_length(p, &n);
3709 r = bus_gvariant_is_fixed_size(t);
3714 if (r == 0 && p[n] != 0) /* except the last item */
3721 if (size < n_variable * sz)
3724 where = m->rindex + size - (n_variable * sz);
3725 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3731 *offsets = new(size_t, n_total);
3737 /* Second, loop again and build an offset table */
3743 r = signature_element_length(p, &n);
3752 k = bus_gvariant_get_size(t);
3760 x = read_word_le((uint8_t*) q + v*sz, sz);
3763 if (m->rindex + x < previous)
3766 /* The last item's end
3767 * is determined from
3770 x = size - (n_variable * sz);
3772 offset = m->rindex + x;
3778 align = bus_gvariant_get_alignment(t);
3781 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3785 previous = (*offsets)[(*n_offsets)++] = offset;
3790 assert(*n_offsets == n_total);
3792 *item_size = (*offsets)[0] - m->rindex;
3796 static int enter_struct_or_dict_entry(
3798 struct bus_container *c,
3799 const char *contents,
3802 size_t *n_offsets) {
3813 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3816 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3820 } else if (c->item_size <= 0) {
3822 /* gvariant empty struct */
3827 /* gvariant with contents */
3828 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3833 static int bus_message_enter_struct(
3835 struct bus_container *c,
3836 const char *contents,
3839 size_t *n_offsets) {
3851 if (!signature_is_valid(contents, false))
3854 if (!c->signature || c->signature[c->index] == 0)
3857 l = strlen(contents);
3859 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3860 !startswith(c->signature + c->index + 1, contents) ||
3861 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3864 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3868 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3869 c->index += 1 + l + 1;
3874 static int bus_message_enter_dict_entry(
3876 struct bus_container *c,
3877 const char *contents,
3880 size_t *n_offsets) {
3889 if (!signature_is_pair(contents))
3892 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3895 if (!c->signature || c->signature[c->index] == 0)
3898 l = strlen(contents);
3900 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3901 !startswith(c->signature + c->index + 1, contents) ||
3902 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3905 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3909 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3910 c->index += 1 + l + 1;
3915 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3917 const char *contents) {
3918 struct bus_container *c, *w;
3919 uint32_t *array_size = NULL;
3922 size_t *offsets = NULL;
3923 size_t n_offsets = 0, item_size = 0;
3926 assert_return(m, -EINVAL);
3927 assert_return(m->sealed, -EPERM);
3928 assert_return(type != 0 || !contents, -EINVAL);
3930 if (type == 0 || !contents) {
3934 /* Allow entering into anonymous containers */
3935 r = sd_bus_message_peek_type(m, &tt, &cc);
3939 if (type != 0 && type != tt)
3942 if (contents && !streq(contents, cc))
3950 * We enforce a global limit on container depth, that is much
3951 * higher than the 32 structs and 32 arrays the specification
3952 * mandates. This is simpler to implement for us, and we need
3953 * this only to ensure our container array doesn't grow
3954 * without bounds. We are happy to return any data from a
3955 * message as long as the data itself is valid, even if the
3956 * overall message might be not.
3958 * Note that the message signature is validated when
3959 * parsing the headers, and that validation does check the
3962 * Note that the specification defines no limits on the depth
3963 * of stacked variants, but we do.
3965 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3968 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3971 if (message_end_of_signature(m))
3974 if (message_end_of_array(m, m->rindex))
3977 c = message_get_container(m);
3979 signature = strdup(contents);
3983 c->saved_index = c->index;
3986 if (type == SD_BUS_TYPE_ARRAY)
3987 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3988 else if (type == SD_BUS_TYPE_VARIANT)
3989 r = bus_message_enter_variant(m, c, contents, &item_size);
3990 else if (type == SD_BUS_TYPE_STRUCT)
3991 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3992 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3993 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4003 /* OK, let's fill it in */
4004 w = m->containers + m->n_containers++;
4005 w->enclosing = type;
4006 w->signature = signature;
4007 w->peeked_signature = NULL;
4011 w->begin = m->rindex;
4012 w->end = m->rindex + c->item_size;
4014 w->array_size = array_size;
4015 w->item_size = item_size;
4016 w->offsets = offsets;
4017 w->n_offsets = n_offsets;
4018 w->offset_index = 0;
4023 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4024 struct bus_container *c;
4028 assert_return(m, -EINVAL);
4029 assert_return(m->sealed, -EPERM);
4030 assert_return(m->n_containers > 0, -ENXIO);
4032 c = message_get_container(m);
4034 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4035 if (c->signature && c->signature[c->index] != 0)
4039 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4040 if (m->rindex < c->end)
4043 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4046 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4047 if (c->begin + l != m->rindex)
4052 free(c->peeked_signature);
4056 c = message_get_container(m);
4059 c->index = c->saved_index;
4060 r = container_next_item(m, c, &m->rindex);
4068 static void message_quit_container(sd_bus_message *m) {
4069 struct bus_container *c;
4073 assert(m->n_containers > 0);
4075 c = message_get_container(m);
4078 assert(m->rindex >= c->before);
4079 m->rindex = c->before;
4081 /* Free container */
4086 /* Correct index of new top-level container */
4087 c = message_get_container(m);
4088 c->index = c->saved_index;
4091 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4092 struct bus_container *c;
4095 assert_return(m, -EINVAL);
4096 assert_return(m->sealed, -EPERM);
4098 if (message_end_of_signature(m))
4101 if (message_end_of_array(m, m->rindex))
4104 c = message_get_container(m);
4106 if (bus_type_is_basic(c->signature[c->index])) {
4110 *type = c->signature[c->index];
4114 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4120 r = signature_element_length(c->signature+c->index+1, &l);
4126 sig = strndup(c->signature + c->index + 1, l);
4130 free(c->peeked_signature);
4131 *contents = c->peeked_signature = sig;
4135 *type = SD_BUS_TYPE_ARRAY;
4140 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4141 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4147 r = signature_element_length(c->signature+c->index, &l);
4152 sig = strndup(c->signature + c->index + 1, l - 2);
4156 free(c->peeked_signature);
4157 *contents = c->peeked_signature = sig;
4161 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4166 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4170 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4173 if (c->item_size < 2)
4176 /* Look for the NUL delimiter that
4177 separates the payload from the
4178 signature. Since the body might be
4179 in a different part that then the
4180 signature we map byte by byte. */
4182 for (k = 2; k <= c->item_size; k++) {
4185 where = m->rindex + c->item_size - k;
4186 r = message_peek_body(m, &where, 1, k, &q);
4190 if (*(char*) q == 0)
4194 if (k > c->item_size)
4197 free(c->peeked_signature);
4198 c->peeked_signature = strndup((char*) q + 1, k - 1);
4199 if (!c->peeked_signature)
4202 if (!signature_is_valid(c->peeked_signature, true))
4205 *contents = c->peeked_signature;
4210 r = message_peek_body(m, &rindex, 1, 1, &q);
4215 r = message_peek_body(m, &rindex, 1, l+1, &q);
4219 if (!validate_signature(q, l))
4227 *type = SD_BUS_TYPE_VARIANT;
4242 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4243 struct bus_container *c;
4245 assert_return(m, -EINVAL);
4246 assert_return(m->sealed, -EPERM);
4249 message_reset_containers(m);
4252 c = message_get_container(m);
4254 c = message_get_container(m);
4256 c->offset_index = 0;
4258 m->rindex = c->begin;
4261 c->offset_index = 0;
4262 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4264 return !isempty(c->signature);
4267 static int message_read_ap(
4272 unsigned n_array, n_struct;
4273 TypeStack stack[BUS_CONTAINER_DEPTH];
4274 unsigned stack_ptr = 0;
4275 unsigned n_loop = 0;
4283 /* Ideally, we'd just call ourselves recursively on every
4284 * complex type. However, the state of a va_list that is
4285 * passed to a function is undefined after that function
4286 * returns. This means we need to docode the va_list linearly
4287 * in a single stackframe. We hence implement our own
4288 * home-grown stack in an array. */
4290 n_array = (unsigned) -1; /* length of current array entries */
4291 n_struct = strlen(types); /* length of current struct contents signature */
4298 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4299 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4305 r = sd_bus_message_exit_container(m);
4313 if (n_array != (unsigned) -1)
4322 case SD_BUS_TYPE_BYTE:
4323 case SD_BUS_TYPE_BOOLEAN:
4324 case SD_BUS_TYPE_INT16:
4325 case SD_BUS_TYPE_UINT16:
4326 case SD_BUS_TYPE_INT32:
4327 case SD_BUS_TYPE_UINT32:
4328 case SD_BUS_TYPE_INT64:
4329 case SD_BUS_TYPE_UINT64:
4330 case SD_BUS_TYPE_DOUBLE:
4331 case SD_BUS_TYPE_STRING:
4332 case SD_BUS_TYPE_OBJECT_PATH:
4333 case SD_BUS_TYPE_SIGNATURE:
4334 case SD_BUS_TYPE_UNIX_FD: {
4337 p = va_arg(ap, void*);
4338 r = sd_bus_message_read_basic(m, *t, p);
4351 case SD_BUS_TYPE_ARRAY: {
4354 r = signature_element_length(t + 1, &k);
4360 memcpy(s, t + 1, k);
4363 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4374 if (n_array == (unsigned) -1) {
4379 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4385 n_array = va_arg(ap, unsigned);
4390 case SD_BUS_TYPE_VARIANT: {
4393 s = va_arg(ap, const char *);
4397 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4407 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4412 n_struct = strlen(s);
4413 n_array = (unsigned) -1;
4418 case SD_BUS_TYPE_STRUCT_BEGIN:
4419 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4422 r = signature_element_length(t, &k);
4428 memcpy(s, t + 1, k - 2);
4431 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4441 if (n_array == (unsigned) -1) {
4446 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4452 n_array = (unsigned) -1;
4465 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4469 assert_return(m, -EINVAL);
4470 assert_return(m->sealed, -EPERM);
4471 assert_return(types, -EINVAL);
4473 va_start(ap, types);
4474 r = message_read_ap(m, types, ap);
4480 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4483 assert_return(m, -EINVAL);
4484 assert_return(m->sealed, -EPERM);
4486 /* If types is NULL, read exactly one element */
4488 struct bus_container *c;
4491 if (message_end_of_signature(m))
4494 if (message_end_of_array(m, m->rindex))
4497 c = message_get_container(m);
4499 r = signature_element_length(c->signature + c->index, &l);
4503 types = strndupa(c->signature + c->index, l);
4508 case 0: /* Nothing to drop */
4511 case SD_BUS_TYPE_BYTE:
4512 case SD_BUS_TYPE_BOOLEAN:
4513 case SD_BUS_TYPE_INT16:
4514 case SD_BUS_TYPE_UINT16:
4515 case SD_BUS_TYPE_INT32:
4516 case SD_BUS_TYPE_UINT32:
4517 case SD_BUS_TYPE_INT64:
4518 case SD_BUS_TYPE_UINT64:
4519 case SD_BUS_TYPE_DOUBLE:
4520 case SD_BUS_TYPE_STRING:
4521 case SD_BUS_TYPE_OBJECT_PATH:
4522 case SD_BUS_TYPE_SIGNATURE:
4523 case SD_BUS_TYPE_UNIX_FD:
4525 r = sd_bus_message_read_basic(m, *types, NULL);
4529 r = sd_bus_message_skip(m, types + 1);
4535 case SD_BUS_TYPE_ARRAY: {
4538 r = signature_element_length(types + 1, &k);
4544 memcpy(s, types+1, k);
4547 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4552 r = sd_bus_message_skip(m, s);
4559 r = sd_bus_message_exit_container(m);
4564 r = sd_bus_message_skip(m, types + 1 + k);
4571 case SD_BUS_TYPE_VARIANT: {
4572 const char *contents;
4575 r = sd_bus_message_peek_type(m, &x, &contents);
4579 if (x != SD_BUS_TYPE_VARIANT)
4582 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4586 r = sd_bus_message_skip(m, contents);
4591 r = sd_bus_message_exit_container(m);
4595 r = sd_bus_message_skip(m, types + 1);
4602 case SD_BUS_TYPE_STRUCT_BEGIN:
4603 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4606 r = signature_element_length(types, &k);
4612 memcpy(s, types+1, k-2);
4615 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4619 r = sd_bus_message_skip(m, s);
4624 r = sd_bus_message_exit_container(m);
4629 r = sd_bus_message_skip(m, types + k);
4641 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4645 struct bus_container *c;
4651 assert_return(m, -EINVAL);
4652 assert_return(m->sealed, -EPERM);
4653 assert_return(bus_type_is_trivial(type), -EINVAL);
4654 assert_return(ptr, -EINVAL);
4655 assert_return(size, -EINVAL);
4656 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4658 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4662 c = message_get_container(m);
4664 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4665 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4669 sz = c->end - c->begin;
4671 align = bus_type_get_alignment(type);
4675 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4679 /* Zero length array, let's return some aligned
4680 * pointer that is not NULL */
4681 p = (uint8_t*) NULL + align;
4683 r = message_peek_body(m, &m->rindex, align, sz, &p);
4688 r = sd_bus_message_exit_container(m);
4692 *ptr = (const void*) p;
4698 message_quit_container(m);
4702 static int message_peek_fields(
4713 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4716 static int message_peek_field_uint32(
4728 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4731 /* identical for gvariant and dbus1 */
4733 r = message_peek_fields(m, ri, 4, 4, &q);
4738 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4743 static int message_peek_field_string(
4745 bool (*validate)(const char *p),
4757 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4762 r = message_peek_fields(m, ri, 1, item_size, &q);
4768 r = message_peek_field_uint32(m, ri, 4, &l);
4772 r = message_peek_fields(m, ri, 1, l+1, &q);
4778 if (!validate_nul(q, l))
4784 if (!validate_string(q, l))
4794 static int message_peek_field_signature(
4807 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4812 r = message_peek_fields(m, ri, 1, item_size, &q);
4818 r = message_peek_fields(m, ri, 1, 1, &q);
4823 r = message_peek_fields(m, ri, 1, l+1, &q);
4828 if (!validate_signature(q, l))
4837 static int message_skip_fields(
4840 uint32_t array_size,
4841 const char **signature) {
4843 size_t original_index;
4849 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4851 original_index = *ri;
4857 if (array_size != (uint32_t) -1 &&
4858 array_size <= *ri - original_index)
4865 if (t == SD_BUS_TYPE_STRING) {
4867 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4873 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4875 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4881 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4883 r = message_peek_field_signature(m, ri, 0, NULL);
4889 } else if (bus_type_is_basic(t)) {
4892 align = bus_type_get_alignment(t);
4893 k = bus_type_get_size(t);
4894 assert(align > 0 && k > 0);
4896 r = message_peek_fields(m, ri, align, k, NULL);
4902 } else if (t == SD_BUS_TYPE_ARRAY) {
4904 r = signature_element_length(*signature+1, &l);
4914 strncpy(sig, *signature + 1, l-1);
4917 alignment = bus_type_get_alignment(sig[0]);
4921 r = message_peek_field_uint32(m, ri, 0, &nas);
4924 if (nas > BUS_ARRAY_MAX_SIZE)
4927 r = message_peek_fields(m, ri, alignment, 0, NULL);
4931 r = message_skip_fields(m, ri, nas, (const char**) &s);
4936 (*signature) += 1 + l;
4938 } else if (t == SD_BUS_TYPE_VARIANT) {
4941 r = message_peek_field_signature(m, ri, 0, &s);
4945 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4951 } else if (t == SD_BUS_TYPE_STRUCT ||
4952 t == SD_BUS_TYPE_DICT_ENTRY) {
4954 r = signature_element_length(*signature, &l);
4961 strncpy(sig, *signature + 1, l-1);
4964 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4975 int bus_message_parse_fields(sd_bus_message *m) {
4978 uint32_t unix_fds = 0;
4979 bool unix_fds_set = false;
4980 void *offsets = NULL;
4981 unsigned n_offsets = 0;
4987 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4990 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4994 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4995 r = message_peek_fields(m, &ri, 1, sz, &q);
4999 framing = read_word_le(q, sz);
5000 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
5002 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
5006 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
5010 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
5015 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
5016 _cleanup_free_ char *sig = NULL;
5017 const char *signature;
5019 size_t item_size = (size_t) -1;
5021 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5028 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5031 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
5035 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5040 end = read_word_le((uint8_t*) offsets + i*sz, sz);
5045 where = ri = ALIGN_TO(ri, 8);
5046 item_size = end - ri;
5047 r = message_peek_fields(m, &where, 1, item_size, &q);
5051 b = memrchr(q, 0, item_size);
5055 sig = strndup(b+1, item_size - (b+1-(char*) q));
5060 item_size = b - (char*) q;
5062 r = message_peek_field_signature(m, &ri, 0, &signature);
5068 case _BUS_MESSAGE_HEADER_INVALID:
5071 case BUS_MESSAGE_HEADER_PATH:
5076 if (!streq(signature, "o"))
5079 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5082 case BUS_MESSAGE_HEADER_INTERFACE:
5087 if (!streq(signature, "s"))
5090 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5093 case BUS_MESSAGE_HEADER_MEMBER:
5098 if (!streq(signature, "s"))
5101 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5104 case BUS_MESSAGE_HEADER_ERROR_NAME:
5109 if (!streq(signature, "s"))
5112 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5114 m->error._need_free = -1;
5118 case BUS_MESSAGE_HEADER_DESTINATION:
5123 if (!streq(signature, "s"))
5126 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5129 case BUS_MESSAGE_HEADER_SENDER:
5134 if (!streq(signature, "s"))
5137 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5139 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5140 m->creds.unique_name = (char*) m->sender;
5141 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5147 case BUS_MESSAGE_HEADER_SIGNATURE: {
5151 if (m->root_container.signature)
5154 if (!streq(signature, "g"))
5157 r = message_peek_field_signature(m, &ri, item_size, &s);
5165 free(m->root_container.signature);
5166 m->root_container.signature = c;
5170 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5173 if (m->reply_cookie != 0)
5176 if (!streq(signature, "u"))
5179 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5183 m->reply_cookie = serial;
5185 if (m->reply_cookie == 0)
5191 case BUS_MESSAGE_HEADER_UNIX_FDS:
5195 if (!streq(signature, "u"))
5198 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5202 unix_fds_set = true;
5206 if (!BUS_MESSAGE_IS_GVARIANT(m))
5207 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5216 if (m->n_fds != unix_fds)
5219 switch (m->header->type) {
5221 case SD_BUS_MESSAGE_SIGNAL:
5222 if (!m->path || !m->interface || !m->member)
5225 if (m->reply_cookie != 0)
5230 case SD_BUS_MESSAGE_METHOD_CALL:
5232 if (!m->path || !m->member)
5235 if (m->reply_cookie != 0)
5240 case SD_BUS_MESSAGE_METHOD_RETURN:
5242 if (m->reply_cookie == 0)
5246 case SD_BUS_MESSAGE_METHOD_ERROR:
5248 if (m->reply_cookie == 0 || !m->error.name)
5253 /* Refuse non-local messages that claim they are local */
5254 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5256 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5258 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5261 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5263 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5264 r = build_struct_offsets(
5266 m->root_container.signature,
5267 BUS_MESSAGE_BODY_SIZE(m),
5268 &m->root_container.item_size,
5269 &m->root_container.offsets,
5270 &m->root_container.n_offsets);
5275 /* Try to read the error message, but if we can't it's a non-issue */
5276 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5277 sd_bus_message_read(m, "s", &m->error.message);
5282 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5283 assert_return(m, -EINVAL);
5284 assert_return(destination, -EINVAL);
5285 assert_return(!m->sealed, -EPERM);
5286 assert_return(!m->destination, -EEXIST);
5288 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5291 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5295 struct bus_body_part *part;
5301 total = BUS_MESSAGE_SIZE(m);
5307 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5308 MESSAGE_FOREACH_PART(part, i, m)
5309 e = mempcpy(e, part->data, part->size);
5311 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5319 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5325 r = sd_bus_message_enter_container(m, 'a', "s");
5332 r = sd_bus_message_read_basic(m, 's', &s);
5338 r = strv_extend(l, s);
5343 r = sd_bus_message_exit_container(m);
5350 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5354 assert_return(m, -EINVAL);
5355 assert_return(m->sealed, -EPERM);
5356 assert_return(l, -EINVAL);
5358 r = bus_message_read_strv_extend(m, &strv);
5368 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5369 const char *contents;
5378 r = sd_bus_message_rewind(m, true);
5383 r = sd_bus_message_peek_type(m, &type, &contents);
5389 /* Don't match against arguments after the first one we don't understand */
5390 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5391 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5397 r = sd_bus_message_skip(m, NULL);
5402 if (type == SD_BUS_TYPE_ARRAY) {
5404 r = sd_bus_message_read_strv(m, strv);
5411 r = sd_bus_message_read_basic(m, type, str);
5421 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5427 if (size < sizeof(struct bus_header))
5430 full = sizeof(struct bus_header) +
5431 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5433 return size >= full;
5436 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5442 if (h->endian == BUS_NATIVE_ENDIAN) {
5443 fs = h->fields_size;
5445 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5446 fs = bswap_32(h->fields_size);
5447 bs = bswap_32(h->body_size);
5451 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5455 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5456 assert_return(m, EINVAL);
5458 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5461 return sd_bus_error_get_errno(&m->error);
5464 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5465 struct bus_container *c;
5467 assert_return(m, NULL);
5469 c = complete ? &m->root_container : message_get_container(m);
5470 return strempty(c->signature);
5473 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5474 assert_return(m, -EINVAL);
5476 return isempty(m->root_container.signature);
5479 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5480 assert_return(m, -EINVAL);
5482 return streq(strempty(m->root_container.signature), strempty(signature));
5485 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5486 bool done_something = false;
5489 assert_return(m, -EINVAL);
5490 assert_return(source, -EINVAL);
5491 assert_return(!m->sealed, -EPERM);
5492 assert_return(source->sealed, -EPERM);
5495 const char *contents;
5510 r = sd_bus_message_peek_type(source, &type, &contents);
5516 done_something = true;
5518 if (bus_type_is_container(type) > 0) {
5520 r = sd_bus_message_enter_container(source, type, contents);
5524 r = sd_bus_message_open_container(m, type, contents);
5528 r = sd_bus_message_copy(m, source, true);
5532 r = sd_bus_message_close_container(m);
5536 r = sd_bus_message_exit_container(source);
5543 r = sd_bus_message_read_basic(source, type, &basic);
5549 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5550 type == SD_BUS_TYPE_SIGNATURE ||
5551 type == SD_BUS_TYPE_STRING)
5552 r = sd_bus_message_append_basic(m, type, basic.string);
5554 r = sd_bus_message_append_basic(m, type, &basic);
5561 return done_something;
5564 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5569 assert_return(m, -EINVAL);
5570 assert_return(m->sealed, -EPERM);
5571 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5572 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5573 assert_return(type || contents, -EINVAL);
5574 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5576 r = sd_bus_message_peek_type(m, &t, &c);
5580 if (type != 0 && type != t)
5583 if (contents && !streq_ptr(contents, c))
5589 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5590 assert_return(m, NULL);
5595 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5596 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5604 switch ((*m)->header->type) {
5606 case SD_BUS_MESSAGE_SIGNAL:
5607 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5613 case SD_BUS_MESSAGE_METHOD_CALL:
5614 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5620 case SD_BUS_MESSAGE_METHOD_RETURN:
5621 case SD_BUS_MESSAGE_METHOD_ERROR:
5623 n = message_new(bus, (*m)->header->type);
5627 n->reply_cookie = (*m)->reply_cookie;
5628 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5632 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5633 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5637 n->error._need_free = -1;
5646 if ((*m)->destination && !n->destination) {
5647 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5652 if ((*m)->sender && !n->sender) {
5653 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5658 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5660 r = sd_bus_message_copy(n, *m, true);
5664 timeout = (*m)->timeout;
5665 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5666 timeout = BUS_DEFAULT_TIMEOUT;
5668 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5672 sd_bus_message_unref(*m);
5679 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5683 assert_return(!m->sealed, -EPERM);
5684 assert_return(!m->sender, -EPERM);
5686 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5689 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5690 assert_return(m, -EINVAL);
5691 assert_return(priority, -EINVAL);
5693 *priority = m->priority;
5697 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5698 assert_return(m, -EINVAL);
5699 assert_return(!m->sealed, -EPERM);
5701 m->priority = priority;