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);
640 _public_ int sd_bus_message_new_signal(
644 const char *interface,
645 const char *member) {
650 assert_return(bus, -ENOTCONN);
651 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
652 assert_return(object_path_is_valid(path), -EINVAL);
653 assert_return(interface_name_is_valid(interface), -EINVAL);
654 assert_return(member_name_is_valid(member), -EINVAL);
655 assert_return(m, -EINVAL);
657 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
661 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
663 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
666 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
669 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
677 sd_bus_message_unref(t);
681 _public_ int sd_bus_message_new_method_call(
684 const char *destination,
686 const char *interface,
687 const char *member) {
692 assert_return(bus, -ENOTCONN);
693 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
694 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
695 assert_return(object_path_is_valid(path), -EINVAL);
696 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
697 assert_return(member_name_is_valid(member), -EINVAL);
698 assert_return(m, -EINVAL);
700 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
704 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
707 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
712 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
718 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
731 static int message_new_reply(
732 sd_bus_message *call,
734 sd_bus_message **m) {
739 assert_return(call, -EINVAL);
740 assert_return(call->sealed, -EPERM);
741 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
742 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
743 assert_return(m, -EINVAL);
745 t = message_new(call->bus, type);
749 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
750 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
751 if (t->reply_cookie == 0)
754 r = message_append_reply_cookie(t, t->reply_cookie);
759 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
764 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
765 t->enforced_reply_signature = call->enforced_reply_signature;
775 _public_ int sd_bus_message_new_method_return(
776 sd_bus_message *call,
777 sd_bus_message **m) {
779 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
782 _public_ int sd_bus_message_new_method_error(
783 sd_bus_message *call,
785 const sd_bus_error *e) {
790 assert_return(sd_bus_error_is_set(e), -EINVAL);
791 assert_return(m, -EINVAL);
793 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
797 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
802 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
807 t->error._need_free = -1;
817 _public_ int sd_bus_message_new_method_errorf(
818 sd_bus_message *call,
824 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
827 assert_return(name, -EINVAL);
828 assert_return(m, -EINVAL);
830 va_start(ap, format);
831 bus_error_setfv(&error, name, format, ap);
834 return sd_bus_message_new_method_error(call, m, &error);
837 _public_ int sd_bus_message_new_method_errno(
838 sd_bus_message *call,
841 const sd_bus_error *p) {
843 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
845 if (sd_bus_error_is_set(p))
846 return sd_bus_message_new_method_error(call, m, p);
848 sd_bus_error_set_errno(&berror, error);
850 return sd_bus_message_new_method_error(call, m, &berror);
853 _public_ int sd_bus_message_new_method_errnof(
854 sd_bus_message *call,
860 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
863 va_start(ap, format);
864 sd_bus_error_set_errnofv(&berror, error, format, ap);
867 return sd_bus_message_new_method_error(call, m, &berror);
870 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
874 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
875 m->creds.well_known_names_local = true;
876 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
879 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
883 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
884 m->creds.well_known_names_driver = true;
885 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
888 int bus_message_new_synthetic_error(
891 const sd_bus_error *e,
892 sd_bus_message **m) {
898 assert(sd_bus_error_is_set(e));
901 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
905 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
906 t->reply_cookie = cookie;
908 r = message_append_reply_cookie(t, t->reply_cookie);
912 if (bus && bus->unique_name) {
913 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
918 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
923 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
928 t->error._need_free = -1;
930 bus_message_set_sender_driver(bus, t);
940 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
941 assert_return(m, NULL);
943 assert(m->n_ref > 0);
949 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
954 assert(m->n_ref > 0);
964 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
965 assert_return(m, -EINVAL);
966 assert_return(type, -EINVAL);
968 *type = m->header->type;
972 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
975 assert_return(m, -EINVAL);
976 assert_return(cookie, -EINVAL);
978 c = BUS_MESSAGE_COOKIE(m);
982 *cookie = BUS_MESSAGE_COOKIE(m);
986 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
987 assert_return(m, -EINVAL);
988 assert_return(cookie, -EINVAL);
990 if (m->reply_cookie == 0)
993 *cookie = m->reply_cookie;
997 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
998 assert_return(m, -EINVAL);
1000 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
1001 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
1004 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
1005 assert_return(m, -EINVAL);
1007 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
1010 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
1011 assert_return(m, -EINVAL);
1013 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
1014 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
1017 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1018 assert_return(m, NULL);
1023 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1024 assert_return(m, NULL);
1026 return m->interface;
1029 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1030 assert_return(m, NULL);
1035 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1036 assert_return(m, NULL);
1038 return m->destination;
1041 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1042 assert_return(m, NULL);
1047 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1048 assert_return(m, NULL);
1049 assert_return(sd_bus_error_is_set(&m->error), NULL);
1054 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1055 assert_return(m, -EINVAL);
1056 assert_return(usec, -EINVAL);
1058 if (m->monotonic <= 0)
1061 *usec = m->monotonic;
1065 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1066 assert_return(m, -EINVAL);
1067 assert_return(usec, -EINVAL);
1069 if (m->realtime <= 0)
1072 *usec = m->realtime;
1076 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1077 assert_return(m, -EINVAL);
1078 assert_return(seqnum, -EINVAL);
1083 *seqnum = m->seqnum;
1087 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1088 assert_return(m, NULL);
1090 if (m->creds.mask == 0)
1096 _public_ int sd_bus_message_is_signal(
1098 const char *interface,
1099 const char *member) {
1101 assert_return(m, -EINVAL);
1103 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1106 if (interface && (!m->interface || !streq(m->interface, interface)))
1109 if (member && (!m->member || !streq(m->member, member)))
1115 _public_ int sd_bus_message_is_method_call(
1117 const char *interface,
1118 const char *member) {
1120 assert_return(m, -EINVAL);
1122 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1125 if (interface && (!m->interface || !streq(m->interface, interface)))
1128 if (member && (!m->member || !streq(m->member, member)))
1134 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1135 assert_return(m, -EINVAL);
1137 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1140 if (name && (!m->error.name || !streq(m->error.name, name)))
1146 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1147 assert_return(m, -EINVAL);
1148 assert_return(!m->sealed, -EPERM);
1149 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1152 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1154 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1159 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1160 assert_return(m, -EINVAL);
1161 assert_return(!m->sealed, -EPERM);
1164 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1166 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1171 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1172 assert_return(m, -EINVAL);
1173 assert_return(!m->sealed, -EPERM);
1176 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1178 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1183 static struct bus_container *message_get_container(sd_bus_message *m) {
1186 if (m->n_containers == 0)
1187 return &m->root_container;
1189 assert(m->containers);
1190 return m->containers + m->n_containers - 1;
1193 struct bus_body_part *message_append_part(sd_bus_message *m) {
1194 struct bus_body_part *part;
1201 if (m->n_body_parts <= 0) {
1205 assert(m->body_end);
1207 part = new0(struct bus_body_part, 1);
1213 m->body_end->next = part;
1223 static void part_zero(struct bus_body_part *part, size_t sz) {
1228 /* All other fields can be left in their defaults */
1229 assert(!part->data);
1230 assert(part->memfd < 0);
1233 part->is_zero = true;
1234 part->sealed = true;
1237 static int part_make_space(
1238 struct sd_bus_message *m,
1239 struct bus_body_part *part,
1248 assert(!part->sealed);
1253 if (!part->data && part->memfd < 0) {
1254 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1255 part->mmap_begin = part->data;
1258 if (part->memfd >= 0) {
1260 if (part->allocated == 0 || sz > part->allocated) {
1261 uint64_t new_allocated;
1263 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1264 r = memfd_set_size(part->memfd, new_allocated);
1270 part->allocated = new_allocated;
1273 if (!part->data || sz > part->mapped) {
1276 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1277 if (part->mapped <= 0)
1278 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1280 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1282 if (n == MAP_FAILED) {
1287 part->mmap_begin = part->data = n;
1289 part->memfd_offset = 0;
1292 part->munmap_this = true;
1294 if (part->allocated == 0 || sz > part->allocated) {
1295 size_t new_allocated;
1297 new_allocated = sz > 0 ? 2 * sz : 64;
1298 n = realloc(part->data, new_allocated);
1305 part->allocated = new_allocated;
1306 part->free_this = true;
1311 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1317 static int message_add_offset(sd_bus_message *m, size_t offset) {
1318 struct bus_container *c;
1321 assert(BUS_MESSAGE_IS_GVARIANT(m));
1323 /* Add offset to current container, unless this is the first
1324 * item in it, which will have the 0 offset, which we can
1326 c = message_get_container(m);
1328 if (!c->need_offsets)
1331 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1334 c->offsets[c->n_offsets++] = offset;
1338 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1339 struct bus_container *c;
1346 /* Update counters */
1347 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1350 *c->array_size += expand;
1354 static void *message_extend_body(
1359 bool force_inline) {
1361 size_t start_body, end_body, padding, added;
1372 start_body = ALIGN_TO((size_t) m->body_size, align);
1373 end_body = start_body + sz;
1375 padding = start_body - m->body_size;
1376 added = padding + sz;
1378 /* Check for 32bit overflows */
1379 if (end_body > (size_t) ((uint32_t) -1) ||
1380 end_body < start_body) {
1386 struct bus_body_part *part = NULL;
1390 m->n_body_parts <= 0 ||
1391 m->body_end->sealed ||
1392 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1393 (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 */
1397 part = message_append_part(m);
1401 part_zero(part, padding);
1404 part = message_append_part(m);
1408 r = part_make_space(m, part, sz, &p);
1412 struct bus_container *c;
1414 size_t os, start_part, end_part;
1420 start_part = ALIGN_TO(part->size, align);
1421 end_part = start_part + sz;
1423 r = part_make_space(m, part, end_part, &p);
1428 memzero(p, padding);
1429 p = (uint8_t*) p + padding;
1432 /* Readjust pointers */
1433 for (c = m->containers; c < m->containers + m->n_containers; c++)
1434 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1436 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1439 /* Return something that is not NULL and is aligned */
1440 p = (uint8_t *) NULL + align;
1442 m->body_size = end_body;
1443 message_extend_containers(m, added);
1446 r = message_add_offset(m, end_body);
1456 static int message_push_fd(sd_bus_message *m, int fd) {
1467 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1471 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1479 m->fds[m->n_fds] = copy;
1485 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1486 _cleanup_close_ int fd = -1;
1487 struct bus_container *c;
1491 assert_return(m, -EINVAL);
1492 assert_return(!m->sealed, -EPERM);
1493 assert_return(bus_type_is_basic(type), -EINVAL);
1494 assert_return(!m->poisoned, -ESTALE);
1496 c = message_get_container(m);
1498 if (c->signature && c->signature[c->index]) {
1499 /* Container signature is already set */
1501 if (c->signature[c->index] != type)
1506 /* Maybe we can append to the signature? But only if this is the top-level container */
1507 if (c->enclosing != 0)
1510 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1517 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1523 case SD_BUS_TYPE_SIGNATURE:
1524 case SD_BUS_TYPE_STRING:
1527 /* Fall through... */
1528 case SD_BUS_TYPE_OBJECT_PATH:
1536 case SD_BUS_TYPE_BOOLEAN:
1538 u8 = p && *(int*) p;
1544 case SD_BUS_TYPE_UNIX_FD:
1549 fd = message_push_fd(m, *(int*) p);
1560 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1561 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1568 a = message_extend_body(m, align, sz, true, false);
1575 *stored = (const uint8_t*) a;
1582 case SD_BUS_TYPE_STRING:
1583 /* To make things easy we'll serialize a NULL string
1584 * into the empty string */
1587 /* Fall through... */
1588 case SD_BUS_TYPE_OBJECT_PATH:
1594 sz = 4 + strlen(p) + 1;
1597 case SD_BUS_TYPE_SIGNATURE:
1602 sz = 1 + strlen(p) + 1;
1605 case SD_BUS_TYPE_BOOLEAN:
1607 u32 = p && *(int*) p;
1613 case SD_BUS_TYPE_UNIX_FD:
1618 fd = message_push_fd(m, *(int*) p);
1629 align = bus_type_get_alignment(type);
1630 sz = bus_type_get_size(type);
1637 a = message_extend_body(m, align, sz, false, false);
1641 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1642 *(uint32_t*) a = sz - 5;
1643 memcpy((uint8_t*) a + 4, p, sz - 4);
1646 *stored = (const uint8_t*) a + 4;
1648 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1649 *(uint8_t*) a = sz - 2;
1650 memcpy((uint8_t*) a + 1, p, sz - 1);
1653 *stored = (const uint8_t*) a + 1;
1662 if (type == SD_BUS_TYPE_UNIX_FD)
1665 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1672 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1673 return message_append_basic(m, type, p, NULL);
1676 _public_ int sd_bus_message_append_string_space(
1681 struct bus_container *c;
1684 assert_return(m, -EINVAL);
1685 assert_return(s, -EINVAL);
1686 assert_return(!m->sealed, -EPERM);
1687 assert_return(!m->poisoned, -ESTALE);
1689 c = message_get_container(m);
1691 if (c->signature && c->signature[c->index]) {
1692 /* Container signature is already set */
1694 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1699 /* Maybe we can append to the signature? But only if this is the top-level container */
1700 if (c->enclosing != 0)
1703 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1710 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1711 a = message_extend_body(m, 1, size + 1, true, false);
1717 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1721 *(uint32_t*) a = size;
1727 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1733 _public_ int sd_bus_message_append_string_iovec(
1735 const struct iovec *iov,
1743 assert_return(m, -EINVAL);
1744 assert_return(!m->sealed, -EPERM);
1745 assert_return(iov || n == 0, -EINVAL);
1746 assert_return(!m->poisoned, -ESTALE);
1748 size = IOVEC_TOTAL_SIZE(iov, n);
1750 r = sd_bus_message_append_string_space(m, size, &p);
1754 for (i = 0; i < n; i++) {
1756 if (iov[i].iov_base)
1757 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1759 memset(p, ' ', iov[i].iov_len);
1761 p += iov[i].iov_len;
1767 static int bus_message_open_array(
1769 struct bus_container *c,
1770 const char *contents,
1771 uint32_t **array_size,
1773 bool *need_offsets) {
1783 assert(need_offsets);
1785 if (!signature_is_single(contents, true))
1788 if (c->signature && c->signature[c->index]) {
1790 /* Verify the existing signature */
1792 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1795 if (!startswith(c->signature + c->index + 1, contents))
1798 nindex = c->index + 1 + strlen(contents);
1802 if (c->enclosing != 0)
1805 /* Extend the existing signature */
1807 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1813 nindex = e - c->signature;
1816 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1817 alignment = bus_gvariant_get_alignment(contents);
1821 /* Add alignment padding and add to offset list */
1822 if (!message_extend_body(m, alignment, 0, false, false))
1825 r = bus_gvariant_is_fixed_size(contents);
1829 *begin = m->body_size;
1830 *need_offsets = r == 0;
1834 struct bus_body_part *o;
1836 alignment = bus_type_get_alignment(contents[0]);
1840 a = message_extend_body(m, 4, 4, false, false);
1845 op = m->body_end->data;
1846 os = m->body_end->size;
1848 /* Add alignment between size and first element */
1849 if (!message_extend_body(m, alignment, 0, false, false))
1852 /* location of array size might have changed so let's readjust a */
1853 if (o == m->body_end)
1854 a = adjust_pointer(a, op, os, m->body_end->data);
1860 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1866 static int bus_message_open_variant(
1868 struct bus_container *c,
1869 const char *contents) {
1875 if (!signature_is_single(contents, false))
1878 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1881 if (c->signature && c->signature[c->index]) {
1883 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1889 if (c->enclosing != 0)
1892 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1899 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1900 /* Variants are always aligned to 8 */
1902 if (!message_extend_body(m, 8, 0, false, false))
1909 l = strlen(contents);
1910 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1915 memcpy((uint8_t*) a + 1, contents, l + 1);
1918 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1924 static int bus_message_open_struct(
1926 struct bus_container *c,
1927 const char *contents,
1929 bool *need_offsets) {
1938 assert(need_offsets);
1940 if (!signature_is_valid(contents, false))
1943 if (c->signature && c->signature[c->index]) {
1946 l = strlen(contents);
1948 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1949 !startswith(c->signature + c->index + 1, contents) ||
1950 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1953 nindex = c->index + 1 + l + 1;
1957 if (c->enclosing != 0)
1960 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1966 nindex = e - c->signature;
1969 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1972 alignment = bus_gvariant_get_alignment(contents);
1976 if (!message_extend_body(m, alignment, 0, false, false))
1979 r = bus_gvariant_is_fixed_size(contents);
1983 *begin = m->body_size;
1984 *need_offsets = r == 0;
1986 /* Align contents to 8 byte boundary */
1987 if (!message_extend_body(m, 8, 0, false, false))
1991 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1997 static int bus_message_open_dict_entry(
1999 struct bus_container *c,
2000 const char *contents,
2002 bool *need_offsets) {
2010 assert(need_offsets);
2012 if (!signature_is_pair(contents))
2015 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2018 if (c->signature && c->signature[c->index]) {
2021 l = strlen(contents);
2023 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2024 !startswith(c->signature + c->index + 1, contents) ||
2025 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2030 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2033 alignment = bus_gvariant_get_alignment(contents);
2037 if (!message_extend_body(m, alignment, 0, false, false))
2040 r = bus_gvariant_is_fixed_size(contents);
2044 *begin = m->body_size;
2045 *need_offsets = r == 0;
2047 /* Align contents to 8 byte boundary */
2048 if (!message_extend_body(m, 8, 0, false, false))
2055 _public_ int sd_bus_message_open_container(
2058 const char *contents) {
2060 struct bus_container *c, *w;
2061 uint32_t *array_size = NULL;
2063 size_t before, begin = 0;
2064 bool need_offsets = false;
2067 assert_return(m, -EINVAL);
2068 assert_return(!m->sealed, -EPERM);
2069 assert_return(contents, -EINVAL);
2070 assert_return(!m->poisoned, -ESTALE);
2072 /* Make sure we have space for one more container */
2073 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2078 c = message_get_container(m);
2080 signature = strdup(contents);
2086 /* Save old index in the parent container, in case we have to
2087 * abort this container */
2088 c->saved_index = c->index;
2089 before = m->body_size;
2091 if (type == SD_BUS_TYPE_ARRAY)
2092 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2093 else if (type == SD_BUS_TYPE_VARIANT)
2094 r = bus_message_open_variant(m, c, contents);
2095 else if (type == SD_BUS_TYPE_STRUCT)
2096 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2097 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2098 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2107 /* OK, let's fill it in */
2108 w = m->containers + m->n_containers++;
2109 w->enclosing = type;
2110 w->signature = signature;
2112 w->array_size = array_size;
2115 w->n_offsets = w->offsets_allocated = 0;
2117 w->need_offsets = need_offsets;
2122 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2127 if (!BUS_MESSAGE_IS_GVARIANT(m))
2130 if (c->need_offsets) {
2131 size_t payload, sz, i;
2134 /* Variable-width arrays */
2136 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2137 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2139 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2143 for (i = 0; i < c->n_offsets; i++)
2144 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2148 /* Fixed-width or empty arrays */
2150 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2158 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2164 assert(c->signature);
2166 if (!BUS_MESSAGE_IS_GVARIANT(m))
2169 l = strlen(c->signature);
2171 a = message_extend_body(m, 1, 1 + l, true, false);
2176 memcpy(a+1, c->signature, l);
2181 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2182 size_t n_variable = 0;
2191 if (!BUS_MESSAGE_IS_GVARIANT(m))
2194 p = strempty(c->signature);
2198 r = signature_element_length(p, &n);
2207 r = bus_gvariant_is_fixed_size(t);
2212 assert(!c->need_offsets || i <= c->n_offsets);
2214 /* We need to add an offset for each item that has a
2215 * variable size and that is not the last one in the
2217 if (r == 0 && p[n] != 0)
2224 assert(!c->need_offsets || i == c->n_offsets);
2225 assert(c->need_offsets || n_variable == 0);
2227 if (n_variable <= 0) {
2228 a = message_extend_body(m, 1, 0, add_offset, false);
2235 assert(c->offsets[c->n_offsets-1] == m->body_size);
2237 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2239 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2243 p = strempty(c->signature);
2244 for (i = 0, j = 0; i < c->n_offsets; i++) {
2248 r = signature_element_length(p, &n);
2259 r = bus_gvariant_is_fixed_size(t);
2262 if (r > 0 || p[0] == 0)
2266 k = n_variable - 1 - j;
2268 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2277 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2278 struct bus_container *c;
2281 assert_return(m, -EINVAL);
2282 assert_return(!m->sealed, -EPERM);
2283 assert_return(m->n_containers > 0, -EINVAL);
2284 assert_return(!m->poisoned, -ESTALE);
2286 c = message_get_container(m);
2288 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2289 if (c->signature && c->signature[c->index] != 0)
2294 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2295 r = bus_message_close_array(m, c);
2296 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2297 r = bus_message_close_variant(m, c);
2298 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2299 r = bus_message_close_struct(m, c, true);
2301 assert_not_reached("Unknown container type");
2315 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2322 stack[*i].types = types;
2323 stack[*i].n_struct = n_struct;
2324 stack[*i].n_array = n_array;
2330 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2341 *types = stack[*i].types;
2342 *n_struct = stack[*i].n_struct;
2343 *n_array = stack[*i].n_array;
2348 int bus_message_append_ap(
2353 unsigned n_array, n_struct;
2354 TypeStack stack[BUS_CONTAINER_DEPTH];
2355 unsigned stack_ptr = 0;
2363 n_array = (unsigned) -1;
2364 n_struct = strlen(types);
2369 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2370 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2376 r = sd_bus_message_close_container(m);
2384 if (n_array != (unsigned) -1)
2393 case SD_BUS_TYPE_BYTE: {
2396 x = (uint8_t) va_arg(ap, int);
2397 r = sd_bus_message_append_basic(m, *t, &x);
2401 case SD_BUS_TYPE_BOOLEAN:
2402 case SD_BUS_TYPE_INT32:
2403 case SD_BUS_TYPE_UINT32:
2404 case SD_BUS_TYPE_UNIX_FD: {
2407 /* We assume a boolean is the same as int32_t */
2408 assert_cc(sizeof(int32_t) == sizeof(int));
2410 x = va_arg(ap, uint32_t);
2411 r = sd_bus_message_append_basic(m, *t, &x);
2415 case SD_BUS_TYPE_INT16:
2416 case SD_BUS_TYPE_UINT16: {
2419 x = (uint16_t) va_arg(ap, int);
2420 r = sd_bus_message_append_basic(m, *t, &x);
2424 case SD_BUS_TYPE_INT64:
2425 case SD_BUS_TYPE_UINT64: {
2428 x = va_arg(ap, uint64_t);
2429 r = sd_bus_message_append_basic(m, *t, &x);
2433 case SD_BUS_TYPE_DOUBLE: {
2436 x = va_arg(ap, double);
2437 r = sd_bus_message_append_basic(m, *t, &x);
2441 case SD_BUS_TYPE_STRING:
2442 case SD_BUS_TYPE_OBJECT_PATH:
2443 case SD_BUS_TYPE_SIGNATURE: {
2446 x = va_arg(ap, const char*);
2447 r = sd_bus_message_append_basic(m, *t, x);
2451 case SD_BUS_TYPE_ARRAY: {
2454 r = signature_element_length(t + 1, &k);
2460 memcpy(s, t + 1, k);
2463 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2468 if (n_array == (unsigned) -1) {
2473 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2479 n_array = va_arg(ap, unsigned);
2484 case SD_BUS_TYPE_VARIANT: {
2487 s = va_arg(ap, const char*);
2491 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2495 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2500 n_struct = strlen(s);
2501 n_array = (unsigned) -1;
2506 case SD_BUS_TYPE_STRUCT_BEGIN:
2507 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2510 r = signature_element_length(t, &k);
2517 memcpy(s, t + 1, k - 2);
2520 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2525 if (n_array == (unsigned) -1) {
2530 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2536 n_array = (unsigned) -1;
2552 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2556 assert_return(m, -EINVAL);
2557 assert_return(types, -EINVAL);
2558 assert_return(!m->sealed, -EPERM);
2559 assert_return(!m->poisoned, -ESTALE);
2561 va_start(ap, types);
2562 r = bus_message_append_ap(m, types, ap);
2568 _public_ int sd_bus_message_append_array_space(
2578 assert_return(m, -EINVAL);
2579 assert_return(!m->sealed, -EPERM);
2580 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2581 assert_return(ptr || size == 0, -EINVAL);
2582 assert_return(!m->poisoned, -ESTALE);
2584 /* alignment and size of the trivial types (except bool) is
2585 * identical for gvariant and dbus1 marshalling */
2586 align = bus_type_get_alignment(type);
2587 sz = bus_type_get_size(type);
2589 assert_se(align > 0);
2595 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2599 a = message_extend_body(m, align, size, false, false);
2603 r = sd_bus_message_close_container(m);
2611 _public_ int sd_bus_message_append_array(
2619 assert_return(m, -EINVAL);
2620 assert_return(!m->sealed, -EPERM);
2621 assert_return(bus_type_is_trivial(type), -EINVAL);
2622 assert_return(ptr || size == 0, -EINVAL);
2623 assert_return(!m->poisoned, -ESTALE);
2625 r = sd_bus_message_append_array_space(m, type, size, &p);
2630 memcpy(p, ptr, size);
2635 _public_ int sd_bus_message_append_array_iovec(
2638 const struct iovec *iov,
2646 assert_return(m, -EINVAL);
2647 assert_return(!m->sealed, -EPERM);
2648 assert_return(bus_type_is_trivial(type), -EINVAL);
2649 assert_return(iov || n == 0, -EINVAL);
2650 assert_return(!m->poisoned, -ESTALE);
2652 size = IOVEC_TOTAL_SIZE(iov, n);
2654 r = sd_bus_message_append_array_space(m, type, size, &p);
2658 for (i = 0; i < n; i++) {
2660 if (iov[i].iov_base)
2661 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2663 memzero(p, iov[i].iov_len);
2665 p = (uint8_t*) p + iov[i].iov_len;
2671 _public_ int sd_bus_message_append_array_memfd(
2678 _cleanup_close_ int copy_fd = -1;
2679 struct bus_body_part *part;
2685 assert_return(m, -EINVAL);
2686 assert_return(memfd >= 0, -EINVAL);
2687 assert_return(bus_type_is_trivial(type), -EINVAL);
2688 assert_return(size > 0, -EINVAL);
2689 assert_return(!m->sealed, -EPERM);
2690 assert_return(!m->poisoned, -ESTALE);
2692 r = memfd_set_sealed(memfd);
2696 copy_fd = dup(memfd);
2700 r = memfd_get_size(memfd, &real_size);
2704 if (offset == 0 && size == (uint64_t) -1)
2706 else if (offset + size > real_size)
2709 align = bus_type_get_alignment(type);
2710 sz = bus_type_get_size(type);
2712 assert_se(align > 0);
2715 if (offset % align != 0)
2721 if (size > (uint64_t) (uint32_t) -1)
2724 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2728 a = message_extend_body(m, align, 0, false, false);
2732 part = message_append_part(m);
2736 part->memfd = copy_fd;
2737 part->memfd_offset = offset;
2738 part->sealed = true;
2742 m->body_size += size;
2743 message_extend_containers(m, size);
2745 return sd_bus_message_close_container(m);
2748 _public_ int sd_bus_message_append_string_memfd(
2754 _cleanup_close_ int copy_fd = -1;
2755 struct bus_body_part *part;
2756 struct bus_container *c;
2761 assert_return(m, -EINVAL);
2762 assert_return(memfd >= 0, -EINVAL);
2763 assert_return(size > 0, -EINVAL);
2764 assert_return(!m->sealed, -EPERM);
2765 assert_return(!m->poisoned, -ESTALE);
2767 r = memfd_set_sealed(memfd);
2771 copy_fd = dup(memfd);
2775 r = memfd_get_size(memfd, &real_size);
2779 if (offset == 0 && size == (uint64_t) -1)
2781 else if (offset + size > real_size)
2784 /* We require this to be NUL terminated */
2788 if (size > (uint64_t) (uint32_t) -1)
2791 c = message_get_container(m);
2792 if (c->signature && c->signature[c->index]) {
2793 /* Container signature is already set */
2795 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2800 /* Maybe we can append to the signature? But only if this is the top-level container */
2801 if (c->enclosing != 0)
2804 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2811 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2812 a = message_extend_body(m, 4, 4, false, false);
2816 *(uint32_t*) a = size - 1;
2819 part = message_append_part(m);
2823 part->memfd = copy_fd;
2824 part->memfd_offset = offset;
2825 part->sealed = true;
2829 m->body_size += size;
2830 message_extend_containers(m, size);
2832 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2833 r = message_add_offset(m, m->body_size);
2840 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2846 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2850 assert_return(m, -EINVAL);
2851 assert_return(!m->sealed, -EPERM);
2852 assert_return(!m->poisoned, -ESTALE);
2854 r = sd_bus_message_open_container(m, 'a', "s");
2858 STRV_FOREACH(i, l) {
2859 r = sd_bus_message_append_basic(m, 's', *i);
2864 return sd_bus_message_close_container(m);
2867 static int bus_message_close_header(sd_bus_message *m) {
2871 /* The actual user data is finished now, we just complete the
2872 variant and struct now (at least on gvariant). Remember
2873 this position, so that during parsing we know where to to
2874 put the outer container end. */
2875 m->user_body_size = m->body_size;
2877 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2878 const char *signature;
2882 /* Add offset table to end of fields array */
2883 if (m->n_header_offsets >= 1) {
2887 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2889 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2890 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2894 for (i = 0; i < m->n_header_offsets; i++)
2895 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2898 /* Add gvariant NUL byte plus signature to the end of
2899 * the body, followed by the final offset pointing to
2900 * the end of the fields array */
2902 signature = strempty(m->root_container.signature);
2903 l = strlen(signature);
2905 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l, 1);
2906 d = message_extend_body(m, 1, 1 + l + sz, false, true);
2911 memcpy((uint8_t*) d + 1, signature, l);
2913 bus_gvariant_write_word_le((uint8_t*) d + 1 + l, sz, sizeof(struct bus_header) + m->fields_size);
2916 m->footer_accessible = 1 + l + sz;
2918 m->header->dbus1.fields_size = m->fields_size;
2919 m->header->dbus1.body_size = m->body_size;
2925 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2926 struct bus_body_part *part;
2936 if (m->n_containers > 0)
2942 if (cookie > 0xffffffffULL &&
2943 !BUS_MESSAGE_IS_GVARIANT(m))
2946 /* In vtables the return signature of method calls is listed,
2947 * let's check if they match if this is a response */
2948 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2949 m->enforced_reply_signature &&
2950 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2953 /* If gvariant marshalling is used we need to close the body structure */
2954 r = bus_message_close_struct(m, &m->root_container, false);
2958 /* If there's a non-trivial signature set, then add it in
2959 * here, but only on dbus1 */
2960 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2961 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2967 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2972 r = bus_message_close_header(m);
2976 if (BUS_MESSAGE_IS_GVARIANT(m))
2977 m->header->dbus2.cookie = cookie;
2979 m->header->dbus1.serial = (uint32_t) cookie;
2981 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2983 /* Add padding at the end of the fields part, since we know
2984 * the body needs to start at an 8 byte alignment. We made
2985 * sure we allocated enough space for this, so all we need to
2986 * do here is to zero it out. */
2987 a = ALIGN8(m->fields_size) - m->fields_size;
2989 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2991 /* If this is something we can send as memfd, then let's seal
2992 the memfd now. Note that we can send memfds as payload only
2993 for directed messages, and not for broadcasts. */
2994 if (m->destination && m->bus->use_memfd) {
2995 MESSAGE_FOREACH_PART(part, i, m)
2996 if (part->memfd >= 0 &&
2998 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2999 part != m->body_end) { /* The last part may never be sent as memfd */
3002 /* Try to seal it if that makes
3003 * sense. First, unmap our own map to
3004 * make sure we don't keep it busy. */
3005 bus_body_part_unmap(part);
3007 /* Then, sync up real memfd size */
3009 r = memfd_set_size(part->memfd, sz);
3013 /* Finally, try to seal */
3014 if (memfd_set_sealed(part->memfd) >= 0)
3015 part->sealed = true;
3019 m->root_container.end = m->user_body_size;
3020 m->root_container.index = 0;
3021 m->root_container.offset_index = 0;
3022 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3029 int bus_body_part_map(struct bus_body_part *part) {
3038 if (part->size <= 0)
3041 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3042 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3043 static const uint8_t zeroes[7] = { };
3044 part->data = (void*) zeroes;
3048 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3049 psz = PAGE_ALIGN(part->size + shift);
3051 if (part->memfd >= 0)
3052 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3053 else if (part->is_zero)
3054 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3058 if (p == MAP_FAILED)
3062 part->mmap_begin = p;
3063 part->data = (uint8_t*) p + shift;
3064 part->munmap_this = true;
3069 void bus_body_part_unmap(struct bus_body_part *part) {
3073 if (part->memfd < 0)
3076 if (!part->mmap_begin)
3079 if (!part->munmap_this)
3082 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3084 part->mmap_begin = NULL;
3087 part->munmap_this = false;
3092 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3093 size_t k, start, end;
3098 start = ALIGN_TO((size_t) *rindex, align);
3099 end = start + nbytes;
3104 /* Verify that padding is 0 */
3105 for (k = *rindex; k < start; k++)
3106 if (((const uint8_t*) p)[k] != 0)
3110 *r = (uint8_t*) p + start;
3117 static bool message_end_of_signature(sd_bus_message *m) {
3118 struct bus_container *c;
3122 c = message_get_container(m);
3123 return !c->signature || c->signature[c->index] == 0;
3126 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3127 struct bus_container *c;
3131 c = message_get_container(m);
3132 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3135 if (BUS_MESSAGE_IS_GVARIANT(m))
3136 return index >= c->end;
3138 assert(c->array_size);
3139 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3143 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3144 assert_return(m, -EINVAL);
3145 assert_return(m->sealed, -EPERM);
3147 if (complete && m->n_containers > 0)
3150 if (message_end_of_signature(m))
3153 if (message_end_of_array(m, m->rindex))
3159 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3160 struct bus_body_part *part;
3166 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3167 part = m->cached_rindex_part;
3168 begin = m->cached_rindex_part_begin;
3178 if (index + sz <= begin + part->size) {
3180 r = bus_body_part_map(part);
3185 *p = (uint8_t*) part->data + index - begin;
3187 m->cached_rindex_part = part;
3188 m->cached_rindex_part_begin = begin;
3193 begin += part->size;
3200 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3207 if (!BUS_MESSAGE_IS_GVARIANT(m))
3210 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3213 sz = bus_gvariant_get_size(c->signature);
3217 if (c->offset_index+1 >= c->n_offsets)
3220 /* Variable-size array */
3222 alignment = bus_gvariant_get_alignment(c->signature);
3223 assert(alignment > 0);
3225 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3226 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3229 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3232 /* Fixed-size array */
3233 *rindex = c->begin + (c->offset_index+1) * sz;
3239 } else if (c->enclosing == 0 ||
3240 c->enclosing == SD_BUS_TYPE_STRUCT ||
3241 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3246 if (c->offset_index+1 >= c->n_offsets)
3249 r = signature_element_length(c->signature + c->index, &n);
3253 r = signature_element_length(c->signature + c->index + n, &j);
3258 memcpy(t, c->signature + c->index + n, j);
3261 alignment = bus_gvariant_get_alignment(t);
3264 assert(alignment > 0);
3266 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3267 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3271 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3274 assert_not_reached("Unknown container type");
3279 /* Reached the end */
3286 static int message_peek_body(
3293 size_t k, start, end, padding;
3294 struct bus_body_part *part;
3301 start = ALIGN_TO((size_t) *rindex, align);
3302 padding = start - *rindex;
3303 end = start + nbytes;
3305 if (end > m->user_body_size)
3308 part = find_part(m, *rindex, padding, (void**) &q);
3313 /* Verify padding */
3314 for (k = 0; k < padding; k++)
3319 part = find_part(m, start, nbytes, (void**) &q);
3320 if (!part || (nbytes > 0 && !q))
3331 static bool validate_nul(const char *s, size_t l) {
3333 /* Check for NUL chars in the string */
3334 if (memchr(s, 0, l))
3337 /* Check for NUL termination */
3344 static bool validate_string(const char *s, size_t l) {
3346 if (!validate_nul(s, l))
3349 /* Check if valid UTF8 */
3350 if (!utf8_is_valid(s))
3356 static bool validate_signature(const char *s, size_t l) {
3358 if (!validate_nul(s, l))
3361 /* Check if valid signature */
3362 if (!signature_is_valid(s, true))
3368 static bool validate_object_path(const char *s, size_t l) {
3370 if (!validate_nul(s, l))
3373 if (!object_path_is_valid(s))
3379 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3380 struct bus_container *c;
3385 assert_return(m, -EINVAL);
3386 assert_return(m->sealed, -EPERM);
3387 assert_return(bus_type_is_basic(type), -EINVAL);
3389 if (message_end_of_signature(m))
3392 if (message_end_of_array(m, m->rindex))
3395 c = message_get_container(m);
3396 if (c->signature[c->index] != type)
3401 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3403 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3406 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3410 if (type == SD_BUS_TYPE_STRING)
3411 ok = validate_string(q, c->item_size-1);
3412 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3413 ok = validate_object_path(q, c->item_size-1);
3415 ok = validate_signature(q, c->item_size-1);
3421 *(const char**) p = q;
3425 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3427 if ((size_t) sz != c->item_size)
3430 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3433 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3439 case SD_BUS_TYPE_BYTE:
3441 *(uint8_t*) p = *(uint8_t*) q;
3444 case SD_BUS_TYPE_BOOLEAN:
3446 *(int*) p = !!*(uint8_t*) q;
3449 case SD_BUS_TYPE_INT16:
3450 case SD_BUS_TYPE_UINT16:
3452 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3455 case SD_BUS_TYPE_INT32:
3456 case SD_BUS_TYPE_UINT32:
3458 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3461 case SD_BUS_TYPE_INT64:
3462 case SD_BUS_TYPE_UINT64:
3463 case SD_BUS_TYPE_DOUBLE:
3465 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3468 case SD_BUS_TYPE_UNIX_FD: {
3471 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3476 *(int*) p = m->fds[j];
3482 assert_not_reached("unexpected type");
3486 r = container_next_item(m, c, &rindex);
3493 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3497 r = message_peek_body(m, &rindex, 4, 4, &q);
3501 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3502 r = message_peek_body(m, &rindex, 1, l+1, &q);
3506 if (type == SD_BUS_TYPE_OBJECT_PATH)
3507 ok = validate_object_path(q, l);
3509 ok = validate_string(q, l);
3514 *(const char**) p = q;
3516 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3519 r = message_peek_body(m, &rindex, 1, 1, &q);
3524 r = message_peek_body(m, &rindex, 1, l+1, &q);
3528 if (!validate_signature(q, l))
3532 *(const char**) p = q;
3537 align = bus_type_get_alignment(type);
3540 sz = bus_type_get_size(type);
3543 r = message_peek_body(m, &rindex, align, sz, &q);
3549 case SD_BUS_TYPE_BYTE:
3551 *(uint8_t*) p = *(uint8_t*) q;
3554 case SD_BUS_TYPE_BOOLEAN:
3556 *(int*) p = !!*(uint32_t*) q;
3559 case SD_BUS_TYPE_INT16:
3560 case SD_BUS_TYPE_UINT16:
3562 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3565 case SD_BUS_TYPE_INT32:
3566 case SD_BUS_TYPE_UINT32:
3568 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3571 case SD_BUS_TYPE_INT64:
3572 case SD_BUS_TYPE_UINT64:
3573 case SD_BUS_TYPE_DOUBLE:
3575 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3578 case SD_BUS_TYPE_UNIX_FD: {
3581 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3586 *(int*) p = m->fds[j];
3591 assert_not_reached("Unknown basic type...");
3598 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3604 static int bus_message_enter_array(
3606 struct bus_container *c,
3607 const char *contents,
3608 uint32_t **array_size,
3611 size_t *n_offsets) {
3625 if (!signature_is_single(contents, true))
3628 if (!c->signature || c->signature[c->index] == 0)
3631 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3634 if (!startswith(c->signature + c->index + 1, contents))
3639 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3642 r = message_peek_body(m, &rindex, 4, 4, &q);
3646 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3649 alignment = bus_type_get_alignment(contents[0]);
3653 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3657 *array_size = (uint32_t*) q;
3659 } else if (c->item_size <= 0) {
3661 /* gvariant: empty array */
3666 } else if (bus_gvariant_is_fixed_size(contents)) {
3668 /* gvariant: fixed length array */
3669 *item_size = bus_gvariant_get_size(contents);
3674 size_t where, p = 0, framing, sz;
3677 /* gvariant: variable length array */
3678 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3680 where = rindex + c->item_size - sz;
3681 r = message_peek_body(m, &where, 1, sz, &q);
3685 framing = bus_gvariant_read_word_le(q, sz);
3686 if (framing > c->item_size - sz)
3688 if ((c->item_size - framing) % sz != 0)
3691 *n_offsets = (c->item_size - framing) / sz;
3693 where = rindex + framing;
3694 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3698 *offsets = new(size_t, *n_offsets);
3702 for (i = 0; i < *n_offsets; i++) {
3705 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3706 if (x > c->item_size - sz)
3711 (*offsets)[i] = rindex + x;
3715 *item_size = (*offsets)[0] - rindex;
3720 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3721 c->index += 1 + strlen(contents);
3726 static int bus_message_enter_variant(
3728 struct bus_container *c,
3729 const char *contents,
3730 size_t *item_size) {
3742 if (!signature_is_single(contents, false))
3745 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3748 if (!c->signature || c->signature[c->index] == 0)
3751 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3756 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3759 k = strlen(contents);
3760 if (1+k > c->item_size)
3763 where = rindex + c->item_size - (1+k);
3764 r = message_peek_body(m, &where, 1, 1+k, &q);
3768 if (*(char*) q != 0)
3771 if (memcmp((uint8_t*) q+1, contents, k))
3774 *item_size = c->item_size - (1+k);
3777 r = message_peek_body(m, &rindex, 1, 1, &q);
3782 r = message_peek_body(m, &rindex, 1, l+1, &q);
3786 if (!validate_signature(q, l))
3789 if (!streq(q, contents))
3795 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3801 static int build_struct_offsets(
3803 const char *signature,
3807 size_t *n_offsets) {
3809 unsigned n_variable = 0, n_total = 0, v;
3810 size_t previous = 0, where;
3821 if (isempty(signature)) {
3828 sz = bus_gvariant_determine_word_size(size, 0);
3832 /* First, loop over signature and count variable elements and
3833 * elements in general. We use this to know how large the
3834 * offset array is at the end of the structure. Note that
3835 * GVariant only stores offsets for all variable size elements
3836 * that are not the last item. */
3842 r = signature_element_length(p, &n);
3851 r = bus_gvariant_is_fixed_size(t);
3856 if (r == 0 && p[n] != 0) /* except the last item */
3863 if (size < n_variable * sz)
3866 where = m->rindex + size - (n_variable * sz);
3867 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3873 *offsets = new(size_t, n_total);
3879 /* Second, loop again and build an offset table */
3885 r = signature_element_length(p, &n);
3894 k = bus_gvariant_get_size(t);
3902 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3905 if (m->rindex + x < previous)
3908 /* The last item's end
3909 * is determined from
3912 x = size - (n_variable * sz);
3914 offset = m->rindex + x;
3920 align = bus_gvariant_get_alignment(t);
3923 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3927 previous = (*offsets)[(*n_offsets)++] = offset;
3932 assert(*n_offsets == n_total);
3934 *item_size = (*offsets)[0] - m->rindex;
3938 static int enter_struct_or_dict_entry(
3940 struct bus_container *c,
3941 const char *contents,
3944 size_t *n_offsets) {
3955 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3958 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3962 } else if (c->item_size <= 0) {
3964 /* gvariant empty struct */
3969 /* gvariant with contents */
3970 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3975 static int bus_message_enter_struct(
3977 struct bus_container *c,
3978 const char *contents,
3981 size_t *n_offsets) {
3993 if (!signature_is_valid(contents, false))
3996 if (!c->signature || c->signature[c->index] == 0)
3999 l = strlen(contents);
4001 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4002 !startswith(c->signature + c->index + 1, contents) ||
4003 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4006 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4010 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4011 c->index += 1 + l + 1;
4016 static int bus_message_enter_dict_entry(
4018 struct bus_container *c,
4019 const char *contents,
4022 size_t *n_offsets) {
4031 if (!signature_is_pair(contents))
4034 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4037 if (!c->signature || c->signature[c->index] == 0)
4040 l = strlen(contents);
4042 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4043 !startswith(c->signature + c->index + 1, contents) ||
4044 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4047 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4051 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4052 c->index += 1 + l + 1;
4057 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4059 const char *contents) {
4060 struct bus_container *c, *w;
4061 uint32_t *array_size = NULL;
4064 size_t *offsets = NULL;
4065 size_t n_offsets = 0, item_size = 0;
4068 assert_return(m, -EINVAL);
4069 assert_return(m->sealed, -EPERM);
4070 assert_return(type != 0 || !contents, -EINVAL);
4072 if (type == 0 || !contents) {
4076 /* Allow entering into anonymous containers */
4077 r = sd_bus_message_peek_type(m, &tt, &cc);
4081 if (type != 0 && type != tt)
4084 if (contents && !streq(contents, cc))
4092 * We enforce a global limit on container depth, that is much
4093 * higher than the 32 structs and 32 arrays the specification
4094 * mandates. This is simpler to implement for us, and we need
4095 * this only to ensure our container array doesn't grow
4096 * without bounds. We are happy to return any data from a
4097 * message as long as the data itself is valid, even if the
4098 * overall message might be not.
4100 * Note that the message signature is validated when
4101 * parsing the headers, and that validation does check the
4104 * Note that the specification defines no limits on the depth
4105 * of stacked variants, but we do.
4107 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4110 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4113 if (message_end_of_signature(m))
4116 if (message_end_of_array(m, m->rindex))
4119 c = message_get_container(m);
4121 signature = strdup(contents);
4125 c->saved_index = c->index;
4128 if (type == SD_BUS_TYPE_ARRAY)
4129 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4130 else if (type == SD_BUS_TYPE_VARIANT)
4131 r = bus_message_enter_variant(m, c, contents, &item_size);
4132 else if (type == SD_BUS_TYPE_STRUCT)
4133 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4134 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4135 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4145 /* OK, let's fill it in */
4146 w = m->containers + m->n_containers++;
4147 w->enclosing = type;
4148 w->signature = signature;
4149 w->peeked_signature = NULL;
4153 w->begin = m->rindex;
4154 w->end = m->rindex + c->item_size;
4156 w->array_size = array_size;
4157 w->item_size = item_size;
4158 w->offsets = offsets;
4159 w->n_offsets = n_offsets;
4160 w->offset_index = 0;
4165 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4166 struct bus_container *c;
4170 assert_return(m, -EINVAL);
4171 assert_return(m->sealed, -EPERM);
4172 assert_return(m->n_containers > 0, -ENXIO);
4174 c = message_get_container(m);
4176 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4177 if (c->signature && c->signature[c->index] != 0)
4181 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4182 if (m->rindex < c->end)
4185 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4188 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4189 if (c->begin + l != m->rindex)
4194 free(c->peeked_signature);
4198 c = message_get_container(m);
4201 c->index = c->saved_index;
4202 r = container_next_item(m, c, &m->rindex);
4210 static void message_quit_container(sd_bus_message *m) {
4211 struct bus_container *c;
4215 assert(m->n_containers > 0);
4217 c = message_get_container(m);
4220 assert(m->rindex >= c->before);
4221 m->rindex = c->before;
4223 /* Free container */
4228 /* Correct index of new top-level container */
4229 c = message_get_container(m);
4230 c->index = c->saved_index;
4233 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4234 struct bus_container *c;
4237 assert_return(m, -EINVAL);
4238 assert_return(m->sealed, -EPERM);
4240 if (message_end_of_signature(m))
4243 if (message_end_of_array(m, m->rindex))
4246 c = message_get_container(m);
4248 if (bus_type_is_basic(c->signature[c->index])) {
4252 *type = c->signature[c->index];
4256 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4262 r = signature_element_length(c->signature+c->index+1, &l);
4268 sig = strndup(c->signature + c->index + 1, l);
4272 free(c->peeked_signature);
4273 *contents = c->peeked_signature = sig;
4277 *type = SD_BUS_TYPE_ARRAY;
4282 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4283 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4289 r = signature_element_length(c->signature+c->index, &l);
4294 sig = strndup(c->signature + c->index + 1, l - 2);
4298 free(c->peeked_signature);
4299 *contents = c->peeked_signature = sig;
4303 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4308 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4312 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4315 if (c->item_size < 2)
4318 /* Look for the NUL delimiter that
4319 separates the payload from the
4320 signature. Since the body might be
4321 in a different part that then the
4322 signature we map byte by byte. */
4324 for (k = 2; k <= c->item_size; k++) {
4327 where = m->rindex + c->item_size - k;
4328 r = message_peek_body(m, &where, 1, k, &q);
4332 if (*(char*) q == 0)
4336 if (k > c->item_size)
4339 free(c->peeked_signature);
4340 c->peeked_signature = strndup((char*) q + 1, k - 1);
4341 if (!c->peeked_signature)
4344 if (!signature_is_valid(c->peeked_signature, true))
4347 *contents = c->peeked_signature;
4352 r = message_peek_body(m, &rindex, 1, 1, &q);
4357 r = message_peek_body(m, &rindex, 1, l+1, &q);
4361 if (!validate_signature(q, l))
4369 *type = SD_BUS_TYPE_VARIANT;
4384 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4385 struct bus_container *c;
4387 assert_return(m, -EINVAL);
4388 assert_return(m->sealed, -EPERM);
4391 message_reset_containers(m);
4394 c = message_get_container(m);
4396 c = message_get_container(m);
4398 c->offset_index = 0;
4400 m->rindex = c->begin;
4403 c->offset_index = 0;
4404 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4406 return !isempty(c->signature);
4409 static int message_read_ap(
4414 unsigned n_array, n_struct;
4415 TypeStack stack[BUS_CONTAINER_DEPTH];
4416 unsigned stack_ptr = 0;
4417 unsigned n_loop = 0;
4425 /* Ideally, we'd just call ourselves recursively on every
4426 * complex type. However, the state of a va_list that is
4427 * passed to a function is undefined after that function
4428 * returns. This means we need to docode the va_list linearly
4429 * in a single stackframe. We hence implement our own
4430 * home-grown stack in an array. */
4432 n_array = (unsigned) -1; /* length of current array entries */
4433 n_struct = strlen(types); /* length of current struct contents signature */
4440 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4441 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4447 r = sd_bus_message_exit_container(m);
4455 if (n_array != (unsigned) -1)
4464 case SD_BUS_TYPE_BYTE:
4465 case SD_BUS_TYPE_BOOLEAN:
4466 case SD_BUS_TYPE_INT16:
4467 case SD_BUS_TYPE_UINT16:
4468 case SD_BUS_TYPE_INT32:
4469 case SD_BUS_TYPE_UINT32:
4470 case SD_BUS_TYPE_INT64:
4471 case SD_BUS_TYPE_UINT64:
4472 case SD_BUS_TYPE_DOUBLE:
4473 case SD_BUS_TYPE_STRING:
4474 case SD_BUS_TYPE_OBJECT_PATH:
4475 case SD_BUS_TYPE_SIGNATURE:
4476 case SD_BUS_TYPE_UNIX_FD: {
4479 p = va_arg(ap, void*);
4480 r = sd_bus_message_read_basic(m, *t, p);
4493 case SD_BUS_TYPE_ARRAY: {
4496 r = signature_element_length(t + 1, &k);
4502 memcpy(s, t + 1, k);
4505 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4516 if (n_array == (unsigned) -1) {
4521 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4527 n_array = va_arg(ap, unsigned);
4532 case SD_BUS_TYPE_VARIANT: {
4535 s = va_arg(ap, const char *);
4539 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4549 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4554 n_struct = strlen(s);
4555 n_array = (unsigned) -1;
4560 case SD_BUS_TYPE_STRUCT_BEGIN:
4561 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4564 r = signature_element_length(t, &k);
4570 memcpy(s, t + 1, k - 2);
4573 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4583 if (n_array == (unsigned) -1) {
4588 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4594 n_array = (unsigned) -1;
4607 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4611 assert_return(m, -EINVAL);
4612 assert_return(m->sealed, -EPERM);
4613 assert_return(types, -EINVAL);
4615 va_start(ap, types);
4616 r = message_read_ap(m, types, ap);
4622 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4625 assert_return(m, -EINVAL);
4626 assert_return(m->sealed, -EPERM);
4628 /* If types is NULL, read exactly one element */
4630 struct bus_container *c;
4633 if (message_end_of_signature(m))
4636 if (message_end_of_array(m, m->rindex))
4639 c = message_get_container(m);
4641 r = signature_element_length(c->signature + c->index, &l);
4645 types = strndupa(c->signature + c->index, l);
4650 case 0: /* Nothing to drop */
4653 case SD_BUS_TYPE_BYTE:
4654 case SD_BUS_TYPE_BOOLEAN:
4655 case SD_BUS_TYPE_INT16:
4656 case SD_BUS_TYPE_UINT16:
4657 case SD_BUS_TYPE_INT32:
4658 case SD_BUS_TYPE_UINT32:
4659 case SD_BUS_TYPE_INT64:
4660 case SD_BUS_TYPE_UINT64:
4661 case SD_BUS_TYPE_DOUBLE:
4662 case SD_BUS_TYPE_STRING:
4663 case SD_BUS_TYPE_OBJECT_PATH:
4664 case SD_BUS_TYPE_SIGNATURE:
4665 case SD_BUS_TYPE_UNIX_FD:
4667 r = sd_bus_message_read_basic(m, *types, NULL);
4671 r = sd_bus_message_skip(m, types + 1);
4677 case SD_BUS_TYPE_ARRAY: {
4680 r = signature_element_length(types + 1, &k);
4686 memcpy(s, types+1, k);
4689 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4694 r = sd_bus_message_skip(m, s);
4701 r = sd_bus_message_exit_container(m);
4706 r = sd_bus_message_skip(m, types + 1 + k);
4713 case SD_BUS_TYPE_VARIANT: {
4714 const char *contents;
4717 r = sd_bus_message_peek_type(m, &x, &contents);
4721 if (x != SD_BUS_TYPE_VARIANT)
4724 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4728 r = sd_bus_message_skip(m, contents);
4733 r = sd_bus_message_exit_container(m);
4737 r = sd_bus_message_skip(m, types + 1);
4744 case SD_BUS_TYPE_STRUCT_BEGIN:
4745 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4748 r = signature_element_length(types, &k);
4754 memcpy(s, types+1, k-2);
4757 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4761 r = sd_bus_message_skip(m, s);
4766 r = sd_bus_message_exit_container(m);
4771 r = sd_bus_message_skip(m, types + k);
4783 _public_ int sd_bus_message_read_array(
4789 struct bus_container *c;
4795 assert_return(m, -EINVAL);
4796 assert_return(m->sealed, -EPERM);
4797 assert_return(bus_type_is_trivial(type), -EINVAL);
4798 assert_return(ptr, -EINVAL);
4799 assert_return(size, -EINVAL);
4800 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
4802 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4806 c = message_get_container(m);
4808 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4809 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4813 sz = c->end - c->begin;
4815 align = bus_type_get_alignment(type);
4819 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4823 /* Zero length array, let's return some aligned
4824 * pointer that is not NULL */
4825 p = (uint8_t*) NULL + align;
4827 r = message_peek_body(m, &m->rindex, align, sz, &p);
4832 r = sd_bus_message_exit_container(m);
4836 *ptr = (const void*) p;
4842 message_quit_container(m);
4846 static int message_peek_fields(
4857 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4860 static int message_peek_field_uint32(
4872 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4875 /* identical for gvariant and dbus1 */
4877 r = message_peek_fields(m, ri, 4, 4, &q);
4882 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4887 static int message_peek_field_uint64(
4899 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4902 /* identical for gvariant and dbus1 */
4904 r = message_peek_fields(m, ri, 8, 8, &q);
4909 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4914 static int message_peek_field_string(
4916 bool (*validate)(const char *p),
4928 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4933 r = message_peek_fields(m, ri, 1, item_size, &q);
4939 r = message_peek_field_uint32(m, ri, 4, &l);
4943 r = message_peek_fields(m, ri, 1, l+1, &q);
4949 if (!validate_nul(q, l))
4955 if (!validate_string(q, l))
4965 static int message_peek_field_signature(
4978 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4983 r = message_peek_fields(m, ri, 1, item_size, &q);
4989 r = message_peek_fields(m, ri, 1, 1, &q);
4994 r = message_peek_fields(m, ri, 1, l+1, &q);
4999 if (!validate_signature(q, l))
5008 static int message_skip_fields(
5011 uint32_t array_size,
5012 const char **signature) {
5014 size_t original_index;
5020 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5022 original_index = *ri;
5028 if (array_size != (uint32_t) -1 &&
5029 array_size <= *ri - original_index)
5036 if (t == SD_BUS_TYPE_STRING) {
5038 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5044 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5046 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5052 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5054 r = message_peek_field_signature(m, ri, 0, NULL);
5060 } else if (bus_type_is_basic(t)) {
5063 align = bus_type_get_alignment(t);
5064 k = bus_type_get_size(t);
5065 assert(align > 0 && k > 0);
5067 r = message_peek_fields(m, ri, align, k, NULL);
5073 } else if (t == SD_BUS_TYPE_ARRAY) {
5075 r = signature_element_length(*signature+1, &l);
5085 strncpy(sig, *signature + 1, l-1);
5088 alignment = bus_type_get_alignment(sig[0]);
5092 r = message_peek_field_uint32(m, ri, 0, &nas);
5095 if (nas > BUS_ARRAY_MAX_SIZE)
5098 r = message_peek_fields(m, ri, alignment, 0, NULL);
5102 r = message_skip_fields(m, ri, nas, (const char**) &s);
5107 (*signature) += 1 + l;
5109 } else if (t == SD_BUS_TYPE_VARIANT) {
5112 r = message_peek_field_signature(m, ri, 0, &s);
5116 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5122 } else if (t == SD_BUS_TYPE_STRUCT ||
5123 t == SD_BUS_TYPE_DICT_ENTRY) {
5125 r = signature_element_length(*signature, &l);
5132 strncpy(sig, *signature + 1, l-1);
5135 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5146 int bus_message_parse_fields(sd_bus_message *m) {
5149 uint32_t unix_fds = 0;
5150 bool unix_fds_set = false;
5151 void *offsets = NULL;
5152 unsigned n_offsets = 0;
5158 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5161 /* Read the signature from the end of the body variant first */
5162 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5163 if (m->footer_accessible < 1 + sz)
5166 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5168 if (p < (char*) m->footer)
5174 /* We found the beginning of the signature string, yay! */
5176 c = strndup(p + 1, ((char*) m->footer + m->footer_accessible) - p - (1 + sz));
5180 free(m->root_container.signature);
5181 m->root_container.signature = c;
5188 /* Calculate the actual user body size, by removing
5189 * the trailing variant signature and struct offset
5191 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5193 /* Pull out the offset table for the fields array */
5194 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5199 ri = m->fields_size - sz;
5200 r = message_peek_fields(m, &ri, 1, sz, &q);
5204 framing = bus_gvariant_read_word_le(q, sz);
5205 if (framing >= m->fields_size - sz)
5207 if ((m->fields_size - framing) % sz != 0)
5211 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5215 n_offsets = (m->fields_size - framing) / sz;
5218 m->user_body_size = m->body_size;
5221 while (ri < m->fields_size) {
5222 _cleanup_free_ char *sig = NULL;
5223 const char *signature;
5224 uint64_t field_type;
5225 size_t item_size = (size_t) -1;
5227 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5236 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5238 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5242 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5246 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5253 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5258 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5263 where = ri = ALIGN_TO(ri, 8);
5264 item_size = end - ri;
5265 r = message_peek_fields(m, &where, 1, item_size, &q);
5269 b = memrchr(q, 0, item_size);
5273 sig = strndup(b+1, item_size - (b+1-(char*) q));
5278 item_size = b - (char*) q;
5280 r = message_peek_field_signature(m, &ri, 0, &signature);
5285 switch (field_type) {
5287 case _BUS_MESSAGE_HEADER_INVALID:
5290 case BUS_MESSAGE_HEADER_PATH:
5295 if (!streq(signature, "o"))
5298 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5301 case BUS_MESSAGE_HEADER_INTERFACE:
5306 if (!streq(signature, "s"))
5309 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5312 case BUS_MESSAGE_HEADER_MEMBER:
5317 if (!streq(signature, "s"))
5320 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5323 case BUS_MESSAGE_HEADER_ERROR_NAME:
5328 if (!streq(signature, "s"))
5331 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5333 m->error._need_free = -1;
5337 case BUS_MESSAGE_HEADER_DESTINATION:
5342 if (!streq(signature, "s"))
5345 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5348 case BUS_MESSAGE_HEADER_SENDER:
5353 if (!streq(signature, "s"))
5356 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5358 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5359 m->creds.unique_name = (char*) m->sender;
5360 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5366 case BUS_MESSAGE_HEADER_SIGNATURE: {
5370 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5373 if (m->root_container.signature)
5376 if (!streq(signature, "g"))
5379 r = message_peek_field_signature(m, &ri, item_size, &s);
5387 free(m->root_container.signature);
5388 m->root_container.signature = c;
5392 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5394 if (m->reply_cookie != 0)
5397 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5398 /* 64bit on dbus2 */
5400 if (!streq(signature, "t"))
5403 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5407 /* 32bit on dbus1 */
5410 if (!streq(signature, "u"))
5413 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5417 m->reply_cookie = serial;
5420 if (m->reply_cookie == 0)
5425 case BUS_MESSAGE_HEADER_UNIX_FDS:
5429 if (!streq(signature, "u"))
5432 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5436 unix_fds_set = true;
5440 if (!BUS_MESSAGE_IS_GVARIANT(m))
5441 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5450 if (m->n_fds != unix_fds)
5453 switch (m->header->type) {
5455 case SD_BUS_MESSAGE_SIGNAL:
5456 if (!m->path || !m->interface || !m->member)
5459 if (m->reply_cookie != 0)
5464 case SD_BUS_MESSAGE_METHOD_CALL:
5466 if (!m->path || !m->member)
5469 if (m->reply_cookie != 0)
5474 case SD_BUS_MESSAGE_METHOD_RETURN:
5476 if (m->reply_cookie == 0)
5480 case SD_BUS_MESSAGE_METHOD_ERROR:
5482 if (m->reply_cookie == 0 || !m->error.name)
5487 /* Refuse non-local messages that claim they are local */
5488 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5490 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5492 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5495 m->root_container.end = m->user_body_size;
5497 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5498 r = build_struct_offsets(
5500 m->root_container.signature,
5502 &m->root_container.item_size,
5503 &m->root_container.offsets,
5504 &m->root_container.n_offsets);
5509 /* Try to read the error message, but if we can't it's a non-issue */
5510 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5511 sd_bus_message_read(m, "s", &m->error.message);
5516 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5517 assert_return(m, -EINVAL);
5518 assert_return(destination, -EINVAL);
5519 assert_return(!m->sealed, -EPERM);
5520 assert_return(!m->destination, -EEXIST);
5522 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5525 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5529 struct bus_body_part *part;
5535 total = BUS_MESSAGE_SIZE(m);
5541 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5542 MESSAGE_FOREACH_PART(part, i, m)
5543 e = mempcpy(e, part->data, part->size);
5545 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5553 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5559 r = sd_bus_message_enter_container(m, 'a', "s");
5566 r = sd_bus_message_read_basic(m, 's', &s);
5572 r = strv_extend(l, s);
5577 r = sd_bus_message_exit_container(m);
5584 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5588 assert_return(m, -EINVAL);
5589 assert_return(m->sealed, -EPERM);
5590 assert_return(l, -EINVAL);
5592 r = bus_message_read_strv_extend(m, &strv);
5602 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
5603 const char *contents;
5612 r = sd_bus_message_rewind(m, true);
5617 r = sd_bus_message_peek_type(m, &type, &contents);
5623 /* Don't match against arguments after the first one we don't understand */
5624 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5625 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5631 r = sd_bus_message_skip(m, NULL);
5636 if (type == SD_BUS_TYPE_ARRAY) {
5638 r = sd_bus_message_read_strv(m, strv);
5645 r = sd_bus_message_read_basic(m, type, str);
5655 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5656 assert_return(m, EINVAL);
5658 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5661 return sd_bus_error_get_errno(&m->error);
5664 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5665 struct bus_container *c;
5667 assert_return(m, NULL);
5669 c = complete ? &m->root_container : message_get_container(m);
5670 return strempty(c->signature);
5673 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5674 assert_return(m, -EINVAL);
5676 return isempty(m->root_container.signature);
5679 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5680 assert_return(m, -EINVAL);
5682 return streq(strempty(m->root_container.signature), strempty(signature));
5685 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5686 bool done_something = false;
5689 assert_return(m, -EINVAL);
5690 assert_return(source, -EINVAL);
5691 assert_return(!m->sealed, -EPERM);
5692 assert_return(source->sealed, -EPERM);
5695 const char *contents;
5710 r = sd_bus_message_peek_type(source, &type, &contents);
5716 done_something = true;
5718 if (bus_type_is_container(type) > 0) {
5720 r = sd_bus_message_enter_container(source, type, contents);
5724 r = sd_bus_message_open_container(m, type, contents);
5728 r = sd_bus_message_copy(m, source, true);
5732 r = sd_bus_message_close_container(m);
5736 r = sd_bus_message_exit_container(source);
5743 r = sd_bus_message_read_basic(source, type, &basic);
5749 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5750 type == SD_BUS_TYPE_SIGNATURE ||
5751 type == SD_BUS_TYPE_STRING)
5752 r = sd_bus_message_append_basic(m, type, basic.string);
5754 r = sd_bus_message_append_basic(m, type, &basic);
5761 return done_something;
5764 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5769 assert_return(m, -EINVAL);
5770 assert_return(m->sealed, -EPERM);
5771 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5772 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5773 assert_return(type || contents, -EINVAL);
5774 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5776 r = sd_bus_message_peek_type(m, &t, &c);
5780 if (type != 0 && type != t)
5783 if (contents && !streq_ptr(contents, c))
5789 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5790 assert_return(m, NULL);
5795 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5796 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5804 switch ((*m)->header->type) {
5806 case SD_BUS_MESSAGE_SIGNAL:
5807 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5813 case SD_BUS_MESSAGE_METHOD_CALL:
5814 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5820 case SD_BUS_MESSAGE_METHOD_RETURN:
5821 case SD_BUS_MESSAGE_METHOD_ERROR:
5823 n = message_new(bus, (*m)->header->type);
5827 n->reply_cookie = (*m)->reply_cookie;
5829 r = message_append_reply_cookie(n, n->reply_cookie);
5833 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5834 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5838 n->error._need_free = -1;
5847 if ((*m)->destination && !n->destination) {
5848 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5853 if ((*m)->sender && !n->sender) {
5854 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5859 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5861 r = sd_bus_message_copy(n, *m, true);
5865 timeout = (*m)->timeout;
5866 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5867 timeout = BUS_DEFAULT_TIMEOUT;
5869 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5873 sd_bus_message_unref(*m);
5880 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5884 assert_return(!m->sealed, -EPERM);
5885 assert_return(!m->sender, -EPERM);
5887 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5890 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5891 assert_return(m, -EINVAL);
5892 assert_return(priority, -EINVAL);
5894 *priority = m->priority;
5898 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5899 assert_return(m, -EINVAL);
5900 assert_return(!m->sealed, -EPERM);
5902 m->priority = priority;