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"
33 #include "bus-message.h"
34 #include "bus-internal.h"
36 #include "bus-signature.h"
37 #include "bus-gvariant.h"
39 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
41 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
46 if (old_base == new_base)
49 if ((uint8_t*) p < (uint8_t*) old_base)
52 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
55 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
58 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
62 if (part->memfd >= 0) {
63 /* If we can reuse the memfd, try that. For that it
64 * can't be sealed yet. */
67 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped);
70 assert_se(munmap(part->data, part->mapped) == 0);
72 close_nointr_nofail(part->memfd);
75 } else if (part->munmap_this)
76 munmap(part->data, part->mapped);
77 else if (part->free_this)
84 static void message_reset_parts(sd_bus_message *m) {
85 struct bus_body_part *part;
90 while (m->n_body_parts > 0) {
91 struct bus_body_part *next = part->next;
92 message_free_part(m, part);
99 m->cached_rindex_part = NULL;
100 m->cached_rindex_part_begin = 0;
103 static void message_reset_containers(sd_bus_message *m) {
108 for (i = 0; i < m->n_containers; i++) {
109 free(m->containers[i].signature);
110 free(m->containers[i].offsets);
114 m->containers = NULL;
117 m->root_container.index = 0;
120 static void message_free(sd_bus_message *m) {
126 message_reset_parts(m);
131 if (m->release_kdbus) {
134 off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
135 ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &off);
139 sd_bus_unref(m->bus);
142 close_many(m->fds, m->n_fds);
146 if (m->iovec != m->iovec_fixed)
149 message_reset_containers(m);
150 free(m->root_container.signature);
151 free(m->root_container.offsets);
153 free(m->peeked_signature);
155 bus_creds_done(&m->creds);
159 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
161 size_t old_size, new_size, start;
164 assert_return(!m->poisoned, NULL);
166 old_size = sizeof(struct bus_header) + m->header->fields_size;
167 start = ALIGN_TO(old_size, align);
168 new_size = start + sz;
170 if (old_size == new_size)
171 return (uint8_t*) m->header + old_size;
173 if (new_size > (size_t) ((uint32_t) -1))
176 if (m->free_header) {
177 np = realloc(m->header, ALIGN8(new_size));
181 /* Initially, the header is allocated as part of of
182 * the sd_bus_message itself, let's replace it by
185 np = malloc(ALIGN8(new_size));
189 memcpy(np, m->header, sizeof(struct bus_header));
192 /* Zero out padding */
193 if (start > old_size)
194 memset((uint8_t*) np + old_size, 0, start - old_size);
198 m->header->fields_size = new_size - sizeof(struct bus_header);
200 /* Adjust quick access pointers */
201 m->path = adjust_pointer(m->path, op, old_size, m->header);
202 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
203 m->member = adjust_pointer(m->member, op, old_size, m->header);
204 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
205 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
206 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
208 m->free_header = true;
211 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
214 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
217 return (uint8_t*) np + start;
224 static int message_append_field_string(
236 /* dbus1 doesn't allow strings over 32bit, let's enforce this
237 * globally, to not risk convertability */
239 if (l > (size_t) (uint32_t) -1)
242 /* Signature "(yv)" where the variant contains "s" */
244 if (BUS_MESSAGE_IS_GVARIANT(m)) {
246 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
247 p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
259 *ret = (char*) p + 8;
262 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
263 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
272 ((uint32_t*) p)[1] = l;
273 memcpy(p + 8, s, l + 1);
276 *ret = (char*) p + 8;
282 static int message_append_field_signature(
293 /* dbus1 doesn't allow signatures over 32bit, let's enforce
294 * this globally, to not risk convertability */
299 /* Signature "(yv)" where the variant contains "g" */
301 if (BUS_MESSAGE_IS_GVARIANT(m))
302 /* For gvariant the serialization is the same as for normal strings */
303 return message_append_field_string(m, h, 'g', s, ret);
305 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
306 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
312 p[2] = SD_BUS_TYPE_SIGNATURE;
315 memcpy(p + 5, s, l + 1);
318 *ret = (const char*) p + 5;
324 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
329 if (BUS_MESSAGE_IS_GVARIANT(m)) {
330 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
332 p = message_extend_fields(m, 8, 1 + 7 + 4 + 1 + 1, true);
338 *((uint32_t*) (p + 8)) = x;
342 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
343 p = message_extend_fields(m, 8, 4 + 4, false);
349 p[2] = SD_BUS_TYPE_UINT32;
352 ((uint32_t*) p)[1] = x;
358 int bus_message_from_header(
364 const struct ucred *ucred,
367 sd_bus_message **ret) {
370 struct bus_header *h;
373 assert(buffer || length <= 0);
374 assert(fds || n_fds <= 0);
377 if (length < sizeof(struct bus_header))
381 if (h->version != 1 &&
388 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
391 if (h->endian != BUS_LITTLE_ENDIAN &&
392 h->endian != BUS_BIG_ENDIAN)
395 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
398 label_sz = strlen(label);
413 m->creds.uid = ucred->uid;
414 m->creds.pid = ucred->pid;
415 m->creds.gid = ucred->gid;
416 m->creds.mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID;
420 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
421 memcpy(m->creds.label, label, label_sz + 1);
423 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
427 m->bus = sd_bus_ref(bus);
433 int bus_message_from_malloc(
439 const struct ucred *ucred,
441 sd_bus_message **ret) {
447 r = bus_message_from_header(bus, buffer, length, fds, n_fds, ucred, label, 0, &m);
451 if (length != BUS_MESSAGE_SIZE(m)) {
456 sz = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
459 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
461 m->body.sealed = true;
466 m->iovec = m->iovec_fixed;
467 m->iovec[0].iov_base = buffer;
468 m->iovec[0].iov_len = length;
470 r = bus_message_parse_fields(m);
474 /* We take possession of the memory and fds now */
475 m->free_header = true;
486 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
489 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
494 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
495 m->header->endian = BUS_NATIVE_ENDIAN;
496 m->header->type = type;
497 m->header->version = bus ? bus->message_version : 1;
498 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
499 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
502 m->bus = sd_bus_ref(bus);
507 _public_ int sd_bus_message_new_signal(
510 const char *interface,
512 sd_bus_message **m) {
517 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
518 assert_return(object_path_is_valid(path), -EINVAL);
519 assert_return(interface_name_is_valid(interface), -EINVAL);
520 assert_return(member_name_is_valid(member), -EINVAL);
521 assert_return(m, -EINVAL);
523 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
527 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
529 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
532 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
535 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
543 sd_bus_message_unref(t);
547 _public_ int sd_bus_message_new_method_call(
549 const char *destination,
551 const char *interface,
553 sd_bus_message **m) {
558 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
559 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
560 assert_return(object_path_is_valid(path), -EINVAL);
561 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
562 assert_return(member_name_is_valid(member), -EINVAL);
563 assert_return(m, -EINVAL);
565 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
569 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
572 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
577 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
583 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
596 static int message_new_reply(
597 sd_bus_message *call,
599 sd_bus_message **m) {
604 assert_return(call, -EINVAL);
605 assert_return(call->sealed, -EPERM);
606 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
607 assert_return(!call->bus || call->bus->state != BUS_UNSET, -ENOTCONN);
608 assert_return(m, -EINVAL);
610 t = message_new(call->bus, type);
614 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
615 t->reply_serial = BUS_MESSAGE_SERIAL(call);
617 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
622 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
627 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
628 t->enforced_reply_signature = call->enforced_reply_signature;
638 _public_ int sd_bus_message_new_method_return(
639 sd_bus_message *call,
640 sd_bus_message **m) {
642 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
645 _public_ int sd_bus_message_new_method_error(
646 sd_bus_message *call,
647 const sd_bus_error *e,
648 sd_bus_message **m) {
653 assert_return(sd_bus_error_is_set(e), -EINVAL);
654 assert_return(m, -EINVAL);
656 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
660 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
665 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
670 t->error._need_free = -1;
680 _public_ int sd_bus_message_new_method_errorf(
681 sd_bus_message *call,
687 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
690 assert_return(name, -EINVAL);
691 assert_return(m, -EINVAL);
693 va_start(ap, format);
694 bus_error_setfv(&error, name, format, ap);
697 return sd_bus_message_new_method_error(call, &error, m);
700 _public_ int sd_bus_message_new_method_errno(
701 sd_bus_message *call,
703 const sd_bus_error *p,
704 sd_bus_message **m) {
706 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
708 if (sd_bus_error_is_set(p))
709 return sd_bus_message_new_method_error(call, p, m);
711 sd_bus_error_set_errno(&berror, error);
713 return sd_bus_message_new_method_error(call, &berror, m);
716 _public_ int sd_bus_message_new_method_errnof(
717 sd_bus_message *call,
723 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
726 va_start(ap, format);
727 bus_error_set_errnofv(&berror, error, format, ap);
730 return sd_bus_message_new_method_error(call, &berror, m);
733 int bus_message_new_synthetic_error(
736 const sd_bus_error *e,
737 sd_bus_message **m) {
742 assert(sd_bus_error_is_set(e));
745 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
749 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
750 t->reply_serial = serial;
752 r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
756 if (bus && bus->unique_name) {
757 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
762 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
767 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
772 t->error._need_free = -1;
782 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
783 assert_return(m, NULL);
785 assert(m->n_ref > 0);
791 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
792 assert_return(m, NULL);
794 assert(m->n_ref > 0);
803 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
804 assert_return(m, -EINVAL);
805 assert_return(type, -EINVAL);
807 *type = m->header->type;
811 _public_ int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
812 assert_return(m, -EINVAL);
813 assert_return(serial, -EINVAL);
814 assert_return(m->header->serial != 0, -ENOENT);
816 *serial = BUS_MESSAGE_SERIAL(m);
820 _public_ int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
821 assert_return(m, -EINVAL);
822 assert_return(serial, -EINVAL);
823 assert_return(m->reply_serial != 0, -ENOENT);
825 *serial = m->reply_serial;
829 _public_ int sd_bus_message_get_no_reply(sd_bus_message *m) {
830 assert_return(m, -EINVAL);
832 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL ? !!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
835 _public_ int sd_bus_message_get_no_auto_start(sd_bus_message *m) {
836 assert_return(m, -EINVAL);
838 return !!(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
841 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
842 assert_return(m, NULL);
847 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
848 assert_return(m, NULL);
853 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
854 assert_return(m, NULL);
859 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
860 assert_return(m, NULL);
862 return m->destination;
865 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
866 assert_return(m, NULL);
871 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
872 assert_return(m, NULL);
873 assert_return(sd_bus_error_is_set(&m->error), NULL);
878 _public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
879 assert_return(m, -EINVAL);
880 assert_return(usec, -EINVAL);
881 assert_return(m->monotonic > 0, -ENODATA);
883 *usec = m->monotonic;
887 _public_ int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
888 assert_return(m, -EINVAL);
889 assert_return(usec, -EINVAL);
890 assert_return(m->realtime > 0, -ENODATA);
896 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
897 assert_return(m, NULL);
899 if (m->creds.mask == 0)
905 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
906 const char *interface,
907 const char *member) {
908 assert_return(m, -EINVAL);
910 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
913 if (interface && (!m->interface || !streq(m->interface, interface)))
916 if (member && (!m->member || !streq(m->member, member)))
922 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
923 const char *interface,
924 const char *member) {
925 assert_return(m, -EINVAL);
927 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
930 if (interface && (!m->interface || !streq(m->interface, interface)))
933 if (member && (!m->member || !streq(m->member, member)))
939 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
940 assert_return(m, -EINVAL);
942 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
945 if (name && (!m->error.name || !streq(m->error.name, name)))
951 _public_ int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
952 assert_return(m, -EINVAL);
953 assert_return(!m->sealed, -EPERM);
954 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
957 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
959 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
964 _public_ int sd_bus_message_set_no_auto_start(sd_bus_message *m, int b) {
965 assert_return(m, -EINVAL);
966 assert_return(!m->sealed, -EPERM);
969 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
971 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
976 static struct bus_container *message_get_container(sd_bus_message *m) {
979 if (m->n_containers == 0)
980 return &m->root_container;
982 assert(m->containers);
983 return m->containers + m->n_containers - 1;
986 struct bus_body_part *message_append_part(sd_bus_message *m) {
987 struct bus_body_part *part;
990 assert_return(!m->poisoned, NULL);
992 if (m->n_body_parts <= 0) {
998 part = new0(struct bus_body_part, 1);
1004 m->body_end->next = part;
1014 static void part_zero(struct bus_body_part *part, size_t sz) {
1019 /* All other fields can be left in their defaults */
1020 assert(!part->data);
1021 assert(part->memfd < 0);
1024 part->is_zero = true;
1025 part->sealed = true;
1028 static int part_make_space(
1029 struct sd_bus_message *m,
1030 struct bus_body_part *part,
1039 assert(!part->sealed);
1044 if (!part->data && part->memfd < 0)
1045 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped);
1047 if (part->memfd >= 0) {
1050 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &u);
1056 if (!part->data || sz > part->mapped) {
1057 size_t psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1059 if (part->mapped <= 0)
1060 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1062 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1064 if (n == MAP_FAILED) {
1073 part->munmap_this = true;
1075 n = realloc(part->data, MAX(sz, 1u));
1082 part->free_this = true;
1086 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1092 static int message_add_offset(sd_bus_message *m, size_t offset) {
1093 struct bus_container *c;
1096 assert(BUS_MESSAGE_IS_GVARIANT(m));
1098 /* Add offset to current container, unless this is the first
1099 * item in it, which will have the 0 offset, which we can
1101 c = message_get_container(m);
1103 if (!c->need_offsets)
1106 if (!GREEDY_REALLOC(c->offsets, c->n_offsets_allocated, c->n_offsets + 1))
1109 c->offsets[c->n_offsets++] = offset;
1113 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1114 struct bus_container *c;
1121 /* Update counters */
1122 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1125 *c->array_size += expand;
1129 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1130 size_t start_body, end_body, padding, added;
1137 assert_return(!m->poisoned, NULL);
1139 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1140 end_body = start_body + sz;
1142 padding = start_body - m->header->body_size;
1143 added = padding + sz;
1145 /* Check for 32bit overflows */
1146 if (end_body > (size_t) ((uint32_t) -1)) {
1152 struct bus_body_part *part = NULL;
1156 m->n_body_parts <= 0 ||
1157 m->body_end->sealed ||
1158 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1162 part = message_append_part(m);
1166 part_zero(part, padding);
1169 part = message_append_part(m);
1173 r = part_make_space(m, part, sz, &p);
1177 struct bus_container *c;
1179 size_t os, start_part, end_part;
1185 start_part = ALIGN_TO(part->size, align);
1186 end_part = start_part + sz;
1188 r = part_make_space(m, part, end_part, &p);
1193 memset(p, 0, padding);
1194 p = (uint8_t*) p + padding;
1197 /* Readjust pointers */
1198 for (c = m->containers; c < m->containers + m->n_containers; c++)
1199 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1201 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1204 /* Return something that is not NULL and is aligned */
1205 p = (uint8_t *) NULL + align;
1207 m->header->body_size = end_body;
1208 message_extend_containers(m, added);
1211 r = message_add_offset(m, end_body);
1221 static int message_push_fd(sd_bus_message *m, int fd) {
1232 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1236 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1239 close_nointr_nofail(copy);
1244 m->fds[m->n_fds] = copy;
1250 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1251 _cleanup_close_ int fd = -1;
1252 struct bus_container *c;
1256 assert_return(m, -EINVAL);
1257 assert_return(!m->sealed, -EPERM);
1258 assert_return(bus_type_is_basic(type), -EINVAL);
1259 assert_return(!m->poisoned, -ESTALE);
1261 c = message_get_container(m);
1263 if (c->signature && c->signature[c->index]) {
1264 /* Container signature is already set */
1266 if (c->signature[c->index] != type)
1271 /* Maybe we can append to the signature? But only if this is the top-level container*/
1272 if (c->enclosing != 0)
1275 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1282 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1288 case SD_BUS_TYPE_SIGNATURE:
1289 case SD_BUS_TYPE_STRING:
1292 /* Fall through... */
1293 case SD_BUS_TYPE_OBJECT_PATH:
1301 case SD_BUS_TYPE_BOOLEAN:
1303 u8 = p && *(int*) p;
1309 case SD_BUS_TYPE_UNIX_FD:
1314 fd = message_push_fd(m, *(int*) p);
1325 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1326 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1333 a = message_extend_body(m, align, sz, true);
1340 *stored = (const uint8_t*) a;
1347 case SD_BUS_TYPE_STRING:
1348 /* To make things easy we'll serialize a NULL string
1349 * into the empty string */
1352 /* Fall through... */
1353 case SD_BUS_TYPE_OBJECT_PATH:
1359 sz = 4 + strlen(p) + 1;
1362 case SD_BUS_TYPE_SIGNATURE:
1367 sz = 1 + strlen(p) + 1;
1370 case SD_BUS_TYPE_BOOLEAN:
1372 u32 = p && *(int*) p;
1378 case SD_BUS_TYPE_UNIX_FD:
1383 fd = message_push_fd(m, *(int*) p);
1394 align = bus_type_get_alignment(type);
1395 sz = bus_type_get_size(type);
1402 a = message_extend_body(m, align, sz, false);
1406 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1407 *(uint32_t*) a = sz - 5;
1408 memcpy((uint8_t*) a + 4, p, sz - 4);
1411 *stored = (const uint8_t*) a + 4;
1413 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1414 *(uint8_t*) a = sz - 1;
1415 memcpy((uint8_t*) a + 1, p, sz - 1);
1418 *stored = (const uint8_t*) a + 1;
1427 if (type == SD_BUS_TYPE_UNIX_FD)
1430 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1437 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1438 return message_append_basic(m, type, p, NULL);
1441 _public_ int sd_bus_message_append_string_space(
1446 struct bus_container *c;
1449 assert_return(m, -EINVAL);
1450 assert_return(s, -EINVAL);
1451 assert_return(!m->sealed, -EPERM);
1452 assert_return(!m->poisoned, -ESTALE);
1454 c = message_get_container(m);
1456 if (c->signature && c->signature[c->index]) {
1457 /* Container signature is already set */
1459 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1464 /* Maybe we can append to the signature? But only if this is the top-level container*/
1465 if (c->enclosing != 0)
1468 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1475 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1476 a = message_extend_body(m, 1, size + 1, true);
1482 a = message_extend_body(m, 4, 4 + size + 1, false);
1486 *(uint32_t*) a = size;
1492 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1498 _public_ int sd_bus_message_append_string_iovec(
1500 const struct iovec *iov,
1508 assert_return(m, -EINVAL);
1509 assert_return(!m->sealed, -EPERM);
1510 assert_return(iov || n == 0, -EINVAL);
1511 assert_return(!m->poisoned, -ESTALE);
1513 size = IOVEC_TOTAL_SIZE(iov, n);
1515 r = sd_bus_message_append_string_space(m, size, &p);
1519 for (i = 0; i < n; i++) {
1521 if (iov[i].iov_base)
1522 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1524 memset(p, ' ', iov[i].iov_len);
1526 p += iov[i].iov_len;
1532 static int bus_message_open_array(
1534 struct bus_container *c,
1535 const char *contents,
1536 uint32_t **array_size,
1538 bool *need_offsets) {
1548 assert(need_offsets);
1550 if (!signature_is_single(contents, true))
1553 if (c->signature && c->signature[c->index]) {
1555 /* Verify the existing signature */
1557 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1560 if (!startswith(c->signature + c->index + 1, contents))
1563 nindex = c->index + 1 + strlen(contents);
1567 if (c->enclosing != 0)
1570 /* Extend the existing signature */
1572 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1578 nindex = e - c->signature;
1581 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1582 alignment = bus_gvariant_get_alignment(contents);
1586 /* Add alignment padding and add to offset list */
1587 if (!message_extend_body(m, alignment, 0, false))
1590 r = bus_gvariant_is_fixed_size(contents);
1594 *begin = m->header->body_size;
1595 *need_offsets = r == 0;
1599 struct bus_body_part *o;
1601 alignment = bus_type_get_alignment(contents[0]);
1605 a = message_extend_body(m, 4, 4, false);
1610 op = m->body_end->data;
1611 os = m->body_end->size;
1613 /* Add alignment between size and first element */
1614 if (!message_extend_body(m, alignment, 0, false))
1617 /* location of array size might have changed so let's readjust a */
1618 if (o == m->body_end)
1619 a = adjust_pointer(a, op, os, m->body_end->data);
1625 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1631 static int bus_message_open_variant(
1633 struct bus_container *c,
1634 const char *contents) {
1640 if (!signature_is_single(contents, false))
1643 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1646 if (c->signature && c->signature[c->index]) {
1648 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1654 if (c->enclosing != 0)
1657 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1664 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1665 /* Variants are always aligned to 8 */
1667 if (!message_extend_body(m, 8, 0, false))
1674 l = strlen(contents);
1675 a = message_extend_body(m, 1, 1 + l + 1, false);
1680 memcpy((uint8_t*) a + 1, contents, l + 1);
1683 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1689 static int bus_message_open_struct(
1691 struct bus_container *c,
1692 const char *contents,
1694 bool *need_offsets) {
1703 assert(need_offsets);
1705 if (!signature_is_valid(contents, false))
1708 if (c->signature && c->signature[c->index]) {
1711 l = strlen(contents);
1713 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1714 !startswith(c->signature + c->index + 1, contents) ||
1715 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1718 nindex = c->index + 1 + l + 1;
1722 if (c->enclosing != 0)
1725 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1731 nindex = e - c->signature;
1734 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1737 alignment = bus_gvariant_get_alignment(contents);
1741 if (!message_extend_body(m, alignment, 0, false))
1744 r = bus_gvariant_is_fixed_size(contents);
1748 *begin = m->header->body_size;
1749 *need_offsets = r == 0;
1751 /* Align contents to 8 byte boundary */
1752 if (!message_extend_body(m, 8, 0, false))
1756 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1762 static int bus_message_open_dict_entry(
1764 struct bus_container *c,
1765 const char *contents,
1767 bool *need_offsets) {
1775 assert(need_offsets);
1777 if (!signature_is_pair(contents))
1780 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1783 if (c->signature && c->signature[c->index]) {
1786 l = strlen(contents);
1788 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1789 !startswith(c->signature + c->index + 1, contents) ||
1790 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1795 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1798 alignment = bus_gvariant_get_alignment(contents);
1802 if (!message_extend_body(m, alignment, 0, false))
1805 r = bus_gvariant_is_fixed_size(contents);
1809 *begin = m->header->body_size;
1810 *need_offsets = r == 0;
1812 /* Align contents to 8 byte boundary */
1813 if (!message_extend_body(m, 8, 0, false))
1820 _public_ int sd_bus_message_open_container(
1823 const char *contents) {
1825 struct bus_container *c, *w;
1826 uint32_t *array_size = NULL;
1828 size_t before, begin;
1829 bool need_offsets = false;
1832 assert_return(m, -EINVAL);
1833 assert_return(!m->sealed, -EPERM);
1834 assert_return(contents, -EINVAL);
1835 assert_return(!m->poisoned, -ESTALE);
1837 /* Make sure we have space for one more container */
1838 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1846 c = message_get_container(m);
1848 signature = strdup(contents);
1854 /* Save old index in the parent container, in case we have to
1855 * abort this container */
1856 c->saved_index = c->index;
1857 before = m->header->body_size;
1859 if (type == SD_BUS_TYPE_ARRAY)
1860 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1861 else if (type == SD_BUS_TYPE_VARIANT)
1862 r = bus_message_open_variant(m, c, contents);
1863 else if (type == SD_BUS_TYPE_STRUCT)
1864 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1865 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1866 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1875 /* OK, let's fill it in */
1876 w += m->n_containers++;
1877 w->enclosing = type;
1878 w->signature = signature;
1880 w->array_size = array_size;
1883 w->n_offsets = w->n_offsets_allocated = 0;
1885 w->need_offsets = need_offsets;
1890 static size_t determine_word_size(size_t sz, size_t extra) {
1891 if (sz + extra <= 0xFF)
1893 else if (sz + extra*2 <= 0xFFFF)
1895 else if (sz + extra*4 <= 0xFFFFFFFF)
1901 static size_t read_word_le(void *p, size_t sz) {
1911 return *(uint8_t*) p;
1916 return le16toh(x.u16);
1918 return le32toh(x.u32);
1920 return le64toh(x.u64);
1922 assert_not_reached("unknown word width");
1925 static void write_word_le(void *p, size_t sz, size_t value) {
1933 assert(sz == 8 || (value < (1ULL << (sz*8))));
1936 *(uint8_t*) p = value;
1939 x.u16 = htole16((uint16_t) value);
1941 x.u32 = htole32((uint32_t) value);
1943 x.u64 = htole64((uint64_t) value);
1945 assert_not_reached("unknown word width");
1950 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1955 if (!BUS_MESSAGE_IS_GVARIANT(m))
1958 if (c->need_offsets) {
1959 size_t payload, sz, i;
1962 /* Variable-width arrays */
1964 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
1965 sz = determine_word_size(payload, c->n_offsets);
1967 a = message_extend_body(m, 1, sz * c->n_offsets, true);
1971 for (i = 0; i < c->n_offsets; i++)
1972 write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
1976 /* Fixed-width or empty arrays */
1978 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
1986 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
1993 if (!BUS_MESSAGE_IS_GVARIANT(m))
1996 l = strlen(c->signature);
1998 a = message_extend_body(m, 1, 1 + l, true);
2003 memcpy(a+1, c->signature, l);
2008 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2009 size_t n_variable = 0;
2018 if (!BUS_MESSAGE_IS_GVARIANT(m))
2021 p = strempty(c->signature);
2025 r = signature_element_length(p, &n);
2034 r = bus_gvariant_is_fixed_size(t);
2039 assert(i <= c->n_offsets);
2041 /* We need to add an offset for each item that has a
2042 * variable size and that is not the last one in the
2044 if (r == 0 && p[n] != 0)
2051 assert(i == c->n_offsets);
2053 if (n_variable <= 0) {
2054 a = message_extend_body(m, 1, 0, add_offset);
2061 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2063 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2065 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2069 p = strempty(c->signature);
2070 for (i = 0, j = 0; i < c->n_offsets; i++) {
2074 r = signature_element_length(p, &n);
2085 r = bus_gvariant_is_fixed_size(t);
2088 if (r > 0 || p[0] == 0)
2092 k = n_variable - 1 - j;
2094 write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2103 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2104 struct bus_container *c;
2107 assert_return(m, -EINVAL);
2108 assert_return(!m->sealed, -EPERM);
2109 assert_return(m->n_containers > 0, -EINVAL);
2110 assert_return(!m->poisoned, -ESTALE);
2112 c = message_get_container(m);
2114 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2115 if (c->signature && c->signature[c->index] != 0)
2120 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2121 r = bus_message_close_array(m, c);
2122 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2123 r = bus_message_close_variant(m, c);
2124 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2125 r = bus_message_close_struct(m, c, true);
2127 assert_not_reached("Unknown container type");
2141 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2148 stack[*i].types = types;
2149 stack[*i].n_struct = n_struct;
2150 stack[*i].n_array = n_array;
2156 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2167 *types = stack[*i].types;
2168 *n_struct = stack[*i].n_struct;
2169 *n_array = stack[*i].n_array;
2174 int bus_message_append_ap(
2179 unsigned n_array, n_struct;
2180 TypeStack stack[BUS_CONTAINER_DEPTH];
2181 unsigned stack_ptr = 0;
2189 n_array = (unsigned) -1;
2190 n_struct = strlen(types);
2195 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2196 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2202 r = sd_bus_message_close_container(m);
2210 if (n_array != (unsigned) -1)
2219 case SD_BUS_TYPE_BYTE: {
2222 x = (uint8_t) va_arg(ap, int);
2223 r = sd_bus_message_append_basic(m, *t, &x);
2227 case SD_BUS_TYPE_BOOLEAN:
2228 case SD_BUS_TYPE_INT32:
2229 case SD_BUS_TYPE_UINT32:
2230 case SD_BUS_TYPE_UNIX_FD: {
2233 /* We assume a boolean is the same as int32_t */
2234 assert_cc(sizeof(int32_t) == sizeof(int));
2236 x = va_arg(ap, uint32_t);
2237 r = sd_bus_message_append_basic(m, *t, &x);
2241 case SD_BUS_TYPE_INT16:
2242 case SD_BUS_TYPE_UINT16: {
2245 x = (uint16_t) va_arg(ap, int);
2246 r = sd_bus_message_append_basic(m, *t, &x);
2250 case SD_BUS_TYPE_INT64:
2251 case SD_BUS_TYPE_UINT64:
2252 case SD_BUS_TYPE_DOUBLE: {
2255 x = va_arg(ap, uint64_t);
2256 r = sd_bus_message_append_basic(m, *t, &x);
2260 case SD_BUS_TYPE_STRING:
2261 case SD_BUS_TYPE_OBJECT_PATH:
2262 case SD_BUS_TYPE_SIGNATURE: {
2265 x = va_arg(ap, const char*);
2266 r = sd_bus_message_append_basic(m, *t, x);
2270 case SD_BUS_TYPE_ARRAY: {
2273 r = signature_element_length(t + 1, &k);
2279 memcpy(s, t + 1, k);
2282 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2287 if (n_array == (unsigned) -1) {
2292 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2298 n_array = va_arg(ap, unsigned);
2303 case SD_BUS_TYPE_VARIANT: {
2306 s = va_arg(ap, const char*);
2310 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2314 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2319 n_struct = strlen(s);
2320 n_array = (unsigned) -1;
2325 case SD_BUS_TYPE_STRUCT_BEGIN:
2326 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2329 r = signature_element_length(t, &k);
2336 memcpy(s, t + 1, k - 2);
2339 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2344 if (n_array == (unsigned) -1) {
2349 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2355 n_array = (unsigned) -1;
2371 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2375 assert_return(m, -EINVAL);
2376 assert_return(types, -EINVAL);
2377 assert_return(!m->sealed, -EPERM);
2378 assert_return(!m->poisoned, -ESTALE);
2380 va_start(ap, types);
2381 r = bus_message_append_ap(m, types, ap);
2387 _public_ int sd_bus_message_append_array_space(
2397 assert_return(m, -EINVAL);
2398 assert_return(!m->sealed, -EPERM);
2399 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2400 assert_return(ptr || size == 0, -EINVAL);
2401 assert_return(!m->poisoned, -ESTALE);
2403 /* alignment and size of the trivial types (except bool) is
2404 * identical for gvariant and dbus1 marshalling */
2405 align = bus_type_get_alignment(type);
2406 sz = bus_type_get_size(type);
2408 assert_se(align > 0);
2414 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2418 a = message_extend_body(m, align, size, false);
2422 r = sd_bus_message_close_container(m);
2430 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2437 assert_return(m, -EINVAL);
2438 assert_return(!m->sealed, -EPERM);
2439 assert_return(bus_type_is_trivial(type), -EINVAL);
2440 assert_return(ptr || size == 0, -EINVAL);
2441 assert_return(!m->poisoned, -ESTALE);
2443 r = sd_bus_message_append_array_space(m, type, size, &p);
2448 memcpy(p, ptr, size);
2453 _public_ int sd_bus_message_append_array_iovec(
2456 const struct iovec *iov,
2464 assert_return(m, -EINVAL);
2465 assert_return(!m->sealed, -EPERM);
2466 assert_return(bus_type_is_trivial(type), -EINVAL);
2467 assert_return(iov || n == 0, -EINVAL);
2468 assert_return(!m->poisoned, -ESTALE);
2470 size = IOVEC_TOTAL_SIZE(iov, n);
2472 r = sd_bus_message_append_array_space(m, type, size, &p);
2476 for (i = 0; i < n; i++) {
2478 if (iov[i].iov_base)
2479 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2481 memset(p, 0, iov[i].iov_len);
2483 p = (uint8_t*) p + iov[i].iov_len;
2489 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2492 _cleanup_close_ int copy_fd = -1;
2493 struct bus_body_part *part;
2505 if (!bus_type_is_trivial(type))
2510 r = sd_memfd_set_sealed(memfd, true);
2514 copy_fd = sd_memfd_dup_fd(memfd);
2518 r = sd_memfd_get_size(memfd, &size);
2522 align = bus_type_get_alignment(type);
2523 sz = bus_type_get_size(type);
2525 assert_se(align > 0);
2531 if (size > (uint64_t) (uint32_t) -1)
2534 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2538 a = message_extend_body(m, align, 0, false);
2542 part = message_append_part(m);
2546 part->memfd = copy_fd;
2547 part->sealed = true;
2551 m->header->body_size += size;
2552 message_extend_containers(m, size);
2554 return sd_bus_message_close_container(m);
2557 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
2558 _cleanup_close_ int copy_fd = -1;
2559 struct bus_body_part *part;
2560 struct bus_container *c;
2565 assert_return(m, -EINVAL);
2566 assert_return(memfd, -EINVAL);
2567 assert_return(!m->sealed, -EPERM);
2568 assert_return(!m->poisoned, -ESTALE);
2570 r = sd_memfd_set_sealed(memfd, true);
2574 copy_fd = sd_memfd_dup_fd(memfd);
2578 r = sd_memfd_get_size(memfd, &size);
2582 /* We require this to be NUL terminated */
2586 if (size > (uint64_t) (uint32_t) -1)
2589 c = message_get_container(m);
2590 if (c->signature && c->signature[c->index]) {
2591 /* Container signature is already set */
2593 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2598 /* Maybe we can append to the signature? But only if this is the top-level container*/
2599 if (c->enclosing != 0)
2602 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2609 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2610 a = message_extend_body(m, 4, 4, false);
2614 *(uint32_t*) a = size - 1;
2617 part = message_append_part(m);
2621 part->memfd = copy_fd;
2622 part->sealed = true;
2626 m->header->body_size += size;
2627 message_extend_containers(m, size);
2629 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2630 r = message_add_offset(m, m->header->body_size);
2637 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2643 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2647 assert_return(m, -EINVAL);
2648 assert_return(!m->sealed, -EPERM);
2649 assert_return(!m->poisoned, -ESTALE);
2651 r = sd_bus_message_open_container(m, 'a', "s");
2655 STRV_FOREACH(i, l) {
2656 r = sd_bus_message_append_basic(m, 's', *i);
2661 return sd_bus_message_close_container(m);
2664 static int bus_message_close_header(sd_bus_message *m) {
2670 if (!BUS_MESSAGE_IS_GVARIANT(m))
2673 if (m->n_header_offsets < 1)
2676 assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2678 sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2680 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2684 for (i = 0; i < m->n_header_offsets; i++)
2685 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2690 int bus_message_seal(sd_bus_message *m, uint64_t serial) {
2691 struct bus_body_part *part;
2701 if (m->n_containers > 0)
2707 /* In vtables the return signature of method calls is listed,
2708 * let's check if they match if this is a response */
2709 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2710 m->enforced_reply_signature &&
2711 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2714 /* If gvariant marshalling is used we need to close the body structure */
2715 r = bus_message_close_struct(m, &m->root_container, false);
2719 /* If there's a non-trivial signature set, then add it in here */
2720 if (!isempty(m->root_container.signature)) {
2721 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2727 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2732 r = bus_message_close_header(m);
2736 m->header->serial = serial;
2738 /* Add padding at the end of the fields part, since we know
2739 * the body needs to start at an 8 byte alignment. We made
2740 * sure we allocated enough space for this, so all we need to
2741 * do here is to zero it out. */
2742 l = BUS_MESSAGE_FIELDS_SIZE(m);
2745 memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
2747 /* If this is something we can send as memfd, then let's seal
2748 the memfd now. Note that we can send memfds as payload only
2749 for directed messages, and not for broadcasts. */
2750 if (m->destination && m->bus && m->bus->use_memfd) {
2751 MESSAGE_FOREACH_PART(part, i, m)
2752 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2753 bus_body_part_unmap(part);
2755 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
2756 part->sealed = true;
2760 m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2761 m->root_container.index = 0;
2762 m->root_container.offset_index = 0;
2763 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2770 int bus_body_part_map(struct bus_body_part *part) {
2779 if (part->size <= 0)
2782 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2783 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2784 static const uint8_t zeroes[7] = { };
2785 part->data = (void*) zeroes;
2789 psz = PAGE_ALIGN(part->size);
2791 if (part->memfd >= 0)
2792 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2793 else if (part->is_zero)
2794 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2798 if (p == MAP_FAILED)
2803 part->munmap_this = true;
2808 void bus_body_part_unmap(struct bus_body_part *part) {
2812 if (part->memfd < 0)
2818 if (!part->munmap_this)
2821 assert_se(munmap(part->data, part->mapped) == 0);
2825 part->munmap_this = false;
2830 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2831 size_t k, start, end;
2836 start = ALIGN_TO((size_t) *rindex, align);
2837 end = start + nbytes;
2842 /* Verify that padding is 0 */
2843 for (k = *rindex; k < start; k++)
2844 if (((const uint8_t*) p)[k] != 0)
2848 *r = (uint8_t*) p + start;
2855 static bool message_end_of_signature(sd_bus_message *m) {
2856 struct bus_container *c;
2860 c = message_get_container(m);
2861 return !c->signature || c->signature[c->index] == 0;
2864 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2865 struct bus_container *c;
2869 c = message_get_container(m);
2870 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2873 if (BUS_MESSAGE_IS_GVARIANT(m))
2874 return index >= c->end;
2876 assert(c->array_size);
2877 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2881 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2882 assert_return(m, -EINVAL);
2883 assert_return(m->sealed, -EPERM);
2885 if (complete && m->n_containers > 0)
2888 if (message_end_of_signature(m))
2891 if (message_end_of_array(m, m->rindex))
2897 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2898 struct bus_body_part *part;
2904 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2905 part = m->cached_rindex_part;
2906 begin = m->cached_rindex_part_begin;
2916 if (index + sz <= begin + part->size) {
2918 r = bus_body_part_map(part);
2923 *p = (uint8_t*) part->data + index - begin;
2925 m->cached_rindex_part = part;
2926 m->cached_rindex_part_begin = begin;
2931 begin += part->size;
2938 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2945 if (!BUS_MESSAGE_IS_GVARIANT(m))
2948 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2951 sz = bus_gvariant_get_size(c->signature);
2955 if (c->offset_index+1 >= c->n_offsets)
2958 /* Variable-size array */
2960 alignment = bus_gvariant_get_alignment(c->signature);
2961 assert(alignment > 0);
2963 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
2964 c->item_size = c->offsets[c->offset_index+1] - *rindex;
2967 if (c->offset_index+1 >= (c->end-c->begin)/sz)
2970 /* Fixed-size array */
2971 *rindex = c->begin + (c->offset_index+1) * sz;
2977 } else if (c->enclosing == 0 ||
2978 c->enclosing == SD_BUS_TYPE_STRUCT ||
2979 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
2984 if (c->offset_index+1 >= c->n_offsets)
2987 r = signature_element_length(c->signature + c->index, &n);
2991 r = signature_element_length(c->signature + c->index + n, &j);
2996 memcpy(t, c->signature + c->index + n, j);
2999 alignment = bus_gvariant_get_alignment(t);
3002 assert(alignment > 0);
3004 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3005 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3009 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3012 assert_not_reached("Unknown container type");
3017 /* Reached the end */
3024 static int message_peek_body(
3031 size_t k, start, end, padding;
3032 struct bus_body_part *part;
3039 start = ALIGN_TO((size_t) *rindex, align);
3040 padding = start - *rindex;
3041 end = start + nbytes;
3043 if (end > BUS_MESSAGE_BODY_SIZE(m))
3046 part = find_part(m, *rindex, padding, (void**) &q);
3051 /* Verify padding */
3052 for (k = 0; k < padding; k++)
3057 part = find_part(m, start, nbytes, (void**) &q);
3058 if (!part || (nbytes > 0 && !q))
3069 static bool validate_nul(const char *s, size_t l) {
3071 /* Check for NUL chars in the string */
3072 if (memchr(s, 0, l))
3075 /* Check for NUL termination */
3082 static bool validate_string(const char *s, size_t l) {
3084 if (!validate_nul(s, l))
3087 /* Check if valid UTF8 */
3088 if (!utf8_is_valid(s))
3094 static bool validate_signature(const char *s, size_t l) {
3096 if (!validate_nul(s, l))
3099 /* Check if valid signature */
3100 if (!signature_is_valid(s, true))
3106 static bool validate_object_path(const char *s, size_t l) {
3108 if (!validate_nul(s, l))
3111 if (!object_path_is_valid(s))
3117 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3118 struct bus_container *c;
3123 assert_return(m, -EINVAL);
3124 assert_return(m->sealed, -EPERM);
3125 assert_return(bus_type_is_basic(type), -EINVAL);
3127 if (message_end_of_signature(m))
3130 if (message_end_of_array(m, m->rindex))
3133 c = message_get_container(m);
3134 if (c->signature[c->index] != type)
3139 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3141 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3144 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3148 if (type == SD_BUS_TYPE_STRING)
3149 ok = validate_string(q, c->item_size-1);
3150 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3151 ok = validate_object_path(q, c->item_size-1);
3153 ok = validate_signature(q, c->item_size-1);
3159 *(const char**) p = q;
3163 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3165 if ((size_t) sz != c->item_size)
3168 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3171 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3177 case SD_BUS_TYPE_BYTE:
3179 *(uint8_t*) p = *(uint8_t*) q;
3182 case SD_BUS_TYPE_BOOLEAN:
3184 *(int*) p = !!*(uint8_t*) q;
3187 case SD_BUS_TYPE_INT16:
3188 case SD_BUS_TYPE_UINT16:
3190 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3193 case SD_BUS_TYPE_INT32:
3194 case SD_BUS_TYPE_UINT32:
3196 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3199 case SD_BUS_TYPE_INT64:
3200 case SD_BUS_TYPE_UINT64:
3201 case SD_BUS_TYPE_DOUBLE:
3203 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3206 case SD_BUS_TYPE_UNIX_FD: {
3209 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3214 *(int*) p = m->fds[j];
3220 assert_not_reached("unexpected type");
3224 r = container_next_item(m, c, &rindex);