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 = { };
136 cmd_free.offset = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
137 (void) ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &cmd_free);
143 sd_bus_unref(m->bus);
146 close_many(m->fds, m->n_fds);
150 if (m->iovec != m->iovec_fixed)
153 if (m->destination_ptr) {
154 free(m->destination_ptr);
155 m->destination_ptr = NULL;
158 message_reset_containers(m);
159 free(m->root_container.signature);
160 free(m->root_container.offsets);
162 free(m->root_container.peeked_signature);
164 bus_creds_done(&m->creds);
168 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
170 size_t old_size, new_size, start;
177 old_size = sizeof(struct bus_header) + m->header->fields_size;
178 start = ALIGN_TO(old_size, align);
179 new_size = start + sz;
181 if (old_size == new_size)
182 return (uint8_t*) m->header + old_size;
184 if (new_size > (size_t) ((uint32_t) -1))
187 if (m->free_header) {
188 np = realloc(m->header, ALIGN8(new_size));
192 /* Initially, the header is allocated as part of of
193 * the sd_bus_message itself, let's replace it by
196 np = malloc(ALIGN8(new_size));
200 memcpy(np, m->header, sizeof(struct bus_header));
203 /* Zero out padding */
204 if (start > old_size)
205 memzero((uint8_t*) np + old_size, start - old_size);
209 m->header->fields_size = new_size - sizeof(struct bus_header);
211 /* Adjust quick access pointers */
212 m->path = adjust_pointer(m->path, op, old_size, m->header);
213 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
214 m->member = adjust_pointer(m->member, op, old_size, m->header);
215 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
216 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
217 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
219 m->free_header = true;
222 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
225 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
228 return (uint8_t*) np + start;
235 static int message_append_field_string(
247 /* dbus1 doesn't allow strings over 32bit, let's enforce this
248 * globally, to not risk convertability */
250 if (l > (size_t) (uint32_t) -1)
253 /* Signature "(yv)" where the variant contains "s" */
255 if (BUS_MESSAGE_IS_GVARIANT(m)) {
257 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
258 p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
270 *ret = (char*) p + 8;
273 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
274 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
283 ((uint32_t*) p)[1] = l;
284 memcpy(p + 8, s, l + 1);
287 *ret = (char*) p + 8;
293 static int message_append_field_signature(
304 /* dbus1 doesn't allow signatures over 32bit, let's enforce
305 * this globally, to not risk convertability */
310 /* Signature "(yv)" where the variant contains "g" */
312 if (BUS_MESSAGE_IS_GVARIANT(m))
313 /* For gvariant the serialization is the same as for normal strings */
314 return message_append_field_string(m, h, 'g', s, ret);
316 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
317 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
323 p[2] = SD_BUS_TYPE_SIGNATURE;
326 memcpy(p + 5, s, l + 1);
329 *ret = (const char*) p + 5;
335 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
340 if (BUS_MESSAGE_IS_GVARIANT(m)) {
341 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
343 p = message_extend_fields(m, 8, 1 + 7 + 4 + 1 + 1, true);
349 *((uint32_t*) (p + 8)) = x;
353 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
354 p = message_extend_fields(m, 8, 4 + 4, false);
360 p[2] = SD_BUS_TYPE_UINT32;
363 ((uint32_t*) p)[1] = x;
369 int bus_message_from_header(
375 const struct ucred *ucred,
378 sd_bus_message **ret) {
381 struct bus_header *h;
385 assert(buffer || length <= 0);
386 assert(fds || n_fds <= 0);
389 if (length < sizeof(struct bus_header))
393 if (h->version != 1 &&
400 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
403 if (h->endian != BUS_LITTLE_ENDIAN &&
404 h->endian != BUS_BIG_ENDIAN)
407 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
410 label_sz = strlen(label);
425 m->creds.pid = ucred->pid;
426 m->creds.uid = ucred->uid;
427 m->creds.gid = ucred->gid;
429 /* Due to namespace translations some data might be
430 * missing from this ucred record. */
431 if (m->creds.pid > 0)
432 m->creds.mask |= SD_BUS_CREDS_PID;
434 if (m->creds.uid != UID_INVALID)
435 m->creds.mask |= SD_BUS_CREDS_UID;
437 if (m->creds.gid != GID_INVALID)
438 m->creds.mask |= SD_BUS_CREDS_GID;
442 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
443 memcpy(m->creds.label, label, label_sz + 1);
445 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
448 m->bus = sd_bus_ref(bus);
454 int bus_message_from_malloc(
460 const struct ucred *ucred,
462 sd_bus_message **ret) {
468 r = bus_message_from_header(bus, buffer, length, fds, n_fds, ucred, label, 0, &m);
472 if (length != BUS_MESSAGE_SIZE(m)) {
477 sz = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
480 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
482 m->body.sealed = true;
487 m->iovec = m->iovec_fixed;
488 m->iovec[0].iov_base = buffer;
489 m->iovec[0].iov_len = length;
491 r = bus_message_parse_fields(m);
495 /* We take possession of the memory and fds now */
496 m->free_header = true;
507 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
512 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
517 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
518 m->header->endian = BUS_NATIVE_ENDIAN;
519 m->header->type = type;
520 m->header->version = bus ? bus->message_version : 1;
521 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
522 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
523 m->bus = sd_bus_ref(bus);
528 _public_ int sd_bus_message_new_signal(
532 const char *interface,
533 const char *member) {
538 assert_return(bus, -ENOTCONN);
539 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
540 assert_return(object_path_is_valid(path), -EINVAL);
541 assert_return(interface_name_is_valid(interface), -EINVAL);
542 assert_return(member_name_is_valid(member), -EINVAL);
543 assert_return(m, -EINVAL);
545 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
549 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
551 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
554 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
557 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
565 sd_bus_message_unref(t);
569 _public_ int sd_bus_message_new_method_call(
572 const char *destination,
574 const char *interface,
575 const char *member) {
580 assert_return(bus, -ENOTCONN);
581 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
582 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
583 assert_return(object_path_is_valid(path), -EINVAL);
584 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
585 assert_return(member_name_is_valid(member), -EINVAL);
586 assert_return(m, -EINVAL);
588 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
592 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
595 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
600 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
606 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
619 static int message_new_reply(
620 sd_bus_message *call,
622 sd_bus_message **m) {
627 assert_return(call, -EINVAL);
628 assert_return(call->sealed, -EPERM);
629 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
630 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
631 assert_return(m, -EINVAL);
633 t = message_new(call->bus, type);
637 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
638 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
640 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
645 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
650 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
651 t->enforced_reply_signature = call->enforced_reply_signature;
661 _public_ int sd_bus_message_new_method_return(
662 sd_bus_message *call,
663 sd_bus_message **m) {
665 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
668 _public_ int sd_bus_message_new_method_error(
669 sd_bus_message *call,
671 const sd_bus_error *e) {
676 assert_return(sd_bus_error_is_set(e), -EINVAL);
677 assert_return(m, -EINVAL);
679 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
683 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
688 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
693 t->error._need_free = -1;
703 _public_ int sd_bus_message_new_method_errorf(
704 sd_bus_message *call,
710 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
713 assert_return(name, -EINVAL);
714 assert_return(m, -EINVAL);
716 va_start(ap, format);
717 bus_error_setfv(&error, name, format, ap);
720 return sd_bus_message_new_method_error(call, m, &error);
723 _public_ int sd_bus_message_new_method_errno(
724 sd_bus_message *call,
727 const sd_bus_error *p) {
729 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
731 if (sd_bus_error_is_set(p))
732 return sd_bus_message_new_method_error(call, m, p);
734 sd_bus_error_set_errno(&berror, error);
736 return sd_bus_message_new_method_error(call, m, &berror);
739 _public_ int sd_bus_message_new_method_errnof(
740 sd_bus_message *call,
746 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
749 va_start(ap, format);
750 bus_error_set_errnofv(&berror, error, format, ap);
753 return sd_bus_message_new_method_error(call, m, &berror);
756 int bus_message_new_synthetic_error(
759 const sd_bus_error *e,
760 sd_bus_message **m) {
766 assert(sd_bus_error_is_set(e));
769 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
773 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
774 t->reply_cookie = cookie;
776 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
780 if (bus && bus->unique_name) {
781 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
786 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
791 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
796 t->error._need_free = -1;
806 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
807 assert_return(m, NULL);
809 assert(m->n_ref > 0);
815 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
820 assert(m->n_ref > 0);
830 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
831 assert_return(m, -EINVAL);
832 assert_return(type, -EINVAL);
834 *type = m->header->type;
838 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
839 assert_return(m, -EINVAL);
840 assert_return(cookie, -EINVAL);
841 assert_return(m->header->serial != 0, -ENODATA);
843 *cookie = BUS_MESSAGE_COOKIE(m);
847 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
848 assert_return(m, -EINVAL);
849 assert_return(cookie, -EINVAL);
850 assert_return(m->reply_cookie != 0, -ENODATA);
852 *cookie = m->reply_cookie;
856 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
857 assert_return(m, -EINVAL);
859 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
860 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
863 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
864 assert_return(m, -EINVAL);
866 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
869 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
870 assert_return(m, -EINVAL);
872 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
873 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
876 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
877 assert_return(m, NULL);
882 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
883 assert_return(m, NULL);
888 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
889 assert_return(m, NULL);
894 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
895 assert_return(m, NULL);
897 return m->destination;
900 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
901 assert_return(m, NULL);
906 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
907 assert_return(m, NULL);
908 assert_return(sd_bus_error_is_set(&m->error), NULL);
913 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
914 assert_return(m, -EINVAL);
915 assert_return(usec, -EINVAL);
917 if (m->monotonic <= 0)
920 *usec = m->monotonic;
924 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
925 assert_return(m, -EINVAL);
926 assert_return(usec, -EINVAL);
928 if (m->realtime <= 0)
935 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
936 assert_return(m, -EINVAL);
937 assert_return(seqnum, -EINVAL);
946 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
947 assert_return(m, NULL);
949 if (m->creds.mask == 0)
955 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
956 const char *interface,
957 const char *member) {
958 assert_return(m, -EINVAL);
960 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
963 if (interface && (!m->interface || !streq(m->interface, interface)))
966 if (member && (!m->member || !streq(m->member, member)))
972 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
973 const char *interface,
974 const char *member) {
975 assert_return(m, -EINVAL);
977 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
980 if (interface && (!m->interface || !streq(m->interface, interface)))
983 if (member && (!m->member || !streq(m->member, member)))
989 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
990 assert_return(m, -EINVAL);
992 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
995 if (name && (!m->error.name || !streq(m->error.name, name)))
1001 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1002 assert_return(m, -EINVAL);
1003 assert_return(!m->sealed, -EPERM);
1004 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1007 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1009 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1014 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1015 assert_return(m, -EINVAL);
1016 assert_return(!m->sealed, -EPERM);
1019 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1021 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1026 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1027 assert_return(m, -EINVAL);
1028 assert_return(!m->sealed, -EPERM);
1031 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1033 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1038 static struct bus_container *message_get_container(sd_bus_message *m) {
1041 if (m->n_containers == 0)
1042 return &m->root_container;
1044 assert(m->containers);
1045 return m->containers + m->n_containers - 1;
1048 struct bus_body_part *message_append_part(sd_bus_message *m) {
1049 struct bus_body_part *part;
1056 if (m->n_body_parts <= 0) {
1060 assert(m->body_end);
1062 part = new0(struct bus_body_part, 1);
1068 m->body_end->next = part;
1078 static void part_zero(struct bus_body_part *part, size_t sz) {
1083 /* All other fields can be left in their defaults */
1084 assert(!part->data);
1085 assert(part->memfd < 0);
1088 part->is_zero = true;
1089 part->sealed = true;
1092 static int part_make_space(
1093 struct sd_bus_message *m,
1094 struct bus_body_part *part,
1103 assert(!part->sealed);
1108 if (!part->data && part->memfd < 0) {
1109 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1110 part->mmap_begin = part->data;
1113 if (part->memfd >= 0) {
1115 if (part->allocated == 0 || sz > part->allocated) {
1116 uint64_t new_allocated;
1118 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1119 r = memfd_set_size(part->memfd, new_allocated);
1125 part->allocated = new_allocated;
1128 if (!part->data || sz > part->mapped) {
1131 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1132 if (part->mapped <= 0)
1133 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1135 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1137 if (n == MAP_FAILED) {
1142 part->mmap_begin = part->data = n;
1144 part->memfd_offset = 0;
1147 part->munmap_this = true;
1149 if (part->allocated == 0 || sz > part->allocated) {
1150 size_t new_allocated;
1152 new_allocated = sz > 0 ? 2 * sz : 64;
1153 n = realloc(part->data, new_allocated);
1160 part->allocated = new_allocated;
1161 part->free_this = true;
1166 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1172 static int message_add_offset(sd_bus_message *m, size_t offset) {
1173 struct bus_container *c;
1176 assert(BUS_MESSAGE_IS_GVARIANT(m));
1178 /* Add offset to current container, unless this is the first
1179 * item in it, which will have the 0 offset, which we can
1181 c = message_get_container(m);
1183 if (!c->need_offsets)
1186 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1189 c->offsets[c->n_offsets++] = offset;
1193 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1194 struct bus_container *c;
1201 /* Update counters */
1202 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1205 *c->array_size += expand;
1209 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1210 size_t start_body, end_body, padding, added;
1221 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1222 end_body = start_body + sz;
1224 padding = start_body - m->header->body_size;
1225 added = padding + sz;
1227 /* Check for 32bit overflows */
1228 if (end_body > (size_t) ((uint32_t) -1)) {
1234 struct bus_body_part *part = NULL;
1238 m->n_body_parts <= 0 ||
1239 m->body_end->sealed ||
1240 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1244 part = message_append_part(m);
1248 part_zero(part, padding);
1251 part = message_append_part(m);
1255 r = part_make_space(m, part, sz, &p);
1259 struct bus_container *c;
1261 size_t os, start_part, end_part;
1267 start_part = ALIGN_TO(part->size, align);
1268 end_part = start_part + sz;
1270 r = part_make_space(m, part, end_part, &p);
1275 memzero(p, padding);
1276 p = (uint8_t*) p + padding;
1279 /* Readjust pointers */
1280 for (c = m->containers; c < m->containers + m->n_containers; c++)
1281 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1283 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1286 /* Return something that is not NULL and is aligned */
1287 p = (uint8_t *) NULL + align;
1289 m->header->body_size = end_body;
1290 message_extend_containers(m, added);
1293 r = message_add_offset(m, end_body);
1303 static int message_push_fd(sd_bus_message *m, int fd) {
1314 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1318 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1326 m->fds[m->n_fds] = copy;
1332 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1333 _cleanup_close_ int fd = -1;
1334 struct bus_container *c;
1338 assert_return(m, -EINVAL);
1339 assert_return(!m->sealed, -EPERM);
1340 assert_return(bus_type_is_basic(type), -EINVAL);
1341 assert_return(!m->poisoned, -ESTALE);
1343 c = message_get_container(m);
1345 if (c->signature && c->signature[c->index]) {
1346 /* Container signature is already set */
1348 if (c->signature[c->index] != type)
1353 /* Maybe we can append to the signature? But only if this is the top-level container */
1354 if (c->enclosing != 0)
1357 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1364 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1370 case SD_BUS_TYPE_SIGNATURE:
1371 case SD_BUS_TYPE_STRING:
1374 /* Fall through... */
1375 case SD_BUS_TYPE_OBJECT_PATH:
1383 case SD_BUS_TYPE_BOOLEAN:
1385 u8 = p && *(int*) p;
1391 case SD_BUS_TYPE_UNIX_FD:
1396 fd = message_push_fd(m, *(int*) p);
1407 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1408 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1415 a = message_extend_body(m, align, sz, true);
1422 *stored = (const uint8_t*) a;
1429 case SD_BUS_TYPE_STRING:
1430 /* To make things easy we'll serialize a NULL string
1431 * into the empty string */
1434 /* Fall through... */
1435 case SD_BUS_TYPE_OBJECT_PATH:
1441 sz = 4 + strlen(p) + 1;
1444 case SD_BUS_TYPE_SIGNATURE:
1449 sz = 1 + strlen(p) + 1;
1452 case SD_BUS_TYPE_BOOLEAN:
1454 u32 = p && *(int*) p;
1460 case SD_BUS_TYPE_UNIX_FD:
1465 fd = message_push_fd(m, *(int*) p);
1476 align = bus_type_get_alignment(type);
1477 sz = bus_type_get_size(type);
1484 a = message_extend_body(m, align, sz, false);
1488 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1489 *(uint32_t*) a = sz - 5;
1490 memcpy((uint8_t*) a + 4, p, sz - 4);
1493 *stored = (const uint8_t*) a + 4;
1495 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1496 *(uint8_t*) a = sz - 2;
1497 memcpy((uint8_t*) a + 1, p, sz - 1);
1500 *stored = (const uint8_t*) a + 1;
1509 if (type == SD_BUS_TYPE_UNIX_FD)
1512 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1519 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1520 return message_append_basic(m, type, p, NULL);
1523 _public_ int sd_bus_message_append_string_space(
1528 struct bus_container *c;
1531 assert_return(m, -EINVAL);
1532 assert_return(s, -EINVAL);
1533 assert_return(!m->sealed, -EPERM);
1534 assert_return(!m->poisoned, -ESTALE);
1536 c = message_get_container(m);
1538 if (c->signature && c->signature[c->index]) {
1539 /* Container signature is already set */
1541 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1546 /* Maybe we can append to the signature? But only if this is the top-level container */
1547 if (c->enclosing != 0)
1550 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1557 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1558 a = message_extend_body(m, 1, size + 1, true);
1564 a = message_extend_body(m, 4, 4 + size + 1, false);
1568 *(uint32_t*) a = size;
1574 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1580 _public_ int sd_bus_message_append_string_iovec(
1582 const struct iovec *iov,
1590 assert_return(m, -EINVAL);
1591 assert_return(!m->sealed, -EPERM);
1592 assert_return(iov || n == 0, -EINVAL);
1593 assert_return(!m->poisoned, -ESTALE);
1595 size = IOVEC_TOTAL_SIZE(iov, n);
1597 r = sd_bus_message_append_string_space(m, size, &p);
1601 for (i = 0; i < n; i++) {
1603 if (iov[i].iov_base)
1604 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1606 memset(p, ' ', iov[i].iov_len);
1608 p += iov[i].iov_len;
1614 static int bus_message_open_array(
1616 struct bus_container *c,
1617 const char *contents,
1618 uint32_t **array_size,
1620 bool *need_offsets) {
1630 assert(need_offsets);
1632 if (!signature_is_single(contents, true))
1635 if (c->signature && c->signature[c->index]) {
1637 /* Verify the existing signature */
1639 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1642 if (!startswith(c->signature + c->index + 1, contents))
1645 nindex = c->index + 1 + strlen(contents);
1649 if (c->enclosing != 0)
1652 /* Extend the existing signature */
1654 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1660 nindex = e - c->signature;
1663 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1664 alignment = bus_gvariant_get_alignment(contents);
1668 /* Add alignment padding and add to offset list */
1669 if (!message_extend_body(m, alignment, 0, false))
1672 r = bus_gvariant_is_fixed_size(contents);
1676 *begin = m->header->body_size;
1677 *need_offsets = r == 0;
1681 struct bus_body_part *o;
1683 alignment = bus_type_get_alignment(contents[0]);
1687 a = message_extend_body(m, 4, 4, false);
1692 op = m->body_end->data;
1693 os = m->body_end->size;
1695 /* Add alignment between size and first element */
1696 if (!message_extend_body(m, alignment, 0, false))
1699 /* location of array size might have changed so let's readjust a */
1700 if (o == m->body_end)
1701 a = adjust_pointer(a, op, os, m->body_end->data);
1707 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1713 static int bus_message_open_variant(
1715 struct bus_container *c,
1716 const char *contents) {
1722 if (!signature_is_single(contents, false))
1725 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1728 if (c->signature && c->signature[c->index]) {
1730 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1736 if (c->enclosing != 0)
1739 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1746 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1747 /* Variants are always aligned to 8 */
1749 if (!message_extend_body(m, 8, 0, false))
1756 l = strlen(contents);
1757 a = message_extend_body(m, 1, 1 + l + 1, false);
1762 memcpy((uint8_t*) a + 1, contents, l + 1);
1765 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1771 static int bus_message_open_struct(
1773 struct bus_container *c,
1774 const char *contents,
1776 bool *need_offsets) {
1785 assert(need_offsets);
1787 if (!signature_is_valid(contents, false))
1790 if (c->signature && c->signature[c->index]) {
1793 l = strlen(contents);
1795 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1796 !startswith(c->signature + c->index + 1, contents) ||
1797 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1800 nindex = c->index + 1 + l + 1;
1804 if (c->enclosing != 0)
1807 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1813 nindex = e - c->signature;
1816 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1819 alignment = bus_gvariant_get_alignment(contents);
1823 if (!message_extend_body(m, alignment, 0, false))
1826 r = bus_gvariant_is_fixed_size(contents);
1830 *begin = m->header->body_size;
1831 *need_offsets = r == 0;
1833 /* Align contents to 8 byte boundary */
1834 if (!message_extend_body(m, 8, 0, false))
1838 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1844 static int bus_message_open_dict_entry(
1846 struct bus_container *c,
1847 const char *contents,
1849 bool *need_offsets) {
1857 assert(need_offsets);
1859 if (!signature_is_pair(contents))
1862 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1865 if (c->signature && c->signature[c->index]) {
1868 l = strlen(contents);
1870 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1871 !startswith(c->signature + c->index + 1, contents) ||
1872 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1877 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1880 alignment = bus_gvariant_get_alignment(contents);
1884 if (!message_extend_body(m, alignment, 0, false))
1887 r = bus_gvariant_is_fixed_size(contents);
1891 *begin = m->header->body_size;
1892 *need_offsets = r == 0;
1894 /* Align contents to 8 byte boundary */
1895 if (!message_extend_body(m, 8, 0, false))
1902 _public_ int sd_bus_message_open_container(
1905 const char *contents) {
1907 struct bus_container *c, *w;
1908 uint32_t *array_size = NULL;
1910 size_t before, begin = 0;
1911 bool need_offsets = false;
1914 assert_return(m, -EINVAL);
1915 assert_return(!m->sealed, -EPERM);
1916 assert_return(contents, -EINVAL);
1917 assert_return(!m->poisoned, -ESTALE);
1919 /* Make sure we have space for one more container */
1920 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
1925 c = message_get_container(m);
1927 signature = strdup(contents);
1933 /* Save old index in the parent container, in case we have to
1934 * abort this container */
1935 c->saved_index = c->index;
1936 before = m->header->body_size;
1938 if (type == SD_BUS_TYPE_ARRAY)
1939 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1940 else if (type == SD_BUS_TYPE_VARIANT)
1941 r = bus_message_open_variant(m, c, contents);
1942 else if (type == SD_BUS_TYPE_STRUCT)
1943 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1944 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1945 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1954 /* OK, let's fill it in */
1955 w = m->containers + m->n_containers++;
1956 w->enclosing = type;
1957 w->signature = signature;
1959 w->array_size = array_size;
1962 w->n_offsets = w->offsets_allocated = 0;
1964 w->need_offsets = need_offsets;
1969 static size_t determine_word_size(size_t sz, size_t extra) {
1970 if (sz + extra <= 0xFF)
1972 else if (sz + extra*2 <= 0xFFFF)
1974 else if (sz + extra*4 <= 0xFFFFFFFF)
1980 static size_t read_word_le(void *p, size_t sz) {
1990 return *(uint8_t*) p;
1995 return le16toh(x.u16);
1997 return le32toh(x.u32);
1999 return le64toh(x.u64);
2001 assert_not_reached("unknown word width");
2004 static void write_word_le(void *p, size_t sz, size_t value) {
2012 assert(sz == 8 || (value < (1ULL << (sz*8))));
2015 *(uint8_t*) p = value;
2018 x.u16 = htole16((uint16_t) value);
2020 x.u32 = htole32((uint32_t) value);
2022 x.u64 = htole64((uint64_t) value);
2024 assert_not_reached("unknown word width");
2029 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2034 if (!BUS_MESSAGE_IS_GVARIANT(m))
2037 if (c->need_offsets) {
2038 size_t payload, sz, i;
2041 /* Variable-width arrays */
2043 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2044 sz = determine_word_size(payload, c->n_offsets);
2046 a = message_extend_body(m, 1, sz * c->n_offsets, true);
2050 for (i = 0; i < c->n_offsets; i++)
2051 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2055 /* Fixed-width or empty arrays */
2057 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
2065 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2071 assert(c->signature);
2073 if (!BUS_MESSAGE_IS_GVARIANT(m))
2076 l = strlen(c->signature);
2078 a = message_extend_body(m, 1, 1 + l, true);
2083 memcpy(a+1, c->signature, l);
2088 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2089 size_t n_variable = 0;
2098 if (!BUS_MESSAGE_IS_GVARIANT(m))
2101 p = strempty(c->signature);
2105 r = signature_element_length(p, &n);
2114 r = bus_gvariant_is_fixed_size(t);
2119 assert(!c->need_offsets || i <= c->n_offsets);
2121 /* We need to add an offset for each item that has a
2122 * variable size and that is not the last one in the
2124 if (r == 0 && p[n] != 0)
2131 assert(!c->need_offsets || i == c->n_offsets);
2132 assert(c->need_offsets || n_variable == 0);
2134 if (n_variable <= 0) {
2135 a = message_extend_body(m, 1, 0, add_offset);
2142 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2144 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2146 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2150 p = strempty(c->signature);
2151 for (i = 0, j = 0; i < c->n_offsets; i++) {
2155 r = signature_element_length(p, &n);
2166 r = bus_gvariant_is_fixed_size(t);
2169 if (r > 0 || p[0] == 0)
2173 k = n_variable - 1 - j;
2175 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2184 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2185 struct bus_container *c;
2188 assert_return(m, -EINVAL);
2189 assert_return(!m->sealed, -EPERM);
2190 assert_return(m->n_containers > 0, -EINVAL);
2191 assert_return(!m->poisoned, -ESTALE);
2193 c = message_get_container(m);
2195 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2196 if (c->signature && c->signature[c->index] != 0)
2201 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2202 r = bus_message_close_array(m, c);
2203 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2204 r = bus_message_close_variant(m, c);
2205 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2206 r = bus_message_close_struct(m, c, true);
2208 assert_not_reached("Unknown container type");
2222 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2229 stack[*i].types = types;
2230 stack[*i].n_struct = n_struct;
2231 stack[*i].n_array = n_array;
2237 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2248 *types = stack[*i].types;
2249 *n_struct = stack[*i].n_struct;
2250 *n_array = stack[*i].n_array;
2255 int bus_message_append_ap(
2260 unsigned n_array, n_struct;
2261 TypeStack stack[BUS_CONTAINER_DEPTH];
2262 unsigned stack_ptr = 0;
2270 n_array = (unsigned) -1;
2271 n_struct = strlen(types);
2276 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2277 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2283 r = sd_bus_message_close_container(m);
2291 if (n_array != (unsigned) -1)
2300 case SD_BUS_TYPE_BYTE: {
2303 x = (uint8_t) va_arg(ap, int);
2304 r = sd_bus_message_append_basic(m, *t, &x);
2308 case SD_BUS_TYPE_BOOLEAN:
2309 case SD_BUS_TYPE_INT32:
2310 case SD_BUS_TYPE_UINT32:
2311 case SD_BUS_TYPE_UNIX_FD: {
2314 /* We assume a boolean is the same as int32_t */
2315 assert_cc(sizeof(int32_t) == sizeof(int));
2317 x = va_arg(ap, uint32_t);
2318 r = sd_bus_message_append_basic(m, *t, &x);
2322 case SD_BUS_TYPE_INT16:
2323 case SD_BUS_TYPE_UINT16: {
2326 x = (uint16_t) va_arg(ap, int);
2327 r = sd_bus_message_append_basic(m, *t, &x);
2331 case SD_BUS_TYPE_INT64:
2332 case SD_BUS_TYPE_UINT64:
2333 case SD_BUS_TYPE_DOUBLE: {
2336 x = va_arg(ap, uint64_t);
2337 r = sd_bus_message_append_basic(m, *t, &x);
2341 case SD_BUS_TYPE_STRING:
2342 case SD_BUS_TYPE_OBJECT_PATH:
2343 case SD_BUS_TYPE_SIGNATURE: {
2346 x = va_arg(ap, const char*);
2347 r = sd_bus_message_append_basic(m, *t, x);
2351 case SD_BUS_TYPE_ARRAY: {
2354 r = signature_element_length(t + 1, &k);
2360 memcpy(s, t + 1, k);
2363 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2368 if (n_array == (unsigned) -1) {
2373 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2379 n_array = va_arg(ap, unsigned);
2384 case SD_BUS_TYPE_VARIANT: {
2387 s = va_arg(ap, const char*);
2391 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2395 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2400 n_struct = strlen(s);
2401 n_array = (unsigned) -1;
2406 case SD_BUS_TYPE_STRUCT_BEGIN:
2407 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2410 r = signature_element_length(t, &k);
2417 memcpy(s, t + 1, k - 2);
2420 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2425 if (n_array == (unsigned) -1) {
2430 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2436 n_array = (unsigned) -1;
2452 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2456 assert_return(m, -EINVAL);
2457 assert_return(types, -EINVAL);
2458 assert_return(!m->sealed, -EPERM);
2459 assert_return(!m->poisoned, -ESTALE);
2461 va_start(ap, types);
2462 r = bus_message_append_ap(m, types, ap);
2468 _public_ int sd_bus_message_append_array_space(
2478 assert_return(m, -EINVAL);
2479 assert_return(!m->sealed, -EPERM);
2480 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2481 assert_return(ptr || size == 0, -EINVAL);
2482 assert_return(!m->poisoned, -ESTALE);
2484 /* alignment and size of the trivial types (except bool) is
2485 * identical for gvariant and dbus1 marshalling */
2486 align = bus_type_get_alignment(type);
2487 sz = bus_type_get_size(type);
2489 assert_se(align > 0);
2495 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2499 a = message_extend_body(m, align, size, false);
2503 r = sd_bus_message_close_container(m);
2511 _public_ int sd_bus_message_append_array(
2519 assert_return(m, -EINVAL);
2520 assert_return(!m->sealed, -EPERM);
2521 assert_return(bus_type_is_trivial(type), -EINVAL);
2522 assert_return(ptr || size == 0, -EINVAL);
2523 assert_return(!m->poisoned, -ESTALE);
2525 r = sd_bus_message_append_array_space(m, type, size, &p);
2530 memcpy(p, ptr, size);
2535 _public_ int sd_bus_message_append_array_iovec(
2538 const struct iovec *iov,
2546 assert_return(m, -EINVAL);
2547 assert_return(!m->sealed, -EPERM);
2548 assert_return(bus_type_is_trivial(type), -EINVAL);
2549 assert_return(iov || n == 0, -EINVAL);
2550 assert_return(!m->poisoned, -ESTALE);
2552 size = IOVEC_TOTAL_SIZE(iov, n);
2554 r = sd_bus_message_append_array_space(m, type, size, &p);
2558 for (i = 0; i < n; i++) {
2560 if (iov[i].iov_base)
2561 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2563 memzero(p, iov[i].iov_len);
2565 p = (uint8_t*) p + iov[i].iov_len;
2571 _public_ int sd_bus_message_append_array_memfd(
2578 _cleanup_close_ int copy_fd = -1;
2579 struct bus_body_part *part;
2585 assert_return(m, -EINVAL);
2586 assert_return(memfd >= 0, -EINVAL);
2587 assert_return(bus_type_is_trivial(type), -EINVAL);
2588 assert_return(size > 0, -EINVAL);
2589 assert_return(!m->sealed, -EPERM);
2590 assert_return(!m->poisoned, -ESTALE);
2592 r = memfd_set_sealed(memfd);
2596 copy_fd = dup(memfd);
2600 r = memfd_get_size(memfd, &real_size);
2604 if (offset == 0 && size == (uint64_t) -1)
2606 else if (offset + size > real_size)
2609 align = bus_type_get_alignment(type);
2610 sz = bus_type_get_size(type);
2612 assert_se(align > 0);
2615 if (offset % align != 0)
2621 if (size > (uint64_t) (uint32_t) -1)
2624 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2628 a = message_extend_body(m, align, 0, false);
2632 part = message_append_part(m);
2636 part->memfd = copy_fd;
2637 part->memfd_offset = offset;
2638 part->sealed = true;
2642 m->header->body_size += size;
2643 message_extend_containers(m, size);
2645 return sd_bus_message_close_container(m);
2648 _public_ int sd_bus_message_append_string_memfd(
2654 _cleanup_close_ int copy_fd = -1;
2655 struct bus_body_part *part;
2656 struct bus_container *c;
2661 assert_return(m, -EINVAL);
2662 assert_return(memfd >= 0, -EINVAL);
2663 assert_return(size > 0, -EINVAL);
2664 assert_return(!m->sealed, -EPERM);
2665 assert_return(!m->poisoned, -ESTALE);
2667 r = memfd_set_sealed(memfd);
2671 copy_fd = dup(memfd);
2675 r = memfd_get_size(memfd, &real_size);
2679 if (offset == 0 && size == (uint64_t) -1)
2681 else if (offset + size > real_size)
2684 /* We require this to be NUL terminated */
2688 if (size > (uint64_t) (uint32_t) -1)
2691 c = message_get_container(m);
2692 if (c->signature && c->signature[c->index]) {
2693 /* Container signature is already set */
2695 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2700 /* Maybe we can append to the signature? But only if this is the top-level container */
2701 if (c->enclosing != 0)
2704 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2711 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2712 a = message_extend_body(m, 4, 4, false);
2716 *(uint32_t*) a = size - 1;
2719 part = message_append_part(m);
2723 part->memfd = copy_fd;
2724 part->memfd_offset = offset;
2725 part->sealed = true;
2729 m->header->body_size += size;
2730 message_extend_containers(m, size);
2732 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2733 r = message_add_offset(m, m->header->body_size);
2740 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2746 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2750 assert_return(m, -EINVAL);
2751 assert_return(!m->sealed, -EPERM);
2752 assert_return(!m->poisoned, -ESTALE);
2754 r = sd_bus_message_open_container(m, 'a', "s");
2758 STRV_FOREACH(i, l) {
2759 r = sd_bus_message_append_basic(m, 's', *i);
2764 return sd_bus_message_close_container(m);
2767 static int bus_message_close_header(sd_bus_message *m) {
2773 if (!BUS_MESSAGE_IS_GVARIANT(m))
2776 if (m->n_header_offsets < 1)
2779 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2781 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2783 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2787 for (i = 0; i < m->n_header_offsets; i++)
2788 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2793 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2794 struct bus_body_part *part;
2804 if (m->n_containers > 0)
2810 /* In vtables the return signature of method calls is listed,
2811 * let's check if they match if this is a response */
2812 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2813 m->enforced_reply_signature &&
2814 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2817 /* If gvariant marshalling is used we need to close the body structure */
2818 r = bus_message_close_struct(m, &m->root_container, false);
2822 /* If there's a non-trivial signature set, then add it in here */
2823 if (!isempty(m->root_container.signature)) {
2824 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2830 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2835 r = bus_message_close_header(m);
2839 m->header->serial = (uint32_t) cookie;
2840 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2842 /* Add padding at the end of the fields part, since we know
2843 * the body needs to start at an 8 byte alignment. We made
2844 * sure we allocated enough space for this, so all we need to
2845 * do here is to zero it out. */
2846 l = BUS_MESSAGE_FIELDS_SIZE(m);
2849 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, a);
2851 /* If this is something we can send as memfd, then let's seal
2852 the memfd now. Note that we can send memfds as payload only
2853 for directed messages, and not for broadcasts. */
2854 if (m->destination && m->bus->use_memfd) {
2855 MESSAGE_FOREACH_PART(part, i, m)
2856 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2859 /* Try to seal it if that makes
2860 * sense. First, unmap our own map to
2861 * make sure we don't keep it busy. */
2862 bus_body_part_unmap(part);
2864 /* Then, sync up real memfd size */
2866 r = memfd_set_size(part->memfd, sz);
2870 /* Finally, try to seal */
2871 if (memfd_set_sealed(part->memfd) >= 0)
2872 part->sealed = true;
2876 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2877 m->root_container.index = 0;
2878 m->root_container.offset_index = 0;
2879 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2886 int bus_body_part_map(struct bus_body_part *part) {
2895 if (part->size <= 0)
2898 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2899 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2900 static const uint8_t zeroes[7] = { };
2901 part->data = (void*) zeroes;
2905 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
2906 psz = PAGE_ALIGN(part->size + shift);
2908 if (part->memfd >= 0)
2909 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
2910 else if (part->is_zero)
2911 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2915 if (p == MAP_FAILED)
2919 part->mmap_begin = p;
2920 part->data = (uint8_t*) p + shift;
2921 part->munmap_this = true;
2926 void bus_body_part_unmap(struct bus_body_part *part) {
2930 if (part->memfd < 0)
2933 if (!part->mmap_begin)
2936 if (!part->munmap_this)
2939 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
2941 part->mmap_begin = NULL;
2944 part->munmap_this = false;
2949 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2950 size_t k, start, end;
2955 start = ALIGN_TO((size_t) *rindex, align);
2956 end = start + nbytes;
2961 /* Verify that padding is 0 */
2962 for (k = *rindex; k < start; k++)
2963 if (((const uint8_t*) p)[k] != 0)
2967 *r = (uint8_t*) p + start;
2974 static bool message_end_of_signature(sd_bus_message *m) {
2975 struct bus_container *c;
2979 c = message_get_container(m);
2980 return !c->signature || c->signature[c->index] == 0;
2983 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2984 struct bus_container *c;
2988 c = message_get_container(m);
2989 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2992 if (BUS_MESSAGE_IS_GVARIANT(m))
2993 return index >= c->end;
2995 assert(c->array_size);
2996 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3000 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3001 assert_return(m, -EINVAL);
3002 assert_return(m->sealed, -EPERM);
3004 if (complete && m->n_containers > 0)
3007 if (message_end_of_signature(m))
3010 if (message_end_of_array(m, m->rindex))
3016 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3017 struct bus_body_part *part;
3023 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3024 part = m->cached_rindex_part;
3025 begin = m->cached_rindex_part_begin;
3035 if (index + sz <= begin + part->size) {
3037 r = bus_body_part_map(part);
3042 *p = (uint8_t*) part->data + index - begin;
3044 m->cached_rindex_part = part;
3045 m->cached_rindex_part_begin = begin;
3050 begin += part->size;
3057 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3064 if (!BUS_MESSAGE_IS_GVARIANT(m))
3067 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3070 sz = bus_gvariant_get_size(c->signature);
3074 if (c->offset_index+1 >= c->n_offsets)
3077 /* Variable-size array */
3079 alignment = bus_gvariant_get_alignment(c->signature);
3080 assert(alignment > 0);
3082 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3083 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3086 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3089 /* Fixed-size array */
3090 *rindex = c->begin + (c->offset_index+1) * sz;
3096 } else if (c->enclosing == 0 ||
3097 c->enclosing == SD_BUS_TYPE_STRUCT ||
3098 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3103 if (c->offset_index+1 >= c->n_offsets)
3106 r = signature_element_length(c->signature + c->index, &n);
3110 r = signature_element_length(c->signature + c->index + n, &j);
3115 memcpy(t, c->signature + c->index + n, j);
3118 alignment = bus_gvariant_get_alignment(t);
3121 assert(alignment > 0);
3123 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3124 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3128 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3131 assert_not_reached("Unknown container type");
3136 /* Reached the end */
3143 static int message_peek_body(
3150 size_t k, start, end, padding;
3151 struct bus_body_part *part;
3158 start = ALIGN_TO((size_t) *rindex, align);
3159 padding = start - *rindex;
3160 end = start + nbytes;
3162 if (end > BUS_MESSAGE_BODY_SIZE(m))
3165 part = find_part(m, *rindex, padding, (void**) &q);
3170 /* Verify padding */
3171 for (k = 0; k < padding; k++)
3176 part = find_part(m, start, nbytes, (void**) &q);
3177 if (!part || (nbytes > 0 && !q))
3188 static bool validate_nul(const char *s, size_t l) {
3190 /* Check for NUL chars in the string */
3191 if (memchr(s, 0, l))
3194 /* Check for NUL termination */
3201 static bool validate_string(const char *s, size_t l) {
3203 if (!validate_nul(s, l))
3206 /* Check if valid UTF8 */
3207 if (!utf8_is_valid(s))
3213 static bool validate_signature(const char *s, size_t l) {
3215 if (!validate_nul(s, l))
3218 /* Check if valid signature */
3219 if (!signature_is_valid(s, true))
3225 static bool validate_object_path(const char *s, size_t l) {
3227 if (!validate_nul(s, l))
3230 if (!object_path_is_valid(s))
3236 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3237 struct bus_container *c;
3242 assert_return(m, -EINVAL);
3243 assert_return(m->sealed, -EPERM);
3244 assert_return(bus_type_is_basic(type), -EINVAL);
3246 if (message_end_of_signature(m))
3249 if (message_end_of_array(m, m->rindex))
3252 c = message_get_container(m);
3253 if (c->signature[c->index] != type)
3258 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3260 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3263 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3267 if (type == SD_BUS_TYPE_STRING)
3268 ok = validate_string(q, c->item_size-1);
3269 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3270 ok = validate_object_path(q, c->item_size-1);
3272 ok = validate_signature(q, c->item_size-1);
3278 *(const char**) p = q;
3282 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3284 if ((size_t) sz != c->item_size)
3287 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3290 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3296 case SD_BUS_TYPE_BYTE:
3298 *(uint8_t*) p = *(uint8_t*) q;
3301 case SD_BUS_TYPE_BOOLEAN:
3303 *(int*) p = !!*(uint8_t*) q;
3306 case SD_BUS_TYPE_INT16:
3307 case SD_BUS_TYPE_UINT16:
3309 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3312 case SD_BUS_TYPE_INT32:
3313 case SD_BUS_TYPE_UINT32:
3315 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3318 case SD_BUS_TYPE_INT64:
3319 case SD_BUS_TYPE_UINT64:
3320 case SD_BUS_TYPE_DOUBLE:
3322 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3325 case SD_BUS_TYPE_UNIX_FD: {
3328 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3333 *(int*) p = m->fds[j];
3339 assert_not_reached("unexpected type");
3343 r = container_next_item(m, c, &rindex);
3350 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3354 r = message_peek_body(m, &rindex, 4, 4, &q);
3358 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3359 r = message_peek_body(m, &rindex, 1, l+1, &q);
3363 if (type == SD_BUS_TYPE_OBJECT_PATH)
3364 ok = validate_object_path(q, l);
3366 ok = validate_string(q, l);
3371 *(const char**) p = q;
3373 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3376 r = message_peek_body(m, &rindex, 1, 1, &q);
3381 r = message_peek_body(m, &rindex, 1, l+1, &q);
3385 if (!validate_signature(q, l))
3389 *(const char**) p = q;
3394 align = bus_type_get_alignment(type);
3397 sz = bus_type_get_size(type);
3400 r = message_peek_body(m, &rindex, align, sz, &q);
3406 case SD_BUS_TYPE_BYTE:
3408 *(uint8_t*) p = *(uint8_t*) q;
3411 case SD_BUS_TYPE_BOOLEAN:
3413 *(int*) p = !!*(uint32_t*) q;
3416 case SD_BUS_TYPE_INT16:
3417 case SD_BUS_TYPE_UINT16:
3419 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3422 case SD_BUS_TYPE_INT32:
3423 case SD_BUS_TYPE_UINT32:
3425 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3428 case SD_BUS_TYPE_INT64:
3429 case SD_BUS_TYPE_UINT64:
3430 case SD_BUS_TYPE_DOUBLE:
3432 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3435 case SD_BUS_TYPE_UNIX_FD: {
3438 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3443 *(int*) p = m->fds[j];
3448 assert_not_reached("Unknown basic type...");
3455 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3461 static int bus_message_enter_array(
3463 struct bus_container *c,
3464 const char *contents,
3465 uint32_t **array_size,
3468 size_t *n_offsets) {
3482 if (!signature_is_single(contents, true))
3485 if (!c->signature || c->signature[c->index] == 0)
3488 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3491 if (!startswith(c->signature + c->index + 1, contents))
3496 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3499 r = message_peek_body(m, &rindex, 4, 4, &q);
3503 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3506 alignment = bus_type_get_alignment(contents[0]);
3510 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3514 *array_size = (uint32_t*) q;
3516 } else if (c->item_size <= 0) {
3518 /* gvariant: empty array */
3523 } else if (bus_gvariant_is_fixed_size(contents)) {
3525 /* gvariant: fixed length array */
3526 *item_size = bus_gvariant_get_size(contents);
3531 size_t where, p = 0, framing, sz;
3534 /* gvariant: variable length array */
3535 sz = determine_word_size(c->item_size, 0);
3537 where = rindex + c->item_size - sz;
3538 r = message_peek_body(m, &where, 1, sz, &q);
3542 framing = read_word_le(q, sz);
3543 if (framing > c->item_size - sz)
3545 if ((c->item_size - framing) % sz != 0)
3548 *n_offsets = (c->item_size - framing) / sz;
3550 where = rindex + framing;
3551 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3555 *offsets = new(size_t, *n_offsets);
3559 for (i = 0; i < *n_offsets; i++) {
3562 x = read_word_le((uint8_t*) q + i * sz, sz);
3563 if (x > c->item_size - sz)
3568 (*offsets)[i] = rindex + x;
3572 *item_size = (*offsets)[0] - rindex;
3577 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3578 c->index += 1 + strlen(contents);
3583 static int bus_message_enter_variant(
3585 struct bus_container *c,
3586 const char *contents,
3587 size_t *item_size) {
3599 if (!signature_is_single(contents, false))
3602 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3605 if (!c->signature || c->signature[c->index] == 0)
3608 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3613 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3616 k = strlen(contents);
3617 if (1+k > c->item_size)
3620 where = rindex + c->item_size - (1+k);
3621 r = message_peek_body(m, &where, 1, 1+k, &q);
3625 if (*(char*) q != 0)
3628 if (memcmp((uint8_t*) q+1, contents, k))
3631 *item_size = c->item_size - (1+k);
3634 r = message_peek_body(m, &rindex, 1, 1, &q);
3639 r = message_peek_body(m, &rindex, 1, l+1, &q);
3643 if (!validate_signature(q, l))
3646 if (!streq(q, contents))
3652 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3658 static int build_struct_offsets(
3660 const char *signature,
3664 size_t *n_offsets) {
3666 unsigned n_variable = 0, n_total = 0, v;
3667 size_t previous = 0, where;
3678 if (isempty(signature)) {
3685 sz = determine_word_size(size, 0);
3689 /* First, loop over signature and count variable elements and
3690 * elements in general. We use this to know how large the
3691 * offset array is at the end of the structure. Note that
3692 * GVariant only stores offsets for all variable size elements
3693 * that are not the last item. */
3699 r = signature_element_length(p, &n);
3708 r = bus_gvariant_is_fixed_size(t);
3713 if (r == 0 && p[n] != 0) /* except the last item */
3720 if (size < n_variable * sz)
3723 where = m->rindex + size - (n_variable * sz);
3724 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3730 *offsets = new(size_t, n_total);
3736 /* Second, loop again and build an offset table */
3742 r = signature_element_length(p, &n);
3751 k = bus_gvariant_get_size(t);
3759 x = read_word_le((uint8_t*) q + v*sz, sz);
3762 if (m->rindex + x < previous)
3765 /* The last item's end
3766 * is determined from
3769 x = size - (n_variable * sz);
3771 offset = m->rindex + x;
3777 align = bus_gvariant_get_alignment(t);
3780 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3784 previous = (*offsets)[(*n_offsets)++] = offset;
3789 assert(*n_offsets == n_total);
3791 *item_size = (*offsets)[0] - m->rindex;
3795 static int enter_struct_or_dict_entry(
3797 struct bus_container *c,
3798 const char *contents,
3801 size_t *n_offsets) {
3812 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3815 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3819 } else if (c->item_size <= 0) {
3821 /* gvariant empty struct */
3826 /* gvariant with contents */
3827 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3832 static int bus_message_enter_struct(
3834 struct bus_container *c,
3835 const char *contents,
3838 size_t *n_offsets) {
3850 if (!signature_is_valid(contents, false))
3853 if (!c->signature || c->signature[c->index] == 0)
3856 l = strlen(contents);
3858 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3859 !startswith(c->signature + c->index + 1, contents) ||
3860 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3863 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3867 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3868 c->index += 1 + l + 1;
3873 static int bus_message_enter_dict_entry(
3875 struct bus_container *c,
3876 const char *contents,
3879 size_t *n_offsets) {
3888 if (!signature_is_pair(contents))
3891 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3894 if (!c->signature || c->signature[c->index] == 0)
3897 l = strlen(contents);
3899 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3900 !startswith(c->signature + c->index + 1, contents) ||
3901 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3904 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3908 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3909 c->index += 1 + l + 1;
3914 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
3916 const char *contents) {
3917 struct bus_container *c, *w;
3918 uint32_t *array_size = NULL;
3921 size_t *offsets = NULL;
3922 size_t n_offsets = 0, item_size = 0;
3925 assert_return(m, -EINVAL);
3926 assert_return(m->sealed, -EPERM);
3927 assert_return(type != 0 || !contents, -EINVAL);
3929 if (type == 0 || !contents) {
3933 /* Allow entering into anonymous containers */
3934 r = sd_bus_message_peek_type(m, &tt, &cc);
3938 if (type != 0 && type != tt)
3941 if (contents && !streq(contents, cc))
3949 * We enforce a global limit on container depth, that is much
3950 * higher than the 32 structs and 32 arrays the specification
3951 * mandates. This is simpler to implement for us, and we need
3952 * this only to ensure our container array doesn't grow
3953 * without bounds. We are happy to return any data from a
3954 * message as long as the data itself is valid, even if the
3955 * overall message might be not.
3957 * Note that the message signature is validated when
3958 * parsing the headers, and that validation does check the
3961 * Note that the specification defines no limits on the depth
3962 * of stacked variants, but we do.
3964 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3967 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
3970 if (message_end_of_signature(m))
3973 if (message_end_of_array(m, m->rindex))
3976 c = message_get_container(m);
3978 signature = strdup(contents);
3982 c->saved_index = c->index;
3985 if (type == SD_BUS_TYPE_ARRAY)
3986 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
3987 else if (type == SD_BUS_TYPE_VARIANT)
3988 r = bus_message_enter_variant(m, c, contents, &item_size);
3989 else if (type == SD_BUS_TYPE_STRUCT)
3990 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
3991 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3992 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4002 /* OK, let's fill it in */
4003 w = m->containers + m->n_containers++;
4004 w->enclosing = type;
4005 w->signature = signature;
4006 w->peeked_signature = NULL;
4010 w->begin = m->rindex;
4011 w->end = m->rindex + c->item_size;
4013 w->array_size = array_size;
4014 w->item_size = item_size;
4015 w->offsets = offsets;
4016 w->n_offsets = n_offsets;
4017 w->offset_index = 0;
4022 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4023 struct bus_container *c;
4027 assert_return(m, -EINVAL);
4028 assert_return(m->sealed, -EPERM);
4029 assert_return(m->n_containers > 0, -ENXIO);
4031 c = message_get_container(m);
4033 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4034 if (c->signature && c->signature[c->index] != 0)
4038 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4039 if (m->rindex < c->end)
4042 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4045 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4046 if (c->begin + l != m->rindex)
4051 free(c->peeked_signature);
4055 c = message_get_container(m);
4058 c->index = c->saved_index;
4059 r = container_next_item(m, c, &m->rindex);
4067 static void message_quit_container(sd_bus_message *m) {
4068 struct bus_container *c;
4072 assert(m->n_containers > 0);
4074 c = message_get_container(m);
4077 assert(m->rindex >= c->before);
4078 m->rindex = c->before;
4080 /* Free container */
4085 /* Correct index of new top-level container */
4086 c = message_get_container(m);
4087 c->index = c->saved_index;
4090 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4091 struct bus_container *c;
4094 assert_return(m, -EINVAL);
4095 assert_return(m->sealed, -EPERM);
4097 if (message_end_of_signature(m))
4100 if (message_end_of_array(m, m->rindex))
4103 c = message_get_container(m);
4105 if (bus_type_is_basic(c->signature[c->index])) {
4109 *type = c->signature[c->index];
4113 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4119 r = signature_element_length(c->signature+c->index+1, &l);
4125 sig = strndup(c->signature + c->index + 1, l);
4129 free(c->peeked_signature);
4130 *contents = c->peeked_signature = sig;
4134 *type = SD_BUS_TYPE_ARRAY;
4139 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4140 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4146 r = signature_element_length(c->signature+c->index, &l);
4151 sig = strndup(c->signature + c->index + 1, l - 2);
4155 free(c->peeked_signature);
4156 *contents = c->peeked_signature = sig;
4160 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4165 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4169 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4172 if (c->item_size < 2)
4175 /* Look for the NUL delimiter that
4176 separates the payload from the
4177 signature. Since the body might be
4178 in a different part that then the
4179 signature we map byte by byte. */
4181 for (k = 2; k <= c->item_size; k++) {
4184 where = m->rindex + c->item_size - k;
4185 r = message_peek_body(m, &where, 1, k, &q);
4189 if (*(char*) q == 0)
4193 if (k > c->item_size)
4196 free(c->peeked_signature);
4197 c->peeked_signature = strndup((char*) q + 1, k - 1);
4198 if (!c->peeked_signature)
4201 if (!signature_is_valid(c->peeked_signature, true))
4204 *contents = c->peeked_signature;
4209 r = message_peek_body(m, &rindex, 1, 1, &q);
4214 r = message_peek_body(m, &rindex, 1, l+1, &q);
4218 if (!validate_signature(q, l))
4226 *type = SD_BUS_TYPE_VARIANT;
4241 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4242 struct bus_container *c;
4244 assert_return(m, -EINVAL);
4245 assert_return(m->sealed, -EPERM);
4248 message_reset_containers(m);
4251 c = message_get_container(m);
4253 c = message_get_container(m);
4255 c->offset_index = 0;
4257 m->rindex = c->begin;
4260 c->offset_index = 0;
4261 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4263 return !isempty(c->signature);
4266 static int message_read_ap(
4271 unsigned n_array, n_struct;
4272 TypeStack stack[BUS_CONTAINER_DEPTH];
4273 unsigned stack_ptr = 0;
4274 unsigned n_loop = 0;
4282 /* Ideally, we'd just call ourselves recursively on every
4283 * complex type. However, the state of a va_list that is
4284 * passed to a function is undefined after that function
4285 * returns. This means we need to docode the va_list linearly
4286 * in a single stackframe. We hence implement our own
4287 * home-grown stack in an array. */
4289 n_array = (unsigned) -1; /* length of current array entries */
4290 n_struct = strlen(types); /* length of current struct contents signature */
4297 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4298 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4304 r = sd_bus_message_exit_container(m);
4312 if (n_array != (unsigned) -1)
4321 case SD_BUS_TYPE_BYTE:
4322 case SD_BUS_TYPE_BOOLEAN:
4323 case SD_BUS_TYPE_INT16:
4324 case SD_BUS_TYPE_UINT16:
4325 case SD_BUS_TYPE_INT32:
4326 case SD_BUS_TYPE_UINT32:
4327 case SD_BUS_TYPE_INT64:
4328 case SD_BUS_TYPE_UINT64:
4329 case SD_BUS_TYPE_DOUBLE:
4330 case SD_BUS_TYPE_STRING:
4331 case SD_BUS_TYPE_OBJECT_PATH:
4332 case SD_BUS_TYPE_SIGNATURE:
4333 case SD_BUS_TYPE_UNIX_FD: {
4336 p = va_arg(ap, void*);
4337 r = sd_bus_message_read_basic(m, *t, p);
4350 case SD_BUS_TYPE_ARRAY: {
4353 r = signature_element_length(t + 1, &k);
4359 memcpy(s, t + 1, k);
4362 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4373 if (n_array == (unsigned) -1) {
4378 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4384 n_array = va_arg(ap, unsigned);
4389 case SD_BUS_TYPE_VARIANT: {
4392 s = va_arg(ap, const char *);
4396 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4406 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4411 n_struct = strlen(s);
4412 n_array = (unsigned) -1;
4417 case SD_BUS_TYPE_STRUCT_BEGIN:
4418 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4421 r = signature_element_length(t, &k);
4427 memcpy(s, t + 1, k - 2);
4430 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4440 if (n_array == (unsigned) -1) {
4445 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4451 n_array = (unsigned) -1;
4464 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4468 assert_return(m, -EINVAL);
4469 assert_return(m->sealed, -EPERM);
4470 assert_return(types, -EINVAL);
4472 va_start(ap, types);
4473 r = message_read_ap(m, types, ap);
4479 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4482 assert_return(m, -EINVAL);
4483 assert_return(m->sealed, -EPERM);
4485 /* If types is NULL, read exactly one element */
4487 struct bus_container *c;
4490 if (message_end_of_signature(m))
4493 if (message_end_of_array(m, m->rindex))
4496 c = message_get_container(m);
4498 r = signature_element_length(c->signature + c->index, &l);
4502 types = strndupa(c->signature + c->index, l);
4507 case 0: /* Nothing to drop */
4510 case SD_BUS_TYPE_BYTE:
4511 case SD_BUS_TYPE_BOOLEAN:
4512 case SD_BUS_TYPE_INT16:
4513 case SD_BUS_TYPE_UINT16:
4514 case SD_BUS_TYPE_INT32:
4515 case SD_BUS_TYPE_UINT32:
4516 case SD_BUS_TYPE_INT64:
4517 case SD_BUS_TYPE_UINT64:
4518 case SD_BUS_TYPE_DOUBLE:
4519 case SD_BUS_TYPE_STRING:
4520 case SD_BUS_TYPE_OBJECT_PATH:
4521 case SD_BUS_TYPE_SIGNATURE:
4522 case SD_BUS_TYPE_UNIX_FD:
4524 r = sd_bus_message_read_basic(m, *types, NULL);
4528 r = sd_bus_message_skip(m, types + 1);
4534 case SD_BUS_TYPE_ARRAY: {
4537 r = signature_element_length(types + 1, &k);
4543 memcpy(s, types+1, k);
4546 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4551 r = sd_bus_message_skip(m, s);
4558 r = sd_bus_message_exit_container(m);
4563 r = sd_bus_message_skip(m, types + 1 + k);
4570 case SD_BUS_TYPE_VARIANT: {
4571 const char *contents;
4574 r = sd_bus_message_peek_type(m, &x, &contents);
4578 if (x != SD_BUS_TYPE_VARIANT)
4581 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4585 r = sd_bus_message_skip(m, contents);
4590 r = sd_bus_message_exit_container(m);
4594 r = sd_bus_message_skip(m, types + 1);
4601 case SD_BUS_TYPE_STRUCT_BEGIN:
4602 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4605 r = signature_element_length(types, &k);
4611 memcpy(s, types+1, k-2);
4614 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4618 r = sd_bus_message_skip(m, s);
4623 r = sd_bus_message_exit_container(m);
4628 r = sd_bus_message_skip(m, types + k);
4640 _public_ int sd_bus_message_read_array(sd_bus_message *m,
4644 struct bus_container *c;
4650 assert_return(m, -EINVAL);
4651 assert_return(m->sealed, -EPERM);
4652 assert_return(bus_type_is_trivial(type), -EINVAL);
4653 assert_return(ptr, -EINVAL);
4654 assert_return(size, -EINVAL);
4655 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4657 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4661 c = message_get_container(m);
4663 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4664 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4668 sz = c->end - c->begin;
4670 align = bus_type_get_alignment(type);
4674 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4678 /* Zero length array, let's return some aligned
4679 * pointer that is not NULL */
4680 p = (uint8_t*) NULL + align;
4682 r = message_peek_body(m, &m->rindex, align, sz, &p);
4687 r = sd_bus_message_exit_container(m);
4691 *ptr = (const void*) p;
4697 message_quit_container(m);
4701 static int message_peek_fields(
4712 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
4715 static int message_peek_field_uint32(
4727 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4730 /* identical for gvariant and dbus1 */
4732 r = message_peek_fields(m, ri, 4, 4, &q);
4737 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4742 static int message_peek_field_string(
4744 bool (*validate)(const char *p),
4756 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4761 r = message_peek_fields(m, ri, 1, item_size, &q);
4767 r = message_peek_field_uint32(m, ri, 4, &l);
4771 r = message_peek_fields(m, ri, 1, l+1, &q);
4777 if (!validate_nul(q, l))
4783 if (!validate_string(q, l))
4793 static int message_peek_field_signature(
4806 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4811 r = message_peek_fields(m, ri, 1, item_size, &q);
4817 r = message_peek_fields(m, ri, 1, 1, &q);
4822 r = message_peek_fields(m, ri, 1, l+1, &q);
4827 if (!validate_signature(q, l))
4836 static int message_skip_fields(
4839 uint32_t array_size,
4840 const char **signature) {
4842 size_t original_index;
4848 assert(!BUS_MESSAGE_IS_GVARIANT(m));
4850 original_index = *ri;
4856 if (array_size != (uint32_t) -1 &&
4857 array_size <= *ri - original_index)
4864 if (t == SD_BUS_TYPE_STRING) {
4866 r = message_peek_field_string(m, NULL, ri, 0, NULL);
4872 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
4874 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
4880 } else if (t == SD_BUS_TYPE_SIGNATURE) {
4882 r = message_peek_field_signature(m, ri, 0, NULL);
4888 } else if (bus_type_is_basic(t)) {
4891 align = bus_type_get_alignment(t);
4892 k = bus_type_get_size(t);
4893 assert(align > 0 && k > 0);
4895 r = message_peek_fields(m, ri, align, k, NULL);
4901 } else if (t == SD_BUS_TYPE_ARRAY) {
4903 r = signature_element_length(*signature+1, &l);
4913 strncpy(sig, *signature + 1, l-1);
4916 alignment = bus_type_get_alignment(sig[0]);
4920 r = message_peek_field_uint32(m, ri, 0, &nas);
4923 if (nas > BUS_ARRAY_MAX_SIZE)
4926 r = message_peek_fields(m, ri, alignment, 0, NULL);
4930 r = message_skip_fields(m, ri, nas, (const char**) &s);
4935 (*signature) += 1 + l;
4937 } else if (t == SD_BUS_TYPE_VARIANT) {
4940 r = message_peek_field_signature(m, ri, 0, &s);
4944 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4950 } else if (t == SD_BUS_TYPE_STRUCT ||
4951 t == SD_BUS_TYPE_DICT_ENTRY) {
4953 r = signature_element_length(*signature, &l);
4960 strncpy(sig, *signature + 1, l-1);
4963 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
4974 int bus_message_parse_fields(sd_bus_message *m) {
4977 uint32_t unix_fds = 0;
4978 bool unix_fds_set = false;
4979 void *offsets = NULL;
4980 unsigned n_offsets = 0;
4986 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4989 sz = determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m), 0);
4993 ri = BUS_MESSAGE_FIELDS_SIZE(m) - sz;
4994 r = message_peek_fields(m, &ri, 1, sz, &q);
4998 framing = read_word_le(q, sz);
4999 if (framing >= BUS_MESSAGE_FIELDS_SIZE(m) - sz)
5001 if ((BUS_MESSAGE_FIELDS_SIZE(m) - framing) % sz != 0)
5005 r = message_peek_fields(m, &ri, 1, BUS_MESSAGE_FIELDS_SIZE(m) - framing, &offsets);
5009 n_offsets = (BUS_MESSAGE_FIELDS_SIZE(m) - framing) / sz;
5014 while (ri < BUS_MESSAGE_FIELDS_SIZE(m)) {
5015 _cleanup_free_ char *sig = NULL;
5016 const char *signature;
5018 size_t item_size = (size_t) -1;
5020 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5027 ri = ALIGN_TO(read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5030 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
5034 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5039 end = read_word_le((uint8_t*) offsets + i*sz, sz);
5044 where = ri = ALIGN_TO(ri, 8);
5045 item_size = end - ri;
5046 r = message_peek_fields(m, &where, 1, item_size, &q);
5050 b = memrchr(q, 0, item_size);
5054 sig = strndup(b+1, item_size - (b+1-(char*) q));
5059 item_size = b - (char*) q;
5061 r = message_peek_field_signature(m, &ri, 0, &signature);
5067 case _BUS_MESSAGE_HEADER_INVALID:
5070 case BUS_MESSAGE_HEADER_PATH:
5075 if (!streq(signature, "o"))
5078 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5081 case BUS_MESSAGE_HEADER_INTERFACE:
5086 if (!streq(signature, "s"))
5089 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5092 case BUS_MESSAGE_HEADER_MEMBER:
5097 if (!streq(signature, "s"))
5100 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5103 case BUS_MESSAGE_HEADER_ERROR_NAME:
5108 if (!streq(signature, "s"))
5111 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5113 m->error._need_free = -1;
5117 case BUS_MESSAGE_HEADER_DESTINATION:
5122 if (!streq(signature, "s"))
5125 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5128 case BUS_MESSAGE_HEADER_SENDER:
5133 if (!streq(signature, "s"))
5136 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5138 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5139 m->creds.unique_name = (char*) m->sender;
5140 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5146 case BUS_MESSAGE_HEADER_SIGNATURE: {
5150 if (m->root_container.signature)
5153 if (!streq(signature, "g"))
5156 r = message_peek_field_signature(m, &ri, item_size, &s);
5164 free(m->root_container.signature);
5165 m->root_container.signature = c;
5169 case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
5172 if (m->reply_cookie != 0)
5175 if (!streq(signature, "u"))
5178 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5182 m->reply_cookie = serial;
5184 if (m->reply_cookie == 0)
5190 case BUS_MESSAGE_HEADER_UNIX_FDS:
5194 if (!streq(signature, "u"))
5197 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5201 unix_fds_set = true;
5205 if (!BUS_MESSAGE_IS_GVARIANT(m))
5206 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5215 if (m->n_fds != unix_fds)
5218 switch (m->header->type) {
5220 case SD_BUS_MESSAGE_SIGNAL:
5221 if (!m->path || !m->interface || !m->member)
5224 if (m->reply_cookie != 0)
5229 case SD_BUS_MESSAGE_METHOD_CALL:
5231 if (!m->path || !m->member)
5234 if (m->reply_cookie != 0)
5239 case SD_BUS_MESSAGE_METHOD_RETURN:
5241 if (m->reply_cookie == 0)
5245 case SD_BUS_MESSAGE_METHOD_ERROR:
5247 if (m->reply_cookie == 0 || !m->error.name)
5252 /* Refuse non-local messages that claim they are local */
5253 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5255 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5257 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5260 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
5262 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5263 r = build_struct_offsets(
5265 m->root_container.signature,
5266 BUS_MESSAGE_BODY_SIZE(m),
5267 &m->root_container.item_size,
5268 &m->root_container.offsets,
5269 &m->root_container.n_offsets);
5274 /* Try to read the error message, but if we can't it's a non-issue */
5275 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5276 sd_bus_message_read(m, "s", &m->error.message);
5281 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5282 assert_return(m, -EINVAL);
5283 assert_return(destination, -EINVAL);
5284 assert_return(!m->sealed, -EPERM);
5285 assert_return(!m->destination, -EEXIST);
5287 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5290 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5294 struct bus_body_part *part;
5300 total = BUS_MESSAGE_SIZE(m);
5306 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5307 MESSAGE_FOREACH_PART(part, i, m)
5308 e = mempcpy(e, part->data, part->size);
5310 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5318 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5324 r = sd_bus_message_enter_container(m, 'a', "s");
5331 r = sd_bus_message_read_basic(m, 's', &s);
5337 r = strv_extend(l, s);
5342 r = sd_bus_message_exit_container(m);
5349 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5353 assert_return(m, -EINVAL);
5354 assert_return(m->sealed, -EPERM);
5355 assert_return(l, -EINVAL);
5357 r = bus_message_read_strv_extend(m, &strv);
5367 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5368 const char *contents;
5377 r = sd_bus_message_rewind(m, true);
5382 r = sd_bus_message_peek_type(m, &type, &contents);
5388 /* Don't match against arguments after the first one we don't understand */
5389 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5390 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5396 r = sd_bus_message_skip(m, NULL);
5401 if (type == SD_BUS_TYPE_ARRAY) {
5403 r = sd_bus_message_read_strv(m, strv);
5410 r = sd_bus_message_read_basic(m, type, str);
5420 bool bus_header_is_complete(struct bus_header *h, size_t size) {
5426 if (size < sizeof(struct bus_header))
5429 full = sizeof(struct bus_header) +
5430 (h->endian == BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
5432 return size >= full;
5435 int bus_header_message_size(struct bus_header *h, size_t *sum) {
5441 if (h->endian == BUS_NATIVE_ENDIAN) {
5442 fs = h->fields_size;
5444 } else if (h->endian == BUS_REVERSE_ENDIAN) {
5445 fs = bswap_32(h->fields_size);
5446 bs = bswap_32(h->body_size);
5450 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
5454 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5455 assert_return(m, EINVAL);
5457 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5460 return sd_bus_error_get_errno(&m->error);
5463 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5464 struct bus_container *c;
5466 assert_return(m, NULL);
5468 c = complete ? &m->root_container : message_get_container(m);
5469 return strempty(c->signature);
5472 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5473 assert_return(m, -EINVAL);
5475 return isempty(m->root_container.signature);
5478 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5479 assert_return(m, -EINVAL);
5481 return streq(strempty(m->root_container.signature), strempty(signature));
5484 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5485 bool done_something = false;
5488 assert_return(m, -EINVAL);
5489 assert_return(source, -EINVAL);
5490 assert_return(!m->sealed, -EPERM);
5491 assert_return(source->sealed, -EPERM);
5494 const char *contents;
5509 r = sd_bus_message_peek_type(source, &type, &contents);
5515 done_something = true;
5517 if (bus_type_is_container(type) > 0) {
5519 r = sd_bus_message_enter_container(source, type, contents);
5523 r = sd_bus_message_open_container(m, type, contents);
5527 r = sd_bus_message_copy(m, source, true);
5531 r = sd_bus_message_close_container(m);
5535 r = sd_bus_message_exit_container(source);
5542 r = sd_bus_message_read_basic(source, type, &basic);
5548 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5549 type == SD_BUS_TYPE_SIGNATURE ||
5550 type == SD_BUS_TYPE_STRING)
5551 r = sd_bus_message_append_basic(m, type, basic.string);
5553 r = sd_bus_message_append_basic(m, type, &basic);
5560 return done_something;
5563 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5568 assert_return(m, -EINVAL);
5569 assert_return(m->sealed, -EPERM);
5570 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5571 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5572 assert_return(type || contents, -EINVAL);
5573 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5575 r = sd_bus_message_peek_type(m, &t, &c);
5579 if (type != 0 && type != t)
5582 if (contents && !streq_ptr(contents, c))
5588 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5589 assert_return(m, NULL);
5594 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5595 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5603 switch ((*m)->header->type) {
5605 case SD_BUS_MESSAGE_SIGNAL:
5606 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5612 case SD_BUS_MESSAGE_METHOD_CALL:
5613 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5619 case SD_BUS_MESSAGE_METHOD_RETURN:
5620 case SD_BUS_MESSAGE_METHOD_ERROR:
5622 n = message_new(bus, (*m)->header->type);
5626 n->reply_cookie = (*m)->reply_cookie;
5627 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5631 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5632 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5636 n->error._need_free = -1;
5645 if ((*m)->destination && !n->destination) {
5646 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5651 if ((*m)->sender && !n->sender) {
5652 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5657 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5659 r = sd_bus_message_copy(n, *m, true);
5663 timeout = (*m)->timeout;
5664 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5665 timeout = BUS_DEFAULT_TIMEOUT;
5667 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5671 sd_bus_message_unref(*m);
5678 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5682 assert_return(!m->sealed, -EPERM);
5683 assert_return(!m->sender, -EPERM);
5685 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5688 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5689 assert_return(m, -EINVAL);
5690 assert_return(priority, -EINVAL);
5692 *priority = m->priority;
5696 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5697 assert_return(m, -EINVAL);
5698 assert_return(!m->sealed, -EPERM);
5700 m->priority = priority;