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 bus_kernel_cmd_free(m->bus, (uint8_t *) m->kdbus - (uint8_t *) m->bus->kdbus_buffer);
138 sd_bus_unref(m->bus);
141 close_many(m->fds, m->n_fds);
145 if (m->iovec != m->iovec_fixed)
148 if (m->destination_ptr) {
149 free(m->destination_ptr);
150 m->destination_ptr = NULL;
153 message_reset_containers(m);
154 free(m->root_container.signature);
155 free(m->root_container.offsets);
157 free(m->root_container.peeked_signature);
159 bus_creds_done(&m->creds);
163 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
165 size_t old_size, new_size, start;
172 old_size = sizeof(struct bus_header) + m->fields_size;
173 start = ALIGN_TO(old_size, align);
174 new_size = start + sz;
176 if (new_size < start ||
177 new_size > (size_t) ((uint32_t) -1))
180 if (old_size == new_size)
181 return (uint8_t*) m->header + old_size;
183 if (m->free_header) {
184 np = realloc(m->header, ALIGN8(new_size));
188 /* Initially, the header is allocated as part of of
189 * the sd_bus_message itself, let's replace it by
192 np = malloc(ALIGN8(new_size));
196 memcpy(np, m->header, sizeof(struct bus_header));
199 /* Zero out padding */
200 if (start > old_size)
201 memzero((uint8_t*) np + old_size, start - old_size);
205 m->fields_size = new_size - sizeof(struct bus_header);
207 /* Adjust quick access pointers */
208 m->path = adjust_pointer(m->path, op, old_size, m->header);
209 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
210 m->member = adjust_pointer(m->member, op, old_size, m->header);
211 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
212 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
213 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
215 m->free_header = true;
218 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
221 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
224 return (uint8_t*) np + start;
231 static int message_append_field_string(
243 /* dbus1 only allows 8bit header field ids */
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 64bit, ((string + NUL) + NUL + signature string 's') */
258 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
262 *((uint64_t*) p) = h;
269 *ret = (char*) p + 8;
272 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
273 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
282 ((uint32_t*) p)[1] = l;
283 memcpy(p + 8, s, l + 1);
286 *ret = (char*) p + 8;
292 static int message_append_field_signature(
303 /* dbus1 only allows 8bit header field ids */
307 /* dbus1 doesn't allow signatures over 8bit, let's enforce
308 * this globally, to not risk convertability */
313 /* Signature "(yv)" where the variant contains "g" */
315 if (BUS_MESSAGE_IS_GVARIANT(m))
316 /* For gvariant the serialization is the same as for normal strings */
317 return message_append_field_string(m, h, 'g', s, ret);
319 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
320 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
326 p[2] = SD_BUS_TYPE_SIGNATURE;
329 memcpy(p + 5, s, l + 1);
332 *ret = (const char*) p + 5;
338 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
343 /* dbus1 only allows 8bit header field ids */
347 if (BUS_MESSAGE_IS_GVARIANT(m)) {
348 /* (field id 64bit + ((value + NUL + signature string 'u') */
350 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
354 *((uint64_t*) p) = h;
355 *((uint32_t*) (p + 8)) = x;
359 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
360 p = message_extend_fields(m, 8, 4 + 4, false);
369 ((uint32_t*) p)[1] = x;
375 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
380 /* dbus1 only allows 8bit header field ids */
384 if (BUS_MESSAGE_IS_GVARIANT(m)) {
385 /* (field id 64bit + ((value + NUL + signature string 't') */
387 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
391 *((uint64_t*) p) = h;
392 *((uint64_t*) (p + 8)) = x;
396 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
397 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
410 ((uint64_t*) p)[1] = x;
416 int bus_message_from_header(
419 size_t header_accessible,
421 size_t footer_accessible,
425 const struct ucred *ucred,
428 sd_bus_message **ret) {
431 struct bus_header *h;
435 assert(header || header_accessible <= 0);
436 assert(footer || footer_accessible <= 0);
437 assert(fds || n_fds <= 0);
440 if (header_accessible < sizeof(struct bus_header))
443 if (header_accessible > message_size)
445 if (footer_accessible > message_size)
449 if (h->version != 1 &&
453 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
456 if (h->endian != BUS_LITTLE_ENDIAN &&
457 h->endian != BUS_BIG_ENDIAN)
460 /* Note that we are happy with unknown flags in the flags header! */
462 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
465 label_sz = strlen(label);
476 m->header_accessible = header_accessible;
478 m->footer_accessible = footer_accessible;
480 if (BUS_MESSAGE_IS_GVARIANT(m)) {
483 if (h->dbus2.cookie == 0)
486 /* dbus2 derives the sizes from the message size and
487 the offset table at the end, since it is formatted as
488 gvariant "yyyyuta{tv}v". Since the message itself is a
489 structure with precisely to variable sized entries,
490 there's only one offset in the table, which marks the
491 end of the fields array. */
493 ws = bus_gvariant_determine_word_size(message_size, 0);
494 if (footer_accessible < ws)
497 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
498 if (ALIGN8(m->fields_size) > message_size - ws)
500 if (m->fields_size < sizeof(struct bus_header))
503 m->fields_size -= sizeof(struct bus_header);
504 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
506 if (h->dbus1.serial == 0)
509 /* dbus1 has the sizes in the header */
510 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
511 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
513 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
521 m->creds.pid = ucred->pid;
522 m->creds.euid = ucred->uid;
523 m->creds.egid = ucred->gid;
525 /* Due to namespace translations some data might be
526 * missing from this ucred record. */
527 if (m->creds.pid > 0)
528 m->creds.mask |= SD_BUS_CREDS_PID;
530 if (m->creds.euid != UID_INVALID)
531 m->creds.mask |= SD_BUS_CREDS_EUID;
533 if (m->creds.egid != GID_INVALID)
534 m->creds.mask |= SD_BUS_CREDS_EGID;
538 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
539 memcpy(m->creds.label, label, label_sz + 1);
541 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
544 m->bus = sd_bus_ref(bus);
550 int bus_message_from_malloc(
556 const struct ucred *ucred,
558 sd_bus_message **ret) {
564 r = bus_message_from_header(
566 buffer, length, /* in this case the initial bytes and the final bytes are the same */
575 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
578 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
580 m->body.sealed = true;
585 m->iovec = m->iovec_fixed;
586 m->iovec[0].iov_base = buffer;
587 m->iovec[0].iov_len = length;
589 r = bus_message_parse_fields(m);
593 /* We take possession of the memory and fds now */
594 m->free_header = true;
605 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
610 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
615 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
616 m->header->endian = BUS_NATIVE_ENDIAN;
617 m->header->type = type;
618 m->header->version = bus ? bus->message_version : 1;
619 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
620 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
621 m->bus = sd_bus_ref(bus);
626 _public_ int sd_bus_message_new_signal(
630 const char *interface,
631 const char *member) {
636 assert_return(bus, -ENOTCONN);
637 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
638 assert_return(object_path_is_valid(path), -EINVAL);
639 assert_return(interface_name_is_valid(interface), -EINVAL);
640 assert_return(member_name_is_valid(member), -EINVAL);
641 assert_return(m, -EINVAL);
643 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
647 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
649 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
652 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
655 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
663 sd_bus_message_unref(t);
667 _public_ int sd_bus_message_new_method_call(
670 const char *destination,
672 const char *interface,
673 const char *member) {
678 assert_return(bus, -ENOTCONN);
679 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
680 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
681 assert_return(object_path_is_valid(path), -EINVAL);
682 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
683 assert_return(member_name_is_valid(member), -EINVAL);
684 assert_return(m, -EINVAL);
686 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
690 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
693 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
698 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
704 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
717 static int message_new_reply(
718 sd_bus_message *call,
720 sd_bus_message **m) {
725 assert_return(call, -EINVAL);
726 assert_return(call->sealed, -EPERM);
727 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
728 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
729 assert_return(m, -EINVAL);
731 t = message_new(call->bus, type);
735 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
736 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
737 if (t->reply_cookie == 0)
740 if (BUS_MESSAGE_IS_GVARIANT(t))
741 r = message_append_field_uint64(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_cookie);
743 if (t->reply_cookie > 0xffffffff)
746 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
752 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
757 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
758 t->enforced_reply_signature = call->enforced_reply_signature;
768 _public_ int sd_bus_message_new_method_return(
769 sd_bus_message *call,
770 sd_bus_message **m) {
772 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
775 _public_ int sd_bus_message_new_method_error(
776 sd_bus_message *call,
778 const sd_bus_error *e) {
783 assert_return(sd_bus_error_is_set(e), -EINVAL);
784 assert_return(m, -EINVAL);
786 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
790 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
795 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
800 t->error._need_free = -1;
810 _public_ int sd_bus_message_new_method_errorf(
811 sd_bus_message *call,
817 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
820 assert_return(name, -EINVAL);
821 assert_return(m, -EINVAL);
823 va_start(ap, format);
824 bus_error_setfv(&error, name, format, ap);
827 return sd_bus_message_new_method_error(call, m, &error);
830 _public_ int sd_bus_message_new_method_errno(
831 sd_bus_message *call,
834 const sd_bus_error *p) {
836 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
838 if (sd_bus_error_is_set(p))
839 return sd_bus_message_new_method_error(call, m, p);
841 sd_bus_error_set_errno(&berror, error);
843 return sd_bus_message_new_method_error(call, m, &berror);
846 _public_ int sd_bus_message_new_method_errnof(
847 sd_bus_message *call,
853 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
856 va_start(ap, format);
857 sd_bus_error_set_errnofv(&berror, error, format, ap);
860 return sd_bus_message_new_method_error(call, m, &berror);
863 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
867 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
868 m->creds.well_known_names_local = true;
869 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
872 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
876 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
877 m->creds.well_known_names_driver = true;
878 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
881 int bus_message_new_synthetic_error(
884 const sd_bus_error *e,
885 sd_bus_message **m) {
891 assert(sd_bus_error_is_set(e));
894 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
898 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
899 t->reply_cookie = cookie;
901 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie);
905 if (bus && bus->unique_name) {
906 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
911 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
916 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
921 t->error._need_free = -1;
923 bus_message_set_sender_driver(bus, t);
933 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
934 assert_return(m, NULL);
936 assert(m->n_ref > 0);
942 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
947 assert(m->n_ref > 0);
957 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
958 assert_return(m, -EINVAL);
959 assert_return(type, -EINVAL);
961 *type = m->header->type;
965 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
968 assert_return(m, -EINVAL);
969 assert_return(cookie, -EINVAL);
971 c = BUS_MESSAGE_COOKIE(m);
975 *cookie = BUS_MESSAGE_COOKIE(m);
979 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
980 assert_return(m, -EINVAL);
981 assert_return(cookie, -EINVAL);
983 if (m->reply_cookie == 0)
986 *cookie = m->reply_cookie;
990 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
991 assert_return(m, -EINVAL);
993 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
994 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
997 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
998 assert_return(m, -EINVAL);
1000 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
1003 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
1004 assert_return(m, -EINVAL);
1006 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
1007 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
1010 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1011 assert_return(m, NULL);
1016 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1017 assert_return(m, NULL);
1019 return m->interface;
1022 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1023 assert_return(m, NULL);
1028 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1029 assert_return(m, NULL);
1031 return m->destination;
1034 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1035 assert_return(m, NULL);
1040 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1041 assert_return(m, NULL);
1042 assert_return(sd_bus_error_is_set(&m->error), NULL);
1047 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1048 assert_return(m, -EINVAL);
1049 assert_return(usec, -EINVAL);
1051 if (m->monotonic <= 0)
1054 *usec = m->monotonic;
1058 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1059 assert_return(m, -EINVAL);
1060 assert_return(usec, -EINVAL);
1062 if (m->realtime <= 0)
1065 *usec = m->realtime;
1069 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1070 assert_return(m, -EINVAL);
1071 assert_return(seqnum, -EINVAL);
1076 *seqnum = m->seqnum;
1080 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1081 assert_return(m, NULL);
1083 if (m->creds.mask == 0)
1089 _public_ int sd_bus_message_is_signal(
1091 const char *interface,
1092 const char *member) {
1094 assert_return(m, -EINVAL);
1096 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1099 if (interface && (!m->interface || !streq(m->interface, interface)))
1102 if (member && (!m->member || !streq(m->member, member)))
1108 _public_ int sd_bus_message_is_method_call(
1110 const char *interface,
1111 const char *member) {
1113 assert_return(m, -EINVAL);
1115 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1118 if (interface && (!m->interface || !streq(m->interface, interface)))
1121 if (member && (!m->member || !streq(m->member, member)))
1127 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1128 assert_return(m, -EINVAL);
1130 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1133 if (name && (!m->error.name || !streq(m->error.name, name)))
1139 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1140 assert_return(m, -EINVAL);
1141 assert_return(!m->sealed, -EPERM);
1142 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1145 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1147 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1152 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1153 assert_return(m, -EINVAL);
1154 assert_return(!m->sealed, -EPERM);
1157 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1159 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1164 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1165 assert_return(m, -EINVAL);
1166 assert_return(!m->sealed, -EPERM);
1169 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1171 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1176 static struct bus_container *message_get_container(sd_bus_message *m) {
1179 if (m->n_containers == 0)
1180 return &m->root_container;
1182 assert(m->containers);
1183 return m->containers + m->n_containers - 1;
1186 struct bus_body_part *message_append_part(sd_bus_message *m) {
1187 struct bus_body_part *part;
1194 if (m->n_body_parts <= 0) {
1198 assert(m->body_end);
1200 part = new0(struct bus_body_part, 1);
1206 m->body_end->next = part;
1216 static void part_zero(struct bus_body_part *part, size_t sz) {
1221 /* All other fields can be left in their defaults */
1222 assert(!part->data);
1223 assert(part->memfd < 0);
1226 part->is_zero = true;
1227 part->sealed = true;
1230 static int part_make_space(
1231 struct sd_bus_message *m,
1232 struct bus_body_part *part,
1241 assert(!part->sealed);
1246 if (!part->data && part->memfd < 0) {
1247 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1248 part->mmap_begin = part->data;
1251 if (part->memfd >= 0) {
1253 if (part->allocated == 0 || sz > part->allocated) {
1254 uint64_t new_allocated;
1256 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1257 r = memfd_set_size(part->memfd, new_allocated);
1263 part->allocated = new_allocated;
1266 if (!part->data || sz > part->mapped) {
1269 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1270 if (part->mapped <= 0)
1271 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1273 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1275 if (n == MAP_FAILED) {
1280 part->mmap_begin = part->data = n;
1282 part->memfd_offset = 0;
1285 part->munmap_this = true;
1287 if (part->allocated == 0 || sz > part->allocated) {
1288 size_t new_allocated;
1290 new_allocated = sz > 0 ? 2 * sz : 64;
1291 n = realloc(part->data, new_allocated);
1298 part->allocated = new_allocated;
1299 part->free_this = true;
1304 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1310 static int message_add_offset(sd_bus_message *m, size_t offset) {
1311 struct bus_container *c;
1314 assert(BUS_MESSAGE_IS_GVARIANT(m));
1316 /* Add offset to current container, unless this is the first
1317 * item in it, which will have the 0 offset, which we can
1319 c = message_get_container(m);
1321 if (!c->need_offsets)
1324 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1327 c->offsets[c->n_offsets++] = offset;
1331 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1332 struct bus_container *c;
1339 /* Update counters */
1340 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1343 *c->array_size += expand;
1347 static void *message_extend_body(
1352 bool force_inline) {
1354 size_t start_body, end_body, padding, added;
1365 start_body = ALIGN_TO((size_t) m->body_size, align);
1366 end_body = start_body + sz;
1368 padding = start_body - m->body_size;
1369 added = padding + sz;
1371 /* Check for 32bit overflows */
1372 if (end_body > (size_t) ((uint32_t) -1) ||
1373 end_body < start_body) {
1379 struct bus_body_part *part = NULL;
1383 m->n_body_parts <= 0 ||
1384 m->body_end->sealed ||
1385 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1386 (force_inline && m->body_end->size > MEMFD_MIN_SIZE); /* if this must be an inlined extension, let's create a new part if the previous part is large enough to be inlined */
1390 part = message_append_part(m);
1394 part_zero(part, padding);
1397 part = message_append_part(m);
1401 r = part_make_space(m, part, sz, &p);
1405 struct bus_container *c;
1407 size_t os, start_part, end_part;
1413 start_part = ALIGN_TO(part->size, align);
1414 end_part = start_part + sz;
1416 r = part_make_space(m, part, end_part, &p);
1421 memzero(p, padding);
1422 p = (uint8_t*) p + padding;
1425 /* Readjust pointers */
1426 for (c = m->containers; c < m->containers + m->n_containers; c++)
1427 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1429 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1432 /* Return something that is not NULL and is aligned */
1433 p = (uint8_t *) NULL + align;
1435 m->body_size = end_body;
1436 message_extend_containers(m, added);
1439 r = message_add_offset(m, end_body);
1449 static int message_push_fd(sd_bus_message *m, int fd) {
1460 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1464 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1472 m->fds[m->n_fds] = copy;
1478 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1479 _cleanup_close_ int fd = -1;
1480 struct bus_container *c;
1484 assert_return(m, -EINVAL);
1485 assert_return(!m->sealed, -EPERM);
1486 assert_return(bus_type_is_basic(type), -EINVAL);
1487 assert_return(!m->poisoned, -ESTALE);
1489 c = message_get_container(m);
1491 if (c->signature && c->signature[c->index]) {
1492 /* Container signature is already set */
1494 if (c->signature[c->index] != type)
1499 /* Maybe we can append to the signature? But only if this is the top-level container */
1500 if (c->enclosing != 0)
1503 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1510 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1516 case SD_BUS_TYPE_SIGNATURE:
1517 case SD_BUS_TYPE_STRING:
1520 /* Fall through... */
1521 case SD_BUS_TYPE_OBJECT_PATH:
1529 case SD_BUS_TYPE_BOOLEAN:
1531 u8 = p && *(int*) p;
1537 case SD_BUS_TYPE_UNIX_FD:
1542 fd = message_push_fd(m, *(int*) p);
1553 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1554 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1561 a = message_extend_body(m, align, sz, true, false);
1568 *stored = (const uint8_t*) a;
1575 case SD_BUS_TYPE_STRING:
1576 /* To make things easy we'll serialize a NULL string
1577 * into the empty string */
1580 /* Fall through... */
1581 case SD_BUS_TYPE_OBJECT_PATH:
1587 sz = 4 + strlen(p) + 1;
1590 case SD_BUS_TYPE_SIGNATURE:
1595 sz = 1 + strlen(p) + 1;
1598 case SD_BUS_TYPE_BOOLEAN:
1600 u32 = p && *(int*) p;
1606 case SD_BUS_TYPE_UNIX_FD:
1611 fd = message_push_fd(m, *(int*) p);
1622 align = bus_type_get_alignment(type);
1623 sz = bus_type_get_size(type);
1630 a = message_extend_body(m, align, sz, false, false);
1634 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1635 *(uint32_t*) a = sz - 5;
1636 memcpy((uint8_t*) a + 4, p, sz - 4);
1639 *stored = (const uint8_t*) a + 4;
1641 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1642 *(uint8_t*) a = sz - 2;
1643 memcpy((uint8_t*) a + 1, p, sz - 1);
1646 *stored = (const uint8_t*) a + 1;
1655 if (type == SD_BUS_TYPE_UNIX_FD)
1658 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1665 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1666 return message_append_basic(m, type, p, NULL);
1669 _public_ int sd_bus_message_append_string_space(
1674 struct bus_container *c;
1677 assert_return(m, -EINVAL);
1678 assert_return(s, -EINVAL);
1679 assert_return(!m->sealed, -EPERM);
1680 assert_return(!m->poisoned, -ESTALE);
1682 c = message_get_container(m);
1684 if (c->signature && c->signature[c->index]) {
1685 /* Container signature is already set */
1687 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1692 /* Maybe we can append to the signature? But only if this is the top-level container */
1693 if (c->enclosing != 0)
1696 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1703 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1704 a = message_extend_body(m, 1, size + 1, true, false);
1710 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1714 *(uint32_t*) a = size;
1720 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1726 _public_ int sd_bus_message_append_string_iovec(
1728 const struct iovec *iov,
1736 assert_return(m, -EINVAL);
1737 assert_return(!m->sealed, -EPERM);
1738 assert_return(iov || n == 0, -EINVAL);
1739 assert_return(!m->poisoned, -ESTALE);
1741 size = IOVEC_TOTAL_SIZE(iov, n);
1743 r = sd_bus_message_append_string_space(m, size, &p);
1747 for (i = 0; i < n; i++) {
1749 if (iov[i].iov_base)
1750 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1752 memset(p, ' ', iov[i].iov_len);
1754 p += iov[i].iov_len;
1760 static int bus_message_open_array(
1762 struct bus_container *c,
1763 const char *contents,
1764 uint32_t **array_size,
1766 bool *need_offsets) {
1776 assert(need_offsets);
1778 if (!signature_is_single(contents, true))
1781 if (c->signature && c->signature[c->index]) {
1783 /* Verify the existing signature */
1785 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1788 if (!startswith(c->signature + c->index + 1, contents))
1791 nindex = c->index + 1 + strlen(contents);
1795 if (c->enclosing != 0)
1798 /* Extend the existing signature */
1800 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1806 nindex = e - c->signature;
1809 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1810 alignment = bus_gvariant_get_alignment(contents);
1814 /* Add alignment padding and add to offset list */
1815 if (!message_extend_body(m, alignment, 0, false, false))
1818 r = bus_gvariant_is_fixed_size(contents);
1822 *begin = m->body_size;
1823 *need_offsets = r == 0;
1827 struct bus_body_part *o;
1829 alignment = bus_type_get_alignment(contents[0]);
1833 a = message_extend_body(m, 4, 4, false, false);
1838 op = m->body_end->data;
1839 os = m->body_end->size;
1841 /* Add alignment between size and first element */
1842 if (!message_extend_body(m, alignment, 0, false, false))
1845 /* location of array size might have changed so let's readjust a */
1846 if (o == m->body_end)
1847 a = adjust_pointer(a, op, os, m->body_end->data);
1853 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1859 static int bus_message_open_variant(
1861 struct bus_container *c,
1862 const char *contents) {
1868 if (!signature_is_single(contents, false))
1871 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1874 if (c->signature && c->signature[c->index]) {
1876 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1882 if (c->enclosing != 0)
1885 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1892 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1893 /* Variants are always aligned to 8 */
1895 if (!message_extend_body(m, 8, 0, false, false))
1902 l = strlen(contents);
1903 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1908 memcpy((uint8_t*) a + 1, contents, l + 1);
1911 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1917 static int bus_message_open_struct(
1919 struct bus_container *c,
1920 const char *contents,
1922 bool *need_offsets) {
1931 assert(need_offsets);
1933 if (!signature_is_valid(contents, false))
1936 if (c->signature && c->signature[c->index]) {
1939 l = strlen(contents);
1941 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1942 !startswith(c->signature + c->index + 1, contents) ||
1943 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1946 nindex = c->index + 1 + l + 1;
1950 if (c->enclosing != 0)
1953 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1959 nindex = e - c->signature;
1962 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1965 alignment = bus_gvariant_get_alignment(contents);
1969 if (!message_extend_body(m, alignment, 0, false, false))
1972 r = bus_gvariant_is_fixed_size(contents);
1976 *begin = m->body_size;
1977 *need_offsets = r == 0;
1979 /* Align contents to 8 byte boundary */
1980 if (!message_extend_body(m, 8, 0, false, false))
1984 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1990 static int bus_message_open_dict_entry(
1992 struct bus_container *c,
1993 const char *contents,
1995 bool *need_offsets) {
2003 assert(need_offsets);
2005 if (!signature_is_pair(contents))
2008 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2011 if (c->signature && c->signature[c->index]) {
2014 l = strlen(contents);
2016 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2017 !startswith(c->signature + c->index + 1, contents) ||
2018 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2023 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2026 alignment = bus_gvariant_get_alignment(contents);
2030 if (!message_extend_body(m, alignment, 0, false, false))
2033 r = bus_gvariant_is_fixed_size(contents);
2037 *begin = m->body_size;
2038 *need_offsets = r == 0;
2040 /* Align contents to 8 byte boundary */
2041 if (!message_extend_body(m, 8, 0, false, false))
2048 _public_ int sd_bus_message_open_container(
2051 const char *contents) {
2053 struct bus_container *c, *w;
2054 uint32_t *array_size = NULL;
2056 size_t before, begin = 0;
2057 bool need_offsets = false;
2060 assert_return(m, -EINVAL);
2061 assert_return(!m->sealed, -EPERM);
2062 assert_return(contents, -EINVAL);
2063 assert_return(!m->poisoned, -ESTALE);
2065 /* Make sure we have space for one more container */
2066 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2071 c = message_get_container(m);
2073 signature = strdup(contents);
2079 /* Save old index in the parent container, in case we have to
2080 * abort this container */
2081 c->saved_index = c->index;
2082 before = m->body_size;
2084 if (type == SD_BUS_TYPE_ARRAY)
2085 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2086 else if (type == SD_BUS_TYPE_VARIANT)
2087 r = bus_message_open_variant(m, c, contents);
2088 else if (type == SD_BUS_TYPE_STRUCT)
2089 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2090 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2091 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2100 /* OK, let's fill it in */
2101 w = m->containers + m->n_containers++;
2102 w->enclosing = type;
2103 w->signature = signature;
2105 w->array_size = array_size;
2108 w->n_offsets = w->offsets_allocated = 0;
2110 w->need_offsets = need_offsets;
2115 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2120 if (!BUS_MESSAGE_IS_GVARIANT(m))
2123 if (c->need_offsets) {
2124 size_t payload, sz, i;
2127 /* Variable-width arrays */
2129 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2130 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2132 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2136 for (i = 0; i < c->n_offsets; i++)
2137 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2141 /* Fixed-width or empty arrays */
2143 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2151 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2157 assert(c->signature);
2159 if (!BUS_MESSAGE_IS_GVARIANT(m))
2162 l = strlen(c->signature);
2164 a = message_extend_body(m, 1, 1 + l, true, false);
2169 memcpy(a+1, c->signature, l);
2174 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2175 size_t n_variable = 0;
2184 if (!BUS_MESSAGE_IS_GVARIANT(m))
2187 p = strempty(c->signature);
2191 r = signature_element_length(p, &n);
2200 r = bus_gvariant_is_fixed_size(t);
2205 assert(!c->need_offsets || i <= c->n_offsets);
2207 /* We need to add an offset for each item that has a
2208 * variable size and that is not the last one in the
2210 if (r == 0 && p[n] != 0)
2217 assert(!c->need_offsets || i == c->n_offsets);
2218 assert(c->need_offsets || n_variable == 0);
2220 if (n_variable <= 0) {
2221 a = message_extend_body(m, 1, 0, add_offset, false);
2228 assert(c->offsets[c->n_offsets-1] == m->body_size);
2230 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2232 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2236 p = strempty(c->signature);
2237 for (i = 0, j = 0; i < c->n_offsets; i++) {
2241 r = signature_element_length(p, &n);
2252 r = bus_gvariant_is_fixed_size(t);
2255 if (r > 0 || p[0] == 0)
2259 k = n_variable - 1 - j;
2261 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2270 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2271 struct bus_container *c;
2274 assert_return(m, -EINVAL);
2275 assert_return(!m->sealed, -EPERM);
2276 assert_return(m->n_containers > 0, -EINVAL);
2277 assert_return(!m->poisoned, -ESTALE);
2279 c = message_get_container(m);
2281 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2282 if (c->signature && c->signature[c->index] != 0)
2287 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2288 r = bus_message_close_array(m, c);
2289 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2290 r = bus_message_close_variant(m, c);
2291 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2292 r = bus_message_close_struct(m, c, true);
2294 assert_not_reached("Unknown container type");
2308 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2315 stack[*i].types = types;
2316 stack[*i].n_struct = n_struct;
2317 stack[*i].n_array = n_array;
2323 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2334 *types = stack[*i].types;
2335 *n_struct = stack[*i].n_struct;
2336 *n_array = stack[*i].n_array;
2341 int bus_message_append_ap(
2346 unsigned n_array, n_struct;
2347 TypeStack stack[BUS_CONTAINER_DEPTH];
2348 unsigned stack_ptr = 0;
2356 n_array = (unsigned) -1;
2357 n_struct = strlen(types);
2362 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2363 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2369 r = sd_bus_message_close_container(m);
2377 if (n_array != (unsigned) -1)
2386 case SD_BUS_TYPE_BYTE: {
2389 x = (uint8_t) va_arg(ap, int);
2390 r = sd_bus_message_append_basic(m, *t, &x);
2394 case SD_BUS_TYPE_BOOLEAN:
2395 case SD_BUS_TYPE_INT32:
2396 case SD_BUS_TYPE_UINT32:
2397 case SD_BUS_TYPE_UNIX_FD: {
2400 /* We assume a boolean is the same as int32_t */
2401 assert_cc(sizeof(int32_t) == sizeof(int));
2403 x = va_arg(ap, uint32_t);
2404 r = sd_bus_message_append_basic(m, *t, &x);
2408 case SD_BUS_TYPE_INT16:
2409 case SD_BUS_TYPE_UINT16: {
2412 x = (uint16_t) va_arg(ap, int);
2413 r = sd_bus_message_append_basic(m, *t, &x);
2417 case SD_BUS_TYPE_INT64:
2418 case SD_BUS_TYPE_UINT64: {
2421 x = va_arg(ap, uint64_t);
2422 r = sd_bus_message_append_basic(m, *t, &x);
2426 case SD_BUS_TYPE_DOUBLE: {
2429 x = va_arg(ap, double);
2430 r = sd_bus_message_append_basic(m, *t, &x);
2434 case SD_BUS_TYPE_STRING:
2435 case SD_BUS_TYPE_OBJECT_PATH:
2436 case SD_BUS_TYPE_SIGNATURE: {
2439 x = va_arg(ap, const char*);
2440 r = sd_bus_message_append_basic(m, *t, x);
2444 case SD_BUS_TYPE_ARRAY: {
2447 r = signature_element_length(t + 1, &k);
2453 memcpy(s, t + 1, k);
2456 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2461 if (n_array == (unsigned) -1) {
2466 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2472 n_array = va_arg(ap, unsigned);
2477 case SD_BUS_TYPE_VARIANT: {
2480 s = va_arg(ap, const char*);
2484 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2488 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2493 n_struct = strlen(s);
2494 n_array = (unsigned) -1;
2499 case SD_BUS_TYPE_STRUCT_BEGIN:
2500 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2503 r = signature_element_length(t, &k);
2510 memcpy(s, t + 1, k - 2);
2513 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2518 if (n_array == (unsigned) -1) {
2523 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2529 n_array = (unsigned) -1;
2545 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2549 assert_return(m, -EINVAL);
2550 assert_return(types, -EINVAL);
2551 assert_return(!m->sealed, -EPERM);
2552 assert_return(!m->poisoned, -ESTALE);
2554 va_start(ap, types);
2555 r = bus_message_append_ap(m, types, ap);
2561 _public_ int sd_bus_message_append_array_space(
2571 assert_return(m, -EINVAL);
2572 assert_return(!m->sealed, -EPERM);
2573 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2574 assert_return(ptr || size == 0, -EINVAL);
2575 assert_return(!m->poisoned, -ESTALE);
2577 /* alignment and size of the trivial types (except bool) is
2578 * identical for gvariant and dbus1 marshalling */
2579 align = bus_type_get_alignment(type);
2580 sz = bus_type_get_size(type);
2582 assert_se(align > 0);
2588 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2592 a = message_extend_body(m, align, size, false, false);
2596 r = sd_bus_message_close_container(m);
2604 _public_ int sd_bus_message_append_array(
2612 assert_return(m, -EINVAL);
2613 assert_return(!m->sealed, -EPERM);
2614 assert_return(bus_type_is_trivial(type), -EINVAL);
2615 assert_return(ptr || size == 0, -EINVAL);
2616 assert_return(!m->poisoned, -ESTALE);
2618 r = sd_bus_message_append_array_space(m, type, size, &p);
2623 memcpy(p, ptr, size);
2628 _public_ int sd_bus_message_append_array_iovec(
2631 const struct iovec *iov,
2639 assert_return(m, -EINVAL);
2640 assert_return(!m->sealed, -EPERM);
2641 assert_return(bus_type_is_trivial(type), -EINVAL);
2642 assert_return(iov || n == 0, -EINVAL);
2643 assert_return(!m->poisoned, -ESTALE);
2645 size = IOVEC_TOTAL_SIZE(iov, n);
2647 r = sd_bus_message_append_array_space(m, type, size, &p);
2651 for (i = 0; i < n; i++) {
2653 if (iov[i].iov_base)
2654 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2656 memzero(p, iov[i].iov_len);
2658 p = (uint8_t*) p + iov[i].iov_len;
2664 _public_ int sd_bus_message_append_array_memfd(
2671 _cleanup_close_ int copy_fd = -1;
2672 struct bus_body_part *part;
2678 assert_return(m, -EINVAL);
2679 assert_return(memfd >= 0, -EINVAL);
2680 assert_return(bus_type_is_trivial(type), -EINVAL);
2681 assert_return(size > 0, -EINVAL);
2682 assert_return(!m->sealed, -EPERM);
2683 assert_return(!m->poisoned, -ESTALE);
2685 r = memfd_set_sealed(memfd);
2689 copy_fd = dup(memfd);
2693 r = memfd_get_size(memfd, &real_size);
2697 if (offset == 0 && size == (uint64_t) -1)
2699 else if (offset + size > real_size)
2702 align = bus_type_get_alignment(type);
2703 sz = bus_type_get_size(type);
2705 assert_se(align > 0);
2708 if (offset % align != 0)
2714 if (size > (uint64_t) (uint32_t) -1)
2717 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2721 a = message_extend_body(m, align, 0, false, false);
2725 part = message_append_part(m);
2729 part->memfd = copy_fd;
2730 part->memfd_offset = offset;
2731 part->sealed = true;
2735 m->body_size += size;
2736 message_extend_containers(m, size);
2738 return sd_bus_message_close_container(m);
2741 _public_ int sd_bus_message_append_string_memfd(
2747 _cleanup_close_ int copy_fd = -1;
2748 struct bus_body_part *part;
2749 struct bus_container *c;
2754 assert_return(m, -EINVAL);
2755 assert_return(memfd >= 0, -EINVAL);
2756 assert_return(size > 0, -EINVAL);
2757 assert_return(!m->sealed, -EPERM);
2758 assert_return(!m->poisoned, -ESTALE);
2760 r = memfd_set_sealed(memfd);
2764 copy_fd = dup(memfd);
2768 r = memfd_get_size(memfd, &real_size);
2772 if (offset == 0 && size == (uint64_t) -1)
2774 else if (offset + size > real_size)
2777 /* We require this to be NUL terminated */
2781 if (size > (uint64_t) (uint32_t) -1)
2784 c = message_get_container(m);
2785 if (c->signature && c->signature[c->index]) {
2786 /* Container signature is already set */
2788 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2793 /* Maybe we can append to the signature? But only if this is the top-level container */
2794 if (c->enclosing != 0)
2797 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2804 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2805 a = message_extend_body(m, 4, 4, false, false);
2809 *(uint32_t*) a = size - 1;
2812 part = message_append_part(m);
2816 part->memfd = copy_fd;
2817 part->memfd_offset = offset;
2818 part->sealed = true;
2822 m->body_size += size;
2823 message_extend_containers(m, size);
2825 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2826 r = message_add_offset(m, m->body_size);
2833 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2839 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2843 assert_return(m, -EINVAL);
2844 assert_return(!m->sealed, -EPERM);
2845 assert_return(!m->poisoned, -ESTALE);
2847 r = sd_bus_message_open_container(m, 'a', "s");
2851 STRV_FOREACH(i, l) {
2852 r = sd_bus_message_append_basic(m, 's', *i);
2857 return sd_bus_message_close_container(m);
2860 static int bus_message_close_header(sd_bus_message *m) {
2864 /* The actual user data is finished now, we just complete the
2865 variant and struct now (at least on gvariant). Remember
2866 this position, so that during parsing we know where to to
2867 put the outer container end. */
2868 m->user_body_size = m->body_size;
2870 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2871 const char *signature;
2875 /* Add offset table to end of fields array */
2876 if (m->n_header_offsets >= 1) {
2880 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2882 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2883 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2887 for (i = 0; i < m->n_header_offsets; i++)
2888 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2891 /* Add gvariant NUL byte plus signature to the end of
2892 * the body, followed by the final offset pointing to
2893 * the end of the fields array */
2895 signature = strempty(m->root_container.signature);
2896 l = strlen(signature);
2898 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l, 1);
2899 d = message_extend_body(m, 1, 1 + l + sz, false, true);
2904 memcpy((uint8_t*) d + 1, signature, l);
2906 bus_gvariant_write_word_le((uint8_t*) d + 1 + l, sz, sizeof(struct bus_header) + m->fields_size);
2909 m->footer_accessible = 1 + l + sz;
2911 m->header->dbus1.fields_size = m->fields_size;
2912 m->header->dbus1.body_size = m->body_size;
2918 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2919 struct bus_body_part *part;
2929 if (m->n_containers > 0)
2935 if (cookie > 0xffffffffULL &&
2936 !BUS_MESSAGE_IS_GVARIANT(m))
2939 /* In vtables the return signature of method calls is listed,
2940 * let's check if they match if this is a response */
2941 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2942 m->enforced_reply_signature &&
2943 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2946 /* If gvariant marshalling is used we need to close the body structure */
2947 r = bus_message_close_struct(m, &m->root_container, false);
2951 /* If there's a non-trivial signature set, then add it in
2952 * here, but only on dbus1 */
2953 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2954 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2960 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2965 r = bus_message_close_header(m);
2969 if (BUS_MESSAGE_IS_GVARIANT(m))
2970 m->header->dbus2.cookie = cookie;
2972 m->header->dbus1.serial = (uint32_t) cookie;
2974 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2976 /* Add padding at the end of the fields part, since we know
2977 * the body needs to start at an 8 byte alignment. We made
2978 * sure we allocated enough space for this, so all we need to
2979 * do here is to zero it out. */
2980 a = ALIGN8(m->fields_size) - m->fields_size;
2982 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2984 /* If this is something we can send as memfd, then let's seal
2985 the memfd now. Note that we can send memfds as payload only
2986 for directed messages, and not for broadcasts. */
2987 if (m->destination && m->bus->use_memfd) {
2988 MESSAGE_FOREACH_PART(part, i, m)
2989 if (part->memfd >= 0 &&
2991 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2992 part != m->body_end) { /* The last part may never be sent as memfd */
2995 /* Try to seal it if that makes
2996 * sense. First, unmap our own map to
2997 * make sure we don't keep it busy. */
2998 bus_body_part_unmap(part);
3000 /* Then, sync up real memfd size */
3002 r = memfd_set_size(part->memfd, sz);
3006 /* Finally, try to seal */
3007 if (memfd_set_sealed(part->memfd) >= 0)
3008 part->sealed = true;
3012 m->root_container.end = m->user_body_size;
3013 m->root_container.index = 0;
3014 m->root_container.offset_index = 0;
3015 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3022 int bus_body_part_map(struct bus_body_part *part) {
3031 if (part->size <= 0)
3034 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3035 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3036 static const uint8_t zeroes[7] = { };
3037 part->data = (void*) zeroes;
3041 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3042 psz = PAGE_ALIGN(part->size + shift);
3044 if (part->memfd >= 0)
3045 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3046 else if (part->is_zero)
3047 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3051 if (p == MAP_FAILED)
3055 part->mmap_begin = p;
3056 part->data = (uint8_t*) p + shift;
3057 part->munmap_this = true;
3062 void bus_body_part_unmap(struct bus_body_part *part) {
3066 if (part->memfd < 0)
3069 if (!part->mmap_begin)
3072 if (!part->munmap_this)
3075 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3077 part->mmap_begin = NULL;
3080 part->munmap_this = false;
3085 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3086 size_t k, start, end;
3091 start = ALIGN_TO((size_t) *rindex, align);
3092 end = start + nbytes;
3097 /* Verify that padding is 0 */
3098 for (k = *rindex; k < start; k++)
3099 if (((const uint8_t*) p)[k] != 0)
3103 *r = (uint8_t*) p + start;
3110 static bool message_end_of_signature(sd_bus_message *m) {
3111 struct bus_container *c;
3115 c = message_get_container(m);
3116 return !c->signature || c->signature[c->index] == 0;
3119 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3120 struct bus_container *c;
3124 c = message_get_container(m);
3125 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3128 if (BUS_MESSAGE_IS_GVARIANT(m))
3129 return index >= c->end;
3131 assert(c->array_size);
3132 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3136 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3137 assert_return(m, -EINVAL);
3138 assert_return(m->sealed, -EPERM);
3140 if (complete && m->n_containers > 0)
3143 if (message_end_of_signature(m))
3146 if (message_end_of_array(m, m->rindex))
3152 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3153 struct bus_body_part *part;
3159 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3160 part = m->cached_rindex_part;
3161 begin = m->cached_rindex_part_begin;
3171 if (index + sz <= begin + part->size) {
3173 r = bus_body_part_map(part);
3178 *p = (uint8_t*) part->data + index - begin;
3180 m->cached_rindex_part = part;
3181 m->cached_rindex_part_begin = begin;
3186 begin += part->size;
3193 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3200 if (!BUS_MESSAGE_IS_GVARIANT(m))
3203 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3206 sz = bus_gvariant_get_size(c->signature);
3210 if (c->offset_index+1 >= c->n_offsets)
3213 /* Variable-size array */
3215 alignment = bus_gvariant_get_alignment(c->signature);
3216 assert(alignment > 0);
3218 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3219 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3222 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3225 /* Fixed-size array */
3226 *rindex = c->begin + (c->offset_index+1) * sz;
3232 } else if (c->enclosing == 0 ||
3233 c->enclosing == SD_BUS_TYPE_STRUCT ||
3234 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3239 if (c->offset_index+1 >= c->n_offsets)
3242 r = signature_element_length(c->signature + c->index, &n);
3246 r = signature_element_length(c->signature + c->index + n, &j);
3251 memcpy(t, c->signature + c->index + n, j);
3254 alignment = bus_gvariant_get_alignment(t);
3257 assert(alignment > 0);
3259 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3260 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3264 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3267 assert_not_reached("Unknown container type");
3272 /* Reached the end */
3279 static int message_peek_body(
3286 size_t k, start, end, padding;
3287 struct bus_body_part *part;
3294 start = ALIGN_TO((size_t) *rindex, align);
3295 padding = start - *rindex;
3296 end = start + nbytes;
3298 if (end > m->user_body_size)
3301 part = find_part(m, *rindex, padding, (void**) &q);
3306 /* Verify padding */
3307 for (k = 0; k < padding; k++)
3312 part = find_part(m, start, nbytes, (void**) &q);
3313 if (!part || (nbytes > 0 && !q))
3324 static bool validate_nul(const char *s, size_t l) {
3326 /* Check for NUL chars in the string */
3327 if (memchr(s, 0, l))
3330 /* Check for NUL termination */
3337 static bool validate_string(const char *s, size_t l) {
3339 if (!validate_nul(s, l))
3342 /* Check if valid UTF8 */
3343 if (!utf8_is_valid(s))
3349 static bool validate_signature(const char *s, size_t l) {
3351 if (!validate_nul(s, l))
3354 /* Check if valid signature */
3355 if (!signature_is_valid(s, true))
3361 static bool validate_object_path(const char *s, size_t l) {
3363 if (!validate_nul(s, l))
3366 if (!object_path_is_valid(s))
3372 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3373 struct bus_container *c;
3378 assert_return(m, -EINVAL);
3379 assert_return(m->sealed, -EPERM);
3380 assert_return(bus_type_is_basic(type), -EINVAL);
3382 if (message_end_of_signature(m))
3385 if (message_end_of_array(m, m->rindex))
3388 c = message_get_container(m);
3389 if (c->signature[c->index] != type)
3394 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3396 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3399 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3403 if (type == SD_BUS_TYPE_STRING)
3404 ok = validate_string(q, c->item_size-1);
3405 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3406 ok = validate_object_path(q, c->item_size-1);
3408 ok = validate_signature(q, c->item_size-1);
3414 *(const char**) p = q;
3418 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3420 if ((size_t) sz != c->item_size)
3423 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3426 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3432 case SD_BUS_TYPE_BYTE:
3434 *(uint8_t*) p = *(uint8_t*) q;
3437 case SD_BUS_TYPE_BOOLEAN:
3439 *(int*) p = !!*(uint8_t*) q;
3442 case SD_BUS_TYPE_INT16:
3443 case SD_BUS_TYPE_UINT16:
3445 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3448 case SD_BUS_TYPE_INT32:
3449 case SD_BUS_TYPE_UINT32:
3451 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3454 case SD_BUS_TYPE_INT64:
3455 case SD_BUS_TYPE_UINT64:
3456 case SD_BUS_TYPE_DOUBLE:
3458 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3461 case SD_BUS_TYPE_UNIX_FD: {
3464 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3469 *(int*) p = m->fds[j];
3475 assert_not_reached("unexpected type");
3479 r = container_next_item(m, c, &rindex);
3486 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3490 r = message_peek_body(m, &rindex, 4, 4, &q);
3494 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3495 r = message_peek_body(m, &rindex, 1, l+1, &q);
3499 if (type == SD_BUS_TYPE_OBJECT_PATH)
3500 ok = validate_object_path(q, l);
3502 ok = validate_string(q, l);
3507 *(const char**) p = q;
3509 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3512 r = message_peek_body(m, &rindex, 1, 1, &q);
3517 r = message_peek_body(m, &rindex, 1, l+1, &q);
3521 if (!validate_signature(q, l))
3525 *(const char**) p = q;
3530 align = bus_type_get_alignment(type);
3533 sz = bus_type_get_size(type);
3536 r = message_peek_body(m, &rindex, align, sz, &q);
3542 case SD_BUS_TYPE_BYTE:
3544 *(uint8_t*) p = *(uint8_t*) q;
3547 case SD_BUS_TYPE_BOOLEAN:
3549 *(int*) p = !!*(uint32_t*) q;
3552 case SD_BUS_TYPE_INT16:
3553 case SD_BUS_TYPE_UINT16:
3555 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3558 case SD_BUS_TYPE_INT32:
3559 case SD_BUS_TYPE_UINT32:
3561 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3564 case SD_BUS_TYPE_INT64:
3565 case SD_BUS_TYPE_UINT64:
3566 case SD_BUS_TYPE_DOUBLE:
3568 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3571 case SD_BUS_TYPE_UNIX_FD: {
3574 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3579 *(int*) p = m->fds[j];
3584 assert_not_reached("Unknown basic type...");
3591 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3597 static int bus_message_enter_array(
3599 struct bus_container *c,
3600 const char *contents,
3601 uint32_t **array_size,
3604 size_t *n_offsets) {
3618 if (!signature_is_single(contents, true))
3621 if (!c->signature || c->signature[c->index] == 0)
3624 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3627 if (!startswith(c->signature + c->index + 1, contents))
3632 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3635 r = message_peek_body(m, &rindex, 4, 4, &q);
3639 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3642 alignment = bus_type_get_alignment(contents[0]);
3646 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3650 *array_size = (uint32_t*) q;
3652 } else if (c->item_size <= 0) {
3654 /* gvariant: empty array */
3659 } else if (bus_gvariant_is_fixed_size(contents)) {
3661 /* gvariant: fixed length array */
3662 *item_size = bus_gvariant_get_size(contents);
3667 size_t where, p = 0, framing, sz;
3670 /* gvariant: variable length array */
3671 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3673 where = rindex + c->item_size - sz;
3674 r = message_peek_body(m, &where, 1, sz, &q);
3678 framing = bus_gvariant_read_word_le(q, sz);
3679 if (framing > c->item_size - sz)
3681 if ((c->item_size - framing) % sz != 0)
3684 *n_offsets = (c->item_size - framing) / sz;
3686 where = rindex + framing;
3687 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3691 *offsets = new(size_t, *n_offsets);
3695 for (i = 0; i < *n_offsets; i++) {
3698 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3699 if (x > c->item_size - sz)
3704 (*offsets)[i] = rindex + x;
3708 *item_size = (*offsets)[0] - rindex;
3713 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3714 c->index += 1 + strlen(contents);
3719 static int bus_message_enter_variant(
3721 struct bus_container *c,
3722 const char *contents,
3723 size_t *item_size) {
3735 if (!signature_is_single(contents, false))
3738 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3741 if (!c->signature || c->signature[c->index] == 0)
3744 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3749 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3752 k = strlen(contents);
3753 if (1+k > c->item_size)
3756 where = rindex + c->item_size - (1+k);
3757 r = message_peek_body(m, &where, 1, 1+k, &q);
3761 if (*(char*) q != 0)
3764 if (memcmp((uint8_t*) q+1, contents, k))
3767 *item_size = c->item_size - (1+k);
3770 r = message_peek_body(m, &rindex, 1, 1, &q);
3775 r = message_peek_body(m, &rindex, 1, l+1, &q);
3779 if (!validate_signature(q, l))
3782 if (!streq(q, contents))
3788 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3794 static int build_struct_offsets(
3796 const char *signature,
3800 size_t *n_offsets) {
3802 unsigned n_variable = 0, n_total = 0, v;
3803 size_t previous = 0, where;
3814 if (isempty(signature)) {
3821 sz = bus_gvariant_determine_word_size(size, 0);
3825 /* First, loop over signature and count variable elements and
3826 * elements in general. We use this to know how large the
3827 * offset array is at the end of the structure. Note that
3828 * GVariant only stores offsets for all variable size elements
3829 * that are not the last item. */
3835 r = signature_element_length(p, &n);
3844 r = bus_gvariant_is_fixed_size(t);
3849 if (r == 0 && p[n] != 0) /* except the last item */
3856 if (size < n_variable * sz)
3859 where = m->rindex + size - (n_variable * sz);
3860 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3866 *offsets = new(size_t, n_total);
3872 /* Second, loop again and build an offset table */
3878 r = signature_element_length(p, &n);
3887 k = bus_gvariant_get_size(t);
3895 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3898 if (m->rindex + x < previous)
3901 /* The last item's end
3902 * is determined from
3905 x = size - (n_variable * sz);
3907 offset = m->rindex + x;
3913 align = bus_gvariant_get_alignment(t);
3916 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3920 previous = (*offsets)[(*n_offsets)++] = offset;
3925 assert(*n_offsets == n_total);
3927 *item_size = (*offsets)[0] - m->rindex;
3931 static int enter_struct_or_dict_entry(
3933 struct bus_container *c,
3934 const char *contents,
3937 size_t *n_offsets) {
3948 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3951 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3955 } else if (c->item_size <= 0) {
3957 /* gvariant empty struct */
3962 /* gvariant with contents */
3963 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3968 static int bus_message_enter_struct(
3970 struct bus_container *c,
3971 const char *contents,
3974 size_t *n_offsets) {
3986 if (!signature_is_valid(contents, false))
3989 if (!c->signature || c->signature[c->index] == 0)
3992 l = strlen(contents);
3994 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3995 !startswith(c->signature + c->index + 1, contents) ||
3996 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3999 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4003 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4004 c->index += 1 + l + 1;
4009 static int bus_message_enter_dict_entry(
4011 struct bus_container *c,
4012 const char *contents,
4015 size_t *n_offsets) {
4024 if (!signature_is_pair(contents))
4027 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4030 if (!c->signature || c->signature[c->index] == 0)
4033 l = strlen(contents);
4035 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4036 !startswith(c->signature + c->index + 1, contents) ||
4037 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4040 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4044 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4045 c->index += 1 + l + 1;
4050 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4052 const char *contents) {
4053 struct bus_container *c, *w;
4054 uint32_t *array_size = NULL;
4057 size_t *offsets = NULL;
4058 size_t n_offsets = 0, item_size = 0;
4061 assert_return(m, -EINVAL);
4062 assert_return(m->sealed, -EPERM);
4063 assert_return(type != 0 || !contents, -EINVAL);
4065 if (type == 0 || !contents) {
4069 /* Allow entering into anonymous containers */
4070 r = sd_bus_message_peek_type(m, &tt, &cc);
4074 if (type != 0 && type != tt)
4077 if (contents && !streq(contents, cc))
4085 * We enforce a global limit on container depth, that is much
4086 * higher than the 32 structs and 32 arrays the specification
4087 * mandates. This is simpler to implement for us, and we need
4088 * this only to ensure our container array doesn't grow
4089 * without bounds. We are happy to return any data from a
4090 * message as long as the data itself is valid, even if the
4091 * overall message might be not.
4093 * Note that the message signature is validated when
4094 * parsing the headers, and that validation does check the
4097 * Note that the specification defines no limits on the depth
4098 * of stacked variants, but we do.
4100 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4103 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4106 if (message_end_of_signature(m))
4109 if (message_end_of_array(m, m->rindex))
4112 c = message_get_container(m);
4114 signature = strdup(contents);
4118 c->saved_index = c->index;
4121 if (type == SD_BUS_TYPE_ARRAY)
4122 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4123 else if (type == SD_BUS_TYPE_VARIANT)
4124 r = bus_message_enter_variant(m, c, contents, &item_size);
4125 else if (type == SD_BUS_TYPE_STRUCT)
4126 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4127 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4128 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4138 /* OK, let's fill it in */
4139 w = m->containers + m->n_containers++;
4140 w->enclosing = type;
4141 w->signature = signature;
4142 w->peeked_signature = NULL;
4146 w->begin = m->rindex;
4147 w->end = m->rindex + c->item_size;
4149 w->array_size = array_size;
4150 w->item_size = item_size;
4151 w->offsets = offsets;
4152 w->n_offsets = n_offsets;
4153 w->offset_index = 0;
4158 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4159 struct bus_container *c;
4163 assert_return(m, -EINVAL);
4164 assert_return(m->sealed, -EPERM);
4165 assert_return(m->n_containers > 0, -ENXIO);
4167 c = message_get_container(m);
4169 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4170 if (c->signature && c->signature[c->index] != 0)
4174 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4175 if (m->rindex < c->end)
4178 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4181 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4182 if (c->begin + l != m->rindex)
4187 free(c->peeked_signature);
4191 c = message_get_container(m);
4194 c->index = c->saved_index;
4195 r = container_next_item(m, c, &m->rindex);
4203 static void message_quit_container(sd_bus_message *m) {
4204 struct bus_container *c;
4208 assert(m->n_containers > 0);
4210 c = message_get_container(m);
4213 assert(m->rindex >= c->before);
4214 m->rindex = c->before;
4216 /* Free container */
4221 /* Correct index of new top-level container */
4222 c = message_get_container(m);
4223 c->index = c->saved_index;
4226 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4227 struct bus_container *c;
4230 assert_return(m, -EINVAL);
4231 assert_return(m->sealed, -EPERM);
4233 if (message_end_of_signature(m))
4236 if (message_end_of_array(m, m->rindex))
4239 c = message_get_container(m);
4241 if (bus_type_is_basic(c->signature[c->index])) {
4245 *type = c->signature[c->index];
4249 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4255 r = signature_element_length(c->signature+c->index+1, &l);
4261 sig = strndup(c->signature + c->index + 1, l);
4265 free(c->peeked_signature);
4266 *contents = c->peeked_signature = sig;
4270 *type = SD_BUS_TYPE_ARRAY;
4275 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4276 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4282 r = signature_element_length(c->signature+c->index, &l);
4287 sig = strndup(c->signature + c->index + 1, l - 2);
4291 free(c->peeked_signature);
4292 *contents = c->peeked_signature = sig;
4296 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4301 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4305 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4308 if (c->item_size < 2)
4311 /* Look for the NUL delimiter that
4312 separates the payload from the
4313 signature. Since the body might be
4314 in a different part that then the
4315 signature we map byte by byte. */
4317 for (k = 2; k <= c->item_size; k++) {
4320 where = m->rindex + c->item_size - k;
4321 r = message_peek_body(m, &where, 1, k, &q);
4325 if (*(char*) q == 0)
4329 if (k > c->item_size)
4332 free(c->peeked_signature);
4333 c->peeked_signature = strndup((char*) q + 1, k - 1);
4334 if (!c->peeked_signature)
4337 if (!signature_is_valid(c->peeked_signature, true))
4340 *contents = c->peeked_signature;
4345 r = message_peek_body(m, &rindex, 1, 1, &q);
4350 r = message_peek_body(m, &rindex, 1, l+1, &q);
4354 if (!validate_signature(q, l))
4362 *type = SD_BUS_TYPE_VARIANT;
4377 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4378 struct bus_container *c;
4380 assert_return(m, -EINVAL);
4381 assert_return(m->sealed, -EPERM);
4384 message_reset_containers(m);
4387 c = message_get_container(m);
4389 c = message_get_container(m);
4391 c->offset_index = 0;
4393 m->rindex = c->begin;
4396 c->offset_index = 0;
4397 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4399 return !isempty(c->signature);
4402 static int message_read_ap(
4407 unsigned n_array, n_struct;
4408 TypeStack stack[BUS_CONTAINER_DEPTH];
4409 unsigned stack_ptr = 0;
4410 unsigned n_loop = 0;
4418 /* Ideally, we'd just call ourselves recursively on every
4419 * complex type. However, the state of a va_list that is
4420 * passed to a function is undefined after that function
4421 * returns. This means we need to docode the va_list linearly
4422 * in a single stackframe. We hence implement our own
4423 * home-grown stack in an array. */
4425 n_array = (unsigned) -1; /* length of current array entries */
4426 n_struct = strlen(types); /* length of current struct contents signature */
4433 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4434 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4440 r = sd_bus_message_exit_container(m);
4448 if (n_array != (unsigned) -1)
4457 case SD_BUS_TYPE_BYTE:
4458 case SD_BUS_TYPE_BOOLEAN:
4459 case SD_BUS_TYPE_INT16:
4460 case SD_BUS_TYPE_UINT16:
4461 case SD_BUS_TYPE_INT32:
4462 case SD_BUS_TYPE_UINT32:
4463 case SD_BUS_TYPE_INT64:
4464 case SD_BUS_TYPE_UINT64:
4465 case SD_BUS_TYPE_DOUBLE:
4466 case SD_BUS_TYPE_STRING:
4467 case SD_BUS_TYPE_OBJECT_PATH:
4468 case SD_BUS_TYPE_SIGNATURE:
4469 case SD_BUS_TYPE_UNIX_FD: {
4472 p = va_arg(ap, void*);
4473 r = sd_bus_message_read_basic(m, *t, p);
4486 case SD_BUS_TYPE_ARRAY: {
4489 r = signature_element_length(t + 1, &k);
4495 memcpy(s, t + 1, k);
4498 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4509 if (n_array == (unsigned) -1) {
4514 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4520 n_array = va_arg(ap, unsigned);
4525 case SD_BUS_TYPE_VARIANT: {
4528 s = va_arg(ap, const char *);
4532 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4542 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4547 n_struct = strlen(s);
4548 n_array = (unsigned) -1;
4553 case SD_BUS_TYPE_STRUCT_BEGIN:
4554 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4557 r = signature_element_length(t, &k);
4563 memcpy(s, t + 1, k - 2);
4566 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4576 if (n_array == (unsigned) -1) {
4581 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4587 n_array = (unsigned) -1;
4600 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4604 assert_return(m, -EINVAL);
4605 assert_return(m->sealed, -EPERM);
4606 assert_return(types, -EINVAL);
4608 va_start(ap, types);
4609 r = message_read_ap(m, types, ap);
4615 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4618 assert_return(m, -EINVAL);
4619 assert_return(m->sealed, -EPERM);
4621 /* If types is NULL, read exactly one element */
4623 struct bus_container *c;
4626 if (message_end_of_signature(m))
4629 if (message_end_of_array(m, m->rindex))
4632 c = message_get_container(m);
4634 r = signature_element_length(c->signature + c->index, &l);
4638 types = strndupa(c->signature + c->index, l);
4643 case 0: /* Nothing to drop */
4646 case SD_BUS_TYPE_BYTE:
4647 case SD_BUS_TYPE_BOOLEAN:
4648 case SD_BUS_TYPE_INT16:
4649 case SD_BUS_TYPE_UINT16:
4650 case SD_BUS_TYPE_INT32:
4651 case SD_BUS_TYPE_UINT32:
4652 case SD_BUS_TYPE_INT64:
4653 case SD_BUS_TYPE_UINT64:
4654 case SD_BUS_TYPE_DOUBLE:
4655 case SD_BUS_TYPE_STRING:
4656 case SD_BUS_TYPE_OBJECT_PATH:
4657 case SD_BUS_TYPE_SIGNATURE:
4658 case SD_BUS_TYPE_UNIX_FD:
4660 r = sd_bus_message_read_basic(m, *types, NULL);
4664 r = sd_bus_message_skip(m, types + 1);
4670 case SD_BUS_TYPE_ARRAY: {
4673 r = signature_element_length(types + 1, &k);
4679 memcpy(s, types+1, k);
4682 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4687 r = sd_bus_message_skip(m, s);
4694 r = sd_bus_message_exit_container(m);
4699 r = sd_bus_message_skip(m, types + 1 + k);
4706 case SD_BUS_TYPE_VARIANT: {
4707 const char *contents;
4710 r = sd_bus_message_peek_type(m, &x, &contents);
4714 if (x != SD_BUS_TYPE_VARIANT)
4717 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4721 r = sd_bus_message_skip(m, contents);
4726 r = sd_bus_message_exit_container(m);
4730 r = sd_bus_message_skip(m, types + 1);
4737 case SD_BUS_TYPE_STRUCT_BEGIN:
4738 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4741 r = signature_element_length(types, &k);
4747 memcpy(s, types+1, k-2);
4750 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4754 r = sd_bus_message_skip(m, s);
4759 r = sd_bus_message_exit_container(m);
4764 r = sd_bus_message_skip(m, types + k);
4776 _public_ int sd_bus_message_read_array(
4782 struct bus_container *c;
4788 assert_return(m, -EINVAL);
4789 assert_return(m->sealed, -EPERM);
4790 assert_return(bus_type_is_trivial(type), -EINVAL);
4791 assert_return(ptr, -EINVAL);
4792 assert_return(size, -EINVAL);
4793 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4795 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4799 c = message_get_container(m);
4801 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4802 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4806 sz = c->end - c->begin;
4808 align = bus_type_get_alignment(type);
4812 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4816 /* Zero length array, let's return some aligned
4817 * pointer that is not NULL */
4818 p = (uint8_t*) NULL + align;
4820 r = message_peek_body(m, &m->rindex, align, sz, &p);
4825 r = sd_bus_message_exit_container(m);
4829 *ptr = (const void*) p;
4835 message_quit_container(m);
4839 static int message_peek_fields(
4850 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4853 static int message_peek_field_uint32(
4865 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4868 /* identical for gvariant and dbus1 */
4870 r = message_peek_fields(m, ri, 4, 4, &q);
4875 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4880 static int message_peek_field_uint64(
4892 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4895 /* identical for gvariant and dbus1 */
4897 r = message_peek_fields(m, ri, 8, 8, &q);
4902 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4907 static int message_peek_field_string(
4909 bool (*validate)(const char *p),
4921 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4926 r = message_peek_fields(m, ri, 1, item_size, &q);
4932 r = message_peek_field_uint32(m, ri, 4, &l);
4936 r = message_peek_fields(m, ri, 1, l+1, &q);
4942 if (!validate_nul(q, l))
4948 if (!validate_string(q, l))
4958 static int message_peek_field_signature(
4971 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4976 r = message_peek_fields(m, ri, 1, item_size, &q);
4982 r = message_peek_fields(m, ri, 1, 1, &q);
4987 r = message_peek_fields(m, ri, 1, l+1, &q);
4992 if (!validate_signature(q, l))
5001 static int message_skip_fields(
5004 uint32_t array_size,
5005 const char **signature) {
5007 size_t original_index;
5013 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5015 original_index = *ri;
5021 if (array_size != (uint32_t) -1 &&
5022 array_size <= *ri - original_index)
5029 if (t == SD_BUS_TYPE_STRING) {
5031 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5037 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5039 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5045 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5047 r = message_peek_field_signature(m, ri, 0, NULL);
5053 } else if (bus_type_is_basic(t)) {
5056 align = bus_type_get_alignment(t);
5057 k = bus_type_get_size(t);
5058 assert(align > 0 && k > 0);
5060 r = message_peek_fields(m, ri, align, k, NULL);
5066 } else if (t == SD_BUS_TYPE_ARRAY) {
5068 r = signature_element_length(*signature+1, &l);
5078 strncpy(sig, *signature + 1, l-1);
5081 alignment = bus_type_get_alignment(sig[0]);
5085 r = message_peek_field_uint32(m, ri, 0, &nas);
5088 if (nas > BUS_ARRAY_MAX_SIZE)
5091 r = message_peek_fields(m, ri, alignment, 0, NULL);
5095 r = message_skip_fields(m, ri, nas, (const char**) &s);
5100 (*signature) += 1 + l;
5102 } else if (t == SD_BUS_TYPE_VARIANT) {
5105 r = message_peek_field_signature(m, ri, 0, &s);
5109 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5115 } else if (t == SD_BUS_TYPE_STRUCT ||
5116 t == SD_BUS_TYPE_DICT_ENTRY) {
5118 r = signature_element_length(*signature, &l);
5125 strncpy(sig, *signature + 1, l-1);
5128 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5139 int bus_message_parse_fields(sd_bus_message *m) {
5142 uint32_t unix_fds = 0;
5143 bool unix_fds_set = false;
5144 void *offsets = NULL;
5145 unsigned n_offsets = 0;
5151 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5154 /* Read the signature from the end of the body variant first */
5155 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5156 if (m->footer_accessible < 1 + sz)
5159 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5161 if (p < (char*) m->footer)
5167 /* We found the beginning of the signature string, yay! */
5169 c = strndup(p + 1, ((char*) m->footer + m->footer_accessible) - p - (1 + sz));
5173 free(m->root_container.signature);
5174 m->root_container.signature = c;
5181 /* Calculate the actual user body size, by removing
5182 * the trailing variant signature and struct offset
5184 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5186 /* Pull out the offset table for the fields array */
5187 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5192 ri = m->fields_size - sz;
5193 r = message_peek_fields(m, &ri, 1, sz, &q);
5197 framing = bus_gvariant_read_word_le(q, sz);
5198 if (framing >= m->fields_size - sz)
5200 if ((m->fields_size - framing) % sz != 0)
5204 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5208 n_offsets = (m->fields_size - framing) / sz;
5211 m->user_body_size = m->body_size;
5214 while (ri < m->fields_size) {
5215 _cleanup_free_ char *sig = NULL;
5216 const char *signature;
5217 uint64_t field_type;
5218 size_t item_size = (size_t) -1;
5220 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5229 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5231 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5235 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5239 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5246 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5251 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5256 where = ri = ALIGN_TO(ri, 8);
5257 item_size = end - ri;
5258 r = message_peek_fields(m, &where, 1, item_size, &q);
5262 b = memrchr(q, 0, item_size);
5266 sig = strndup(b+1, item_size - (b+1-(char*) q));
5271 item_size = b - (char*) q;
5273 r = message_peek_field_signature(m, &ri, 0, &signature);
5278 switch (field_type) {
5280 case _BUS_MESSAGE_HEADER_INVALID:
5283 case BUS_MESSAGE_HEADER_PATH:
5288 if (!streq(signature, "o"))
5291 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5294 case BUS_MESSAGE_HEADER_INTERFACE:
5299 if (!streq(signature, "s"))
5302 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5305 case BUS_MESSAGE_HEADER_MEMBER:
5310 if (!streq(signature, "s"))
5313 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5316 case BUS_MESSAGE_HEADER_ERROR_NAME:
5321 if (!streq(signature, "s"))
5324 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5326 m->error._need_free = -1;
5330 case BUS_MESSAGE_HEADER_DESTINATION:
5335 if (!streq(signature, "s"))
5338 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5341 case BUS_MESSAGE_HEADER_SENDER:
5346 if (!streq(signature, "s"))
5349 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5351 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5352 m->creds.unique_name = (char*) m->sender;
5353 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5359 case BUS_MESSAGE_HEADER_SIGNATURE: {
5363 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5366 if (m->root_container.signature)
5369 if (!streq(signature, "g"))
5372 r = message_peek_field_signature(m, &ri, item_size, &s);
5380 free(m->root_container.signature);
5381 m->root_container.signature = c;
5385 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5387 if (m->reply_cookie != 0)
5390 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5391 /* 64bit on dbus2 */
5393 if (!streq(signature, "t"))
5396 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5400 /* 32bit on dbus1 */
5403 if (!streq(signature, "u"))
5406 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5410 m->reply_cookie = serial;
5413 if (m->reply_cookie == 0)
5418 case BUS_MESSAGE_HEADER_UNIX_FDS:
5422 if (!streq(signature, "u"))
5425 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5429 unix_fds_set = true;
5433 if (!BUS_MESSAGE_IS_GVARIANT(m))
5434 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5443 if (m->n_fds != unix_fds)
5446 switch (m->header->type) {
5448 case SD_BUS_MESSAGE_SIGNAL:
5449 if (!m->path || !m->interface || !m->member)
5452 if (m->reply_cookie != 0)
5457 case SD_BUS_MESSAGE_METHOD_CALL:
5459 if (!m->path || !m->member)
5462 if (m->reply_cookie != 0)
5467 case SD_BUS_MESSAGE_METHOD_RETURN:
5469 if (m->reply_cookie == 0)
5473 case SD_BUS_MESSAGE_METHOD_ERROR:
5475 if (m->reply_cookie == 0 || !m->error.name)
5480 /* Refuse non-local messages that claim they are local */
5481 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5483 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5485 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5488 m->root_container.end = m->user_body_size;
5490 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5491 r = build_struct_offsets(
5493 m->root_container.signature,
5495 &m->root_container.item_size,
5496 &m->root_container.offsets,
5497 &m->root_container.n_offsets);
5502 /* Try to read the error message, but if we can't it's a non-issue */
5503 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5504 sd_bus_message_read(m, "s", &m->error.message);
5509 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5510 assert_return(m, -EINVAL);
5511 assert_return(destination, -EINVAL);
5512 assert_return(!m->sealed, -EPERM);
5513 assert_return(!m->destination, -EEXIST);
5515 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5518 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5522 struct bus_body_part *part;
5528 total = BUS_MESSAGE_SIZE(m);
5534 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5535 MESSAGE_FOREACH_PART(part, i, m)
5536 e = mempcpy(e, part->data, part->size);
5538 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5546 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5552 r = sd_bus_message_enter_container(m, 'a', "s");
5559 r = sd_bus_message_read_basic(m, 's', &s);
5565 r = strv_extend(l, s);
5570 r = sd_bus_message_exit_container(m);
5577 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5581 assert_return(m, -EINVAL);
5582 assert_return(m->sealed, -EPERM);
5583 assert_return(l, -EINVAL);
5585 r = bus_message_read_strv_extend(m, &strv);
5595 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5596 const char *contents;
5605 r = sd_bus_message_rewind(m, true);
5610 r = sd_bus_message_peek_type(m, &type, &contents);
5616 /* Don't match against arguments after the first one we don't understand */
5617 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5618 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5624 r = sd_bus_message_skip(m, NULL);
5629 if (type == SD_BUS_TYPE_ARRAY) {
5631 r = sd_bus_message_read_strv(m, strv);
5638 r = sd_bus_message_read_basic(m, type, str);
5648 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5649 assert_return(m, EINVAL);
5651 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5654 return sd_bus_error_get_errno(&m->error);
5657 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5658 struct bus_container *c;
5660 assert_return(m, NULL);
5662 c = complete ? &m->root_container : message_get_container(m);
5663 return strempty(c->signature);
5666 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5667 assert_return(m, -EINVAL);
5669 return isempty(m->root_container.signature);
5672 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5673 assert_return(m, -EINVAL);
5675 return streq(strempty(m->root_container.signature), strempty(signature));
5678 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5679 bool done_something = false;
5682 assert_return(m, -EINVAL);
5683 assert_return(source, -EINVAL);
5684 assert_return(!m->sealed, -EPERM);
5685 assert_return(source->sealed, -EPERM);
5688 const char *contents;
5703 r = sd_bus_message_peek_type(source, &type, &contents);
5709 done_something = true;
5711 if (bus_type_is_container(type) > 0) {
5713 r = sd_bus_message_enter_container(source, type, contents);
5717 r = sd_bus_message_open_container(m, type, contents);
5721 r = sd_bus_message_copy(m, source, true);
5725 r = sd_bus_message_close_container(m);
5729 r = sd_bus_message_exit_container(source);
5736 r = sd_bus_message_read_basic(source, type, &basic);
5742 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5743 type == SD_BUS_TYPE_SIGNATURE ||
5744 type == SD_BUS_TYPE_STRING)
5745 r = sd_bus_message_append_basic(m, type, basic.string);
5747 r = sd_bus_message_append_basic(m, type, &basic);
5754 return done_something;
5757 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5762 assert_return(m, -EINVAL);
5763 assert_return(m->sealed, -EPERM);
5764 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5765 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5766 assert_return(type || contents, -EINVAL);
5767 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5769 r = sd_bus_message_peek_type(m, &t, &c);
5773 if (type != 0 && type != t)
5776 if (contents && !streq_ptr(contents, c))
5782 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5783 assert_return(m, NULL);
5788 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5789 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5797 switch ((*m)->header->type) {
5799 case SD_BUS_MESSAGE_SIGNAL:
5800 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5806 case SD_BUS_MESSAGE_METHOD_CALL:
5807 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5813 case SD_BUS_MESSAGE_METHOD_RETURN:
5814 case SD_BUS_MESSAGE_METHOD_ERROR:
5816 n = message_new(bus, (*m)->header->type);
5820 n->reply_cookie = (*m)->reply_cookie;
5821 r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie);
5825 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5826 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5830 n->error._need_free = -1;
5839 if ((*m)->destination && !n->destination) {
5840 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5845 if ((*m)->sender && !n->sender) {
5846 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5851 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5853 r = sd_bus_message_copy(n, *m, true);
5857 timeout = (*m)->timeout;
5858 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5859 timeout = BUS_DEFAULT_TIMEOUT;
5861 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5865 sd_bus_message_unref(*m);
5872 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5876 assert_return(!m->sealed, -EPERM);
5877 assert_return(!m->sender, -EPERM);
5879 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5882 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5883 assert_return(m, -EINVAL);
5884 assert_return(priority, -EINVAL);
5886 *priority = m->priority;
5890 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5891 assert_return(m, -EINVAL);
5892 assert_return(!m->sealed, -EPERM);
5894 m->priority = priority;