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: {
2356 x = va_arg(ap, uint64_t);
2357 r = sd_bus_message_append_basic(m, *t, &x);
2361 case SD_BUS_TYPE_DOUBLE: {
2364 x = va_arg(ap, double);
2365 r = sd_bus_message_append_basic(m, *t, &x);
2369 case SD_BUS_TYPE_STRING:
2370 case SD_BUS_TYPE_OBJECT_PATH:
2371 case SD_BUS_TYPE_SIGNATURE: {
2374 x = va_arg(ap, const char*);
2375 r = sd_bus_message_append_basic(m, *t, x);
2379 case SD_BUS_TYPE_ARRAY: {
2382 r = signature_element_length(t + 1, &k);
2388 memcpy(s, t + 1, k);
2391 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2396 if (n_array == (unsigned) -1) {
2401 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2407 n_array = va_arg(ap, unsigned);
2412 case SD_BUS_TYPE_VARIANT: {
2415 s = va_arg(ap, const char*);
2419 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2423 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2428 n_struct = strlen(s);
2429 n_array = (unsigned) -1;
2434 case SD_BUS_TYPE_STRUCT_BEGIN:
2435 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2438 r = signature_element_length(t, &k);
2445 memcpy(s, t + 1, k - 2);
2448 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2453 if (n_array == (unsigned) -1) {
2458 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2464 n_array = (unsigned) -1;
2480 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2484 assert_return(m, -EINVAL);
2485 assert_return(types, -EINVAL);
2486 assert_return(!m->sealed, -EPERM);
2487 assert_return(!m->poisoned, -ESTALE);
2489 va_start(ap, types);
2490 r = bus_message_append_ap(m, types, ap);
2496 _public_ int sd_bus_message_append_array_space(
2506 assert_return(m, -EINVAL);
2507 assert_return(!m->sealed, -EPERM);
2508 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2509 assert_return(ptr || size == 0, -EINVAL);
2510 assert_return(!m->poisoned, -ESTALE);
2512 /* alignment and size of the trivial types (except bool) is
2513 * identical for gvariant and dbus1 marshalling */
2514 align = bus_type_get_alignment(type);
2515 sz = bus_type_get_size(type);
2517 assert_se(align > 0);
2523 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2527 a = message_extend_body(m, align, size, false);
2531 r = sd_bus_message_close_container(m);
2539 _public_ int sd_bus_message_append_array(
2547 assert_return(m, -EINVAL);
2548 assert_return(!m->sealed, -EPERM);
2549 assert_return(bus_type_is_trivial(type), -EINVAL);
2550 assert_return(ptr || size == 0, -EINVAL);
2551 assert_return(!m->poisoned, -ESTALE);
2553 r = sd_bus_message_append_array_space(m, type, size, &p);
2558 memcpy(p, ptr, size);
2563 _public_ int sd_bus_message_append_array_iovec(
2566 const struct iovec *iov,
2574 assert_return(m, -EINVAL);
2575 assert_return(!m->sealed, -EPERM);
2576 assert_return(bus_type_is_trivial(type), -EINVAL);
2577 assert_return(iov || n == 0, -EINVAL);
2578 assert_return(!m->poisoned, -ESTALE);
2580 size = IOVEC_TOTAL_SIZE(iov, n);
2582 r = sd_bus_message_append_array_space(m, type, size, &p);
2586 for (i = 0; i < n; i++) {
2588 if (iov[i].iov_base)
2589 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2591 memzero(p, iov[i].iov_len);
2593 p = (uint8_t*) p + iov[i].iov_len;
2599 _public_ int sd_bus_message_append_array_memfd(
2606 _cleanup_close_ int copy_fd = -1;
2607 struct bus_body_part *part;
2613 assert_return(m, -EINVAL);
2614 assert_return(memfd >= 0, -EINVAL);
2615 assert_return(bus_type_is_trivial(type), -EINVAL);
2616 assert_return(size > 0, -EINVAL);
2617 assert_return(!m->sealed, -EPERM);
2618 assert_return(!m->poisoned, -ESTALE);
2620 r = memfd_set_sealed(memfd);
2624 copy_fd = dup(memfd);
2628 r = memfd_get_size(memfd, &real_size);
2632 if (offset == 0 && size == (uint64_t) -1)
2634 else if (offset + size > real_size)
2637 align = bus_type_get_alignment(type);
2638 sz = bus_type_get_size(type);
2640 assert_se(align > 0);
2643 if (offset % align != 0)
2649 if (size > (uint64_t) (uint32_t) -1)
2652 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2656 a = message_extend_body(m, align, 0, false);
2660 part = message_append_part(m);
2664 part->memfd = copy_fd;
2665 part->memfd_offset = offset;
2666 part->sealed = true;
2670 m->header->body_size += size;
2671 message_extend_containers(m, size);
2673 return sd_bus_message_close_container(m);
2676 _public_ int sd_bus_message_append_string_memfd(
2682 _cleanup_close_ int copy_fd = -1;
2683 struct bus_body_part *part;
2684 struct bus_container *c;
2689 assert_return(m, -EINVAL);
2690 assert_return(memfd >= 0, -EINVAL);
2691 assert_return(size > 0, -EINVAL);
2692 assert_return(!m->sealed, -EPERM);
2693 assert_return(!m->poisoned, -ESTALE);
2695 r = memfd_set_sealed(memfd);
2699 copy_fd = dup(memfd);
2703 r = memfd_get_size(memfd, &real_size);
2707 if (offset == 0 && size == (uint64_t) -1)
2709 else if (offset + size > real_size)
2712 /* We require this to be NUL terminated */
2716 if (size > (uint64_t) (uint32_t) -1)
2719 c = message_get_container(m);
2720 if (c->signature && c->signature[c->index]) {
2721 /* Container signature is already set */
2723 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2728 /* Maybe we can append to the signature? But only if this is the top-level container */
2729 if (c->enclosing != 0)
2732 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2739 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2740 a = message_extend_body(m, 4, 4, false);
2744 *(uint32_t*) a = size - 1;
2747 part = message_append_part(m);
2751 part->memfd = copy_fd;
2752 part->memfd_offset = offset;
2753 part->sealed = true;
2757 m->header->body_size += size;
2758 message_extend_containers(m, size);
2760 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2761 r = message_add_offset(m, m->header->body_size);
2768 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2774 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2778 assert_return(m, -EINVAL);
2779 assert_return(!m->sealed, -EPERM);
2780 assert_return(!m->poisoned, -ESTALE);
2782 r = sd_bus_message_open_container(m, 'a', "s");
2786 STRV_FOREACH(i, l) {
2787 r = sd_bus_message_append_basic(m, 's', *i);
2792 return sd_bus_message_close_container(m);
2795 static int bus_message_close_header(sd_bus_message *m) {
2801 if (!BUS_MESSAGE_IS_GVARIANT(m))
2804 if (m->n_header_offsets < 1)
2807 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2809 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2811 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2815 for (i = 0; i < m->n_header_offsets; i++)
2816 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2821 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2822 struct bus_body_part *part;
2832 if (m->n_containers > 0)
2838 /* In vtables the return signature of method calls is listed,
2839 * let's check if they match if this is a response */
2840 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2841 m->enforced_reply_signature &&
2842 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2845 /* If gvariant marshalling is used we need to close the body structure */
2846 r = bus_message_close_struct(m, &m->root_container, false);
2850 /* If there's a non-trivial signature set, then add it in here */
2851 if (!isempty(m->root_container.signature)) {
2852 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2858 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2863 r = bus_message_close_header(m);
2867 m->header->serial = (uint32_t) cookie;
2868 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2870 /* Add padding at the end of the fields part, since we know
2871 * the body needs to start at an 8 byte alignment. We made
2872 * sure we allocated enough space for this, so all we need to
2873 * do here is to zero it out. */
2874 l = BUS_MESSAGE_FIELDS_SIZE(m);
2877 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, a);
2879 /* If this is something we can send as memfd, then let's seal
2880 the memfd now. Note that we can send memfds as payload only
2881 for directed messages, and not for broadcasts. */
2882 if (m->destination && m->bus->use_memfd) {
2883 MESSAGE_FOREACH_PART(part, i, m)
2884 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2887 /* Try to seal it if that makes
2888 * sense. First, unmap our own map to
2889 * make sure we don't keep it busy. */
2890 bus_body_part_unmap(part);
2892 /* Then, sync up real memfd size */
2894 r = memfd_set_size(part->memfd, sz);
2898 /* Finally, try to seal */
2899 if (memfd_set_sealed(part->memfd) >= 0)
2900 part->sealed = true;
2904 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2905 m->root_container.index = 0;
2906 m->root_container.offset_index = 0;
2907 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2914 int bus_body_part_map(struct bus_body_part *part) {
2923 if (part->size <= 0)
2926 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2927 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2928 static const uint8_t zeroes[7] = { };
2929 part->data = (void*) zeroes;
2933 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
2934 psz = PAGE_ALIGN(part->size + shift);
2936 if (part->memfd >= 0)
2937 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
2938 else if (part->is_zero)
2939 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2943 if (p == MAP_FAILED)
2947 part->mmap_begin = p;
2948 part->data = (uint8_t*) p + shift;
2949 part->munmap_this = true;
2954 void bus_body_part_unmap(struct bus_body_part *part) {
2958 if (part->memfd < 0)
2961 if (!part->mmap_begin)
2964 if (!part->munmap_this)
2967 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
2969 part->mmap_begin = NULL;
2972 part->munmap_this = false;
2977 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2978 size_t k, start, end;
2983 start = ALIGN_TO((size_t) *rindex, align);
2984 end = start + nbytes;
2989 /* Verify that padding is 0 */
2990 for (k = *rindex; k < start; k++)
2991 if (((const uint8_t*) p)[k] != 0)
2995 *r = (uint8_t*) p + start;
3002 static bool message_end_of_signature(sd_bus_message *m) {
3003 struct bus_container *c;
3007 c = message_get_container(m);
3008 return !c->signature || c->signature[c->index] == 0;
3011 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3012 struct bus_container *c;
3016 c = message_get_container(m);
3017 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3020 if (BUS_MESSAGE_IS_GVARIANT(m))
3021 return index >= c->end;
3023 assert(c->array_size);
3024 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3028 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3029 assert_return(m, -EINVAL);
3030 assert_return(m->sealed, -EPERM);
3032 if (complete && m->n_containers > 0)
3035 if (message_end_of_signature(m))
3038 if (message_end_of_array(m, m->rindex))
3044 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3045 struct bus_body_part *part;
3051 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3052 part = m->cached_rindex_part;
3053 begin = m->cached_rindex_part_begin;
3063 if (index + sz <= begin + part->size) {
3065 r = bus_body_part_map(part);
3070 *p = (uint8_t*) part->data + index - begin;
3072 m->cached_rindex_part = part;
3073 m->cached_rindex_part_begin = begin;
3078 begin += part->size;
3085 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3092 if (!BUS_MESSAGE_IS_GVARIANT(m))
3095 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3098 sz = bus_gvariant_get_size(c->signature);
3102 if (c->offset_index+1 >= c->n_offsets)
3105 /* Variable-size array */
3107 alignment = bus_gvariant_get_alignment(c->signature);
3108 assert(alignment > 0);
3110 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3111 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3114 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3117 /* Fixed-size array */
3118 *rindex = c->begin + (c->offset_index+1) * sz;
3124 } else if (c->enclosing == 0 ||
3125 c->enclosing == SD_BUS_TYPE_STRUCT ||
3126 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3131 if (c->offset_index+1 >= c->n_offsets)
3134 r = signature_element_length(c->signature + c->index, &n);
3138 r = signature_element_length(c->signature + c->index + n, &j);
3143 memcpy(t, c->signature + c->index + n, j);
3146 alignment = bus_gvariant_get_alignment(t);
3149 assert(alignment > 0);
3151 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3152 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3156 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3159 assert_not_reached("Unknown container type");
3164 /* Reached the end */
3171 static int message_peek_body(
3178 size_t k, start, end, padding;
3179 struct bus_body_part *part;
3186 start = ALIGN_TO((size_t) *rindex, align);
3187 padding = start - *rindex;
3188 end = start + nbytes;
3190 if (end > BUS_MESSAGE_BODY_SIZE(m))
3193 part = find_part(m, *rindex, padding, (void**) &q);
3198 /* Verify padding */
3199 for (k = 0; k < padding; k++)
3204 part = find_part(m, start, nbytes, (void**) &q);
3205 if (!part || (nbytes > 0 && !q))
3216 static bool validate_nul(const char *s, size_t l) {
3218 /* Check for NUL chars in the string */
3219 if (memchr(s, 0, l))
3222 /* Check for NUL termination */
3229 static bool validate_string(const char *s, size_t l) {
3231 if (!validate_nul(s, l))
3234 /* Check if valid UTF8 */
3235 if (!utf8_is_valid(s))
3241 static bool validate_signature(const char *s, size_t l) {
3243 if (!validate_nul(s, l))
3246 /* Check if valid signature */
3247 if (!signature_is_valid(s, true))
3253 static bool validate_object_path(const char *s, size_t l) {
3255 if (!validate_nul(s, l))
3258 if (!object_path_is_valid(s))
3264 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3265 struct bus_container *c;
3270 assert_return(m, -EINVAL);
3271 assert_return(m->sealed, -EPERM);
3272 assert_return(bus_type_is_basic(type), -EINVAL);
3274 if (message_end_of_signature(m))
3277 if (message_end_of_array(m, m->rindex))
3280 c = message_get_container(m);
3281 if (c->signature[c->index] != type)
3286 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3288 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3291 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3295 if (type == SD_BUS_TYPE_STRING)
3296 ok = validate_string(q, c->item_size-1);
3297 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3298 ok = validate_object_path(q, c->item_size-1);
3300 ok = validate_signature(q, c->item_size-1);
3306 *(const char**) p = q;
3310 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3312 if ((size_t) sz != c->item_size)
3315 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3318 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3324 case SD_BUS_TYPE_BYTE:
3326 *(uint8_t*) p = *(uint8_t*) q;
3329 case SD_BUS_TYPE_BOOLEAN:
3331 *(int*) p = !!*(uint8_t*) q;
3334 case SD_BUS_TYPE_INT16:
3335 case SD_BUS_TYPE_UINT16:
3337 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3340 case SD_BUS_TYPE_INT32:
3341 case SD_BUS_TYPE_UINT32:
3343 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3346 case SD_BUS_TYPE_INT64:
3347 case SD_BUS_TYPE_UINT64:
3348 case SD_BUS_TYPE_DOUBLE:
3350 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3353 case SD_BUS_TYPE_UNIX_FD: {
3356 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3361 *(int*) p = m->fds[j];
3367 assert_not_reached("unexpected type");
3371 r = container_next_item(m, c, &rindex);
3378 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3382 r = message_peek_body(m, &rindex, 4, 4, &q);
3386 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3387 r = message_peek_body(m, &rindex, 1, l+1, &q);
3391 if (type == SD_BUS_TYPE_OBJECT_PATH)
3392 ok = validate_object_path(q, l);
3394 ok = validate_string(q, l);
3399 *(const char**) p = q;
3401 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3404 r = message_peek_body(m, &rindex, 1, 1, &q);
3409 r = message_peek_body(m, &rindex, 1, l+1, &q);
3413 if (!validate_signature(q, l))
3417 *(const char**) p = q;
3422 align = bus_type_get_alignment(type);
3425 sz = bus_type_get_size(type);
3428 r = message_peek_body(m, &rindex, align, sz, &q);
3434 case SD_BUS_TYPE_BYTE:
3436 *(uint8_t*) p = *(uint8_t*) q;
3439 case SD_BUS_TYPE_BOOLEAN:
3441 *(int*) p = !!*(uint32_t*) q;
3444 case SD_BUS_TYPE_INT16:
3445 case SD_BUS_TYPE_UINT16:
3447 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3450 case SD_BUS_TYPE_INT32:
3451 case SD_BUS_TYPE_UINT32:
3453 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3456 case SD_BUS_TYPE_INT64:
3457 case SD_BUS_TYPE_UINT64:
3458 case SD_BUS_TYPE_DOUBLE:
3460 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3463 case SD_BUS_TYPE_UNIX_FD: {
3466 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3471 *(int*) p = m->fds[j];
3476 assert_not_reached("Unknown basic type...");
3483 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3489 static int bus_message_enter_array(
3491 struct bus_container *c,
3492 const char *contents,
3493 uint32_t **array_size,
3496 size_t *n_offsets) {
3510 if (!signature_is_single(contents, true))
3513 if (!c->signature || c->signature[c->index] == 0)
3516 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3519 if (!startswith(c->signature + c->index + 1, contents))
3524 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3527 r = message_peek_body(m, &rindex, 4, 4, &q);
3531 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3534 alignment = bus_type_get_alignment(contents[0]);
3538 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3542 *array_size = (uint32_t*) q;
3544 } else if (c->item_size <= 0) {
3546 /* gvariant: empty array */
3551 } else if (bus_gvariant_is_fixed_size(contents)) {
3553 /* gvariant: fixed length array */
3554 *item_size = bus_gvariant_get_size(contents);
3559 size_t where, p = 0, framing, sz;
3562 /* gvariant: variable length array */
3563 sz = determine_word_size(c->item_size, 0);
3565 where = rindex + c->item_size - sz;
3566 r = message_peek_body(m, &where, 1, sz, &q);
3570 framing = read_word_le(q, sz);
3571 if (framing > c->item_size - sz)
3573 if ((c->item_size - framing) % sz != 0)
3576 *n_offsets = (c->item_size - framing) / sz;
3578 where = rindex + framing;
3579 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3583 *offsets = new(size_t, *n_offsets);
3587 for (i = 0; i < *n_offsets; i++) {
3590 x = read_word_le((uint8_t*) q + i * sz, sz);
3591 if (x > c->item_size - sz)
3596 (*offsets)[i] = rindex + x;
3600 *item_size = (*offsets)[0] - rindex;
3605 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3606 c->index += 1 + strlen(contents);
3611 static int bus_message_enter_variant(
3613 struct bus_container *c,
3614 const char *contents,
3615 size_t *item_size) {
3627 if (!signature_is_single(contents, false))
3630 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3633 if (!c->signature || c->signature[c->index] == 0)
3636 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3641 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3644 k = strlen(contents);
3645 if (1+k > c->item_size)
3648 where = rindex + c->item_size - (1+k);
3649 r = message_peek_body(m, &where, 1, 1+k, &q);
3653 if (*(char*) q != 0)
3656 if (memcmp((uint8_t*) q+1, contents, k))
3659 *item_size = c->item_size - (1+k);
3662 r = message_peek_body(m, &rindex, 1, 1, &q);
3667 r = message_peek_body(m, &rindex, 1, l+1, &q);
3671 if (!validate_signature(q, l))
3674 if (!streq(q, contents))
3680 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3686 static int build_struct_offsets(
3688 const char *signature,
3692 size_t *n_offsets) {
3694 unsigned n_variable = 0, n_total = 0, v;
3695 size_t previous = 0, where;
3706 if (isempty(signature)) {
3713 sz = determine_word_size(size, 0);
3717 /* First, loop over signature and count variable elements and
3718 * elements in general. We use this to know how large the
3719 * offset array is at the end of the structure. Note that
3720 * GVariant only stores offsets for all variable size elements
3721 * that are not the last item. */
3727 r = signature_element_length(p, &n);
3736 r = bus_gvariant_is_fixed_size(t);
3741 if (r == 0 && p[n] != 0) /* except the last item */
3748 if (size < n_variable * sz)
3751 where = m->rindex + size - (n_variable * sz);
3752 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3758 *offsets = new(size_t, n_total);
3764 /* Second, loop again and build an offset table */
3770 r = signature_element_length(p, &n);
3779 k = bus_gvariant_get_size(t);
3787 x = read_word_le((uint8_t*) q + v*sz, sz);
3790 if (m->rindex + x < previous)
3793 /* The last item's end
3794 * is determined from
3797 x = size - (n_variable * sz);
3799 offset = m->rindex + x;
3805 align = bus_gvariant_get_alignment(t);
3808 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3812 previous = (*offsets)[(*n_offsets)++] = offset;
3817 assert(*n_offsets == n_total);
3819 *item_size = (*offsets)[0] - m->rindex;
3823 static int enter_struct_or_dict_entry(
3825 struct bus_container *c,
3826 const char *contents,
3829 size_t *n_offsets) {
3840 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3843 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3847 } else if (c->item_size <= 0) {
3849 /* gvariant empty struct */
3854 /* gvariant with contents */
3855 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3860 static int bus_message_enter_struct(
3862 struct bus_container *c,
3863 const char *contents,
3866 size_t *n_offsets) {
3878 if (!signature_is_valid(contents, false))
3881 if (!c->signature || c->signature[c->index] == 0)
3884 l = strlen(contents);
3886 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3887 !startswith(c->signature + c->index + 1, contents) ||
3888 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3891 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3895 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3896 c->index += 1 + l + 1;
3901 static int bus_message_enter_dict_entry(
3903 struct bus_container *c,
3904 const char *contents,
3907 size_t *n_offsets) {
3916 if (!signature_is_pair(contents))
3919 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3922 if (!c->signature || c->signature[c->index] == 0)
3925 l = strlen(contents);
3927 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3928 !startswith(c->signature + c->index + 1, contents) ||
3929 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3932 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3936 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3937 c->index += 1 + l + 1;
3942 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3944 const char *contents) {
3945 struct bus_container *c, *w;
3946 uint32_t *array_size = NULL;
3949 size_t *offsets = NULL;
3950 size_t n_offsets = 0, item_size = 0;
3953 assert_return(m, -EINVAL);
3954 assert_return(m->sealed, -EPERM);
3955 assert_return(type != 0 || !contents, -EINVAL);
3957 if (type == 0 || !contents) {
3961 /* Allow entering into anonymous containers */
3962 r = sd_bus_message_peek_type(m, &tt, &cc);
3966 if (type != 0 && type != tt)
3969 if (contents && !streq(contents, cc))
3977 * We enforce a global limit on container depth, that is much
3978 * higher than the 32 structs and 32 arrays the specification
3979 * mandates. This is simpler to implement for us, and we need
3980 * this only to ensure our container array doesn't grow
3981 * without bounds. We are happy to return any data from a
3982 * message as long as the data itself is valid, even if the
3983 * overall message might be not.
3985 * Note that the message signature is validated when
3986 * parsing the headers, and that validation does check the
3989 * Note that the specification defines no limits on the depth
3990 * of stacked variants, but we do.
3992 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3995 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3998 if (message_end_of_signature(m))
4001 if (message_end_of_array(m, m->rindex))
4004 c = message_get_container(m);
4006 signature = strdup(contents);
4010 c->saved_index = c->index;
4013 if (type == SD_BUS_TYPE_ARRAY)
4014 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4015 else if (type == SD_BUS_TYPE_VARIANT)
4016 r = bus_message_enter_variant(m, c, contents, &item_size);
4017 else if (type == SD_BUS_TYPE_STRUCT)
4018 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4019 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4020 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4030 /* OK, let's fill it in */
4031 w = m->containers + m->n_containers++;
4032 w->enclosing = type;
4033 w->signature = signature;
4034 w->peeked_signature = NULL;
4038 w->begin = m->rindex;
4039 w->end = m->rindex + c->item_size;
4041 w->array_size = array_size;
4042 w->item_size = item_size;
4043 w->offsets = offsets;
4044 w->n_offsets = n_offsets;
4045 w->offset_index = 0;
4050 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4051 struct bus_container *c;
4055 assert_return(m, -EINVAL);
4056 assert_return(m->sealed, -EPERM);
4057 assert_return(m->n_containers > 0, -ENXIO);
4059 c = message_get_container(m);
4061 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4062 if (c->signature && c->signature[c->index] != 0)
4066 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4067 if (m->rindex < c->end)
4070 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4073 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4074 if (c->begin + l != m->rindex)
4079 free(c->peeked_signature);
4083 c = message_get_container(m);
4086 c->index = c->saved_index;
4087 r = container_next_item(m, c, &m->rindex);
4095 static void message_quit_container(sd_bus_message *m) {
4096 struct bus_container *c;
4100 assert(m->n_containers > 0);
4102 c = message_get_container(m);
4105 assert(m->rindex >= c->before);
4106 m->rindex = c->before;
4108 /* Free container */
4113 /* Correct index of new top-level container */
4114 c = message_get_container(m);
4115 c->index = c->saved_index;
4118 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4119 struct bus_container *c;
4122 assert_return(m, -EINVAL);
4123 assert_return(m->sealed, -EPERM);
4125 if (message_end_of_signature(m))
4128 if (message_end_of_array(m, m->rindex))
4131 c = message_get_container(m);
4133 if (bus_type_is_basic(c->signature[c->index])) {
4137 *type = c->signature[c->index];
4141 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4147 r = signature_element_length(c->signature+c->index+1, &l);
4153 sig = strndup(c->signature + c->index + 1, l);
4157 free(c->peeked_signature);
4158 *contents = c->peeked_signature = sig;
4162 *type = SD_BUS_TYPE_ARRAY;
4167 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4168 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4174 r = signature_element_length(c->signature+c->index, &l);
4179 sig = strndup(c->signature + c->index + 1, l - 2);
4183 free(c->peeked_signature);
4184 *contents = c->peeked_signature = sig;
4188 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4193 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4197 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4200 if (c->item_size < 2)
4203 /* Look for the NUL delimiter that
4204 separates the payload from the
4205 signature. Since the body might be
4206 in a different part that then the
4207 signature we map byte by byte. */
4209 for (k = 2; k <= c->item_size; k++) {
4212 where = m->rindex + c->item_size - k;
4213 r = message_peek_body(m, &where, 1, k, &q);
4217 if (*(char*) q == 0)
4221 if (k > c->item_size)
4224 free(c->peeked_signature);
4225 c->peeked_signature = strndup((char*) q + 1, k - 1);
4226 if (!c->peeked_signature)
4229 if (!signature_is_valid(c->peeked_signature, true))
4232 *contents = c->peeked_signature;
4237 r = message_peek_body(m, &rindex, 1, 1, &q);
4242 r = message_peek_body(m, &rindex, 1, l+1, &q);
4246 if (!validate_signature(q, l))
4254 *type = SD_BUS_TYPE_VARIANT;
4269 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4270 struct bus_container *c;
4272 assert_return(m, -EINVAL);
4273 assert_return(m->sealed, -EPERM);
4276 message_reset_containers(m);
4279 c = message_get_container(m);
4281 c = message_get_container(m);
4283 c->offset_index = 0;
4285 m->rindex = c->begin;
4288 c->offset_index = 0;
4289 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4291 return !isempty(c->signature);
4294 static int message_read_ap(
4299 unsigned n_array, n_struct;
4300 TypeStack stack[BUS_CONTAINER_DEPTH];
4301 unsigned stack_ptr = 0;
4302 unsigned n_loop = 0;
4310 /* Ideally, we'd just call ourselves recursively on every
4311 * complex type. However, the state of a va_list that is
4312 * passed to a function is undefined after that function
4313 * returns. This means we need to docode the va_list linearly
4314 * in a single stackframe. We hence implement our own
4315 * home-grown stack in an array. */
4317 n_array = (unsigned) -1; /* length of current array entries */
4318 n_struct = strlen(types); /* length of current struct contents signature */
4325 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4326 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4332 r = sd_bus_message_exit_container(m);
4340 if (n_array != (unsigned) -1)
4349 case SD_BUS_TYPE_BYTE:
4350 case SD_BUS_TYPE_BOOLEAN:
4351 case SD_BUS_TYPE_INT16:
4352 case SD_BUS_TYPE_UINT16:
4353 case SD_BUS_TYPE_INT32:
4354 case SD_BUS_TYPE_UINT32:
4355 case SD_BUS_TYPE_INT64:
4356 case SD_BUS_TYPE_UINT64:
4357 case SD_BUS_TYPE_DOUBLE:
4358 case SD_BUS_TYPE_STRING:
4359 case SD_BUS_TYPE_OBJECT_PATH:
4360 case SD_BUS_TYPE_SIGNATURE:
4361 case SD_BUS_TYPE_UNIX_FD: {
4364 p = va_arg(ap, void*);
4365 r = sd_bus_message_read_basic(m, *t, p);
4378 case SD_BUS_TYPE_ARRAY: {
4381 r = signature_element_length(t + 1, &k);
4387 memcpy(s, t + 1, k);
4390 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4401 if (n_array == (unsigned) -1) {
4406 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4412 n_array = va_arg(ap, unsigned);
4417 case SD_BUS_TYPE_VARIANT: {
4420 s = va_arg(ap, const char *);
4424 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4434 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4439 n_struct = strlen(s);
4440 n_array = (unsigned) -1;
4445 case SD_BUS_TYPE_STRUCT_BEGIN:
4446 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4449 r = signature_element_length(t, &k);
4455 memcpy(s, t + 1, k - 2);
4458 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4468 if (n_array == (unsigned) -1) {
4473 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4479 n_array = (unsigned) -1;
4492 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4496 assert_return(m, -EINVAL);
4497 assert_return(m->sealed, -EPERM);
4498 assert_return(types, -EINVAL);
4500 va_start(ap, types);
4501 r = message_read_ap(m, types, ap);
4507 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4510 assert_return(m, -EINVAL);
4511 assert_return(m->sealed, -EPERM);
4513 /* If types is NULL, read exactly one element */
4515 struct bus_container *c;
4518 if (message_end_of_signature(m))
4521 if (message_end_of_array(m, m->rindex))
4524 c = message_get_container(m);
4526 r = signature_element_length(c->signature + c->index, &l);
4530 types = strndupa(c->signature + c->index, l);
4535 case 0: /* Nothing to drop */
4538 case SD_BUS_TYPE_BYTE:
4539 case SD_BUS_TYPE_BOOLEAN:
4540 case SD_BUS_TYPE_INT16:
4541 case SD_BUS_TYPE_UINT16:
4542 case SD_BUS_TYPE_INT32:
4543 case SD_BUS_TYPE_UINT32:
4544 case SD_BUS_TYPE_INT64:
4545 case SD_BUS_TYPE_UINT64:
4546 case SD_BUS_TYPE_DOUBLE:
4547 case SD_BUS_TYPE_STRING:
4548 case SD_BUS_TYPE_OBJECT_PATH:
4549 case SD_BUS_TYPE_SIGNATURE:
4550 case SD_BUS_TYPE_UNIX_FD:
4552 r = sd_bus_message_read_basic(m, *types, NULL);
4556 r = sd_bus_message_skip(m, types + 1);
4562 case SD_BUS_TYPE_ARRAY: {
4565 r = signature_element_length(types + 1, &k);
4571 memcpy(s, types+1, k);
4574 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4579 r = sd_bus_message_skip(m, s);
4586 r = sd_bus_message_exit_container(m);
4591 r = sd_bus_message_skip(m, types + 1 + k);
4598 case SD_BUS_TYPE_VARIANT: {
4599 const char *contents;
4602 r = sd_bus_message_peek_type(m, &x, &contents);
4606 if (x != SD_BUS_TYPE_VARIANT)
4609 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4613 r = sd_bus_message_skip(m, contents);
4618 r = sd_bus_message_exit_container(m);
4622 r = sd_bus_message_skip(m, types + 1);
4629 case SD_BUS_TYPE_STRUCT_BEGIN:
4630 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4633 r = signature_element_length(types, &k);
4639 memcpy(s, types+1, k-2);
4642 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4646 r = sd_bus_message_skip(m, s);
4651 r = sd_bus_message_exit_container(m);
4656 r = sd_bus_message_skip(m, types + k);
4668 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4672 struct bus_container *c;
4678 assert_return(m, -EINVAL);
4679 assert_return(m->sealed, -EPERM);
4680 assert_return(bus_type_is_trivial(type), -EINVAL);
4681 assert_return(ptr, -EINVAL);
4682 assert_return(size, -EINVAL);
4683 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4685 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4689 c = message_get_container(m);
4691 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4692 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4696 sz = c->end - c->begin;
4698 align = bus_type_get_alignment(type);
4702 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4706 /* Zero length array, let's return some aligned
4707 * pointer that is not NULL */
4708 p = (uint8_t*) NULL + align;
4710 r = message_peek_body(m, &m->rindex, align, sz, &p);
4715 r = sd_bus_message_exit_container(m);
4719 *ptr = (const void*) p;
4725 message_quit_container(m);
4729 static int message_peek_fields(
4740 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4743 static int message_peek_field_uint32(
4755 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4758 /* identical for gvariant and dbus1 */
4760 r = message_peek_fields(m, ri, 4, 4, &q);
4765 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4770 static int message_peek_field_string(
4772 bool (*validate)(const char *p),
4784 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4789 r = message_peek_fields(m, ri, 1, item_size, &q);
4795 r = message_peek_field_uint32(m, ri, 4, &l);
4799 r = message_peek_fields(m, ri, 1, l+1, &q);
4805 if (!validate_nul(q, l))
4811 if (!validate_string(q, l))
4821 static int message_peek_field_signature(
4834 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4839 r = message_peek_fields(m, ri, 1, item_size, &q);
4845 r = message_peek_fields(m, ri, 1, 1, &q);
4850 r = message_peek_fields(m, ri, 1, l+1, &q);
4855 if (!validate_signature(q, l))
4864 static int message_skip_fields(
4867 uint32_t array_size,
4868 const char **signature) {
4870 size_t original_index;
4876 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4878 original_index = *ri;
4884 if (array_size != (uint32_t) -1 &&
4885 array_size <= *ri - original_index)
4892 if (t == SD_BUS_TYPE_STRING) {
4894 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4900 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4902 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4908 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4910 r = message_peek_field_signature(m, ri, 0, NULL);
4916 } else if (bus_type_is_basic(t)) {
4919 align = bus_type_get_alignment(t);
4920 k = bus_type_get_size(t);
4921 assert(align > 0 && k > 0);
4923 r = message_peek_fields(m, ri, align, k, NULL);
4929 } else if (t == SD_BUS_TYPE_ARRAY) {
4931 r = signature_element_length(*signature+1, &l);
4941 strncpy(sig, *signature + 1, l-1);
4944 alignment = bus_type_get_alignment(sig[0]);
4948 r = message_peek_field_uint32(m, ri, 0, &nas);
4951 if (nas > BUS_ARRAY_MAX_SIZE)
4954 r = message_peek_fields(m, ri, alignment, 0, NULL);
4958 r = message_skip_fields(m, ri, nas, (const char**) &s);
4963 (*signature) += 1 + l;
4965 } else if (t == SD_BUS_TYPE_VARIANT) {
4968 r = message_peek_field_signature(m, ri, 0, &s);
4972 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4978 } else if (t == SD_BUS_TYPE_STRUCT ||
4979 t == SD_BUS_TYPE_DICT_ENTRY) {
4981 r = signature_element_length(*signature, &l);
4988 strncpy(sig, *signature + 1, l-1);
4991 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5002 int bus_message_parse_fields(sd_bus_message *m) {
5005 uint32_t unix_fds = 0;
5006 bool unix_fds_set = false;
5007 void *offsets = NULL;
5008 unsigned n_offsets = 0;
5014 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5017 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
5021 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
5022 r = message_peek_fields(m, &ri, 1, sz, &q);
5026 framing = read_word_le(q, sz);
5027 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
5029 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
5033 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
5037 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
5042 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
5043 _cleanup_free_ char *sig = NULL;
5044 const char *signature;
5046 size_t item_size = (size_t) -1;
5048 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5055 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5058 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
5062 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5067 end = read_word_le((uint8_t*) offsets + i*sz, sz);
5072 where = ri = ALIGN_TO(ri, 8);
5073 item_size = end - ri;
5074 r = message_peek_fields(m, &where, 1, item_size, &q);
5078 b = memrchr(q, 0, item_size);
5082 sig = strndup(b+1, item_size - (b+1-(char*) q));
5087 item_size = b - (char*) q;
5089 r = message_peek_field_signature(m, &ri, 0, &signature);
5095 case _BUS_MESSAGE_HEADER_INVALID:
5098 case BUS_MESSAGE_HEADER_PATH:
5103 if (!streq(signature, "o"))
5106 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5109 case BUS_MESSAGE_HEADER_INTERFACE:
5114 if (!streq(signature, "s"))
5117 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5120 case BUS_MESSAGE_HEADER_MEMBER:
5125 if (!streq(signature, "s"))
5128 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5131 case BUS_MESSAGE_HEADER_ERROR_NAME:
5136 if (!streq(signature, "s"))
5139 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5141 m->error._need_free = -1;
5145 case BUS_MESSAGE_HEADER_DESTINATION:
5150 if (!streq(signature, "s"))
5153 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5156 case BUS_MESSAGE_HEADER_SENDER:
5161 if (!streq(signature, "s"))
5164 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5166 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5167 m->creds.unique_name = (char*) m->sender;
5168 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5174 case BUS_MESSAGE_HEADER_SIGNATURE: {
5178 if (m->root_container.signature)
5181 if (!streq(signature, "g"))
5184 r = message_peek_field_signature(m, &ri, item_size, &s);
5192 free(m->root_container.signature);
5193 m->root_container.signature = c;
5197 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5200 if (m->reply_cookie != 0)
5203 if (!streq(signature, "u"))
5206 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5210 m->reply_cookie = serial;
5212 if (m->reply_cookie == 0)
5218 case BUS_MESSAGE_HEADER_UNIX_FDS:
5222 if (!streq(signature, "u"))
5225 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5229 unix_fds_set = true;
5233 if (!BUS_MESSAGE_IS_GVARIANT(m))
5234 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5243 if (m->n_fds != unix_fds)
5246 switch (m->header->type) {
5248 case SD_BUS_MESSAGE_SIGNAL:
5249 if (!m->path || !m->interface || !m->member)
5252 if (m->reply_cookie != 0)
5257 case SD_BUS_MESSAGE_METHOD_CALL:
5259 if (!m->path || !m->member)
5262 if (m->reply_cookie != 0)
5267 case SD_BUS_MESSAGE_METHOD_RETURN:
5269 if (m->reply_cookie == 0)
5273 case SD_BUS_MESSAGE_METHOD_ERROR:
5275 if (m->reply_cookie == 0 || !m->error.name)
5280 /* Refuse non-local messages that claim they are local */
5281 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5283 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5285 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5288 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5290 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5291 r = build_struct_offsets(
5293 m->root_container.signature,
5294 BUS_MESSAGE_BODY_SIZE(m),
5295 &m->root_container.item_size,
5296 &m->root_container.offsets,
5297 &m->root_container.n_offsets);
5302 /* Try to read the error message, but if we can't it's a non-issue */
5303 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5304 sd_bus_message_read(m, "s", &m->error.message);
5309 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5310 assert_return(m, -EINVAL);
5311 assert_return(destination, -EINVAL);
5312 assert_return(!m->sealed, -EPERM);
5313 assert_return(!m->destination, -EEXIST);
5315 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5318 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5322 struct bus_body_part *part;
5328 total = BUS_MESSAGE_SIZE(m);
5334 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5335 MESSAGE_FOREACH_PART(part, i, m)
5336 e = mempcpy(e, part->data, part->size);
5338 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5346 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5352 r = sd_bus_message_enter_container(m, 'a', "s");
5359 r = sd_bus_message_read_basic(m, 's', &s);
5365 r = strv_extend(l, s);
5370 r = sd_bus_message_exit_container(m);
5377 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5381 assert_return(m, -EINVAL);
5382 assert_return(m->sealed, -EPERM);
5383 assert_return(l, -EINVAL);
5385 r = bus_message_read_strv_extend(m, &strv);
5395 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5396 const char *contents;
5405 r = sd_bus_message_rewind(m, true);
5410 r = sd_bus_message_peek_type(m, &type, &contents);
5416 /* Don't match against arguments after the first one we don't understand */
5417 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5418 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5424 r = sd_bus_message_skip(m, NULL);
5429 if (type == SD_BUS_TYPE_ARRAY) {
5431 r = sd_bus_message_read_strv(m, strv);
5438 r = sd_bus_message_read_basic(m, type, str);
5448 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5454 if (size < sizeof(struct bus_header))
5457 full = sizeof(struct bus_header) +
5458 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5460 return size >= full;
5463 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5469 if (h->endian == BUS_NATIVE_ENDIAN) {
5470 fs = h->fields_size;
5472 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5473 fs = bswap_32(h->fields_size);
5474 bs = bswap_32(h->body_size);
5478 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5482 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5483 assert_return(m, EINVAL);
5485 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5488 return sd_bus_error_get_errno(&m->error);
5491 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5492 struct bus_container *c;
5494 assert_return(m, NULL);
5496 c = complete ? &m->root_container : message_get_container(m);
5497 return strempty(c->signature);
5500 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5501 assert_return(m, -EINVAL);
5503 return isempty(m->root_container.signature);
5506 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5507 assert_return(m, -EINVAL);
5509 return streq(strempty(m->root_container.signature), strempty(signature));
5512 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5513 bool done_something = false;
5516 assert_return(m, -EINVAL);
5517 assert_return(source, -EINVAL);
5518 assert_return(!m->sealed, -EPERM);
5519 assert_return(source->sealed, -EPERM);
5522 const char *contents;
5537 r = sd_bus_message_peek_type(source, &type, &contents);
5543 done_something = true;
5545 if (bus_type_is_container(type) > 0) {
5547 r = sd_bus_message_enter_container(source, type, contents);
5551 r = sd_bus_message_open_container(m, type, contents);
5555 r = sd_bus_message_copy(m, source, true);
5559 r = sd_bus_message_close_container(m);
5563 r = sd_bus_message_exit_container(source);
5570 r = sd_bus_message_read_basic(source, type, &basic);
5576 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5577 type == SD_BUS_TYPE_SIGNATURE ||
5578 type == SD_BUS_TYPE_STRING)
5579 r = sd_bus_message_append_basic(m, type, basic.string);
5581 r = sd_bus_message_append_basic(m, type, &basic);
5588 return done_something;
5591 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5596 assert_return(m, -EINVAL);
5597 assert_return(m->sealed, -EPERM);
5598 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5599 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5600 assert_return(type || contents, -EINVAL);
5601 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5603 r = sd_bus_message_peek_type(m, &t, &c);
5607 if (type != 0 && type != t)
5610 if (contents && !streq_ptr(contents, c))
5616 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5617 assert_return(m, NULL);
5622 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5623 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5631 switch ((*m)->header->type) {
5633 case SD_BUS_MESSAGE_SIGNAL:
5634 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5640 case SD_BUS_MESSAGE_METHOD_CALL:
5641 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5647 case SD_BUS_MESSAGE_METHOD_RETURN:
5648 case SD_BUS_MESSAGE_METHOD_ERROR:
5650 n = message_new(bus, (*m)->header->type);
5654 n->reply_cookie = (*m)->reply_cookie;
5655 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5659 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5660 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5664 n->error._need_free = -1;
5673 if ((*m)->destination && !n->destination) {
5674 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5679 if ((*m)->sender && !n->sender) {
5680 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5685 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5687 r = sd_bus_message_copy(n, *m, true);
5691 timeout = (*m)->timeout;
5692 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5693 timeout = BUS_DEFAULT_TIMEOUT;
5695 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5699 sd_bus_message_unref(*m);
5706 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5710 assert_return(!m->sealed, -EPERM);
5711 assert_return(!m->sender, -EPERM);
5713 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5716 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5717 assert_return(m, -EINVAL);
5718 assert_return(priority, -EINVAL);
5720 *priority = m->priority;
5724 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5725 assert_return(m, -EINVAL);
5726 assert_return(!m->sealed, -EPERM);
5728 m->priority = priority;