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.euid = ucred->uid;
428 m->creds.egid = 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.euid != UID_INVALID)
436 m->creds.mask |= SD_BUS_CREDS_EUID;
438 if (m->creds.egid != GID_INVALID)
439 m->creds.mask |= SD_BUS_CREDS_EGID;
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 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
761 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
762 m->creds.well_known_names_local = true;
763 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
766 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
770 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
771 m->creds.well_known_names_driver = true;
772 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
775 int bus_message_new_synthetic_error(
778 const sd_bus_error *e,
779 sd_bus_message **m) {
785 assert(sd_bus_error_is_set(e));
788 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
792 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
793 t->reply_cookie = cookie;
795 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
799 if (bus && bus->unique_name) {
800 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
805 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
810 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
815 t->error._need_free = -1;
817 bus_message_set_sender_driver(bus, t);
827 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
828 assert_return(m, NULL);
830 assert(m->n_ref > 0);
836 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
841 assert(m->n_ref > 0);
851 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
852 assert_return(m, -EINVAL);
853 assert_return(type, -EINVAL);
855 *type = m->header->type;
859 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
860 assert_return(m, -EINVAL);
861 assert_return(cookie, -EINVAL);
862 assert_return(m->header->serial != 0, -ENODATA);
864 *cookie = BUS_MESSAGE_COOKIE(m);
868 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
869 assert_return(m, -EINVAL);
870 assert_return(cookie, -EINVAL);
871 assert_return(m->reply_cookie != 0, -ENODATA);
873 *cookie = m->reply_cookie;
877 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
878 assert_return(m, -EINVAL);
880 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
881 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
884 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
885 assert_return(m, -EINVAL);
887 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
890 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
891 assert_return(m, -EINVAL);
893 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
894 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
897 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
898 assert_return(m, NULL);
903 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
904 assert_return(m, NULL);
909 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
910 assert_return(m, NULL);
915 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
916 assert_return(m, NULL);
918 return m->destination;
921 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
922 assert_return(m, NULL);
927 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
928 assert_return(m, NULL);
929 assert_return(sd_bus_error_is_set(&m->error), NULL);
934 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
935 assert_return(m, -EINVAL);
936 assert_return(usec, -EINVAL);
938 if (m->monotonic <= 0)
941 *usec = m->monotonic;
945 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
946 assert_return(m, -EINVAL);
947 assert_return(usec, -EINVAL);
949 if (m->realtime <= 0)
956 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
957 assert_return(m, -EINVAL);
958 assert_return(seqnum, -EINVAL);
967 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
968 assert_return(m, NULL);
970 if (m->creds.mask == 0)
976 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
977 const char *interface,
978 const char *member) {
979 assert_return(m, -EINVAL);
981 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
984 if (interface && (!m->interface || !streq(m->interface, interface)))
987 if (member && (!m->member || !streq(m->member, member)))
993 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
994 const char *interface,
995 const char *member) {
996 assert_return(m, -EINVAL);
998 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1001 if (interface && (!m->interface || !streq(m->interface, interface)))
1004 if (member && (!m->member || !streq(m->member, member)))
1010 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1011 assert_return(m, -EINVAL);
1013 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1016 if (name && (!m->error.name || !streq(m->error.name, name)))
1022 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1023 assert_return(m, -EINVAL);
1024 assert_return(!m->sealed, -EPERM);
1025 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1028 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1030 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1035 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1036 assert_return(m, -EINVAL);
1037 assert_return(!m->sealed, -EPERM);
1040 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1042 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1047 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1048 assert_return(m, -EINVAL);
1049 assert_return(!m->sealed, -EPERM);
1052 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1054 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1059 static struct bus_container *message_get_container(sd_bus_message *m) {
1062 if (m->n_containers == 0)
1063 return &m->root_container;
1065 assert(m->containers);
1066 return m->containers + m->n_containers - 1;
1069 struct bus_body_part *message_append_part(sd_bus_message *m) {
1070 struct bus_body_part *part;
1077 if (m->n_body_parts <= 0) {
1081 assert(m->body_end);
1083 part = new0(struct bus_body_part, 1);
1089 m->body_end->next = part;
1099 static void part_zero(struct bus_body_part *part, size_t sz) {
1104 /* All other fields can be left in their defaults */
1105 assert(!part->data);
1106 assert(part->memfd < 0);
1109 part->is_zero = true;
1110 part->sealed = true;
1113 static int part_make_space(
1114 struct sd_bus_message *m,
1115 struct bus_body_part *part,
1124 assert(!part->sealed);
1129 if (!part->data && part->memfd < 0) {
1130 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1131 part->mmap_begin = part->data;
1134 if (part->memfd >= 0) {
1136 if (part->allocated == 0 || sz > part->allocated) {
1137 uint64_t new_allocated;
1139 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1140 r = memfd_set_size(part->memfd, new_allocated);
1146 part->allocated = new_allocated;
1149 if (!part->data || sz > part->mapped) {
1152 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1153 if (part->mapped <= 0)
1154 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1156 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1158 if (n == MAP_FAILED) {
1163 part->mmap_begin = part->data = n;
1165 part->memfd_offset = 0;
1168 part->munmap_this = true;
1170 if (part->allocated == 0 || sz > part->allocated) {
1171 size_t new_allocated;
1173 new_allocated = sz > 0 ? 2 * sz : 64;
1174 n = realloc(part->data, new_allocated);
1181 part->allocated = new_allocated;
1182 part->free_this = true;
1187 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1193 static int message_add_offset(sd_bus_message *m, size_t offset) {
1194 struct bus_container *c;
1197 assert(BUS_MESSAGE_IS_GVARIANT(m));
1199 /* Add offset to current container, unless this is the first
1200 * item in it, which will have the 0 offset, which we can
1202 c = message_get_container(m);
1204 if (!c->need_offsets)
1207 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1210 c->offsets[c->n_offsets++] = offset;
1214 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1215 struct bus_container *c;
1222 /* Update counters */
1223 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1226 *c->array_size += expand;
1230 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1231 size_t start_body, end_body, padding, added;
1242 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1243 end_body = start_body + sz;
1245 padding = start_body - m->header->body_size;
1246 added = padding + sz;
1248 /* Check for 32bit overflows */
1249 if (end_body > (size_t) ((uint32_t) -1)) {
1255 struct bus_body_part *part = NULL;
1259 m->n_body_parts <= 0 ||
1260 m->body_end->sealed ||
1261 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1265 part = message_append_part(m);
1269 part_zero(part, padding);
1272 part = message_append_part(m);
1276 r = part_make_space(m, part, sz, &p);
1280 struct bus_container *c;
1282 size_t os, start_part, end_part;
1288 start_part = ALIGN_TO(part->size, align);
1289 end_part = start_part + sz;
1291 r = part_make_space(m, part, end_part, &p);
1296 memzero(p, padding);
1297 p = (uint8_t*) p + padding;
1300 /* Readjust pointers */
1301 for (c = m->containers; c < m->containers + m->n_containers; c++)
1302 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1304 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1307 /* Return something that is not NULL and is aligned */
1308 p = (uint8_t *) NULL + align;
1310 m->header->body_size = end_body;
1311 message_extend_containers(m, added);
1314 r = message_add_offset(m, end_body);
1324 static int message_push_fd(sd_bus_message *m, int fd) {
1335 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1339 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1347 m->fds[m->n_fds] = copy;
1353 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1354 _cleanup_close_ int fd = -1;
1355 struct bus_container *c;
1359 assert_return(m, -EINVAL);
1360 assert_return(!m->sealed, -EPERM);
1361 assert_return(bus_type_is_basic(type), -EINVAL);
1362 assert_return(!m->poisoned, -ESTALE);
1364 c = message_get_container(m);
1366 if (c->signature && c->signature[c->index]) {
1367 /* Container signature is already set */
1369 if (c->signature[c->index] != type)
1374 /* Maybe we can append to the signature? But only if this is the top-level container */
1375 if (c->enclosing != 0)
1378 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1385 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1391 case SD_BUS_TYPE_SIGNATURE:
1392 case SD_BUS_TYPE_STRING:
1395 /* Fall through... */
1396 case SD_BUS_TYPE_OBJECT_PATH:
1404 case SD_BUS_TYPE_BOOLEAN:
1406 u8 = p && *(int*) p;
1412 case SD_BUS_TYPE_UNIX_FD:
1417 fd = message_push_fd(m, *(int*) p);
1428 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1429 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1436 a = message_extend_body(m, align, sz, true);
1443 *stored = (const uint8_t*) a;
1450 case SD_BUS_TYPE_STRING:
1451 /* To make things easy we'll serialize a NULL string
1452 * into the empty string */
1455 /* Fall through... */
1456 case SD_BUS_TYPE_OBJECT_PATH:
1462 sz = 4 + strlen(p) + 1;
1465 case SD_BUS_TYPE_SIGNATURE:
1470 sz = 1 + strlen(p) + 1;
1473 case SD_BUS_TYPE_BOOLEAN:
1475 u32 = p && *(int*) p;
1481 case SD_BUS_TYPE_UNIX_FD:
1486 fd = message_push_fd(m, *(int*) p);
1497 align = bus_type_get_alignment(type);
1498 sz = bus_type_get_size(type);
1505 a = message_extend_body(m, align, sz, false);
1509 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1510 *(uint32_t*) a = sz - 5;
1511 memcpy((uint8_t*) a + 4, p, sz - 4);
1514 *stored = (const uint8_t*) a + 4;
1516 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1517 *(uint8_t*) a = sz - 2;
1518 memcpy((uint8_t*) a + 1, p, sz - 1);
1521 *stored = (const uint8_t*) a + 1;
1530 if (type == SD_BUS_TYPE_UNIX_FD)
1533 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1540 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1541 return message_append_basic(m, type, p, NULL);
1544 _public_ int sd_bus_message_append_string_space(
1549 struct bus_container *c;
1552 assert_return(m, -EINVAL);
1553 assert_return(s, -EINVAL);
1554 assert_return(!m->sealed, -EPERM);
1555 assert_return(!m->poisoned, -ESTALE);
1557 c = message_get_container(m);
1559 if (c->signature && c->signature[c->index]) {
1560 /* Container signature is already set */
1562 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1567 /* Maybe we can append to the signature? But only if this is the top-level container */
1568 if (c->enclosing != 0)
1571 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1578 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1579 a = message_extend_body(m, 1, size + 1, true);
1585 a = message_extend_body(m, 4, 4 + size + 1, false);
1589 *(uint32_t*) a = size;
1595 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1601 _public_ int sd_bus_message_append_string_iovec(
1603 const struct iovec *iov,
1611 assert_return(m, -EINVAL);
1612 assert_return(!m->sealed, -EPERM);
1613 assert_return(iov || n == 0, -EINVAL);
1614 assert_return(!m->poisoned, -ESTALE);
1616 size = IOVEC_TOTAL_SIZE(iov, n);
1618 r = sd_bus_message_append_string_space(m, size, &p);
1622 for (i = 0; i < n; i++) {
1624 if (iov[i].iov_base)
1625 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1627 memset(p, ' ', iov[i].iov_len);
1629 p += iov[i].iov_len;
1635 static int bus_message_open_array(
1637 struct bus_container *c,
1638 const char *contents,
1639 uint32_t **array_size,
1641 bool *need_offsets) {
1651 assert(need_offsets);
1653 if (!signature_is_single(contents, true))
1656 if (c->signature && c->signature[c->index]) {
1658 /* Verify the existing signature */
1660 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1663 if (!startswith(c->signature + c->index + 1, contents))
1666 nindex = c->index + 1 + strlen(contents);
1670 if (c->enclosing != 0)
1673 /* Extend the existing signature */
1675 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1681 nindex = e - c->signature;
1684 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1685 alignment = bus_gvariant_get_alignment(contents);
1689 /* Add alignment padding and add to offset list */
1690 if (!message_extend_body(m, alignment, 0, false))
1693 r = bus_gvariant_is_fixed_size(contents);
1697 *begin = m->header->body_size;
1698 *need_offsets = r == 0;
1702 struct bus_body_part *o;
1704 alignment = bus_type_get_alignment(contents[0]);
1708 a = message_extend_body(m, 4, 4, false);
1713 op = m->body_end->data;
1714 os = m->body_end->size;
1716 /* Add alignment between size and first element */
1717 if (!message_extend_body(m, alignment, 0, false))
1720 /* location of array size might have changed so let's readjust a */
1721 if (o == m->body_end)
1722 a = adjust_pointer(a, op, os, m->body_end->data);
1728 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1734 static int bus_message_open_variant(
1736 struct bus_container *c,
1737 const char *contents) {
1743 if (!signature_is_single(contents, false))
1746 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1749 if (c->signature && c->signature[c->index]) {
1751 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1757 if (c->enclosing != 0)
1760 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1767 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1768 /* Variants are always aligned to 8 */
1770 if (!message_extend_body(m, 8, 0, false))
1777 l = strlen(contents);
1778 a = message_extend_body(m, 1, 1 + l + 1, false);
1783 memcpy((uint8_t*) a + 1, contents, l + 1);
1786 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1792 static int bus_message_open_struct(
1794 struct bus_container *c,
1795 const char *contents,
1797 bool *need_offsets) {
1806 assert(need_offsets);
1808 if (!signature_is_valid(contents, false))
1811 if (c->signature && c->signature[c->index]) {
1814 l = strlen(contents);
1816 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1817 !startswith(c->signature + c->index + 1, contents) ||
1818 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1821 nindex = c->index + 1 + l + 1;
1825 if (c->enclosing != 0)
1828 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1834 nindex = e - c->signature;
1837 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1840 alignment = bus_gvariant_get_alignment(contents);
1844 if (!message_extend_body(m, alignment, 0, false))
1847 r = bus_gvariant_is_fixed_size(contents);
1851 *begin = m->header->body_size;
1852 *need_offsets = r == 0;
1854 /* Align contents to 8 byte boundary */
1855 if (!message_extend_body(m, 8, 0, false))
1859 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1865 static int bus_message_open_dict_entry(
1867 struct bus_container *c,
1868 const char *contents,
1870 bool *need_offsets) {
1878 assert(need_offsets);
1880 if (!signature_is_pair(contents))
1883 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1886 if (c->signature && c->signature[c->index]) {
1889 l = strlen(contents);
1891 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1892 !startswith(c->signature + c->index + 1, contents) ||
1893 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1898 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1901 alignment = bus_gvariant_get_alignment(contents);
1905 if (!message_extend_body(m, alignment, 0, false))
1908 r = bus_gvariant_is_fixed_size(contents);
1912 *begin = m->header->body_size;
1913 *need_offsets = r == 0;
1915 /* Align contents to 8 byte boundary */
1916 if (!message_extend_body(m, 8, 0, false))
1923 _public_ int sd_bus_message_open_container(
1926 const char *contents) {
1928 struct bus_container *c, *w;
1929 uint32_t *array_size = NULL;
1931 size_t before, begin = 0;
1932 bool need_offsets = false;
1935 assert_return(m, -EINVAL);
1936 assert_return(!m->sealed, -EPERM);
1937 assert_return(contents, -EINVAL);
1938 assert_return(!m->poisoned, -ESTALE);
1940 /* Make sure we have space for one more container */
1941 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1946 c = message_get_container(m);
1948 signature = strdup(contents);
1954 /* Save old index in the parent container, in case we have to
1955 * abort this container */
1956 c->saved_index = c->index;
1957 before = m->header->body_size;
1959 if (type == SD_BUS_TYPE_ARRAY)
1960 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1961 else if (type == SD_BUS_TYPE_VARIANT)
1962 r = bus_message_open_variant(m, c, contents);
1963 else if (type == SD_BUS_TYPE_STRUCT)
1964 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1965 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1966 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1975 /* OK, let's fill it in */
1976 w = m->containers + m->n_containers++;
1977 w->enclosing = type;
1978 w->signature = signature;
1980 w->array_size = array_size;
1983 w->n_offsets = w->offsets_allocated = 0;
1985 w->need_offsets = need_offsets;
1990 static size_t determine_word_size(size_t sz, size_t extra) {
1991 if (sz + extra <= 0xFF)
1993 else if (sz + extra*2 <= 0xFFFF)
1995 else if (sz + extra*4 <= 0xFFFFFFFF)
2001 static size_t read_word_le(void *p, size_t sz) {
2011 return *(uint8_t*) p;
2016 return le16toh(x.u16);
2018 return le32toh(x.u32);
2020 return le64toh(x.u64);
2022 assert_not_reached("unknown word width");
2025 static void write_word_le(void *p, size_t sz, size_t value) {
2033 assert(sz == 8 || (value < (1ULL << (sz*8))));
2036 *(uint8_t*) p = value;
2039 x.u16 = htole16((uint16_t) value);
2041 x.u32 = htole32((uint32_t) value);
2043 x.u64 = htole64((uint64_t) value);
2045 assert_not_reached("unknown word width");
2050 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2055 if (!BUS_MESSAGE_IS_GVARIANT(m))
2058 if (c->need_offsets) {
2059 size_t payload, sz, i;
2062 /* Variable-width arrays */
2064 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2065 sz = determine_word_size(payload, c->n_offsets);
2067 a = message_extend_body(m, 1, sz * c->n_offsets, true);
2071 for (i = 0; i < c->n_offsets; i++)
2072 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2076 /* Fixed-width or empty arrays */
2078 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
2086 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2092 assert(c->signature);
2094 if (!BUS_MESSAGE_IS_GVARIANT(m))
2097 l = strlen(c->signature);
2099 a = message_extend_body(m, 1, 1 + l, true);
2104 memcpy(a+1, c->signature, l);
2109 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2110 size_t n_variable = 0;
2119 if (!BUS_MESSAGE_IS_GVARIANT(m))
2122 p = strempty(c->signature);
2126 r = signature_element_length(p, &n);
2135 r = bus_gvariant_is_fixed_size(t);
2140 assert(!c->need_offsets || i <= c->n_offsets);
2142 /* We need to add an offset for each item that has a
2143 * variable size and that is not the last one in the
2145 if (r == 0 && p[n] != 0)
2152 assert(!c->need_offsets || i == c->n_offsets);
2153 assert(c->need_offsets || n_variable == 0);
2155 if (n_variable <= 0) {
2156 a = message_extend_body(m, 1, 0, add_offset);
2163 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2165 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2167 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2171 p = strempty(c->signature);
2172 for (i = 0, j = 0; i < c->n_offsets; i++) {
2176 r = signature_element_length(p, &n);
2187 r = bus_gvariant_is_fixed_size(t);
2190 if (r > 0 || p[0] == 0)
2194 k = n_variable - 1 - j;
2196 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2205 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2206 struct bus_container *c;
2209 assert_return(m, -EINVAL);
2210 assert_return(!m->sealed, -EPERM);
2211 assert_return(m->n_containers > 0, -EINVAL);
2212 assert_return(!m->poisoned, -ESTALE);
2214 c = message_get_container(m);
2216 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2217 if (c->signature && c->signature[c->index] != 0)
2222 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2223 r = bus_message_close_array(m, c);
2224 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2225 r = bus_message_close_variant(m, c);
2226 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2227 r = bus_message_close_struct(m, c, true);
2229 assert_not_reached("Unknown container type");
2243 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2250 stack[*i].types = types;
2251 stack[*i].n_struct = n_struct;
2252 stack[*i].n_array = n_array;
2258 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2269 *types = stack[*i].types;
2270 *n_struct = stack[*i].n_struct;
2271 *n_array = stack[*i].n_array;
2276 int bus_message_append_ap(
2281 unsigned n_array, n_struct;
2282 TypeStack stack[BUS_CONTAINER_DEPTH];
2283 unsigned stack_ptr = 0;
2291 n_array = (unsigned) -1;
2292 n_struct = strlen(types);
2297 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2298 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2304 r = sd_bus_message_close_container(m);
2312 if (n_array != (unsigned) -1)
2321 case SD_BUS_TYPE_BYTE: {
2324 x = (uint8_t) va_arg(ap, int);
2325 r = sd_bus_message_append_basic(m, *t, &x);
2329 case SD_BUS_TYPE_BOOLEAN:
2330 case SD_BUS_TYPE_INT32:
2331 case SD_BUS_TYPE_UINT32:
2332 case SD_BUS_TYPE_UNIX_FD: {
2335 /* We assume a boolean is the same as int32_t */
2336 assert_cc(sizeof(int32_t) == sizeof(int));
2338 x = va_arg(ap, uint32_t);
2339 r = sd_bus_message_append_basic(m, *t, &x);
2343 case SD_BUS_TYPE_INT16:
2344 case SD_BUS_TYPE_UINT16: {
2347 x = (uint16_t) va_arg(ap, int);
2348 r = sd_bus_message_append_basic(m, *t, &x);
2352 case SD_BUS_TYPE_INT64:
2353 case SD_BUS_TYPE_UINT64:
2354 case SD_BUS_TYPE_DOUBLE: {
2357 x = va_arg(ap, uint64_t);
2358 r = sd_bus_message_append_basic(m, *t, &x);
2362 case SD_BUS_TYPE_STRING:
2363 case SD_BUS_TYPE_OBJECT_PATH:
2364 case SD_BUS_TYPE_SIGNATURE: {
2367 x = va_arg(ap, const char*);
2368 r = sd_bus_message_append_basic(m, *t, x);
2372 case SD_BUS_TYPE_ARRAY: {
2375 r = signature_element_length(t + 1, &k);
2381 memcpy(s, t + 1, k);
2384 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2389 if (n_array == (unsigned) -1) {
2394 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2400 n_array = va_arg(ap, unsigned);
2405 case SD_BUS_TYPE_VARIANT: {
2408 s = va_arg(ap, const char*);
2412 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2416 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2421 n_struct = strlen(s);
2422 n_array = (unsigned) -1;
2427 case SD_BUS_TYPE_STRUCT_BEGIN:
2428 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2431 r = signature_element_length(t, &k);
2438 memcpy(s, t + 1, k - 2);
2441 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2446 if (n_array == (unsigned) -1) {
2451 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2457 n_array = (unsigned) -1;
2473 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2477 assert_return(m, -EINVAL);
2478 assert_return(types, -EINVAL);
2479 assert_return(!m->sealed, -EPERM);
2480 assert_return(!m->poisoned, -ESTALE);
2482 va_start(ap, types);
2483 r = bus_message_append_ap(m, types, ap);
2489 _public_ int sd_bus_message_append_array_space(
2499 assert_return(m, -EINVAL);
2500 assert_return(!m->sealed, -EPERM);
2501 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2502 assert_return(ptr || size == 0, -EINVAL);
2503 assert_return(!m->poisoned, -ESTALE);
2505 /* alignment and size of the trivial types (except bool) is
2506 * identical for gvariant and dbus1 marshalling */
2507 align = bus_type_get_alignment(type);
2508 sz = bus_type_get_size(type);
2510 assert_se(align > 0);
2516 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2520 a = message_extend_body(m, align, size, false);
2524 r = sd_bus_message_close_container(m);
2532 _public_ int sd_bus_message_append_array(
2540 assert_return(m, -EINVAL);
2541 assert_return(!m->sealed, -EPERM);
2542 assert_return(bus_type_is_trivial(type), -EINVAL);
2543 assert_return(ptr || size == 0, -EINVAL);
2544 assert_return(!m->poisoned, -ESTALE);
2546 r = sd_bus_message_append_array_space(m, type, size, &p);
2551 memcpy(p, ptr, size);
2556 _public_ int sd_bus_message_append_array_iovec(
2559 const struct iovec *iov,
2567 assert_return(m, -EINVAL);
2568 assert_return(!m->sealed, -EPERM);
2569 assert_return(bus_type_is_trivial(type), -EINVAL);
2570 assert_return(iov || n == 0, -EINVAL);
2571 assert_return(!m->poisoned, -ESTALE);
2573 size = IOVEC_TOTAL_SIZE(iov, n);
2575 r = sd_bus_message_append_array_space(m, type, size, &p);
2579 for (i = 0; i < n; i++) {
2581 if (iov[i].iov_base)
2582 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2584 memzero(p, iov[i].iov_len);
2586 p = (uint8_t*) p + iov[i].iov_len;
2592 _public_ int sd_bus_message_append_array_memfd(
2599 _cleanup_close_ int copy_fd = -1;
2600 struct bus_body_part *part;
2606 assert_return(m, -EINVAL);
2607 assert_return(memfd >= 0, -EINVAL);
2608 assert_return(bus_type_is_trivial(type), -EINVAL);
2609 assert_return(size > 0, -EINVAL);
2610 assert_return(!m->sealed, -EPERM);
2611 assert_return(!m->poisoned, -ESTALE);
2613 r = memfd_set_sealed(memfd);
2617 copy_fd = dup(memfd);
2621 r = memfd_get_size(memfd, &real_size);
2625 if (offset == 0 && size == (uint64_t) -1)
2627 else if (offset + size > real_size)
2630 align = bus_type_get_alignment(type);
2631 sz = bus_type_get_size(type);
2633 assert_se(align > 0);
2636 if (offset % align != 0)
2642 if (size > (uint64_t) (uint32_t) -1)
2645 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2649 a = message_extend_body(m, align, 0, false);
2653 part = message_append_part(m);
2657 part->memfd = copy_fd;
2658 part->memfd_offset = offset;
2659 part->sealed = true;
2663 m->header->body_size += size;
2664 message_extend_containers(m, size);
2666 return sd_bus_message_close_container(m);
2669 _public_ int sd_bus_message_append_string_memfd(
2675 _cleanup_close_ int copy_fd = -1;
2676 struct bus_body_part *part;
2677 struct bus_container *c;
2682 assert_return(m, -EINVAL);
2683 assert_return(memfd >= 0, -EINVAL);
2684 assert_return(size > 0, -EINVAL);
2685 assert_return(!m->sealed, -EPERM);
2686 assert_return(!m->poisoned, -ESTALE);
2688 r = memfd_set_sealed(memfd);
2692 copy_fd = dup(memfd);
2696 r = memfd_get_size(memfd, &real_size);
2700 if (offset == 0 && size == (uint64_t) -1)
2702 else if (offset + size > real_size)
2705 /* We require this to be NUL terminated */
2709 if (size > (uint64_t) (uint32_t) -1)
2712 c = message_get_container(m);
2713 if (c->signature && c->signature[c->index]) {
2714 /* Container signature is already set */
2716 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2721 /* Maybe we can append to the signature? But only if this is the top-level container */
2722 if (c->enclosing != 0)
2725 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2732 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2733 a = message_extend_body(m, 4, 4, false);
2737 *(uint32_t*) a = size - 1;
2740 part = message_append_part(m);
2744 part->memfd = copy_fd;
2745 part->memfd_offset = offset;
2746 part->sealed = true;
2750 m->header->body_size += size;
2751 message_extend_containers(m, size);
2753 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2754 r = message_add_offset(m, m->header->body_size);
2761 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2767 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2771 assert_return(m, -EINVAL);
2772 assert_return(!m->sealed, -EPERM);
2773 assert_return(!m->poisoned, -ESTALE);
2775 r = sd_bus_message_open_container(m, 'a', "s");
2779 STRV_FOREACH(i, l) {
2780 r = sd_bus_message_append_basic(m, 's', *i);
2785 return sd_bus_message_close_container(m);
2788 static int bus_message_close_header(sd_bus_message *m) {
2794 if (!BUS_MESSAGE_IS_GVARIANT(m))
2797 if (m->n_header_offsets < 1)
2800 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2802 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2804 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2808 for (i = 0; i < m->n_header_offsets; i++)
2809 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2814 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2815 struct bus_body_part *part;
2825 if (m->n_containers > 0)
2831 /* In vtables the return signature of method calls is listed,
2832 * let's check if they match if this is a response */
2833 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2834 m->enforced_reply_signature &&
2835 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2838 /* If gvariant marshalling is used we need to close the body structure */
2839 r = bus_message_close_struct(m, &m->root_container, false);
2843 /* If there's a non-trivial signature set, then add it in here */
2844 if (!isempty(m->root_container.signature)) {
2845 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2851 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2856 r = bus_message_close_header(m);
2860 m->header->serial = (uint32_t) cookie;
2861 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2863 /* Add padding at the end of the fields part, since we know
2864 * the body needs to start at an 8 byte alignment. We made
2865 * sure we allocated enough space for this, so all we need to
2866 * do here is to zero it out. */
2867 l = BUS_MESSAGE_FIELDS_SIZE(m);
2870 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, a);
2872 /* If this is something we can send as memfd, then let's seal
2873 the memfd now. Note that we can send memfds as payload only
2874 for directed messages, and not for broadcasts. */
2875 if (m->destination && m->bus->use_memfd) {
2876 MESSAGE_FOREACH_PART(part, i, m)
2877 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2880 /* Try to seal it if that makes
2881 * sense. First, unmap our own map to
2882 * make sure we don't keep it busy. */
2883 bus_body_part_unmap(part);
2885 /* Then, sync up real memfd size */
2887 r = memfd_set_size(part->memfd, sz);
2891 /* Finally, try to seal */
2892 if (memfd_set_sealed(part->memfd) >= 0)
2893 part->sealed = true;
2897 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2898 m->root_container.index = 0;
2899 m->root_container.offset_index = 0;
2900 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2907 int bus_body_part_map(struct bus_body_part *part) {
2916 if (part->size <= 0)
2919 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2920 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2921 static const uint8_t zeroes[7] = { };
2922 part->data = (void*) zeroes;
2926 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
2927 psz = PAGE_ALIGN(part->size + shift);
2929 if (part->memfd >= 0)
2930 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
2931 else if (part->is_zero)
2932 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2936 if (p == MAP_FAILED)
2940 part->mmap_begin = p;
2941 part->data = (uint8_t*) p + shift;
2942 part->munmap_this = true;
2947 void bus_body_part_unmap(struct bus_body_part *part) {
2951 if (part->memfd < 0)
2954 if (!part->mmap_begin)
2957 if (!part->munmap_this)
2960 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
2962 part->mmap_begin = NULL;
2965 part->munmap_this = false;
2970 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2971 size_t k, start, end;
2976 start = ALIGN_TO((size_t) *rindex, align);
2977 end = start + nbytes;
2982 /* Verify that padding is 0 */
2983 for (k = *rindex; k < start; k++)
2984 if (((const uint8_t*) p)[k] != 0)
2988 *r = (uint8_t*) p + start;
2995 static bool message_end_of_signature(sd_bus_message *m) {
2996 struct bus_container *c;
3000 c = message_get_container(m);
3001 return !c->signature || c->signature[c->index] == 0;
3004 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3005 struct bus_container *c;
3009 c = message_get_container(m);
3010 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3013 if (BUS_MESSAGE_IS_GVARIANT(m))
3014 return index >= c->end;
3016 assert(c->array_size);
3017 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3021 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3022 assert_return(m, -EINVAL);
3023 assert_return(m->sealed, -EPERM);
3025 if (complete && m->n_containers > 0)
3028 if (message_end_of_signature(m))
3031 if (message_end_of_array(m, m->rindex))
3037 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3038 struct bus_body_part *part;
3044 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3045 part = m->cached_rindex_part;
3046 begin = m->cached_rindex_part_begin;
3056 if (index + sz <= begin + part->size) {
3058 r = bus_body_part_map(part);
3063 *p = (uint8_t*) part->data + index - begin;
3065 m->cached_rindex_part = part;
3066 m->cached_rindex_part_begin = begin;
3071 begin += part->size;
3078 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3085 if (!BUS_MESSAGE_IS_GVARIANT(m))
3088 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3091 sz = bus_gvariant_get_size(c->signature);
3095 if (c->offset_index+1 >= c->n_offsets)
3098 /* Variable-size array */
3100 alignment = bus_gvariant_get_alignment(c->signature);
3101 assert(alignment > 0);
3103 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3104 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3107 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3110 /* Fixed-size array */
3111 *rindex = c->begin + (c->offset_index+1) * sz;
3117 } else if (c->enclosing == 0 ||
3118 c->enclosing == SD_BUS_TYPE_STRUCT ||
3119 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3124 if (c->offset_index+1 >= c->n_offsets)
3127 r = signature_element_length(c->signature + c->index, &n);
3131 r = signature_element_length(c->signature + c->index + n, &j);
3136 memcpy(t, c->signature + c->index + n, j);
3139 alignment = bus_gvariant_get_alignment(t);
3142 assert(alignment > 0);
3144 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3145 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3149 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3152 assert_not_reached("Unknown container type");
3157 /* Reached the end */
3164 static int message_peek_body(
3171 size_t k, start, end, padding;
3172 struct bus_body_part *part;
3179 start = ALIGN_TO((size_t) *rindex, align);
3180 padding = start - *rindex;
3181 end = start + nbytes;
3183 if (end > BUS_MESSAGE_BODY_SIZE(m))
3186 part = find_part(m, *rindex, padding, (void**) &q);
3191 /* Verify padding */
3192 for (k = 0; k < padding; k++)
3197 part = find_part(m, start, nbytes, (void**) &q);
3198 if (!part || (nbytes > 0 && !q))
3209 static bool validate_nul(const char *s, size_t l) {
3211 /* Check for NUL chars in the string */
3212 if (memchr(s, 0, l))
3215 /* Check for NUL termination */
3222 static bool validate_string(const char *s, size_t l) {
3224 if (!validate_nul(s, l))
3227 /* Check if valid UTF8 */
3228 if (!utf8_is_valid(s))
3234 static bool validate_signature(const char *s, size_t l) {
3236 if (!validate_nul(s, l))
3239 /* Check if valid signature */
3240 if (!signature_is_valid(s, true))
3246 static bool validate_object_path(const char *s, size_t l) {
3248 if (!validate_nul(s, l))
3251 if (!object_path_is_valid(s))
3257 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3258 struct bus_container *c;
3263 assert_return(m, -EINVAL);
3264 assert_return(m->sealed, -EPERM);
3265 assert_return(bus_type_is_basic(type), -EINVAL);
3267 if (message_end_of_signature(m))
3270 if (message_end_of_array(m, m->rindex))
3273 c = message_get_container(m);
3274 if (c->signature[c->index] != type)
3279 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3281 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3284 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3288 if (type == SD_BUS_TYPE_STRING)
3289 ok = validate_string(q, c->item_size-1);
3290 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3291 ok = validate_object_path(q, c->item_size-1);
3293 ok = validate_signature(q, c->item_size-1);
3299 *(const char**) p = q;
3303 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3305 if ((size_t) sz != c->item_size)
3308 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3311 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3317 case SD_BUS_TYPE_BYTE:
3319 *(uint8_t*) p = *(uint8_t*) q;
3322 case SD_BUS_TYPE_BOOLEAN:
3324 *(int*) p = !!*(uint8_t*) q;
3327 case SD_BUS_TYPE_INT16:
3328 case SD_BUS_TYPE_UINT16:
3330 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3333 case SD_BUS_TYPE_INT32:
3334 case SD_BUS_TYPE_UINT32:
3336 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3339 case SD_BUS_TYPE_INT64:
3340 case SD_BUS_TYPE_UINT64:
3341 case SD_BUS_TYPE_DOUBLE:
3343 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3346 case SD_BUS_TYPE_UNIX_FD: {
3349 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3354 *(int*) p = m->fds[j];
3360 assert_not_reached("unexpected type");
3364 r = container_next_item(m, c, &rindex);
3371 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3375 r = message_peek_body(m, &rindex, 4, 4, &q);
3379 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3380 r = message_peek_body(m, &rindex, 1, l+1, &q);
3384 if (type == SD_BUS_TYPE_OBJECT_PATH)
3385 ok = validate_object_path(q, l);
3387 ok = validate_string(q, l);
3392 *(const char**) p = q;
3394 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3397 r = message_peek_body(m, &rindex, 1, 1, &q);
3402 r = message_peek_body(m, &rindex, 1, l+1, &q);
3406 if (!validate_signature(q, l))
3410 *(const char**) p = q;
3415 align = bus_type_get_alignment(type);
3418 sz = bus_type_get_size(type);
3421 r = message_peek_body(m, &rindex, align, sz, &q);
3427 case SD_BUS_TYPE_BYTE:
3429 *(uint8_t*) p = *(uint8_t*) q;
3432 case SD_BUS_TYPE_BOOLEAN:
3434 *(int*) p = !!*(uint32_t*) q;
3437 case SD_BUS_TYPE_INT16:
3438 case SD_BUS_TYPE_UINT16:
3440 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3443 case SD_BUS_TYPE_INT32:
3444 case SD_BUS_TYPE_UINT32:
3446 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3449 case SD_BUS_TYPE_INT64:
3450 case SD_BUS_TYPE_UINT64:
3451 case SD_BUS_TYPE_DOUBLE:
3453 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3456 case SD_BUS_TYPE_UNIX_FD: {
3459 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3464 *(int*) p = m->fds[j];
3469 assert_not_reached("Unknown basic type...");
3476 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3482 static int bus_message_enter_array(
3484 struct bus_container *c,
3485 const char *contents,
3486 uint32_t **array_size,
3489 size_t *n_offsets) {
3503 if (!signature_is_single(contents, true))
3506 if (!c->signature || c->signature[c->index] == 0)
3509 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3512 if (!startswith(c->signature + c->index + 1, contents))
3517 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3520 r = message_peek_body(m, &rindex, 4, 4, &q);
3524 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3527 alignment = bus_type_get_alignment(contents[0]);
3531 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3535 *array_size = (uint32_t*) q;
3537 } else if (c->item_size <= 0) {
3539 /* gvariant: empty array */
3544 } else if (bus_gvariant_is_fixed_size(contents)) {
3546 /* gvariant: fixed length array */
3547 *item_size = bus_gvariant_get_size(contents);
3552 size_t where, p = 0, framing, sz;
3555 /* gvariant: variable length array */
3556 sz = determine_word_size(c->item_size, 0);
3558 where = rindex + c->item_size - sz;
3559 r = message_peek_body(m, &where, 1, sz, &q);
3563 framing = read_word_le(q, sz);
3564 if (framing > c->item_size - sz)
3566 if ((c->item_size - framing) % sz != 0)
3569 *n_offsets = (c->item_size - framing) / sz;
3571 where = rindex + framing;
3572 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3576 *offsets = new(size_t, *n_offsets);
3580 for (i = 0; i < *n_offsets; i++) {
3583 x = read_word_le((uint8_t*) q + i * sz, sz);
3584 if (x > c->item_size - sz)
3589 (*offsets)[i] = rindex + x;
3593 *item_size = (*offsets)[0] - rindex;
3598 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3599 c->index += 1 + strlen(contents);
3604 static int bus_message_enter_variant(
3606 struct bus_container *c,
3607 const char *contents,
3608 size_t *item_size) {
3620 if (!signature_is_single(contents, false))
3623 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3626 if (!c->signature || c->signature[c->index] == 0)
3629 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3634 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3637 k = strlen(contents);
3638 if (1+k > c->item_size)
3641 where = rindex + c->item_size - (1+k);
3642 r = message_peek_body(m, &where, 1, 1+k, &q);
3646 if (*(char*) q != 0)
3649 if (memcmp((uint8_t*) q+1, contents, k))
3652 *item_size = c->item_size - (1+k);
3655 r = message_peek_body(m, &rindex, 1, 1, &q);
3660 r = message_peek_body(m, &rindex, 1, l+1, &q);
3664 if (!validate_signature(q, l))
3667 if (!streq(q, contents))
3673 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3679 static int build_struct_offsets(
3681 const char *signature,
3685 size_t *n_offsets) {
3687 unsigned n_variable = 0, n_total = 0, v;
3688 size_t previous = 0, where;
3699 if (isempty(signature)) {
3706 sz = determine_word_size(size, 0);
3710 /* First, loop over signature and count variable elements and
3711 * elements in general. We use this to know how large the
3712 * offset array is at the end of the structure. Note that
3713 * GVariant only stores offsets for all variable size elements
3714 * that are not the last item. */
3720 r = signature_element_length(p, &n);
3729 r = bus_gvariant_is_fixed_size(t);
3734 if (r == 0 && p[n] != 0) /* except the last item */
3741 if (size < n_variable * sz)
3744 where = m->rindex + size - (n_variable * sz);
3745 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3751 *offsets = new(size_t, n_total);
3757 /* Second, loop again and build an offset table */
3763 r = signature_element_length(p, &n);
3772 k = bus_gvariant_get_size(t);
3780 x = read_word_le((uint8_t*) q + v*sz, sz);
3783 if (m->rindex + x < previous)
3786 /* The last item's end
3787 * is determined from
3790 x = size - (n_variable * sz);
3792 offset = m->rindex + x;
3798 align = bus_gvariant_get_alignment(t);
3801 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3805 previous = (*offsets)[(*n_offsets)++] = offset;
3810 assert(*n_offsets == n_total);
3812 *item_size = (*offsets)[0] - m->rindex;
3816 static int enter_struct_or_dict_entry(
3818 struct bus_container *c,
3819 const char *contents,
3822 size_t *n_offsets) {
3833 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3836 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3840 } else if (c->item_size <= 0) {
3842 /* gvariant empty struct */
3847 /* gvariant with contents */
3848 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3853 static int bus_message_enter_struct(
3855 struct bus_container *c,
3856 const char *contents,
3859 size_t *n_offsets) {
3871 if (!signature_is_valid(contents, false))
3874 if (!c->signature || c->signature[c->index] == 0)
3877 l = strlen(contents);
3879 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3880 !startswith(c->signature + c->index + 1, contents) ||
3881 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3884 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3888 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3889 c->index += 1 + l + 1;
3894 static int bus_message_enter_dict_entry(
3896 struct bus_container *c,
3897 const char *contents,
3900 size_t *n_offsets) {
3909 if (!signature_is_pair(contents))
3912 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3915 if (!c->signature || c->signature[c->index] == 0)
3918 l = strlen(contents);
3920 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3921 !startswith(c->signature + c->index + 1, contents) ||
3922 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3925 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3929 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3930 c->index += 1 + l + 1;
3935 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3937 const char *contents) {
3938 struct bus_container *c, *w;
3939 uint32_t *array_size = NULL;
3942 size_t *offsets = NULL;
3943 size_t n_offsets = 0, item_size = 0;
3946 assert_return(m, -EINVAL);
3947 assert_return(m->sealed, -EPERM);
3948 assert_return(type != 0 || !contents, -EINVAL);
3950 if (type == 0 || !contents) {
3954 /* Allow entering into anonymous containers */
3955 r = sd_bus_message_peek_type(m, &tt, &cc);
3959 if (type != 0 && type != tt)
3962 if (contents && !streq(contents, cc))
3970 * We enforce a global limit on container depth, that is much
3971 * higher than the 32 structs and 32 arrays the specification
3972 * mandates. This is simpler to implement for us, and we need
3973 * this only to ensure our container array doesn't grow
3974 * without bounds. We are happy to return any data from a
3975 * message as long as the data itself is valid, even if the
3976 * overall message might be not.
3978 * Note that the message signature is validated when
3979 * parsing the headers, and that validation does check the
3982 * Note that the specification defines no limits on the depth
3983 * of stacked variants, but we do.
3985 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3988 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3991 if (message_end_of_signature(m))
3994 if (message_end_of_array(m, m->rindex))
3997 c = message_get_container(m);
3999 signature = strdup(contents);
4003 c->saved_index = c->index;
4006 if (type == SD_BUS_TYPE_ARRAY)
4007 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4008 else if (type == SD_BUS_TYPE_VARIANT)
4009 r = bus_message_enter_variant(m, c, contents, &item_size);
4010 else if (type == SD_BUS_TYPE_STRUCT)
4011 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4012 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4013 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4023 /* OK, let's fill it in */
4024 w = m->containers + m->n_containers++;
4025 w->enclosing = type;
4026 w->signature = signature;
4027 w->peeked_signature = NULL;
4031 w->begin = m->rindex;
4032 w->end = m->rindex + c->item_size;
4034 w->array_size = array_size;
4035 w->item_size = item_size;
4036 w->offsets = offsets;
4037 w->n_offsets = n_offsets;
4038 w->offset_index = 0;
4043 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4044 struct bus_container *c;
4048 assert_return(m, -EINVAL);
4049 assert_return(m->sealed, -EPERM);
4050 assert_return(m->n_containers > 0, -ENXIO);
4052 c = message_get_container(m);
4054 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4055 if (c->signature && c->signature[c->index] != 0)
4059 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4060 if (m->rindex < c->end)
4063 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4066 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4067 if (c->begin + l != m->rindex)
4072 free(c->peeked_signature);
4076 c = message_get_container(m);
4079 c->index = c->saved_index;
4080 r = container_next_item(m, c, &m->rindex);
4088 static void message_quit_container(sd_bus_message *m) {
4089 struct bus_container *c;
4093 assert(m->n_containers > 0);
4095 c = message_get_container(m);
4098 assert(m->rindex >= c->before);
4099 m->rindex = c->before;
4101 /* Free container */
4106 /* Correct index of new top-level container */
4107 c = message_get_container(m);
4108 c->index = c->saved_index;
4111 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4112 struct bus_container *c;
4115 assert_return(m, -EINVAL);
4116 assert_return(m->sealed, -EPERM);
4118 if (message_end_of_signature(m))
4121 if (message_end_of_array(m, m->rindex))
4124 c = message_get_container(m);
4126 if (bus_type_is_basic(c->signature[c->index])) {
4130 *type = c->signature[c->index];
4134 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4140 r = signature_element_length(c->signature+c->index+1, &l);
4146 sig = strndup(c->signature + c->index + 1, l);
4150 free(c->peeked_signature);
4151 *contents = c->peeked_signature = sig;
4155 *type = SD_BUS_TYPE_ARRAY;
4160 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4161 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4167 r = signature_element_length(c->signature+c->index, &l);
4172 sig = strndup(c->signature + c->index + 1, l - 2);
4176 free(c->peeked_signature);
4177 *contents = c->peeked_signature = sig;
4181 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4186 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4190 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4193 if (c->item_size < 2)
4196 /* Look for the NUL delimiter that
4197 separates the payload from the
4198 signature. Since the body might be
4199 in a different part that then the
4200 signature we map byte by byte. */
4202 for (k = 2; k <= c->item_size; k++) {
4205 where = m->rindex + c->item_size - k;
4206 r = message_peek_body(m, &where, 1, k, &q);
4210 if (*(char*) q == 0)
4214 if (k > c->item_size)
4217 free(c->peeked_signature);
4218 c->peeked_signature = strndup((char*) q + 1, k - 1);
4219 if (!c->peeked_signature)
4222 if (!signature_is_valid(c->peeked_signature, true))
4225 *contents = c->peeked_signature;
4230 r = message_peek_body(m, &rindex, 1, 1, &q);
4235 r = message_peek_body(m, &rindex, 1, l+1, &q);
4239 if (!validate_signature(q, l))
4247 *type = SD_BUS_TYPE_VARIANT;
4262 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4263 struct bus_container *c;
4265 assert_return(m, -EINVAL);
4266 assert_return(m->sealed, -EPERM);
4269 message_reset_containers(m);
4272 c = message_get_container(m);
4274 c = message_get_container(m);
4276 c->offset_index = 0;
4278 m->rindex = c->begin;
4281 c->offset_index = 0;
4282 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4284 return !isempty(c->signature);
4287 static int message_read_ap(
4292 unsigned n_array, n_struct;
4293 TypeStack stack[BUS_CONTAINER_DEPTH];
4294 unsigned stack_ptr = 0;
4295 unsigned n_loop = 0;
4303 /* Ideally, we'd just call ourselves recursively on every
4304 * complex type. However, the state of a va_list that is
4305 * passed to a function is undefined after that function
4306 * returns. This means we need to docode the va_list linearly
4307 * in a single stackframe. We hence implement our own
4308 * home-grown stack in an array. */
4310 n_array = (unsigned) -1; /* length of current array entries */
4311 n_struct = strlen(types); /* length of current struct contents signature */
4318 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4319 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4325 r = sd_bus_message_exit_container(m);
4333 if (n_array != (unsigned) -1)
4342 case SD_BUS_TYPE_BYTE:
4343 case SD_BUS_TYPE_BOOLEAN:
4344 case SD_BUS_TYPE_INT16:
4345 case SD_BUS_TYPE_UINT16:
4346 case SD_BUS_TYPE_INT32:
4347 case SD_BUS_TYPE_UINT32:
4348 case SD_BUS_TYPE_INT64:
4349 case SD_BUS_TYPE_UINT64:
4350 case SD_BUS_TYPE_DOUBLE:
4351 case SD_BUS_TYPE_STRING:
4352 case SD_BUS_TYPE_OBJECT_PATH:
4353 case SD_BUS_TYPE_SIGNATURE:
4354 case SD_BUS_TYPE_UNIX_FD: {
4357 p = va_arg(ap, void*);
4358 r = sd_bus_message_read_basic(m, *t, p);
4371 case SD_BUS_TYPE_ARRAY: {
4374 r = signature_element_length(t + 1, &k);
4380 memcpy(s, t + 1, k);
4383 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4394 if (n_array == (unsigned) -1) {
4399 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4405 n_array = va_arg(ap, unsigned);
4410 case SD_BUS_TYPE_VARIANT: {
4413 s = va_arg(ap, const char *);
4417 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4427 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4432 n_struct = strlen(s);
4433 n_array = (unsigned) -1;
4438 case SD_BUS_TYPE_STRUCT_BEGIN:
4439 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4442 r = signature_element_length(t, &k);
4448 memcpy(s, t + 1, k - 2);
4451 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4461 if (n_array == (unsigned) -1) {
4466 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4472 n_array = (unsigned) -1;
4485 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4489 assert_return(m, -EINVAL);
4490 assert_return(m->sealed, -EPERM);
4491 assert_return(types, -EINVAL);
4493 va_start(ap, types);
4494 r = message_read_ap(m, types, ap);
4500 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4503 assert_return(m, -EINVAL);
4504 assert_return(m->sealed, -EPERM);
4506 /* If types is NULL, read exactly one element */
4508 struct bus_container *c;
4511 if (message_end_of_signature(m))
4514 if (message_end_of_array(m, m->rindex))
4517 c = message_get_container(m);
4519 r = signature_element_length(c->signature + c->index, &l);
4523 types = strndupa(c->signature + c->index, l);
4528 case 0: /* Nothing to drop */
4531 case SD_BUS_TYPE_BYTE:
4532 case SD_BUS_TYPE_BOOLEAN:
4533 case SD_BUS_TYPE_INT16:
4534 case SD_BUS_TYPE_UINT16:
4535 case SD_BUS_TYPE_INT32:
4536 case SD_BUS_TYPE_UINT32:
4537 case SD_BUS_TYPE_INT64:
4538 case SD_BUS_TYPE_UINT64:
4539 case SD_BUS_TYPE_DOUBLE:
4540 case SD_BUS_TYPE_STRING:
4541 case SD_BUS_TYPE_OBJECT_PATH:
4542 case SD_BUS_TYPE_SIGNATURE:
4543 case SD_BUS_TYPE_UNIX_FD:
4545 r = sd_bus_message_read_basic(m, *types, NULL);
4549 r = sd_bus_message_skip(m, types + 1);
4555 case SD_BUS_TYPE_ARRAY: {
4558 r = signature_element_length(types + 1, &k);
4564 memcpy(s, types+1, k);
4567 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4572 r = sd_bus_message_skip(m, s);
4579 r = sd_bus_message_exit_container(m);
4584 r = sd_bus_message_skip(m, types + 1 + k);
4591 case SD_BUS_TYPE_VARIANT: {
4592 const char *contents;
4595 r = sd_bus_message_peek_type(m, &x, &contents);
4599 if (x != SD_BUS_TYPE_VARIANT)
4602 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4606 r = sd_bus_message_skip(m, contents);
4611 r = sd_bus_message_exit_container(m);
4615 r = sd_bus_message_skip(m, types + 1);
4622 case SD_BUS_TYPE_STRUCT_BEGIN:
4623 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4626 r = signature_element_length(types, &k);
4632 memcpy(s, types+1, k-2);
4635 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4639 r = sd_bus_message_skip(m, s);
4644 r = sd_bus_message_exit_container(m);
4649 r = sd_bus_message_skip(m, types + k);
4661 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4665 struct bus_container *c;
4671 assert_return(m, -EINVAL);
4672 assert_return(m->sealed, -EPERM);
4673 assert_return(bus_type_is_trivial(type), -EINVAL);
4674 assert_return(ptr, -EINVAL);
4675 assert_return(size, -EINVAL);
4676 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4678 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4682 c = message_get_container(m);
4684 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4685 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4689 sz = c->end - c->begin;
4691 align = bus_type_get_alignment(type);
4695 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4699 /* Zero length array, let's return some aligned
4700 * pointer that is not NULL */
4701 p = (uint8_t*) NULL + align;
4703 r = message_peek_body(m, &m->rindex, align, sz, &p);
4708 r = sd_bus_message_exit_container(m);
4712 *ptr = (const void*) p;
4718 message_quit_container(m);
4722 static int message_peek_fields(
4733 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4736 static int message_peek_field_uint32(
4748 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4751 /* identical for gvariant and dbus1 */
4753 r = message_peek_fields(m, ri, 4, 4, &q);
4758 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4763 static int message_peek_field_string(
4765 bool (*validate)(const char *p),
4777 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4782 r = message_peek_fields(m, ri, 1, item_size, &q);
4788 r = message_peek_field_uint32(m, ri, 4, &l);
4792 r = message_peek_fields(m, ri, 1, l+1, &q);
4798 if (!validate_nul(q, l))
4804 if (!validate_string(q, l))
4814 static int message_peek_field_signature(
4827 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4832 r = message_peek_fields(m, ri, 1, item_size, &q);
4838 r = message_peek_fields(m, ri, 1, 1, &q);
4843 r = message_peek_fields(m, ri, 1, l+1, &q);
4848 if (!validate_signature(q, l))
4857 static int message_skip_fields(
4860 uint32_t array_size,
4861 const char **signature) {
4863 size_t original_index;
4869 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4871 original_index = *ri;
4877 if (array_size != (uint32_t) -1 &&
4878 array_size <= *ri - original_index)
4885 if (t == SD_BUS_TYPE_STRING) {
4887 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4893 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4895 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4901 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4903 r = message_peek_field_signature(m, ri, 0, NULL);
4909 } else if (bus_type_is_basic(t)) {
4912 align = bus_type_get_alignment(t);
4913 k = bus_type_get_size(t);
4914 assert(align > 0 && k > 0);
4916 r = message_peek_fields(m, ri, align, k, NULL);
4922 } else if (t == SD_BUS_TYPE_ARRAY) {
4924 r = signature_element_length(*signature+1, &l);
4934 strncpy(sig, *signature + 1, l-1);
4937 alignment = bus_type_get_alignment(sig[0]);
4941 r = message_peek_field_uint32(m, ri, 0, &nas);
4944 if (nas > BUS_ARRAY_MAX_SIZE)
4947 r = message_peek_fields(m, ri, alignment, 0, NULL);
4951 r = message_skip_fields(m, ri, nas, (const char**) &s);
4956 (*signature) += 1 + l;
4958 } else if (t == SD_BUS_TYPE_VARIANT) {
4961 r = message_peek_field_signature(m, ri, 0, &s);
4965 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4971 } else if (t == SD_BUS_TYPE_STRUCT ||
4972 t == SD_BUS_TYPE_DICT_ENTRY) {
4974 r = signature_element_length(*signature, &l);
4981 strncpy(sig, *signature + 1, l-1);
4984 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4995 int bus_message_parse_fields(sd_bus_message *m) {
4998 uint32_t unix_fds = 0;
4999 bool unix_fds_set = false;
5000 void *offsets = NULL;
5001 unsigned n_offsets = 0;
5007 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5010 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
5014 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
5015 r = message_peek_fields(m, &ri, 1, sz, &q);
5019 framing = read_word_le(q, sz);
5020 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
5022 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
5026 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
5030 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
5035 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
5036 _cleanup_free_ char *sig = NULL;
5037 const char *signature;
5039 size_t item_size = (size_t) -1;
5041 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5048 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5051 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
5055 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5060 end = read_word_le((uint8_t*) offsets + i*sz, sz);
5065 where = ri = ALIGN_TO(ri, 8);
5066 item_size = end - ri;
5067 r = message_peek_fields(m, &where, 1, item_size, &q);
5071 b = memrchr(q, 0, item_size);
5075 sig = strndup(b+1, item_size - (b+1-(char*) q));
5080 item_size = b - (char*) q;
5082 r = message_peek_field_signature(m, &ri, 0, &signature);
5088 case _BUS_MESSAGE_HEADER_INVALID:
5091 case BUS_MESSAGE_HEADER_PATH:
5096 if (!streq(signature, "o"))
5099 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5102 case BUS_MESSAGE_HEADER_INTERFACE:
5107 if (!streq(signature, "s"))
5110 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5113 case BUS_MESSAGE_HEADER_MEMBER:
5118 if (!streq(signature, "s"))
5121 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5124 case BUS_MESSAGE_HEADER_ERROR_NAME:
5129 if (!streq(signature, "s"))
5132 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5134 m->error._need_free = -1;
5138 case BUS_MESSAGE_HEADER_DESTINATION:
5143 if (!streq(signature, "s"))
5146 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5149 case BUS_MESSAGE_HEADER_SENDER:
5154 if (!streq(signature, "s"))
5157 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5159 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5160 m->creds.unique_name = (char*) m->sender;
5161 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5167 case BUS_MESSAGE_HEADER_SIGNATURE: {
5171 if (m->root_container.signature)
5174 if (!streq(signature, "g"))
5177 r = message_peek_field_signature(m, &ri, item_size, &s);
5185 free(m->root_container.signature);
5186 m->root_container.signature = c;
5190 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5193 if (m->reply_cookie != 0)
5196 if (!streq(signature, "u"))
5199 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5203 m->reply_cookie = serial;
5205 if (m->reply_cookie == 0)
5211 case BUS_MESSAGE_HEADER_UNIX_FDS:
5215 if (!streq(signature, "u"))
5218 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5222 unix_fds_set = true;
5226 if (!BUS_MESSAGE_IS_GVARIANT(m))
5227 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5236 if (m->n_fds != unix_fds)
5239 switch (m->header->type) {
5241 case SD_BUS_MESSAGE_SIGNAL:
5242 if (!m->path || !m->interface || !m->member)
5245 if (m->reply_cookie != 0)
5250 case SD_BUS_MESSAGE_METHOD_CALL:
5252 if (!m->path || !m->member)
5255 if (m->reply_cookie != 0)
5260 case SD_BUS_MESSAGE_METHOD_RETURN:
5262 if (m->reply_cookie == 0)
5266 case SD_BUS_MESSAGE_METHOD_ERROR:
5268 if (m->reply_cookie == 0 || !m->error.name)
5273 /* Refuse non-local messages that claim they are local */
5274 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5276 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5278 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5281 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5283 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5284 r = build_struct_offsets(
5286 m->root_container.signature,
5287 BUS_MESSAGE_BODY_SIZE(m),
5288 &m->root_container.item_size,
5289 &m->root_container.offsets,
5290 &m->root_container.n_offsets);
5295 /* Try to read the error message, but if we can't it's a non-issue */
5296 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5297 sd_bus_message_read(m, "s", &m->error.message);
5302 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5303 assert_return(m, -EINVAL);
5304 assert_return(destination, -EINVAL);
5305 assert_return(!m->sealed, -EPERM);
5306 assert_return(!m->destination, -EEXIST);
5308 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5311 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5315 struct bus_body_part *part;
5321 total = BUS_MESSAGE_SIZE(m);
5327 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5328 MESSAGE_FOREACH_PART(part, i, m)
5329 e = mempcpy(e, part->data, part->size);
5331 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5339 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5345 r = sd_bus_message_enter_container(m, 'a', "s");
5352 r = sd_bus_message_read_basic(m, 's', &s);
5358 r = strv_extend(l, s);
5363 r = sd_bus_message_exit_container(m);
5370 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5374 assert_return(m, -EINVAL);
5375 assert_return(m->sealed, -EPERM);
5376 assert_return(l, -EINVAL);
5378 r = bus_message_read_strv_extend(m, &strv);
5388 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5389 const char *contents;
5398 r = sd_bus_message_rewind(m, true);
5403 r = sd_bus_message_peek_type(m, &type, &contents);
5409 /* Don't match against arguments after the first one we don't understand */
5410 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5411 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5417 r = sd_bus_message_skip(m, NULL);
5422 if (type == SD_BUS_TYPE_ARRAY) {
5424 r = sd_bus_message_read_strv(m, strv);
5431 r = sd_bus_message_read_basic(m, type, str);
5441 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5447 if (size < sizeof(struct bus_header))
5450 full = sizeof(struct bus_header) +
5451 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5453 return size >= full;
5456 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5462 if (h->endian == BUS_NATIVE_ENDIAN) {
5463 fs = h->fields_size;
5465 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5466 fs = bswap_32(h->fields_size);
5467 bs = bswap_32(h->body_size);
5471 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5475 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5476 assert_return(m, EINVAL);
5478 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5481 return sd_bus_error_get_errno(&m->error);
5484 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5485 struct bus_container *c;
5487 assert_return(m, NULL);
5489 c = complete ? &m->root_container : message_get_container(m);
5490 return strempty(c->signature);
5493 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5494 assert_return(m, -EINVAL);
5496 return isempty(m->root_container.signature);
5499 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5500 assert_return(m, -EINVAL);
5502 return streq(strempty(m->root_container.signature), strempty(signature));
5505 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5506 bool done_something = false;
5509 assert_return(m, -EINVAL);
5510 assert_return(source, -EINVAL);
5511 assert_return(!m->sealed, -EPERM);
5512 assert_return(source->sealed, -EPERM);
5515 const char *contents;
5530 r = sd_bus_message_peek_type(source, &type, &contents);
5536 done_something = true;
5538 if (bus_type_is_container(type) > 0) {
5540 r = sd_bus_message_enter_container(source, type, contents);
5544 r = sd_bus_message_open_container(m, type, contents);
5548 r = sd_bus_message_copy(m, source, true);
5552 r = sd_bus_message_close_container(m);
5556 r = sd_bus_message_exit_container(source);
5563 r = sd_bus_message_read_basic(source, type, &basic);
5569 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5570 type == SD_BUS_TYPE_SIGNATURE ||
5571 type == SD_BUS_TYPE_STRING)
5572 r = sd_bus_message_append_basic(m, type, basic.string);
5574 r = sd_bus_message_append_basic(m, type, &basic);
5581 return done_something;
5584 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5589 assert_return(m, -EINVAL);
5590 assert_return(m->sealed, -EPERM);
5591 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5592 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5593 assert_return(type || contents, -EINVAL);
5594 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5596 r = sd_bus_message_peek_type(m, &t, &c);
5600 if (type != 0 && type != t)
5603 if (contents && !streq_ptr(contents, c))
5609 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5610 assert_return(m, NULL);
5615 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5616 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5624 switch ((*m)->header->type) {
5626 case SD_BUS_MESSAGE_SIGNAL:
5627 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5633 case SD_BUS_MESSAGE_METHOD_CALL:
5634 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5640 case SD_BUS_MESSAGE_METHOD_RETURN:
5641 case SD_BUS_MESSAGE_METHOD_ERROR:
5643 n = message_new(bus, (*m)->header->type);
5647 n->reply_cookie = (*m)->reply_cookie;
5648 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5652 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5653 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5657 n->error._need_free = -1;
5666 if ((*m)->destination && !n->destination) {
5667 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5672 if ((*m)->sender && !n->sender) {
5673 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5678 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5680 r = sd_bus_message_copy(n, *m, true);
5684 timeout = (*m)->timeout;
5685 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5686 timeout = BUS_DEFAULT_TIMEOUT;
5688 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5692 sd_bus_message_unref(*m);
5699 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5703 assert_return(!m->sealed, -EPERM);
5704 assert_return(!m->sender, -EPERM);
5706 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5709 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5710 assert_return(m, -EINVAL);
5711 assert_return(priority, -EINVAL);
5713 *priority = m->priority;
5717 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5718 assert_return(m, -EINVAL);
5719 assert_return(!m->sealed, -EPERM);
5721 m->priority = priority;