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 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
419 if (BUS_MESSAGE_IS_GVARIANT(m))
420 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
422 /* 64bit cookies are not supported on dbus1 */
423 if (cookie > 0xffffffffUL)
426 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
430 int bus_message_from_header(
433 size_t header_accessible,
435 size_t footer_accessible,
439 const struct ucred *ucred,
442 sd_bus_message **ret) {
445 struct bus_header *h;
449 assert(header || header_accessible <= 0);
450 assert(footer || footer_accessible <= 0);
451 assert(fds || n_fds <= 0);
454 if (header_accessible < sizeof(struct bus_header))
457 if (header_accessible > message_size)
459 if (footer_accessible > message_size)
463 if (h->version != 1 &&
467 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
470 if (h->endian != BUS_LITTLE_ENDIAN &&
471 h->endian != BUS_BIG_ENDIAN)
474 /* Note that we are happy with unknown flags in the flags header! */
476 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
479 label_sz = strlen(label);
490 m->header_accessible = header_accessible;
492 m->footer_accessible = footer_accessible;
494 if (BUS_MESSAGE_IS_GVARIANT(m)) {
497 if (h->dbus2.cookie == 0)
500 /* dbus2 derives the sizes from the message size and
501 the offset table at the end, since it is formatted as
502 gvariant "yyyyuta{tv}v". Since the message itself is a
503 structure with precisely to variable sized entries,
504 there's only one offset in the table, which marks the
505 end of the fields array. */
507 ws = bus_gvariant_determine_word_size(message_size, 0);
508 if (footer_accessible < ws)
511 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
512 if (ALIGN8(m->fields_size) > message_size - ws)
514 if (m->fields_size < sizeof(struct bus_header))
517 m->fields_size -= sizeof(struct bus_header);
518 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
520 if (h->dbus1.serial == 0)
523 /* dbus1 has the sizes in the header */
524 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
525 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
527 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
535 m->creds.pid = ucred->pid;
536 m->creds.euid = ucred->uid;
537 m->creds.egid = ucred->gid;
539 /* Due to namespace translations some data might be
540 * missing from this ucred record. */
541 if (m->creds.pid > 0)
542 m->creds.mask |= SD_BUS_CREDS_PID;
544 if (m->creds.euid != UID_INVALID)
545 m->creds.mask |= SD_BUS_CREDS_EUID;
547 if (m->creds.egid != GID_INVALID)
548 m->creds.mask |= SD_BUS_CREDS_EGID;
552 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
553 memcpy(m->creds.label, label, label_sz + 1);
555 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
558 m->bus = sd_bus_ref(bus);
564 int bus_message_from_malloc(
570 const struct ucred *ucred,
572 sd_bus_message **ret) {
578 r = bus_message_from_header(
580 buffer, length, /* in this case the initial bytes and the final bytes are the same */
589 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
592 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
594 m->body.sealed = true;
599 m->iovec = m->iovec_fixed;
600 m->iovec[0].iov_base = buffer;
601 m->iovec[0].iov_len = length;
603 r = bus_message_parse_fields(m);
607 /* We take possession of the memory and fds now */
608 m->free_header = true;
619 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
624 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
629 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
630 m->header->endian = BUS_NATIVE_ENDIAN;
631 m->header->type = type;
632 m->header->version = bus ? bus->message_version : 1;
633 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
634 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
635 m->bus = sd_bus_ref(bus);
637 if (bus->allow_interactive_authorization)
638 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
643 _public_ int sd_bus_message_new_signal(
647 const char *interface,
648 const char *member) {
653 assert_return(bus, -ENOTCONN);
654 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
655 assert_return(object_path_is_valid(path), -EINVAL);
656 assert_return(interface_name_is_valid(interface), -EINVAL);
657 assert_return(member_name_is_valid(member), -EINVAL);
658 assert_return(m, -EINVAL);
660 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
664 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
666 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
669 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
672 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
680 sd_bus_message_unref(t);
684 _public_ int sd_bus_message_new_method_call(
687 const char *destination,
689 const char *interface,
690 const char *member) {
695 assert_return(bus, -ENOTCONN);
696 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
697 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
698 assert_return(object_path_is_valid(path), -EINVAL);
699 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
700 assert_return(member_name_is_valid(member), -EINVAL);
701 assert_return(m, -EINVAL);
703 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
707 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
710 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
715 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
721 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
734 static int message_new_reply(
735 sd_bus_message *call,
737 sd_bus_message **m) {
742 assert_return(call, -EINVAL);
743 assert_return(call->sealed, -EPERM);
744 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
745 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
746 assert_return(m, -EINVAL);
748 t = message_new(call->bus, type);
752 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
753 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
754 if (t->reply_cookie == 0)
757 r = message_append_reply_cookie(t, t->reply_cookie);
762 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
767 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
768 t->enforced_reply_signature = call->enforced_reply_signature;
778 _public_ int sd_bus_message_new_method_return(
779 sd_bus_message *call,
780 sd_bus_message **m) {
782 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
785 _public_ int sd_bus_message_new_method_error(
786 sd_bus_message *call,
788 const sd_bus_error *e) {
793 assert_return(sd_bus_error_is_set(e), -EINVAL);
794 assert_return(m, -EINVAL);
796 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
800 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
805 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
810 t->error._need_free = -1;
820 _public_ int sd_bus_message_new_method_errorf(
821 sd_bus_message *call,
827 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
830 assert_return(name, -EINVAL);
831 assert_return(m, -EINVAL);
833 va_start(ap, format);
834 bus_error_setfv(&error, name, format, ap);
837 return sd_bus_message_new_method_error(call, m, &error);
840 _public_ int sd_bus_message_new_method_errno(
841 sd_bus_message *call,
844 const sd_bus_error *p) {
846 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
848 if (sd_bus_error_is_set(p))
849 return sd_bus_message_new_method_error(call, m, p);
851 sd_bus_error_set_errno(&berror, error);
853 return sd_bus_message_new_method_error(call, m, &berror);
856 _public_ int sd_bus_message_new_method_errnof(
857 sd_bus_message *call,
863 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
866 va_start(ap, format);
867 sd_bus_error_set_errnofv(&berror, error, format, ap);
870 return sd_bus_message_new_method_error(call, m, &berror);
873 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
877 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
878 m->creds.well_known_names_local = true;
879 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
882 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
886 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
887 m->creds.well_known_names_driver = true;
888 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
891 int bus_message_new_synthetic_error(
894 const sd_bus_error *e,
895 sd_bus_message **m) {
901 assert(sd_bus_error_is_set(e));
904 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
908 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
909 t->reply_cookie = cookie;
911 r = message_append_reply_cookie(t, t->reply_cookie);
915 if (bus && bus->unique_name) {
916 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
921 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
926 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
931 t->error._need_free = -1;
933 bus_message_set_sender_driver(bus, t);
943 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
944 assert_return(m, NULL);
946 assert(m->n_ref > 0);
952 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
957 assert(m->n_ref > 0);
967 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
968 assert_return(m, -EINVAL);
969 assert_return(type, -EINVAL);
971 *type = m->header->type;
975 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
978 assert_return(m, -EINVAL);
979 assert_return(cookie, -EINVAL);
981 c = BUS_MESSAGE_COOKIE(m);
985 *cookie = BUS_MESSAGE_COOKIE(m);
989 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
990 assert_return(m, -EINVAL);
991 assert_return(cookie, -EINVAL);
993 if (m->reply_cookie == 0)
996 *cookie = m->reply_cookie;
1000 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
1001 assert_return(m, -EINVAL);
1003 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
1004 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
1007 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
1008 assert_return(m, -EINVAL);
1010 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
1013 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
1014 assert_return(m, -EINVAL);
1016 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
1017 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
1020 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1021 assert_return(m, NULL);
1026 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1027 assert_return(m, NULL);
1029 return m->interface;
1032 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1033 assert_return(m, NULL);
1038 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1039 assert_return(m, NULL);
1041 return m->destination;
1044 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1045 assert_return(m, NULL);
1050 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1051 assert_return(m, NULL);
1052 assert_return(sd_bus_error_is_set(&m->error), NULL);
1057 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1058 assert_return(m, -EINVAL);
1059 assert_return(usec, -EINVAL);
1061 if (m->monotonic <= 0)
1064 *usec = m->monotonic;
1068 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1069 assert_return(m, -EINVAL);
1070 assert_return(usec, -EINVAL);
1072 if (m->realtime <= 0)
1075 *usec = m->realtime;
1079 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1080 assert_return(m, -EINVAL);
1081 assert_return(seqnum, -EINVAL);
1086 *seqnum = m->seqnum;
1090 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1091 assert_return(m, NULL);
1093 if (m->creds.mask == 0)
1099 _public_ int sd_bus_message_is_signal(
1101 const char *interface,
1102 const char *member) {
1104 assert_return(m, -EINVAL);
1106 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1109 if (interface && (!m->interface || !streq(m->interface, interface)))
1112 if (member && (!m->member || !streq(m->member, member)))
1118 _public_ int sd_bus_message_is_method_call(
1120 const char *interface,
1121 const char *member) {
1123 assert_return(m, -EINVAL);
1125 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1128 if (interface && (!m->interface || !streq(m->interface, interface)))
1131 if (member && (!m->member || !streq(m->member, member)))
1137 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1138 assert_return(m, -EINVAL);
1140 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1143 if (name && (!m->error.name || !streq(m->error.name, name)))
1149 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1150 assert_return(m, -EINVAL);
1151 assert_return(!m->sealed, -EPERM);
1152 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1155 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1157 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1162 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1163 assert_return(m, -EINVAL);
1164 assert_return(!m->sealed, -EPERM);
1167 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1169 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1174 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1175 assert_return(m, -EINVAL);
1176 assert_return(!m->sealed, -EPERM);
1179 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1181 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1186 static struct bus_container *message_get_container(sd_bus_message *m) {
1189 if (m->n_containers == 0)
1190 return &m->root_container;
1192 assert(m->containers);
1193 return m->containers + m->n_containers - 1;
1196 struct bus_body_part *message_append_part(sd_bus_message *m) {
1197 struct bus_body_part *part;
1204 if (m->n_body_parts <= 0) {
1208 assert(m->body_end);
1210 part = new0(struct bus_body_part, 1);
1216 m->body_end->next = part;
1226 static void part_zero(struct bus_body_part *part, size_t sz) {
1231 /* All other fields can be left in their defaults */
1232 assert(!part->data);
1233 assert(part->memfd < 0);
1236 part->is_zero = true;
1237 part->sealed = true;
1240 static int part_make_space(
1241 struct sd_bus_message *m,
1242 struct bus_body_part *part,
1251 assert(!part->sealed);
1256 if (!part->data && part->memfd < 0) {
1257 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1258 part->mmap_begin = part->data;
1261 if (part->memfd >= 0) {
1263 if (part->allocated == 0 || sz > part->allocated) {
1264 uint64_t new_allocated;
1266 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1267 r = memfd_set_size(part->memfd, new_allocated);
1273 part->allocated = new_allocated;
1276 if (!part->data || sz > part->mapped) {
1279 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1280 if (part->mapped <= 0)
1281 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1283 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1285 if (n == MAP_FAILED) {
1290 part->mmap_begin = part->data = n;
1292 part->memfd_offset = 0;
1295 part->munmap_this = true;
1297 if (part->allocated == 0 || sz > part->allocated) {
1298 size_t new_allocated;
1300 new_allocated = sz > 0 ? 2 * sz : 64;
1301 n = realloc(part->data, new_allocated);
1308 part->allocated = new_allocated;
1309 part->free_this = true;
1314 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1320 static int message_add_offset(sd_bus_message *m, size_t offset) {
1321 struct bus_container *c;
1324 assert(BUS_MESSAGE_IS_GVARIANT(m));
1326 /* Add offset to current container, unless this is the first
1327 * item in it, which will have the 0 offset, which we can
1329 c = message_get_container(m);
1331 if (!c->need_offsets)
1334 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1337 c->offsets[c->n_offsets++] = offset;
1341 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1342 struct bus_container *c;
1349 /* Update counters */
1350 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1353 *c->array_size += expand;
1357 static void *message_extend_body(
1362 bool force_inline) {
1364 size_t start_body, end_body, padding, added;
1375 start_body = ALIGN_TO((size_t) m->body_size, align);
1376 end_body = start_body + sz;
1378 padding = start_body - m->body_size;
1379 added = padding + sz;
1381 /* Check for 32bit overflows */
1382 if (end_body > (size_t) ((uint32_t) -1) ||
1383 end_body < start_body) {
1389 struct bus_body_part *part = NULL;
1393 m->n_body_parts <= 0 ||
1394 m->body_end->sealed ||
1395 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1396 (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 */
1400 part = message_append_part(m);
1404 part_zero(part, padding);
1407 part = message_append_part(m);
1411 r = part_make_space(m, part, sz, &p);
1415 struct bus_container *c;
1417 size_t os, start_part, end_part;
1423 start_part = ALIGN_TO(part->size, align);
1424 end_part = start_part + sz;
1426 r = part_make_space(m, part, end_part, &p);
1431 memzero(p, padding);
1432 p = (uint8_t*) p + padding;
1435 /* Readjust pointers */
1436 for (c = m->containers; c < m->containers + m->n_containers; c++)
1437 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1439 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1442 /* Return something that is not NULL and is aligned */
1443 p = (uint8_t *) NULL + align;
1445 m->body_size = end_body;
1446 message_extend_containers(m, added);
1449 r = message_add_offset(m, end_body);
1459 static int message_push_fd(sd_bus_message *m, int fd) {
1470 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1474 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1482 m->fds[m->n_fds] = copy;
1488 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1489 _cleanup_close_ int fd = -1;
1490 struct bus_container *c;
1494 assert_return(m, -EINVAL);
1495 assert_return(!m->sealed, -EPERM);
1496 assert_return(bus_type_is_basic(type), -EINVAL);
1497 assert_return(!m->poisoned, -ESTALE);
1499 c = message_get_container(m);
1501 if (c->signature && c->signature[c->index]) {
1502 /* Container signature is already set */
1504 if (c->signature[c->index] != type)
1509 /* Maybe we can append to the signature? But only if this is the top-level container */
1510 if (c->enclosing != 0)
1513 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1520 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1526 case SD_BUS_TYPE_SIGNATURE:
1527 case SD_BUS_TYPE_STRING:
1530 /* Fall through... */
1531 case SD_BUS_TYPE_OBJECT_PATH:
1539 case SD_BUS_TYPE_BOOLEAN:
1541 u8 = p && *(int*) p;
1547 case SD_BUS_TYPE_UNIX_FD:
1552 fd = message_push_fd(m, *(int*) p);
1563 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1564 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1571 a = message_extend_body(m, align, sz, true, false);
1578 *stored = (const uint8_t*) a;
1585 case SD_BUS_TYPE_STRING:
1586 /* To make things easy we'll serialize a NULL string
1587 * into the empty string */
1590 /* Fall through... */
1591 case SD_BUS_TYPE_OBJECT_PATH:
1597 sz = 4 + strlen(p) + 1;
1600 case SD_BUS_TYPE_SIGNATURE:
1605 sz = 1 + strlen(p) + 1;
1608 case SD_BUS_TYPE_BOOLEAN:
1610 u32 = p && *(int*) p;
1616 case SD_BUS_TYPE_UNIX_FD:
1621 fd = message_push_fd(m, *(int*) p);
1632 align = bus_type_get_alignment(type);
1633 sz = bus_type_get_size(type);
1640 a = message_extend_body(m, align, sz, false, false);
1644 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1645 *(uint32_t*) a = sz - 5;
1646 memcpy((uint8_t*) a + 4, p, sz - 4);
1649 *stored = (const uint8_t*) a + 4;
1651 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1652 *(uint8_t*) a = sz - 2;
1653 memcpy((uint8_t*) a + 1, p, sz - 1);
1656 *stored = (const uint8_t*) a + 1;
1665 if (type == SD_BUS_TYPE_UNIX_FD)
1668 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1675 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1676 return message_append_basic(m, type, p, NULL);
1679 _public_ int sd_bus_message_append_string_space(
1684 struct bus_container *c;
1687 assert_return(m, -EINVAL);
1688 assert_return(s, -EINVAL);
1689 assert_return(!m->sealed, -EPERM);
1690 assert_return(!m->poisoned, -ESTALE);
1692 c = message_get_container(m);
1694 if (c->signature && c->signature[c->index]) {
1695 /* Container signature is already set */
1697 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1702 /* Maybe we can append to the signature? But only if this is the top-level container */
1703 if (c->enclosing != 0)
1706 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1713 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1714 a = message_extend_body(m, 1, size + 1, true, false);
1720 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1724 *(uint32_t*) a = size;
1730 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1736 _public_ int sd_bus_message_append_string_iovec(
1738 const struct iovec *iov,
1746 assert_return(m, -EINVAL);
1747 assert_return(!m->sealed, -EPERM);
1748 assert_return(iov || n == 0, -EINVAL);
1749 assert_return(!m->poisoned, -ESTALE);
1751 size = IOVEC_TOTAL_SIZE(iov, n);
1753 r = sd_bus_message_append_string_space(m, size, &p);
1757 for (i = 0; i < n; i++) {
1759 if (iov[i].iov_base)
1760 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1762 memset(p, ' ', iov[i].iov_len);
1764 p += iov[i].iov_len;
1770 static int bus_message_open_array(
1772 struct bus_container *c,
1773 const char *contents,
1774 uint32_t **array_size,
1776 bool *need_offsets) {
1786 assert(need_offsets);
1788 if (!signature_is_single(contents, true))
1791 if (c->signature && c->signature[c->index]) {
1793 /* Verify the existing signature */
1795 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1798 if (!startswith(c->signature + c->index + 1, contents))
1801 nindex = c->index + 1 + strlen(contents);
1805 if (c->enclosing != 0)
1808 /* Extend the existing signature */
1810 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1816 nindex = e - c->signature;
1819 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1820 alignment = bus_gvariant_get_alignment(contents);
1824 /* Add alignment padding and add to offset list */
1825 if (!message_extend_body(m, alignment, 0, false, false))
1828 r = bus_gvariant_is_fixed_size(contents);
1832 *begin = m->body_size;
1833 *need_offsets = r == 0;
1837 struct bus_body_part *o;
1839 alignment = bus_type_get_alignment(contents[0]);
1843 a = message_extend_body(m, 4, 4, false, false);
1848 op = m->body_end->data;
1849 os = m->body_end->size;
1851 /* Add alignment between size and first element */
1852 if (!message_extend_body(m, alignment, 0, false, false))
1855 /* location of array size might have changed so let's readjust a */
1856 if (o == m->body_end)
1857 a = adjust_pointer(a, op, os, m->body_end->data);
1863 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1869 static int bus_message_open_variant(
1871 struct bus_container *c,
1872 const char *contents) {
1878 if (!signature_is_single(contents, false))
1881 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1884 if (c->signature && c->signature[c->index]) {
1886 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1892 if (c->enclosing != 0)
1895 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1902 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1903 /* Variants are always aligned to 8 */
1905 if (!message_extend_body(m, 8, 0, false, false))
1912 l = strlen(contents);
1913 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1918 memcpy((uint8_t*) a + 1, contents, l + 1);
1921 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1927 static int bus_message_open_struct(
1929 struct bus_container *c,
1930 const char *contents,
1932 bool *need_offsets) {
1941 assert(need_offsets);
1943 if (!signature_is_valid(contents, false))
1946 if (c->signature && c->signature[c->index]) {
1949 l = strlen(contents);
1951 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1952 !startswith(c->signature + c->index + 1, contents) ||
1953 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1956 nindex = c->index + 1 + l + 1;
1960 if (c->enclosing != 0)
1963 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1969 nindex = e - c->signature;
1972 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1975 alignment = bus_gvariant_get_alignment(contents);
1979 if (!message_extend_body(m, alignment, 0, false, false))
1982 r = bus_gvariant_is_fixed_size(contents);
1986 *begin = m->body_size;
1987 *need_offsets = r == 0;
1989 /* Align contents to 8 byte boundary */
1990 if (!message_extend_body(m, 8, 0, false, false))
1994 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2000 static int bus_message_open_dict_entry(
2002 struct bus_container *c,
2003 const char *contents,
2005 bool *need_offsets) {
2013 assert(need_offsets);
2015 if (!signature_is_pair(contents))
2018 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2021 if (c->signature && c->signature[c->index]) {
2024 l = strlen(contents);
2026 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2027 !startswith(c->signature + c->index + 1, contents) ||
2028 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2033 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2036 alignment = bus_gvariant_get_alignment(contents);
2040 if (!message_extend_body(m, alignment, 0, false, false))
2043 r = bus_gvariant_is_fixed_size(contents);
2047 *begin = m->body_size;
2048 *need_offsets = r == 0;
2050 /* Align contents to 8 byte boundary */
2051 if (!message_extend_body(m, 8, 0, false, false))
2058 _public_ int sd_bus_message_open_container(
2061 const char *contents) {
2063 struct bus_container *c, *w;
2064 uint32_t *array_size = NULL;
2066 size_t before, begin = 0;
2067 bool need_offsets = false;
2070 assert_return(m, -EINVAL);
2071 assert_return(!m->sealed, -EPERM);
2072 assert_return(contents, -EINVAL);
2073 assert_return(!m->poisoned, -ESTALE);
2075 /* Make sure we have space for one more container */
2076 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2081 c = message_get_container(m);
2083 signature = strdup(contents);
2089 /* Save old index in the parent container, in case we have to
2090 * abort this container */
2091 c->saved_index = c->index;
2092 before = m->body_size;
2094 if (type == SD_BUS_TYPE_ARRAY)
2095 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2096 else if (type == SD_BUS_TYPE_VARIANT)
2097 r = bus_message_open_variant(m, c, contents);
2098 else if (type == SD_BUS_TYPE_STRUCT)
2099 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2100 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2101 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2110 /* OK, let's fill it in */
2111 w = m->containers + m->n_containers++;
2112 w->enclosing = type;
2113 w->signature = signature;
2115 w->array_size = array_size;
2118 w->n_offsets = w->offsets_allocated = 0;
2120 w->need_offsets = need_offsets;
2125 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2130 if (!BUS_MESSAGE_IS_GVARIANT(m))
2133 if (c->need_offsets) {
2134 size_t payload, sz, i;
2137 /* Variable-width arrays */
2139 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2140 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2142 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2146 for (i = 0; i < c->n_offsets; i++)
2147 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2151 /* Fixed-width or empty arrays */
2153 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2161 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2167 assert(c->signature);
2169 if (!BUS_MESSAGE_IS_GVARIANT(m))
2172 l = strlen(c->signature);
2174 a = message_extend_body(m, 1, 1 + l, true, false);
2179 memcpy(a+1, c->signature, l);
2184 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2185 size_t n_variable = 0;
2194 if (!BUS_MESSAGE_IS_GVARIANT(m))
2197 p = strempty(c->signature);
2201 r = signature_element_length(p, &n);
2210 r = bus_gvariant_is_fixed_size(t);
2215 assert(!c->need_offsets || i <= c->n_offsets);
2217 /* We need to add an offset for each item that has a
2218 * variable size and that is not the last one in the
2220 if (r == 0 && p[n] != 0)
2227 assert(!c->need_offsets || i == c->n_offsets);
2228 assert(c->need_offsets || n_variable == 0);
2230 if (n_variable <= 0) {
2231 a = message_extend_body(m, 1, 0, add_offset, false);
2238 assert(c->offsets[c->n_offsets-1] == m->body_size);
2240 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2242 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2246 p = strempty(c->signature);
2247 for (i = 0, j = 0; i < c->n_offsets; i++) {
2251 r = signature_element_length(p, &n);
2262 r = bus_gvariant_is_fixed_size(t);
2265 if (r > 0 || p[0] == 0)
2269 k = n_variable - 1 - j;
2271 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2280 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2281 struct bus_container *c;
2284 assert_return(m, -EINVAL);
2285 assert_return(!m->sealed, -EPERM);
2286 assert_return(m->n_containers > 0, -EINVAL);
2287 assert_return(!m->poisoned, -ESTALE);
2289 c = message_get_container(m);
2291 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2292 if (c->signature && c->signature[c->index] != 0)
2297 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2298 r = bus_message_close_array(m, c);
2299 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2300 r = bus_message_close_variant(m, c);
2301 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2302 r = bus_message_close_struct(m, c, true);
2304 assert_not_reached("Unknown container type");
2318 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2325 stack[*i].types = types;
2326 stack[*i].n_struct = n_struct;
2327 stack[*i].n_array = n_array;
2333 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2344 *types = stack[*i].types;
2345 *n_struct = stack[*i].n_struct;
2346 *n_array = stack[*i].n_array;
2351 int bus_message_append_ap(
2356 unsigned n_array, n_struct;
2357 TypeStack stack[BUS_CONTAINER_DEPTH];
2358 unsigned stack_ptr = 0;
2366 n_array = (unsigned) -1;
2367 n_struct = strlen(types);
2372 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2373 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2379 r = sd_bus_message_close_container(m);
2387 if (n_array != (unsigned) -1)
2396 case SD_BUS_TYPE_BYTE: {
2399 x = (uint8_t) va_arg(ap, int);
2400 r = sd_bus_message_append_basic(m, *t, &x);
2404 case SD_BUS_TYPE_BOOLEAN:
2405 case SD_BUS_TYPE_INT32:
2406 case SD_BUS_TYPE_UINT32:
2407 case SD_BUS_TYPE_UNIX_FD: {
2410 /* We assume a boolean is the same as int32_t */
2411 assert_cc(sizeof(int32_t) == sizeof(int));
2413 x = va_arg(ap, uint32_t);
2414 r = sd_bus_message_append_basic(m, *t, &x);
2418 case SD_BUS_TYPE_INT16:
2419 case SD_BUS_TYPE_UINT16: {
2422 x = (uint16_t) va_arg(ap, int);
2423 r = sd_bus_message_append_basic(m, *t, &x);
2427 case SD_BUS_TYPE_INT64:
2428 case SD_BUS_TYPE_UINT64: {
2431 x = va_arg(ap, uint64_t);
2432 r = sd_bus_message_append_basic(m, *t, &x);
2436 case SD_BUS_TYPE_DOUBLE: {
2439 x = va_arg(ap, double);
2440 r = sd_bus_message_append_basic(m, *t, &x);
2444 case SD_BUS_TYPE_STRING:
2445 case SD_BUS_TYPE_OBJECT_PATH:
2446 case SD_BUS_TYPE_SIGNATURE: {
2449 x = va_arg(ap, const char*);
2450 r = sd_bus_message_append_basic(m, *t, x);
2454 case SD_BUS_TYPE_ARRAY: {
2457 r = signature_element_length(t + 1, &k);
2463 memcpy(s, t + 1, k);
2466 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2471 if (n_array == (unsigned) -1) {
2476 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2482 n_array = va_arg(ap, unsigned);
2487 case SD_BUS_TYPE_VARIANT: {
2490 s = va_arg(ap, const char*);
2494 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2498 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2503 n_struct = strlen(s);
2504 n_array = (unsigned) -1;
2509 case SD_BUS_TYPE_STRUCT_BEGIN:
2510 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2513 r = signature_element_length(t, &k);
2520 memcpy(s, t + 1, k - 2);
2523 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2528 if (n_array == (unsigned) -1) {
2533 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2539 n_array = (unsigned) -1;
2555 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2559 assert_return(m, -EINVAL);
2560 assert_return(types, -EINVAL);
2561 assert_return(!m->sealed, -EPERM);
2562 assert_return(!m->poisoned, -ESTALE);
2564 va_start(ap, types);
2565 r = bus_message_append_ap(m, types, ap);
2571 _public_ int sd_bus_message_append_array_space(
2581 assert_return(m, -EINVAL);
2582 assert_return(!m->sealed, -EPERM);
2583 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2584 assert_return(ptr || size == 0, -EINVAL);
2585 assert_return(!m->poisoned, -ESTALE);
2587 /* alignment and size of the trivial types (except bool) is
2588 * identical for gvariant and dbus1 marshalling */
2589 align = bus_type_get_alignment(type);
2590 sz = bus_type_get_size(type);
2592 assert_se(align > 0);
2598 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2602 a = message_extend_body(m, align, size, false, false);
2606 r = sd_bus_message_close_container(m);
2614 _public_ int sd_bus_message_append_array(
2622 assert_return(m, -EINVAL);
2623 assert_return(!m->sealed, -EPERM);
2624 assert_return(bus_type_is_trivial(type), -EINVAL);
2625 assert_return(ptr || size == 0, -EINVAL);
2626 assert_return(!m->poisoned, -ESTALE);
2628 r = sd_bus_message_append_array_space(m, type, size, &p);
2633 memcpy(p, ptr, size);
2638 _public_ int sd_bus_message_append_array_iovec(
2641 const struct iovec *iov,
2649 assert_return(m, -EINVAL);
2650 assert_return(!m->sealed, -EPERM);
2651 assert_return(bus_type_is_trivial(type), -EINVAL);
2652 assert_return(iov || n == 0, -EINVAL);
2653 assert_return(!m->poisoned, -ESTALE);
2655 size = IOVEC_TOTAL_SIZE(iov, n);
2657 r = sd_bus_message_append_array_space(m, type, size, &p);
2661 for (i = 0; i < n; i++) {
2663 if (iov[i].iov_base)
2664 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2666 memzero(p, iov[i].iov_len);
2668 p = (uint8_t*) p + iov[i].iov_len;
2674 _public_ int sd_bus_message_append_array_memfd(
2681 _cleanup_close_ int copy_fd = -1;
2682 struct bus_body_part *part;
2688 assert_return(m, -EINVAL);
2689 assert_return(memfd >= 0, -EINVAL);
2690 assert_return(bus_type_is_trivial(type), -EINVAL);
2691 assert_return(size > 0, -EINVAL);
2692 assert_return(!m->sealed, -EPERM);
2693 assert_return(!m->poisoned, -ESTALE);
2695 r = memfd_set_sealed(memfd);
2699 copy_fd = dup(memfd);
2703 r = memfd_get_size(memfd, &real_size);
2707 if (offset == 0 && size == (uint64_t) -1)
2709 else if (offset + size > real_size)
2712 align = bus_type_get_alignment(type);
2713 sz = bus_type_get_size(type);
2715 assert_se(align > 0);
2718 if (offset % align != 0)
2724 if (size > (uint64_t) (uint32_t) -1)
2727 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2731 a = message_extend_body(m, align, 0, false, false);
2735 part = message_append_part(m);
2739 part->memfd = copy_fd;
2740 part->memfd_offset = offset;
2741 part->sealed = true;
2745 m->body_size += size;
2746 message_extend_containers(m, size);
2748 return sd_bus_message_close_container(m);
2751 _public_ int sd_bus_message_append_string_memfd(
2757 _cleanup_close_ int copy_fd = -1;
2758 struct bus_body_part *part;
2759 struct bus_container *c;
2764 assert_return(m, -EINVAL);
2765 assert_return(memfd >= 0, -EINVAL);
2766 assert_return(size > 0, -EINVAL);
2767 assert_return(!m->sealed, -EPERM);
2768 assert_return(!m->poisoned, -ESTALE);
2770 r = memfd_set_sealed(memfd);
2774 copy_fd = dup(memfd);
2778 r = memfd_get_size(memfd, &real_size);
2782 if (offset == 0 && size == (uint64_t) -1)
2784 else if (offset + size > real_size)
2787 /* We require this to be NUL terminated */
2791 if (size > (uint64_t) (uint32_t) -1)
2794 c = message_get_container(m);
2795 if (c->signature && c->signature[c->index]) {
2796 /* Container signature is already set */
2798 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2803 /* Maybe we can append to the signature? But only if this is the top-level container */
2804 if (c->enclosing != 0)
2807 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2814 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2815 a = message_extend_body(m, 4, 4, false, false);
2819 *(uint32_t*) a = size - 1;
2822 part = message_append_part(m);
2826 part->memfd = copy_fd;
2827 part->memfd_offset = offset;
2828 part->sealed = true;
2832 m->body_size += size;
2833 message_extend_containers(m, size);
2835 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2836 r = message_add_offset(m, m->body_size);
2843 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2849 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2853 assert_return(m, -EINVAL);
2854 assert_return(!m->sealed, -EPERM);
2855 assert_return(!m->poisoned, -ESTALE);
2857 r = sd_bus_message_open_container(m, 'a', "s");
2861 STRV_FOREACH(i, l) {
2862 r = sd_bus_message_append_basic(m, 's', *i);
2867 return sd_bus_message_close_container(m);
2870 static int bus_message_close_header(sd_bus_message *m) {
2874 /* The actual user data is finished now, we just complete the
2875 variant and struct now (at least on gvariant). Remember
2876 this position, so that during parsing we know where to to
2877 put the outer container end. */
2878 m->user_body_size = m->body_size;
2880 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2881 const char *signature;
2885 /* Add offset table to end of fields array */
2886 if (m->n_header_offsets >= 1) {
2890 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2892 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2893 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2897 for (i = 0; i < m->n_header_offsets; i++)
2898 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2901 /* Add gvariant NUL byte plus signature to the end of
2902 * the body, followed by the final offset pointing to
2903 * the end of the fields array */
2905 signature = strempty(m->root_container.signature);
2906 l = strlen(signature);
2908 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l, 1);
2909 d = message_extend_body(m, 1, 1 + l + sz, false, true);
2914 memcpy((uint8_t*) d + 1, signature, l);
2916 bus_gvariant_write_word_le((uint8_t*) d + 1 + l, sz, sizeof(struct bus_header) + m->fields_size);
2919 m->footer_accessible = 1 + l + sz;
2921 m->header->dbus1.fields_size = m->fields_size;
2922 m->header->dbus1.body_size = m->body_size;
2928 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2929 struct bus_body_part *part;
2939 if (m->n_containers > 0)
2945 if (cookie > 0xffffffffULL &&
2946 !BUS_MESSAGE_IS_GVARIANT(m))
2949 /* In vtables the return signature of method calls is listed,
2950 * let's check if they match if this is a response */
2951 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2952 m->enforced_reply_signature &&
2953 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2956 /* If gvariant marshalling is used we need to close the body structure */
2957 r = bus_message_close_struct(m, &m->root_container, false);
2961 /* If there's a non-trivial signature set, then add it in
2962 * here, but only on dbus1 */
2963 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2964 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2970 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2975 r = bus_message_close_header(m);
2979 if (BUS_MESSAGE_IS_GVARIANT(m))
2980 m->header->dbus2.cookie = cookie;
2982 m->header->dbus1.serial = (uint32_t) cookie;
2984 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2986 /* Add padding at the end of the fields part, since we know
2987 * the body needs to start at an 8 byte alignment. We made
2988 * sure we allocated enough space for this, so all we need to
2989 * do here is to zero it out. */
2990 a = ALIGN8(m->fields_size) - m->fields_size;
2992 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2994 /* If this is something we can send as memfd, then let's seal
2995 the memfd now. Note that we can send memfds as payload only
2996 for directed messages, and not for broadcasts. */
2997 if (m->destination && m->bus->use_memfd) {
2998 MESSAGE_FOREACH_PART(part, i, m)
2999 if (part->memfd >= 0 &&
3001 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3002 part != m->body_end) { /* The last part may never be sent as memfd */
3005 /* Try to seal it if that makes
3006 * sense. First, unmap our own map to
3007 * make sure we don't keep it busy. */
3008 bus_body_part_unmap(part);
3010 /* Then, sync up real memfd size */
3012 r = memfd_set_size(part->memfd, sz);
3016 /* Finally, try to seal */
3017 if (memfd_set_sealed(part->memfd) >= 0)
3018 part->sealed = true;
3022 m->root_container.end = m->user_body_size;
3023 m->root_container.index = 0;
3024 m->root_container.offset_index = 0;
3025 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3032 int bus_body_part_map(struct bus_body_part *part) {
3041 if (part->size <= 0)
3044 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3045 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3046 static const uint8_t zeroes[7] = { };
3047 part->data = (void*) zeroes;
3051 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3052 psz = PAGE_ALIGN(part->size + shift);
3054 if (part->memfd >= 0)
3055 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3056 else if (part->is_zero)
3057 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3061 if (p == MAP_FAILED)
3065 part->mmap_begin = p;
3066 part->data = (uint8_t*) p + shift;
3067 part->munmap_this = true;
3072 void bus_body_part_unmap(struct bus_body_part *part) {
3076 if (part->memfd < 0)
3079 if (!part->mmap_begin)
3082 if (!part->munmap_this)
3085 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3087 part->mmap_begin = NULL;
3090 part->munmap_this = false;
3095 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3096 size_t k, start, end;
3101 start = ALIGN_TO((size_t) *rindex, align);
3102 end = start + nbytes;
3107 /* Verify that padding is 0 */
3108 for (k = *rindex; k < start; k++)
3109 if (((const uint8_t*) p)[k] != 0)
3113 *r = (uint8_t*) p + start;
3120 static bool message_end_of_signature(sd_bus_message *m) {
3121 struct bus_container *c;
3125 c = message_get_container(m);
3126 return !c->signature || c->signature[c->index] == 0;
3129 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3130 struct bus_container *c;
3134 c = message_get_container(m);
3135 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3138 if (BUS_MESSAGE_IS_GVARIANT(m))
3139 return index >= c->end;
3141 assert(c->array_size);
3142 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3146 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3147 assert_return(m, -EINVAL);
3148 assert_return(m->sealed, -EPERM);
3150 if (complete && m->n_containers > 0)
3153 if (message_end_of_signature(m))
3156 if (message_end_of_array(m, m->rindex))
3162 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3163 struct bus_body_part *part;
3169 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3170 part = m->cached_rindex_part;
3171 begin = m->cached_rindex_part_begin;
3181 if (index + sz <= begin + part->size) {
3183 r = bus_body_part_map(part);
3188 *p = (uint8_t*) part->data + index - begin;
3190 m->cached_rindex_part = part;
3191 m->cached_rindex_part_begin = begin;
3196 begin += part->size;
3203 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3210 if (!BUS_MESSAGE_IS_GVARIANT(m))
3213 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3216 sz = bus_gvariant_get_size(c->signature);
3220 if (c->offset_index+1 >= c->n_offsets)
3223 /* Variable-size array */
3225 alignment = bus_gvariant_get_alignment(c->signature);
3226 assert(alignment > 0);
3228 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3229 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3232 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3235 /* Fixed-size array */
3236 *rindex = c->begin + (c->offset_index+1) * sz;
3242 } else if (c->enclosing == 0 ||
3243 c->enclosing == SD_BUS_TYPE_STRUCT ||
3244 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3249 if (c->offset_index+1 >= c->n_offsets)
3252 r = signature_element_length(c->signature + c->index, &n);
3256 r = signature_element_length(c->signature + c->index + n, &j);
3261 memcpy(t, c->signature + c->index + n, j);
3264 alignment = bus_gvariant_get_alignment(t);
3267 assert(alignment > 0);
3269 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3270 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3274 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3277 assert_not_reached("Unknown container type");
3282 /* Reached the end */
3289 static int message_peek_body(
3296 size_t k, start, end, padding;
3297 struct bus_body_part *part;
3304 start = ALIGN_TO((size_t) *rindex, align);
3305 padding = start - *rindex;
3306 end = start + nbytes;
3308 if (end > m->user_body_size)
3311 part = find_part(m, *rindex, padding, (void**) &q);
3316 /* Verify padding */
3317 for (k = 0; k < padding; k++)
3322 part = find_part(m, start, nbytes, (void**) &q);
3323 if (!part || (nbytes > 0 && !q))
3334 static bool validate_nul(const char *s, size_t l) {
3336 /* Check for NUL chars in the string */
3337 if (memchr(s, 0, l))
3340 /* Check for NUL termination */
3347 static bool validate_string(const char *s, size_t l) {
3349 if (!validate_nul(s, l))
3352 /* Check if valid UTF8 */
3353 if (!utf8_is_valid(s))
3359 static bool validate_signature(const char *s, size_t l) {
3361 if (!validate_nul(s, l))
3364 /* Check if valid signature */
3365 if (!signature_is_valid(s, true))
3371 static bool validate_object_path(const char *s, size_t l) {
3373 if (!validate_nul(s, l))
3376 if (!object_path_is_valid(s))
3382 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3383 struct bus_container *c;
3388 assert_return(m, -EINVAL);
3389 assert_return(m->sealed, -EPERM);
3390 assert_return(bus_type_is_basic(type), -EINVAL);
3392 if (message_end_of_signature(m))
3395 if (message_end_of_array(m, m->rindex))
3398 c = message_get_container(m);
3399 if (c->signature[c->index] != type)
3404 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3406 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3409 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3413 if (type == SD_BUS_TYPE_STRING)
3414 ok = validate_string(q, c->item_size-1);
3415 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3416 ok = validate_object_path(q, c->item_size-1);
3418 ok = validate_signature(q, c->item_size-1);
3424 *(const char**) p = q;
3428 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3430 if ((size_t) sz != c->item_size)
3433 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3436 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3442 case SD_BUS_TYPE_BYTE:
3444 *(uint8_t*) p = *(uint8_t*) q;
3447 case SD_BUS_TYPE_BOOLEAN:
3449 *(int*) p = !!*(uint8_t*) q;
3452 case SD_BUS_TYPE_INT16:
3453 case SD_BUS_TYPE_UINT16:
3455 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3458 case SD_BUS_TYPE_INT32:
3459 case SD_BUS_TYPE_UINT32:
3461 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3464 case SD_BUS_TYPE_INT64:
3465 case SD_BUS_TYPE_UINT64:
3466 case SD_BUS_TYPE_DOUBLE:
3468 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3471 case SD_BUS_TYPE_UNIX_FD: {
3474 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3479 *(int*) p = m->fds[j];
3485 assert_not_reached("unexpected type");
3489 r = container_next_item(m, c, &rindex);
3496 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3500 r = message_peek_body(m, &rindex, 4, 4, &q);
3504 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3505 r = message_peek_body(m, &rindex, 1, l+1, &q);
3509 if (type == SD_BUS_TYPE_OBJECT_PATH)
3510 ok = validate_object_path(q, l);
3512 ok = validate_string(q, l);
3517 *(const char**) p = q;
3519 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3522 r = message_peek_body(m, &rindex, 1, 1, &q);
3527 r = message_peek_body(m, &rindex, 1, l+1, &q);
3531 if (!validate_signature(q, l))
3535 *(const char**) p = q;
3540 align = bus_type_get_alignment(type);
3543 sz = bus_type_get_size(type);
3546 r = message_peek_body(m, &rindex, align, sz, &q);
3552 case SD_BUS_TYPE_BYTE:
3554 *(uint8_t*) p = *(uint8_t*) q;
3557 case SD_BUS_TYPE_BOOLEAN:
3559 *(int*) p = !!*(uint32_t*) q;
3562 case SD_BUS_TYPE_INT16:
3563 case SD_BUS_TYPE_UINT16:
3565 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3568 case SD_BUS_TYPE_INT32:
3569 case SD_BUS_TYPE_UINT32:
3571 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3574 case SD_BUS_TYPE_INT64:
3575 case SD_BUS_TYPE_UINT64:
3576 case SD_BUS_TYPE_DOUBLE:
3578 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3581 case SD_BUS_TYPE_UNIX_FD: {
3584 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3589 *(int*) p = m->fds[j];
3594 assert_not_reached("Unknown basic type...");
3601 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3607 static int bus_message_enter_array(
3609 struct bus_container *c,
3610 const char *contents,
3611 uint32_t **array_size,
3614 size_t *n_offsets) {
3628 if (!signature_is_single(contents, true))
3631 if (!c->signature || c->signature[c->index] == 0)
3634 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3637 if (!startswith(c->signature + c->index + 1, contents))
3642 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3645 r = message_peek_body(m, &rindex, 4, 4, &q);
3649 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3652 alignment = bus_type_get_alignment(contents[0]);
3656 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3660 *array_size = (uint32_t*) q;
3662 } else if (c->item_size <= 0) {
3664 /* gvariant: empty array */
3669 } else if (bus_gvariant_is_fixed_size(contents)) {
3671 /* gvariant: fixed length array */
3672 *item_size = bus_gvariant_get_size(contents);
3677 size_t where, p = 0, framing, sz;
3680 /* gvariant: variable length array */
3681 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3683 where = rindex + c->item_size - sz;
3684 r = message_peek_body(m, &where, 1, sz, &q);
3688 framing = bus_gvariant_read_word_le(q, sz);
3689 if (framing > c->item_size - sz)
3691 if ((c->item_size - framing) % sz != 0)
3694 *n_offsets = (c->item_size - framing) / sz;
3696 where = rindex + framing;
3697 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3701 *offsets = new(size_t, *n_offsets);
3705 for (i = 0; i < *n_offsets; i++) {
3708 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3709 if (x > c->item_size - sz)
3714 (*offsets)[i] = rindex + x;
3718 *item_size = (*offsets)[0] - rindex;
3723 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3724 c->index += 1 + strlen(contents);
3729 static int bus_message_enter_variant(
3731 struct bus_container *c,
3732 const char *contents,
3733 size_t *item_size) {
3745 if (!signature_is_single(contents, false))
3748 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3751 if (!c->signature || c->signature[c->index] == 0)
3754 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3759 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3762 k = strlen(contents);
3763 if (1+k > c->item_size)
3766 where = rindex + c->item_size - (1+k);
3767 r = message_peek_body(m, &where, 1, 1+k, &q);
3771 if (*(char*) q != 0)
3774 if (memcmp((uint8_t*) q+1, contents, k))
3777 *item_size = c->item_size - (1+k);
3780 r = message_peek_body(m, &rindex, 1, 1, &q);
3785 r = message_peek_body(m, &rindex, 1, l+1, &q);
3789 if (!validate_signature(q, l))
3792 if (!streq(q, contents))
3798 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3804 static int build_struct_offsets(
3806 const char *signature,
3810 size_t *n_offsets) {
3812 unsigned n_variable = 0, n_total = 0, v;
3813 size_t previous = 0, where;
3824 if (isempty(signature)) {
3831 sz = bus_gvariant_determine_word_size(size, 0);
3835 /* First, loop over signature and count variable elements and
3836 * elements in general. We use this to know how large the
3837 * offset array is at the end of the structure. Note that
3838 * GVariant only stores offsets for all variable size elements
3839 * that are not the last item. */
3845 r = signature_element_length(p, &n);
3854 r = bus_gvariant_is_fixed_size(t);
3859 if (r == 0 && p[n] != 0) /* except the last item */
3866 if (size < n_variable * sz)
3869 where = m->rindex + size - (n_variable * sz);
3870 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3876 *offsets = new(size_t, n_total);
3882 /* Second, loop again and build an offset table */
3888 r = signature_element_length(p, &n);
3897 k = bus_gvariant_get_size(t);
3905 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3908 if (m->rindex + x < previous)
3911 /* The last item's end
3912 * is determined from
3915 x = size - (n_variable * sz);
3917 offset = m->rindex + x;
3923 align = bus_gvariant_get_alignment(t);
3926 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3930 previous = (*offsets)[(*n_offsets)++] = offset;
3935 assert(*n_offsets == n_total);
3937 *item_size = (*offsets)[0] - m->rindex;
3941 static int enter_struct_or_dict_entry(
3943 struct bus_container *c,
3944 const char *contents,
3947 size_t *n_offsets) {
3958 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3961 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3965 } else if (c->item_size <= 0) {
3967 /* gvariant empty struct */
3972 /* gvariant with contents */
3973 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3978 static int bus_message_enter_struct(
3980 struct bus_container *c,
3981 const char *contents,
3984 size_t *n_offsets) {
3996 if (!signature_is_valid(contents, false))
3999 if (!c->signature || c->signature[c->index] == 0)
4002 l = strlen(contents);
4004 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4005 !startswith(c->signature + c->index + 1, contents) ||
4006 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4009 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4013 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4014 c->index += 1 + l + 1;
4019 static int bus_message_enter_dict_entry(
4021 struct bus_container *c,
4022 const char *contents,
4025 size_t *n_offsets) {
4034 if (!signature_is_pair(contents))
4037 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4040 if (!c->signature || c->signature[c->index] == 0)
4043 l = strlen(contents);
4045 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4046 !startswith(c->signature + c->index + 1, contents) ||
4047 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4050 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4054 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4055 c->index += 1 + l + 1;
4060 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4062 const char *contents) {
4063 struct bus_container *c, *w;
4064 uint32_t *array_size = NULL;
4067 size_t *offsets = NULL;
4068 size_t n_offsets = 0, item_size = 0;
4071 assert_return(m, -EINVAL);
4072 assert_return(m->sealed, -EPERM);
4073 assert_return(type != 0 || !contents, -EINVAL);
4075 if (type == 0 || !contents) {
4079 /* Allow entering into anonymous containers */
4080 r = sd_bus_message_peek_type(m, &tt, &cc);
4084 if (type != 0 && type != tt)
4087 if (contents && !streq(contents, cc))
4095 * We enforce a global limit on container depth, that is much
4096 * higher than the 32 structs and 32 arrays the specification
4097 * mandates. This is simpler to implement for us, and we need
4098 * this only to ensure our container array doesn't grow
4099 * without bounds. We are happy to return any data from a
4100 * message as long as the data itself is valid, even if the
4101 * overall message might be not.
4103 * Note that the message signature is validated when
4104 * parsing the headers, and that validation does check the
4107 * Note that the specification defines no limits on the depth
4108 * of stacked variants, but we do.
4110 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4113 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4116 if (message_end_of_signature(m))
4119 if (message_end_of_array(m, m->rindex))
4122 c = message_get_container(m);
4124 signature = strdup(contents);
4128 c->saved_index = c->index;
4131 if (type == SD_BUS_TYPE_ARRAY)
4132 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4133 else if (type == SD_BUS_TYPE_VARIANT)
4134 r = bus_message_enter_variant(m, c, contents, &item_size);
4135 else if (type == SD_BUS_TYPE_STRUCT)
4136 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4137 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4138 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4148 /* OK, let's fill it in */
4149 w = m->containers + m->n_containers++;
4150 w->enclosing = type;
4151 w->signature = signature;
4152 w->peeked_signature = NULL;
4156 w->begin = m->rindex;
4157 w->end = m->rindex + c->item_size;
4159 w->array_size = array_size;
4160 w->item_size = item_size;
4161 w->offsets = offsets;
4162 w->n_offsets = n_offsets;
4163 w->offset_index = 0;
4168 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4169 struct bus_container *c;
4173 assert_return(m, -EINVAL);
4174 assert_return(m->sealed, -EPERM);
4175 assert_return(m->n_containers > 0, -ENXIO);
4177 c = message_get_container(m);
4179 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4180 if (c->signature && c->signature[c->index] != 0)
4184 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4185 if (m->rindex < c->end)
4188 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4191 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4192 if (c->begin + l != m->rindex)
4197 free(c->peeked_signature);
4201 c = message_get_container(m);
4204 c->index = c->saved_index;
4205 r = container_next_item(m, c, &m->rindex);
4213 static void message_quit_container(sd_bus_message *m) {
4214 struct bus_container *c;
4218 assert(m->n_containers > 0);
4220 c = message_get_container(m);
4223 assert(m->rindex >= c->before);
4224 m->rindex = c->before;
4226 /* Free container */
4231 /* Correct index of new top-level container */
4232 c = message_get_container(m);
4233 c->index = c->saved_index;
4236 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4237 struct bus_container *c;
4240 assert_return(m, -EINVAL);
4241 assert_return(m->sealed, -EPERM);
4243 if (message_end_of_signature(m))
4246 if (message_end_of_array(m, m->rindex))
4249 c = message_get_container(m);
4251 if (bus_type_is_basic(c->signature[c->index])) {
4255 *type = c->signature[c->index];
4259 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4265 r = signature_element_length(c->signature+c->index+1, &l);
4271 sig = strndup(c->signature + c->index + 1, l);
4275 free(c->peeked_signature);
4276 *contents = c->peeked_signature = sig;
4280 *type = SD_BUS_TYPE_ARRAY;
4285 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4286 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4292 r = signature_element_length(c->signature+c->index, &l);
4297 sig = strndup(c->signature + c->index + 1, l - 2);
4301 free(c->peeked_signature);
4302 *contents = c->peeked_signature = sig;
4306 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4311 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4315 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4318 if (c->item_size < 2)
4321 /* Look for the NUL delimiter that
4322 separates the payload from the
4323 signature. Since the body might be
4324 in a different part that then the
4325 signature we map byte by byte. */
4327 for (k = 2; k <= c->item_size; k++) {
4330 where = m->rindex + c->item_size - k;
4331 r = message_peek_body(m, &where, 1, k, &q);
4335 if (*(char*) q == 0)
4339 if (k > c->item_size)
4342 free(c->peeked_signature);
4343 c->peeked_signature = strndup((char*) q + 1, k - 1);
4344 if (!c->peeked_signature)
4347 if (!signature_is_valid(c->peeked_signature, true))
4350 *contents = c->peeked_signature;
4355 r = message_peek_body(m, &rindex, 1, 1, &q);
4360 r = message_peek_body(m, &rindex, 1, l+1, &q);
4364 if (!validate_signature(q, l))
4372 *type = SD_BUS_TYPE_VARIANT;
4387 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4388 struct bus_container *c;
4390 assert_return(m, -EINVAL);
4391 assert_return(m->sealed, -EPERM);
4394 message_reset_containers(m);
4397 c = message_get_container(m);
4399 c = message_get_container(m);
4401 c->offset_index = 0;
4403 m->rindex = c->begin;
4406 c->offset_index = 0;
4407 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4409 return !isempty(c->signature);
4412 static int message_read_ap(
4417 unsigned n_array, n_struct;
4418 TypeStack stack[BUS_CONTAINER_DEPTH];
4419 unsigned stack_ptr = 0;
4420 unsigned n_loop = 0;
4428 /* Ideally, we'd just call ourselves recursively on every
4429 * complex type. However, the state of a va_list that is
4430 * passed to a function is undefined after that function
4431 * returns. This means we need to docode the va_list linearly
4432 * in a single stackframe. We hence implement our own
4433 * home-grown stack in an array. */
4435 n_array = (unsigned) -1; /* length of current array entries */
4436 n_struct = strlen(types); /* length of current struct contents signature */
4443 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4444 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4450 r = sd_bus_message_exit_container(m);
4458 if (n_array != (unsigned) -1)
4467 case SD_BUS_TYPE_BYTE:
4468 case SD_BUS_TYPE_BOOLEAN:
4469 case SD_BUS_TYPE_INT16:
4470 case SD_BUS_TYPE_UINT16:
4471 case SD_BUS_TYPE_INT32:
4472 case SD_BUS_TYPE_UINT32:
4473 case SD_BUS_TYPE_INT64:
4474 case SD_BUS_TYPE_UINT64:
4475 case SD_BUS_TYPE_DOUBLE:
4476 case SD_BUS_TYPE_STRING:
4477 case SD_BUS_TYPE_OBJECT_PATH:
4478 case SD_BUS_TYPE_SIGNATURE:
4479 case SD_BUS_TYPE_UNIX_FD: {
4482 p = va_arg(ap, void*);
4483 r = sd_bus_message_read_basic(m, *t, p);
4496 case SD_BUS_TYPE_ARRAY: {
4499 r = signature_element_length(t + 1, &k);
4505 memcpy(s, t + 1, k);
4508 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4519 if (n_array == (unsigned) -1) {
4524 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4530 n_array = va_arg(ap, unsigned);
4535 case SD_BUS_TYPE_VARIANT: {
4538 s = va_arg(ap, const char *);
4542 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4552 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4557 n_struct = strlen(s);
4558 n_array = (unsigned) -1;
4563 case SD_BUS_TYPE_STRUCT_BEGIN:
4564 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4567 r = signature_element_length(t, &k);
4573 memcpy(s, t + 1, k - 2);
4576 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4586 if (n_array == (unsigned) -1) {
4591 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4597 n_array = (unsigned) -1;
4610 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4614 assert_return(m, -EINVAL);
4615 assert_return(m->sealed, -EPERM);
4616 assert_return(types, -EINVAL);
4618 va_start(ap, types);
4619 r = message_read_ap(m, types, ap);
4625 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4628 assert_return(m, -EINVAL);
4629 assert_return(m->sealed, -EPERM);
4631 /* If types is NULL, read exactly one element */
4633 struct bus_container *c;
4636 if (message_end_of_signature(m))
4639 if (message_end_of_array(m, m->rindex))
4642 c = message_get_container(m);
4644 r = signature_element_length(c->signature + c->index, &l);
4648 types = strndupa(c->signature + c->index, l);
4653 case 0: /* Nothing to drop */
4656 case SD_BUS_TYPE_BYTE:
4657 case SD_BUS_TYPE_BOOLEAN:
4658 case SD_BUS_TYPE_INT16:
4659 case SD_BUS_TYPE_UINT16:
4660 case SD_BUS_TYPE_INT32:
4661 case SD_BUS_TYPE_UINT32:
4662 case SD_BUS_TYPE_INT64:
4663 case SD_BUS_TYPE_UINT64:
4664 case SD_BUS_TYPE_DOUBLE:
4665 case SD_BUS_TYPE_STRING:
4666 case SD_BUS_TYPE_OBJECT_PATH:
4667 case SD_BUS_TYPE_SIGNATURE:
4668 case SD_BUS_TYPE_UNIX_FD:
4670 r = sd_bus_message_read_basic(m, *types, NULL);
4674 r = sd_bus_message_skip(m, types + 1);
4680 case SD_BUS_TYPE_ARRAY: {
4683 r = signature_element_length(types + 1, &k);
4689 memcpy(s, types+1, k);
4692 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4697 r = sd_bus_message_skip(m, s);
4704 r = sd_bus_message_exit_container(m);
4709 r = sd_bus_message_skip(m, types + 1 + k);
4716 case SD_BUS_TYPE_VARIANT: {
4717 const char *contents;
4720 r = sd_bus_message_peek_type(m, &x, &contents);
4724 if (x != SD_BUS_TYPE_VARIANT)
4727 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4731 r = sd_bus_message_skip(m, contents);
4736 r = sd_bus_message_exit_container(m);
4740 r = sd_bus_message_skip(m, types + 1);
4747 case SD_BUS_TYPE_STRUCT_BEGIN:
4748 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4751 r = signature_element_length(types, &k);
4757 memcpy(s, types+1, k-2);
4760 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4764 r = sd_bus_message_skip(m, s);
4769 r = sd_bus_message_exit_container(m);
4774 r = sd_bus_message_skip(m, types + k);
4786 _public_ int sd_bus_message_read_array(
4792 struct bus_container *c;
4798 assert_return(m, -EINVAL);
4799 assert_return(m->sealed, -EPERM);
4800 assert_return(bus_type_is_trivial(type), -EINVAL);
4801 assert_return(ptr, -EINVAL);
4802 assert_return(size, -EINVAL);
4803 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4805 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4809 c = message_get_container(m);
4811 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4812 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4816 sz = c->end - c->begin;
4818 align = bus_type_get_alignment(type);
4822 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4826 /* Zero length array, let's return some aligned
4827 * pointer that is not NULL */
4828 p = (uint8_t*) NULL + align;
4830 r = message_peek_body(m, &m->rindex, align, sz, &p);
4835 r = sd_bus_message_exit_container(m);
4839 *ptr = (const void*) p;
4845 message_quit_container(m);
4849 static int message_peek_fields(
4860 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4863 static int message_peek_field_uint32(
4875 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4878 /* identical for gvariant and dbus1 */
4880 r = message_peek_fields(m, ri, 4, 4, &q);
4885 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4890 static int message_peek_field_uint64(
4902 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4905 /* identical for gvariant and dbus1 */
4907 r = message_peek_fields(m, ri, 8, 8, &q);
4912 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4917 static int message_peek_field_string(
4919 bool (*validate)(const char *p),
4931 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4936 r = message_peek_fields(m, ri, 1, item_size, &q);
4942 r = message_peek_field_uint32(m, ri, 4, &l);
4946 r = message_peek_fields(m, ri, 1, l+1, &q);
4952 if (!validate_nul(q, l))
4958 if (!validate_string(q, l))
4968 static int message_peek_field_signature(
4981 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4986 r = message_peek_fields(m, ri, 1, item_size, &q);
4992 r = message_peek_fields(m, ri, 1, 1, &q);
4997 r = message_peek_fields(m, ri, 1, l+1, &q);
5002 if (!validate_signature(q, l))
5011 static int message_skip_fields(
5014 uint32_t array_size,
5015 const char **signature) {
5017 size_t original_index;
5023 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5025 original_index = *ri;
5031 if (array_size != (uint32_t) -1 &&
5032 array_size <= *ri - original_index)
5039 if (t == SD_BUS_TYPE_STRING) {
5041 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5047 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5049 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5055 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5057 r = message_peek_field_signature(m, ri, 0, NULL);
5063 } else if (bus_type_is_basic(t)) {
5066 align = bus_type_get_alignment(t);
5067 k = bus_type_get_size(t);
5068 assert(align > 0 && k > 0);
5070 r = message_peek_fields(m, ri, align, k, NULL);
5076 } else if (t == SD_BUS_TYPE_ARRAY) {
5078 r = signature_element_length(*signature+1, &l);
5088 strncpy(sig, *signature + 1, l-1);
5091 alignment = bus_type_get_alignment(sig[0]);
5095 r = message_peek_field_uint32(m, ri, 0, &nas);
5098 if (nas > BUS_ARRAY_MAX_SIZE)
5101 r = message_peek_fields(m, ri, alignment, 0, NULL);
5105 r = message_skip_fields(m, ri, nas, (const char**) &s);
5110 (*signature) += 1 + l;
5112 } else if (t == SD_BUS_TYPE_VARIANT) {
5115 r = message_peek_field_signature(m, ri, 0, &s);
5119 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5125 } else if (t == SD_BUS_TYPE_STRUCT ||
5126 t == SD_BUS_TYPE_DICT_ENTRY) {
5128 r = signature_element_length(*signature, &l);
5135 strncpy(sig, *signature + 1, l-1);
5138 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5149 int bus_message_parse_fields(sd_bus_message *m) {
5152 uint32_t unix_fds = 0;
5153 bool unix_fds_set = false;
5154 void *offsets = NULL;
5155 unsigned n_offsets = 0;
5161 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5164 /* Read the signature from the end of the body variant first */
5165 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5166 if (m->footer_accessible < 1 + sz)
5169 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5171 if (p < (char*) m->footer)
5177 /* We found the beginning of the signature string, yay! */
5179 c = strndup(p + 1, ((char*) m->footer + m->footer_accessible) - p - (1 + sz));
5183 free(m->root_container.signature);
5184 m->root_container.signature = c;
5191 /* Calculate the actual user body size, by removing
5192 * the trailing variant signature and struct offset
5194 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5196 /* Pull out the offset table for the fields array */
5197 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5202 ri = m->fields_size - sz;
5203 r = message_peek_fields(m, &ri, 1, sz, &q);
5207 framing = bus_gvariant_read_word_le(q, sz);
5208 if (framing >= m->fields_size - sz)
5210 if ((m->fields_size - framing) % sz != 0)
5214 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5218 n_offsets = (m->fields_size - framing) / sz;
5221 m->user_body_size = m->body_size;
5224 while (ri < m->fields_size) {
5225 _cleanup_free_ char *sig = NULL;
5226 const char *signature;
5227 uint64_t field_type;
5228 size_t item_size = (size_t) -1;
5230 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5239 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5241 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5245 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5249 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5256 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5261 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5266 where = ri = ALIGN_TO(ri, 8);
5267 item_size = end - ri;
5268 r = message_peek_fields(m, &where, 1, item_size, &q);
5272 b = memrchr(q, 0, item_size);
5276 sig = strndup(b+1, item_size - (b+1-(char*) q));
5281 item_size = b - (char*) q;
5283 r = message_peek_field_signature(m, &ri, 0, &signature);
5288 switch (field_type) {
5290 case _BUS_MESSAGE_HEADER_INVALID:
5293 case BUS_MESSAGE_HEADER_PATH:
5298 if (!streq(signature, "o"))
5301 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5304 case BUS_MESSAGE_HEADER_INTERFACE:
5309 if (!streq(signature, "s"))
5312 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5315 case BUS_MESSAGE_HEADER_MEMBER:
5320 if (!streq(signature, "s"))
5323 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5326 case BUS_MESSAGE_HEADER_ERROR_NAME:
5331 if (!streq(signature, "s"))
5334 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5336 m->error._need_free = -1;
5340 case BUS_MESSAGE_HEADER_DESTINATION:
5345 if (!streq(signature, "s"))
5348 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5351 case BUS_MESSAGE_HEADER_SENDER:
5356 if (!streq(signature, "s"))
5359 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5361 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5362 m->creds.unique_name = (char*) m->sender;
5363 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5369 case BUS_MESSAGE_HEADER_SIGNATURE: {
5373 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5376 if (m->root_container.signature)
5379 if (!streq(signature, "g"))
5382 r = message_peek_field_signature(m, &ri, item_size, &s);
5390 free(m->root_container.signature);
5391 m->root_container.signature = c;
5395 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5397 if (m->reply_cookie != 0)
5400 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5401 /* 64bit on dbus2 */
5403 if (!streq(signature, "t"))
5406 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5410 /* 32bit on dbus1 */
5413 if (!streq(signature, "u"))
5416 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5420 m->reply_cookie = serial;
5423 if (m->reply_cookie == 0)
5428 case BUS_MESSAGE_HEADER_UNIX_FDS:
5432 if (!streq(signature, "u"))
5435 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5439 unix_fds_set = true;
5443 if (!BUS_MESSAGE_IS_GVARIANT(m))
5444 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5453 if (m->n_fds != unix_fds)
5456 switch (m->header->type) {
5458 case SD_BUS_MESSAGE_SIGNAL:
5459 if (!m->path || !m->interface || !m->member)
5462 if (m->reply_cookie != 0)
5467 case SD_BUS_MESSAGE_METHOD_CALL:
5469 if (!m->path || !m->member)
5472 if (m->reply_cookie != 0)
5477 case SD_BUS_MESSAGE_METHOD_RETURN:
5479 if (m->reply_cookie == 0)
5483 case SD_BUS_MESSAGE_METHOD_ERROR:
5485 if (m->reply_cookie == 0 || !m->error.name)
5490 /* Refuse non-local messages that claim they are local */
5491 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5493 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5495 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5498 m->root_container.end = m->user_body_size;
5500 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5501 r = build_struct_offsets(
5503 m->root_container.signature,
5505 &m->root_container.item_size,
5506 &m->root_container.offsets,
5507 &m->root_container.n_offsets);
5512 /* Try to read the error message, but if we can't it's a non-issue */
5513 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5514 sd_bus_message_read(m, "s", &m->error.message);
5519 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5520 assert_return(m, -EINVAL);
5521 assert_return(destination, -EINVAL);
5522 assert_return(!m->sealed, -EPERM);
5523 assert_return(!m->destination, -EEXIST);
5525 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5528 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5532 struct bus_body_part *part;
5538 total = BUS_MESSAGE_SIZE(m);
5544 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5545 MESSAGE_FOREACH_PART(part, i, m)
5546 e = mempcpy(e, part->data, part->size);
5548 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5556 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5562 r = sd_bus_message_enter_container(m, 'a', "s");
5569 r = sd_bus_message_read_basic(m, 's', &s);
5575 r = strv_extend(l, s);
5580 r = sd_bus_message_exit_container(m);
5587 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5591 assert_return(m, -EINVAL);
5592 assert_return(m->sealed, -EPERM);
5593 assert_return(l, -EINVAL);
5595 r = bus_message_read_strv_extend(m, &strv);
5605 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5606 const char *contents;
5615 r = sd_bus_message_rewind(m, true);
5620 r = sd_bus_message_peek_type(m, &type, &contents);
5626 /* Don't match against arguments after the first one we don't understand */
5627 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5628 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5634 r = sd_bus_message_skip(m, NULL);
5639 if (type == SD_BUS_TYPE_ARRAY) {
5641 r = sd_bus_message_read_strv(m, strv);
5648 r = sd_bus_message_read_basic(m, type, str);
5658 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5659 assert_return(m, EINVAL);
5661 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5664 return sd_bus_error_get_errno(&m->error);
5667 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5668 struct bus_container *c;
5670 assert_return(m, NULL);
5672 c = complete ? &m->root_container : message_get_container(m);
5673 return strempty(c->signature);
5676 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5677 assert_return(m, -EINVAL);
5679 return isempty(m->root_container.signature);
5682 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5683 assert_return(m, -EINVAL);
5685 return streq(strempty(m->root_container.signature), strempty(signature));
5688 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5689 bool done_something = false;
5692 assert_return(m, -EINVAL);
5693 assert_return(source, -EINVAL);
5694 assert_return(!m->sealed, -EPERM);
5695 assert_return(source->sealed, -EPERM);
5698 const char *contents;
5713 r = sd_bus_message_peek_type(source, &type, &contents);
5719 done_something = true;
5721 if (bus_type_is_container(type) > 0) {
5723 r = sd_bus_message_enter_container(source, type, contents);
5727 r = sd_bus_message_open_container(m, type, contents);
5731 r = sd_bus_message_copy(m, source, true);
5735 r = sd_bus_message_close_container(m);
5739 r = sd_bus_message_exit_container(source);
5746 r = sd_bus_message_read_basic(source, type, &basic);
5752 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5753 type == SD_BUS_TYPE_SIGNATURE ||
5754 type == SD_BUS_TYPE_STRING)
5755 r = sd_bus_message_append_basic(m, type, basic.string);
5757 r = sd_bus_message_append_basic(m, type, &basic);
5764 return done_something;
5767 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5772 assert_return(m, -EINVAL);
5773 assert_return(m->sealed, -EPERM);
5774 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5775 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5776 assert_return(type || contents, -EINVAL);
5777 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5779 r = sd_bus_message_peek_type(m, &t, &c);
5783 if (type != 0 && type != t)
5786 if (contents && !streq_ptr(contents, c))
5792 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5793 assert_return(m, NULL);
5798 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5799 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5807 switch ((*m)->header->type) {
5809 case SD_BUS_MESSAGE_SIGNAL:
5810 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5816 case SD_BUS_MESSAGE_METHOD_CALL:
5817 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5823 case SD_BUS_MESSAGE_METHOD_RETURN:
5824 case SD_BUS_MESSAGE_METHOD_ERROR:
5826 n = message_new(bus, (*m)->header->type);
5830 n->reply_cookie = (*m)->reply_cookie;
5832 r = message_append_reply_cookie(n, n->reply_cookie);
5836 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5837 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5841 n->error._need_free = -1;
5850 if ((*m)->destination && !n->destination) {
5851 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5856 if ((*m)->sender && !n->sender) {
5857 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5862 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5864 r = sd_bus_message_copy(n, *m, true);
5868 timeout = (*m)->timeout;
5869 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5870 timeout = BUS_DEFAULT_TIMEOUT;
5872 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5876 sd_bus_message_unref(*m);
5883 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5887 assert_return(!m->sealed, -EPERM);
5888 assert_return(!m->sender, -EPERM);
5890 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5893 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5894 assert_return(m, -EINVAL);
5895 assert_return(priority, -EINVAL);
5897 *priority = m->priority;
5901 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5902 assert_return(m, -EINVAL);
5903 assert_return(!m->sealed, -EPERM);
5905 m->priority = priority;