chiark / gitweb /
sd-bus: remove ucred parameter from bus_message_from_header() since we don't use...
[elogind.git] / src / libelogind / sd-bus / bus-message.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <sys/mman.h>
25
26 #include "util.h"
27 #include "utf8.h"
28 #include "strv.h"
29 #include "time-util.h"
30 #include "memfd-util.h"
31
32 #include "sd-bus.h"
33 #include "bus-message.h"
34 #include "bus-internal.h"
35 #include "bus-type.h"
36 #include "bus-signature.h"
37 #include "bus-gvariant.h"
38 #include "bus-util.h"
39
40 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
41
42 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
43
44         if (p == NULL)
45                 return NULL;
46
47         if (old_base == new_base)
48                 return (void*) p;
49
50         if ((uint8_t*) p < (uint8_t*) old_base)
51                 return (void*) p;
52
53         if ((uint8_t*) p >= (uint8_t*) old_base + sz)
54                 return (void*) p;
55
56         return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
57 }
58
59 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
60         assert(m);
61         assert(part);
62
63         if (part->memfd >= 0) {
64                 /* If we can reuse the memfd, try that. For that it
65                  * can't be sealed yet. */
66
67                 if (!part->sealed) {
68                         assert(part->memfd_offset == 0);
69                         assert(part->data == part->mmap_begin);
70                         bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
71                 } else {
72                         if (part->mapped > 0)
73                                 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
74
75                         safe_close(part->memfd);
76                 }
77
78         } else if (part->munmap_this)
79                 munmap(part->mmap_begin, part->mapped);
80         else if (part->free_this)
81                 free(part->data);
82
83         if (part != &m->body)
84                 free(part);
85 }
86
87 static void message_reset_parts(sd_bus_message *m) {
88         struct bus_body_part *part;
89
90         assert(m);
91
92         part = &m->body;
93         while (m->n_body_parts > 0) {
94                 struct bus_body_part *next = part->next;
95                 message_free_part(m, part);
96                 part = next;
97                 m->n_body_parts--;
98         }
99
100         m->body_end = NULL;
101
102         m->cached_rindex_part = NULL;
103         m->cached_rindex_part_begin = 0;
104 }
105
106 static void message_reset_containers(sd_bus_message *m) {
107         unsigned i;
108
109         assert(m);
110
111         for (i = 0; i < m->n_containers; i++) {
112                 free(m->containers[i].signature);
113                 free(m->containers[i].offsets);
114         }
115
116         free(m->containers);
117         m->containers = NULL;
118
119         m->n_containers = m->containers_allocated = 0;
120         m->root_container.index = 0;
121 }
122
123 static void message_free(sd_bus_message *m) {
124         assert(m);
125
126         if (m->free_header)
127                 free(m->header);
128
129         message_reset_parts(m);
130
131         if (m->release_kdbus)
132                 bus_kernel_cmd_free(m->bus, (uint8_t *) m->kdbus - (uint8_t *) m->bus->kdbus_buffer);
133
134         if (m->free_kdbus)
135                 free(m->kdbus);
136
137         sd_bus_unref(m->bus);
138
139         if (m->free_fds) {
140                 close_many(m->fds, m->n_fds);
141                 free(m->fds);
142         }
143
144         if (m->iovec != m->iovec_fixed)
145                 free(m->iovec);
146
147         if (m->destination_ptr) {
148                 free(m->destination_ptr);
149                 m->destination_ptr = NULL;
150         }
151
152         message_reset_containers(m);
153         free(m->root_container.signature);
154         free(m->root_container.offsets);
155
156         free(m->root_container.peeked_signature);
157
158         bus_creds_done(&m->creds);
159         free(m);
160 }
161
162 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
163         void *op, *np;
164         size_t old_size, new_size, start;
165
166         assert(m);
167
168         if (m->poisoned)
169                 return NULL;
170
171         old_size = sizeof(struct bus_header) + m->fields_size;
172         start = ALIGN_TO(old_size, align);
173         new_size = start + sz;
174
175         if (new_size < start ||
176             new_size > (size_t) ((uint32_t) -1))
177                 goto poison;
178
179         if (old_size == new_size)
180                 return (uint8_t*) m->header + old_size;
181
182         if (m->free_header) {
183                 np = realloc(m->header, ALIGN8(new_size));
184                 if (!np)
185                         goto poison;
186         } else {
187                 /* Initially, the header is allocated as part of of
188                  * the sd_bus_message itself, let's replace it by
189                  * dynamic data */
190
191                 np = malloc(ALIGN8(new_size));
192                 if (!np)
193                         goto poison;
194
195                 memcpy(np, m->header, sizeof(struct bus_header));
196         }
197
198         /* Zero out padding */
199         if (start > old_size)
200                 memzero((uint8_t*) np + old_size, start - old_size);
201
202         op = m->header;
203         m->header = np;
204         m->fields_size = new_size - sizeof(struct bus_header);
205
206         /* Adjust quick access pointers */
207         m->path = adjust_pointer(m->path, op, old_size, m->header);
208         m->interface = adjust_pointer(m->interface, op, old_size, m->header);
209         m->member = adjust_pointer(m->member, op, old_size, m->header);
210         m->destination = adjust_pointer(m->destination, op, old_size, m->header);
211         m->sender = adjust_pointer(m->sender, op, old_size, m->header);
212         m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
213
214         m->free_header = true;
215
216         if (add_offset) {
217                 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
218                         goto poison;
219
220                 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
221         }
222
223         return (uint8_t*) np + start;
224
225 poison:
226         m->poisoned = true;
227         return NULL;
228 }
229
230 static int message_append_field_string(
231                 sd_bus_message *m,
232                 uint64_t h,
233                 char type,
234                 const char *s,
235                 const char **ret) {
236
237         size_t l;
238         uint8_t *p;
239
240         assert(m);
241
242         /* dbus1 only allows 8bit header field ids */
243         if (h > 0xFF)
244                 return -EINVAL;
245
246         /* dbus1 doesn't allow strings over 32bit, let's enforce this
247          * globally, to not risk convertability */
248         l = strlen(s);
249         if (l > (size_t) (uint32_t) -1)
250                 return -EINVAL;
251
252         /* Signature "(yv)" where the variant contains "s" */
253
254         if (BUS_MESSAGE_IS_GVARIANT(m)) {
255
256                 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
257                 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
258                 if (!p)
259                         return -ENOMEM;
260
261                 *((uint64_t*) p) = h;
262                 memcpy(p+8, s, l);
263                 p[8+l] = 0;
264                 p[8+l+1] = 0;
265                 p[8+l+2] = type;
266
267                 if (ret)
268                         *ret = (char*) p + 8;
269
270         } else {
271                 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
272                 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
273                 if (!p)
274                         return -ENOMEM;
275
276                 p[0] = (uint8_t) h;
277                 p[1] = 1;
278                 p[2] = type;
279                 p[3] = 0;
280
281                 ((uint32_t*) p)[1] = l;
282                 memcpy(p + 8, s, l + 1);
283
284                 if (ret)
285                         *ret = (char*) p + 8;
286         }
287
288         return 0;
289 }
290
291 static int message_append_field_signature(
292                 sd_bus_message *m,
293                 uint64_t h,
294                 const char *s,
295                 const char **ret) {
296
297         size_t l;
298         uint8_t *p;
299
300         assert(m);
301
302         /* dbus1 only allows 8bit header field ids */
303         if (h > 0xFF)
304                 return -EINVAL;
305
306         /* dbus1 doesn't allow signatures over 8bit, let's enforce
307          * this globally, to not risk convertability */
308         l = strlen(s);
309         if (l > 255)
310                 return -EINVAL;
311
312         /* Signature "(yv)" where the variant contains "g" */
313
314         if (BUS_MESSAGE_IS_GVARIANT(m))
315                 /* For gvariant the serialization is the same as for normal strings */
316                 return message_append_field_string(m, h, 'g', s, ret);
317         else {
318                 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
319                 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
320                 if (!p)
321                         return -ENOMEM;
322
323                 p[0] = (uint8_t) h;
324                 p[1] = 1;
325                 p[2] = SD_BUS_TYPE_SIGNATURE;
326                 p[3] = 0;
327                 p[4] = l;
328                 memcpy(p + 5, s, l + 1);
329
330                 if (ret)
331                         *ret = (const char*) p + 5;
332         }
333
334         return 0;
335 }
336
337 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
338         uint8_t *p;
339
340         assert(m);
341
342         /* dbus1 only allows 8bit header field ids */
343         if (h > 0xFF)
344                 return -EINVAL;
345
346         if (BUS_MESSAGE_IS_GVARIANT(m)) {
347                 /* (field id 64bit + ((value + NUL + signature string 'u') */
348
349                 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
350                 if (!p)
351                         return -ENOMEM;
352
353                 *((uint64_t*) p) = h;
354                 *((uint32_t*) (p + 8)) = x;
355                 p[12] = 0;
356                 p[13] = 'u';
357         } else {
358                 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
359                 p = message_extend_fields(m, 8, 4 + 4, false);
360                 if (!p)
361                         return -ENOMEM;
362
363                 p[0] = (uint8_t) h;
364                 p[1] = 1;
365                 p[2] = 'u';
366                 p[3] = 0;
367
368                 ((uint32_t*) p)[1] = x;
369         }
370
371         return 0;
372 }
373
374 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
375         uint8_t *p;
376
377         assert(m);
378
379         /* dbus1 only allows 8bit header field ids */
380         if (h > 0xFF)
381                 return -EINVAL;
382
383         if (BUS_MESSAGE_IS_GVARIANT(m)) {
384                 /* (field id 64bit + ((value + NUL + signature string 't') */
385
386                 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
387                 if (!p)
388                         return -ENOMEM;
389
390                 *((uint64_t*) p) = h;
391                 *((uint64_t*) (p + 8)) = x;
392                 p[16] = 0;
393                 p[17] = 't';
394         } else {
395                 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
396                 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
397                 if (!p)
398                         return -ENOMEM;
399
400                 p[0] = (uint8_t) h;
401                 p[1] = 1;
402                 p[2] = 't';
403                 p[3] = 0;
404                 p[4] = 0;
405                 p[5] = 0;
406                 p[6] = 0;
407                 p[7] = 0;
408
409                 ((uint64_t*) p)[1] = x;
410         }
411
412         return 0;
413 }
414
415 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
416         assert(m);
417
418         if (BUS_MESSAGE_IS_GVARIANT(m))
419                 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
420         else {
421                 /* 64bit cookies are not supported on dbus1 */
422                 if (cookie > 0xffffffffUL)
423                         return -EOPNOTSUPP;
424
425                 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
426         }
427 }
428
429 int bus_message_from_header(
430                 sd_bus *bus,
431                 void *header,
432                 size_t header_accessible,
433                 void *footer,
434                 size_t footer_accessible,
435                 size_t message_size,
436                 int *fds,
437                 unsigned n_fds,
438                 const char *label,
439                 size_t extra,
440                 sd_bus_message **ret) {
441
442         _cleanup_free_ sd_bus_message *m = NULL;
443         struct bus_header *h;
444         size_t a, label_sz;
445
446         assert(bus);
447         assert(header || header_accessible <= 0);
448         assert(footer || footer_accessible <= 0);
449         assert(fds || n_fds <= 0);
450         assert(ret);
451
452         if (header_accessible < sizeof(struct bus_header))
453                 return -EBADMSG;
454
455         if (header_accessible > message_size)
456                 return -EBADMSG;
457         if (footer_accessible > message_size)
458                 return -EBADMSG;
459
460         h = header;
461         if (!IN_SET(h->version, 1, 2))
462                 return -EBADMSG;
463
464         if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
465                 return -EBADMSG;
466
467         if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
468                 return -EBADMSG;
469
470         /* Note that we are happy with unknown flags in the flags header! */
471
472         a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
473
474         if (label) {
475                 label_sz = strlen(label);
476                 a += label_sz + 1;
477         }
478
479         m = malloc0(a);
480         if (!m)
481                 return -ENOMEM;
482
483         m->n_ref = 1;
484         m->sealed = true;
485         m->header = header;
486         m->header_accessible = header_accessible;
487         m->footer = footer;
488         m->footer_accessible = footer_accessible;
489
490         if (BUS_MESSAGE_IS_GVARIANT(m)) {
491                 size_t ws;
492
493                 if (h->dbus2.cookie == 0)
494                         return -EBADMSG;
495
496                 /* dbus2 derives the sizes from the message size and
497                 the offset table at the end, since it is formatted as
498                 gvariant "yyyyuta{tv}v". Since the message itself is a
499                 structure with precisely to variable sized entries,
500                 there's only one offset in the table, which marks the
501                 end of the fields array. */
502
503                 ws = bus_gvariant_determine_word_size(message_size, 0);
504                 if (footer_accessible < ws)
505                         return -EBADMSG;
506
507                 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
508                 if (ALIGN8(m->fields_size) > message_size - ws)
509                         return -EBADMSG;
510                 if (m->fields_size < sizeof(struct bus_header))
511                         return -EBADMSG;
512
513                 m->fields_size -= sizeof(struct bus_header);
514                 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
515         } else {
516                 if (h->dbus1.serial == 0)
517                         return -EBADMSG;
518
519                 /* dbus1 has the sizes in the header */
520                 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
521                 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
522
523                 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
524                         return -EBADMSG;
525         }
526
527         m->fds = fds;
528         m->n_fds = n_fds;
529
530         if (label) {
531                 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
532                 memcpy(m->creds.label, label, label_sz + 1);
533
534                 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
535         }
536
537         m->bus = sd_bus_ref(bus);
538         *ret = m;
539         m = NULL;
540
541         return 0;
542 }
543
544 int bus_message_from_malloc(
545                 sd_bus *bus,
546                 void *buffer,
547                 size_t length,
548                 int *fds,
549                 unsigned n_fds,
550                 const char *label,
551                 sd_bus_message **ret) {
552
553         sd_bus_message *m;
554         size_t sz;
555         int r;
556
557         r = bus_message_from_header(
558                         bus,
559                         buffer, length, /* in this case the initial bytes and the final bytes are the same */
560                         buffer, length,
561                         length,
562                         fds, n_fds,
563                         label,
564                         0, &m);
565         if (r < 0)
566                 return r;
567
568         sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
569         if (sz > 0) {
570                 m->n_body_parts = 1;
571                 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
572                 m->body.size = sz;
573                 m->body.sealed = true;
574                 m->body.memfd = -1;
575         }
576
577         m->n_iovec = 1;
578         m->iovec = m->iovec_fixed;
579         m->iovec[0].iov_base = buffer;
580         m->iovec[0].iov_len = length;
581
582         r = bus_message_parse_fields(m);
583         if (r < 0)
584                 goto fail;
585
586         /* We take possession of the memory and fds now */
587         m->free_header = true;
588         m->free_fds = true;
589
590         *ret = m;
591         return 0;
592
593 fail:
594         message_free(m);
595         return r;
596 }
597
598 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
599         sd_bus_message *m;
600
601         assert(bus);
602
603         m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
604         if (!m)
605                 return NULL;
606
607         m->n_ref = 1;
608         m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
609         m->header->endian = BUS_NATIVE_ENDIAN;
610         m->header->type = type;
611         m->header->version = bus ? bus->message_version : 1;
612         m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
613         m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
614         m->bus = sd_bus_ref(bus);
615
616         if (bus->allow_interactive_authorization)
617                 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
618
619         return m;
620 }
621
622 _public_ int sd_bus_message_new_signal(
623                 sd_bus *bus,
624                 sd_bus_message **m,
625                 const char *path,
626                 const char *interface,
627                 const char *member) {
628
629         sd_bus_message *t;
630         int r;
631
632         assert_return(bus, -ENOTCONN);
633         assert_return(bus->state != BUS_UNSET, -ENOTCONN);
634         assert_return(object_path_is_valid(path), -EINVAL);
635         assert_return(interface_name_is_valid(interface), -EINVAL);
636         assert_return(member_name_is_valid(member), -EINVAL);
637         assert_return(m, -EINVAL);
638
639         t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
640         if (!t)
641                 return -ENOMEM;
642
643         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
644
645         r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
646         if (r < 0)
647                 goto fail;
648         r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
649         if (r < 0)
650                 goto fail;
651         r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
652         if (r < 0)
653                 goto fail;
654
655         *m = t;
656         return 0;
657
658 fail:
659         sd_bus_message_unref(t);
660         return r;
661 }
662
663 _public_ int sd_bus_message_new_method_call(
664                 sd_bus *bus,
665                 sd_bus_message **m,
666                 const char *destination,
667                 const char *path,
668                 const char *interface,
669                 const char *member) {
670
671         sd_bus_message *t;
672         int r;
673
674         assert_return(bus, -ENOTCONN);
675         assert_return(bus->state != BUS_UNSET, -ENOTCONN);
676         assert_return(!destination || service_name_is_valid(destination), -EINVAL);
677         assert_return(object_path_is_valid(path), -EINVAL);
678         assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
679         assert_return(member_name_is_valid(member), -EINVAL);
680         assert_return(m, -EINVAL);
681
682         t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
683         if (!t)
684                 return -ENOMEM;
685
686         r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
687         if (r < 0)
688                 goto fail;
689         r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
690         if (r < 0)
691                 goto fail;
692
693         if (interface) {
694                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
695                 if (r < 0)
696                         goto fail;
697         }
698
699         if (destination) {
700                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
701                 if (r < 0)
702                         goto fail;
703         }
704
705         *m = t;
706         return 0;
707
708 fail:
709         message_free(t);
710         return r;
711 }
712
713 static int message_new_reply(
714                 sd_bus_message *call,
715                 uint8_t type,
716                 sd_bus_message **m) {
717
718         sd_bus_message *t;
719         int r;
720
721         assert_return(call, -EINVAL);
722         assert_return(call->sealed, -EPERM);
723         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
724         assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
725         assert_return(m, -EINVAL);
726
727         t = message_new(call->bus, type);
728         if (!t)
729                 return -ENOMEM;
730
731         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
732         t->reply_cookie = BUS_MESSAGE_COOKIE(call);
733         if (t->reply_cookie == 0)
734                 return -EOPNOTSUPP;
735
736         r = message_append_reply_cookie(t, t->reply_cookie);
737         if (r < 0)
738                 goto fail;
739
740         if (call->sender) {
741                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
742                 if (r < 0)
743                         goto fail;
744         }
745
746         t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
747         t->enforced_reply_signature = call->enforced_reply_signature;
748
749         *m = t;
750         return 0;
751
752 fail:
753         message_free(t);
754         return r;
755 }
756
757 _public_ int sd_bus_message_new_method_return(
758                 sd_bus_message *call,
759                 sd_bus_message **m) {
760
761         return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
762 }
763
764 _public_ int sd_bus_message_new_method_error(
765                 sd_bus_message *call,
766                 sd_bus_message **m,
767                 const sd_bus_error *e) {
768
769         sd_bus_message *t;
770         int r;
771
772         assert_return(sd_bus_error_is_set(e), -EINVAL);
773         assert_return(m, -EINVAL);
774
775         r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
776         if (r < 0)
777                 return r;
778
779         r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
780         if (r < 0)
781                 goto fail;
782
783         if (e->message) {
784                 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
785                 if (r < 0)
786                         goto fail;
787         }
788
789         t->error._need_free = -1;
790
791         *m = t;
792         return 0;
793
794 fail:
795         message_free(t);
796         return r;
797 }
798
799 _public_ int sd_bus_message_new_method_errorf(
800                 sd_bus_message *call,
801                 sd_bus_message **m,
802                 const char *name,
803                 const char *format,
804                 ...) {
805
806         _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
807         va_list ap;
808
809         assert_return(name, -EINVAL);
810         assert_return(m, -EINVAL);
811
812         va_start(ap, format);
813         bus_error_setfv(&error, name, format, ap);
814         va_end(ap);
815
816         return sd_bus_message_new_method_error(call, m, &error);
817 }
818
819 _public_ int sd_bus_message_new_method_errno(
820                 sd_bus_message *call,
821                 sd_bus_message **m,
822                 int error,
823                 const sd_bus_error *p) {
824
825         _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
826
827         if (sd_bus_error_is_set(p))
828                 return sd_bus_message_new_method_error(call, m, p);
829
830         sd_bus_error_set_errno(&berror, error);
831
832         return sd_bus_message_new_method_error(call, m, &berror);
833 }
834
835 _public_ int sd_bus_message_new_method_errnof(
836                 sd_bus_message *call,
837                 sd_bus_message **m,
838                 int error,
839                 const char *format,
840                 ...) {
841
842         _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
843         va_list ap;
844
845         va_start(ap, format);
846         sd_bus_error_set_errnofv(&berror, error, format, ap);
847         va_end(ap);
848
849         return sd_bus_message_new_method_error(call, m, &berror);
850 }
851
852 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
853         assert(bus);
854         assert(m);
855
856         m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
857         m->creds.well_known_names_local = true;
858         m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
859 }
860
861 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
862         assert(bus);
863         assert(m);
864
865         m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
866         m->creds.well_known_names_driver = true;
867         m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
868 }
869
870 int bus_message_new_synthetic_error(
871                 sd_bus *bus,
872                 uint64_t cookie,
873                 const sd_bus_error *e,
874                 sd_bus_message **m) {
875
876         sd_bus_message *t;
877         int r;
878
879         assert(bus);
880         assert(sd_bus_error_is_set(e));
881         assert(m);
882
883         t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
884         if (!t)
885                 return -ENOMEM;
886
887         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
888         t->reply_cookie = cookie;
889
890         r = message_append_reply_cookie(t, t->reply_cookie);
891         if (r < 0)
892                 goto fail;
893
894         if (bus && bus->unique_name) {
895                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
896                 if (r < 0)
897                         goto fail;
898         }
899
900         r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
901         if (r < 0)
902                 goto fail;
903
904         if (e->message) {
905                 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
906                 if (r < 0)
907                         goto fail;
908         }
909
910         t->error._need_free = -1;
911
912         bus_message_set_sender_driver(bus, t);
913
914         *m = t;
915         return 0;
916
917 fail:
918         message_free(t);
919         return r;
920 }
921
922 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
923         assert_return(m, NULL);
924
925         assert(m->n_ref > 0);
926         m->n_ref++;
927
928         return m;
929 }
930
931 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
932
933         if (!m)
934                 return NULL;
935
936         assert(m->n_ref > 0);
937         m->n_ref--;
938
939         if (m->n_ref > 0)
940                 return NULL;
941
942         message_free(m);
943         return NULL;
944 }
945
946 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
947         assert_return(m, -EINVAL);
948         assert_return(type, -EINVAL);
949
950         *type = m->header->type;
951         return 0;
952 }
953
954 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
955         uint64_t c;
956
957         assert_return(m, -EINVAL);
958         assert_return(cookie, -EINVAL);
959
960         c = BUS_MESSAGE_COOKIE(m);
961         if (c == 0)
962                 return -ENODATA;
963
964         *cookie = BUS_MESSAGE_COOKIE(m);
965         return 0;
966 }
967
968 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
969         assert_return(m, -EINVAL);
970         assert_return(cookie, -EINVAL);
971
972         if (m->reply_cookie == 0)
973                 return -ENODATA;
974
975         *cookie = m->reply_cookie;
976         return 0;
977 }
978
979 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
980         assert_return(m, -EINVAL);
981
982         return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
983                 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
984 }
985
986 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
987         assert_return(m, -EINVAL);
988
989         return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
990 }
991
992 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
993         assert_return(m, -EINVAL);
994
995         return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
996                 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
997 }
998
999 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1000         assert_return(m, NULL);
1001
1002         return m->path;
1003 }
1004
1005 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1006         assert_return(m, NULL);
1007
1008         return m->interface;
1009 }
1010
1011 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1012         assert_return(m, NULL);
1013
1014         return m->member;
1015 }
1016
1017 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1018         assert_return(m, NULL);
1019
1020         return m->destination;
1021 }
1022
1023 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1024         assert_return(m, NULL);
1025
1026         return m->sender;
1027 }
1028
1029 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1030         assert_return(m, NULL);
1031         assert_return(sd_bus_error_is_set(&m->error), NULL);
1032
1033         return &m->error;
1034 }
1035
1036 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1037         assert_return(m, -EINVAL);
1038         assert_return(usec, -EINVAL);
1039
1040         if (m->monotonic <= 0)
1041                 return -ENODATA;
1042
1043         *usec = m->monotonic;
1044         return 0;
1045 }
1046
1047 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1048         assert_return(m, -EINVAL);
1049         assert_return(usec, -EINVAL);
1050
1051         if (m->realtime <= 0)
1052                 return -ENODATA;
1053
1054         *usec = m->realtime;
1055         return 0;
1056 }
1057
1058 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1059         assert_return(m, -EINVAL);
1060         assert_return(seqnum, -EINVAL);
1061
1062         if (m->seqnum <= 0)
1063                 return -ENODATA;
1064
1065         *seqnum = m->seqnum;
1066         return 0;
1067 }
1068
1069 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1070         assert_return(m, NULL);
1071
1072         if (m->creds.mask == 0)
1073                 return NULL;
1074
1075         return &m->creds;
1076 }
1077
1078 _public_ int sd_bus_message_is_signal(
1079                 sd_bus_message *m,
1080                 const char *interface,
1081                 const char *member) {
1082
1083         assert_return(m, -EINVAL);
1084
1085         if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1086                 return 0;
1087
1088         if (interface && (!m->interface || !streq(m->interface, interface)))
1089                 return 0;
1090
1091         if (member &&  (!m->member || !streq(m->member, member)))
1092                 return 0;
1093
1094         return 1;
1095 }
1096
1097 _public_ int sd_bus_message_is_method_call(
1098                 sd_bus_message *m,
1099                 const char *interface,
1100                 const char *member) {
1101
1102         assert_return(m, -EINVAL);
1103
1104         if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1105                 return 0;
1106
1107         if (interface && (!m->interface || !streq(m->interface, interface)))
1108                 return 0;
1109
1110         if (member &&  (!m->member || !streq(m->member, member)))
1111                 return 0;
1112
1113         return 1;
1114 }
1115
1116 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1117         assert_return(m, -EINVAL);
1118
1119         if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1120                 return 0;
1121
1122         if (name && (!m->error.name || !streq(m->error.name, name)))
1123                 return 0;
1124
1125         return 1;
1126 }
1127
1128 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1129         assert_return(m, -EINVAL);
1130         assert_return(!m->sealed, -EPERM);
1131         assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1132
1133         if (b)
1134                 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1135         else
1136                 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1137
1138         return 0;
1139 }
1140
1141 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1142         assert_return(m, -EINVAL);
1143         assert_return(!m->sealed, -EPERM);
1144
1145         if (b)
1146                 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1147         else
1148                 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1149
1150         return 0;
1151 }
1152
1153 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1154         assert_return(m, -EINVAL);
1155         assert_return(!m->sealed, -EPERM);
1156
1157         if (b)
1158                 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1159         else
1160                 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1161
1162         return 0;
1163 }
1164
1165 static struct bus_container *message_get_container(sd_bus_message *m) {
1166         assert(m);
1167
1168         if (m->n_containers == 0)
1169                 return &m->root_container;
1170
1171         assert(m->containers);
1172         return m->containers + m->n_containers - 1;
1173 }
1174
1175 struct bus_body_part *message_append_part(sd_bus_message *m) {
1176         struct bus_body_part *part;
1177
1178         assert(m);
1179
1180         if (m->poisoned)
1181                 return NULL;
1182
1183         if (m->n_body_parts <= 0) {
1184                 part = &m->body;
1185                 zero(*part);
1186         } else {
1187                 assert(m->body_end);
1188
1189                 part = new0(struct bus_body_part, 1);
1190                 if (!part) {
1191                         m->poisoned = true;
1192                         return NULL;
1193                 }
1194
1195                 m->body_end->next = part;
1196         }
1197
1198         part->memfd = -1;
1199         m->body_end = part;
1200         m->n_body_parts ++;
1201
1202         return part;
1203 }
1204
1205 static void part_zero(struct bus_body_part *part, size_t sz) {
1206         assert(part);
1207         assert(sz > 0);
1208         assert(sz < 8);
1209
1210         /* All other fields can be left in their defaults */
1211         assert(!part->data);
1212         assert(part->memfd < 0);
1213
1214         part->size = sz;
1215         part->is_zero = true;
1216         part->sealed = true;
1217 }
1218
1219 static int part_make_space(
1220                 struct sd_bus_message *m,
1221                 struct bus_body_part *part,
1222                 size_t sz,
1223                 void **q) {
1224
1225         void *n;
1226         int r;
1227
1228         assert(m);
1229         assert(part);
1230         assert(!part->sealed);
1231
1232         if (m->poisoned)
1233                 return -ENOMEM;
1234
1235         if (!part->data && part->memfd < 0) {
1236                 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1237                 part->mmap_begin = part->data;
1238         }
1239
1240         if (part->memfd >= 0) {
1241
1242                 if (part->allocated == 0 || sz > part->allocated) {
1243                         uint64_t new_allocated;
1244
1245                         new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1246                         r = memfd_set_size(part->memfd, new_allocated);
1247                         if (r < 0) {
1248                                 m->poisoned = true;
1249                                 return r;
1250                         }
1251
1252                         part->allocated = new_allocated;
1253                 }
1254
1255                 if (!part->data || sz > part->mapped) {
1256                         size_t psz;
1257
1258                         psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1259                         if (part->mapped <= 0)
1260                                 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1261                         else
1262                                 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1263
1264                         if (n == MAP_FAILED) {
1265                                 m->poisoned = true;
1266                                 return -errno;
1267                         }
1268
1269                         part->mmap_begin = part->data = n;
1270                         part->mapped = psz;
1271                         part->memfd_offset = 0;
1272                 }
1273
1274                 part->munmap_this = true;
1275         } else {
1276                 if (part->allocated == 0 || sz > part->allocated) {
1277                         size_t new_allocated;
1278
1279                         new_allocated = sz > 0 ? 2 * sz : 64;
1280                         n = realloc(part->data, new_allocated);
1281                         if (!n) {
1282                                 m->poisoned = true;
1283                                 return -ENOMEM;
1284                         }
1285
1286                         part->data = n;
1287                         part->allocated = new_allocated;
1288                         part->free_this = true;
1289                 }
1290         }
1291
1292         if (q)
1293                 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1294
1295         part->size = sz;
1296         return 0;
1297 }
1298
1299 static int message_add_offset(sd_bus_message *m, size_t offset) {
1300         struct bus_container *c;
1301
1302         assert(m);
1303         assert(BUS_MESSAGE_IS_GVARIANT(m));
1304
1305         /* Add offset to current container, unless this is the first
1306          * item in it, which will have the 0 offset, which we can
1307          * ignore. */
1308         c = message_get_container(m);
1309
1310         if (!c->need_offsets)
1311                 return 0;
1312
1313         if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1314                 return -ENOMEM;
1315
1316         c->offsets[c->n_offsets++] = offset;
1317         return 0;
1318 }
1319
1320 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1321         struct bus_container *c;
1322
1323         assert(m);
1324
1325         if (expand <= 0)
1326                 return;
1327
1328         /* Update counters */
1329         for (c = m->containers; c < m->containers + m->n_containers; c++) {
1330
1331                 if (c->array_size)
1332                         *c->array_size += expand;
1333         }
1334 }
1335
1336 static void *message_extend_body(
1337                 sd_bus_message *m,
1338                 size_t align,
1339                 size_t sz,
1340                 bool add_offset,
1341                 bool force_inline) {
1342
1343         size_t start_body, end_body, padding, added;
1344         void *p;
1345         int r;
1346
1347         assert(m);
1348         assert(align > 0);
1349         assert(!m->sealed);
1350
1351         if (m->poisoned)
1352                 return NULL;
1353
1354         start_body = ALIGN_TO((size_t) m->body_size, align);
1355         end_body = start_body + sz;
1356
1357         padding = start_body - m->body_size;
1358         added = padding + sz;
1359
1360         /* Check for 32bit overflows */
1361         if (end_body > (size_t) ((uint32_t) -1) ||
1362             end_body < start_body) {
1363                 m->poisoned = true;
1364                 return NULL;
1365         }
1366
1367         if (added > 0) {
1368                 struct bus_body_part *part = NULL;
1369                 bool add_new_part;
1370
1371                 add_new_part =
1372                         m->n_body_parts <= 0 ||
1373                         m->body_end->sealed ||
1374                         (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1375                         (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 */
1376
1377                 if (add_new_part) {
1378                         if (padding > 0) {
1379                                 part = message_append_part(m);
1380                                 if (!part)
1381                                         return NULL;
1382
1383                                 part_zero(part, padding);
1384                         }
1385
1386                         part = message_append_part(m);
1387                         if (!part)
1388                                 return NULL;
1389
1390                         r = part_make_space(m, part, sz, &p);
1391                         if (r < 0)
1392                                 return NULL;
1393                 } else {
1394                         struct bus_container *c;
1395                         void *op;
1396                         size_t os, start_part, end_part;
1397
1398                         part = m->body_end;
1399                         op = part->data;
1400                         os = part->size;
1401
1402                         start_part = ALIGN_TO(part->size, align);
1403                         end_part = start_part + sz;
1404
1405                         r = part_make_space(m, part, end_part, &p);
1406                         if (r < 0)
1407                                 return NULL;
1408
1409                         if (padding > 0) {
1410                                 memzero(p, padding);
1411                                 p = (uint8_t*) p + padding;
1412                         }
1413
1414                         /* Readjust pointers */
1415                         for (c = m->containers; c < m->containers + m->n_containers; c++)
1416                                 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1417
1418                         m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1419                 }
1420         } else
1421                 /* Return something that is not NULL and is aligned */
1422                 p = (uint8_t *) NULL + align;
1423
1424         m->body_size = end_body;
1425         message_extend_containers(m, added);
1426
1427         if (add_offset) {
1428                 r = message_add_offset(m, end_body);
1429                 if (r < 0) {
1430                         m->poisoned = true;
1431                         return NULL;
1432                 }
1433         }
1434
1435         return p;
1436 }
1437
1438 static int message_push_fd(sd_bus_message *m, int fd) {
1439         int *f, copy;
1440
1441         assert(m);
1442
1443         if (fd < 0)
1444                 return -EINVAL;
1445
1446         if (!m->allow_fds)
1447                 return -EOPNOTSUPP;
1448
1449         copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1450         if (copy < 0)
1451                 return -errno;
1452
1453         f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1454         if (!f) {
1455                 m->poisoned = true;
1456                 safe_close(copy);
1457                 return -ENOMEM;
1458         }
1459
1460         m->fds = f;
1461         m->fds[m->n_fds] = copy;
1462         m->free_fds = true;
1463
1464         return copy;
1465 }
1466
1467 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1468         _cleanup_close_ int fd = -1;
1469         struct bus_container *c;
1470         ssize_t align, sz;
1471         void *a;
1472
1473         assert_return(m, -EINVAL);
1474         assert_return(!m->sealed, -EPERM);
1475         assert_return(bus_type_is_basic(type), -EINVAL);
1476         assert_return(!m->poisoned, -ESTALE);
1477
1478         c = message_get_container(m);
1479
1480         if (c->signature && c->signature[c->index]) {
1481                 /* Container signature is already set */
1482
1483                 if (c->signature[c->index] != type)
1484                         return -ENXIO;
1485         } else {
1486                 char *e;
1487
1488                 /* Maybe we can append to the signature? But only if this is the top-level container */
1489                 if (c->enclosing != 0)
1490                         return -ENXIO;
1491
1492                 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1493                 if (!e) {
1494                         m->poisoned = true;
1495                         return -ENOMEM;
1496                 }
1497         }
1498
1499         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1500                 uint8_t u8;
1501                 uint32_t u32;
1502
1503                 switch (type) {
1504
1505                 case SD_BUS_TYPE_SIGNATURE:
1506                 case SD_BUS_TYPE_STRING:
1507                         p = strempty(p);
1508
1509                         /* Fall through... */
1510                 case SD_BUS_TYPE_OBJECT_PATH:
1511                         if (!p)
1512                                 return -EINVAL;
1513
1514                         align = 1;
1515                         sz = strlen(p) + 1;
1516                         break;
1517
1518                 case SD_BUS_TYPE_BOOLEAN:
1519
1520                         u8 = p && *(int*) p;
1521                         p = &u8;
1522
1523                         align = sz = 1;
1524                         break;
1525
1526                 case SD_BUS_TYPE_UNIX_FD:
1527
1528                         if (!p)
1529                                 return -EINVAL;
1530
1531                         fd = message_push_fd(m, *(int*) p);
1532                         if (fd < 0)
1533                                 return fd;
1534
1535                         u32 = m->n_fds;
1536                         p = &u32;
1537
1538                         align = sz = 4;
1539                         break;
1540
1541                 default:
1542                         align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1543                         sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1544                         break;
1545                 }
1546
1547                 assert(align > 0);
1548                 assert(sz > 0);
1549
1550                 a = message_extend_body(m, align, sz, true, false);
1551                 if (!a)
1552                         return -ENOMEM;
1553
1554                 memcpy(a, p, sz);
1555
1556                 if (stored)
1557                         *stored = (const uint8_t*) a;
1558
1559         } else {
1560                 uint32_t u32;
1561
1562                 switch (type) {
1563
1564                 case SD_BUS_TYPE_STRING:
1565                         /* To make things easy we'll serialize a NULL string
1566                          * into the empty string */
1567                         p = strempty(p);
1568
1569                         /* Fall through... */
1570                 case SD_BUS_TYPE_OBJECT_PATH:
1571
1572                         if (!p)
1573                                 return -EINVAL;
1574
1575                         align = 4;
1576                         sz = 4 + strlen(p) + 1;
1577                         break;
1578
1579                 case SD_BUS_TYPE_SIGNATURE:
1580
1581                         p = strempty(p);
1582
1583                         align = 1;
1584                         sz = 1 + strlen(p) + 1;
1585                         break;
1586
1587                 case SD_BUS_TYPE_BOOLEAN:
1588
1589                         u32 = p && *(int*) p;
1590                         p = &u32;
1591
1592                         align = sz = 4;
1593                         break;
1594
1595                 case SD_BUS_TYPE_UNIX_FD:
1596
1597                         if (!p)
1598                                 return -EINVAL;
1599
1600                         fd = message_push_fd(m, *(int*) p);
1601                         if (fd < 0)
1602                                 return fd;
1603
1604                         u32 = m->n_fds;
1605                         p = &u32;
1606
1607                         align = sz = 4;
1608                         break;
1609
1610                 default:
1611                         align = bus_type_get_alignment(type);
1612                         sz = bus_type_get_size(type);
1613                         break;
1614                 }
1615
1616                 assert(align > 0);
1617                 assert(sz > 0);
1618
1619                 a = message_extend_body(m, align, sz, false, false);
1620                 if (!a)
1621                         return -ENOMEM;
1622
1623                 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1624                         *(uint32_t*) a = sz - 5;
1625                         memcpy((uint8_t*) a + 4, p, sz - 4);
1626
1627                         if (stored)
1628                                 *stored = (const uint8_t*) a + 4;
1629
1630                 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1631                         *(uint8_t*) a = sz - 2;
1632                         memcpy((uint8_t*) a + 1, p, sz - 1);
1633
1634                         if (stored)
1635                                 *stored = (const uint8_t*) a + 1;
1636                 } else {
1637                         memcpy(a, p, sz);
1638
1639                         if (stored)
1640                                 *stored = a;
1641                 }
1642         }
1643
1644         if (type == SD_BUS_TYPE_UNIX_FD)
1645                 m->n_fds ++;
1646
1647         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1648                 c->index++;
1649
1650         fd = -1;
1651         return 0;
1652 }
1653
1654 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1655         return message_append_basic(m, type, p, NULL);
1656 }
1657
1658 _public_ int sd_bus_message_append_string_space(
1659                 sd_bus_message *m,
1660                 size_t size,
1661                 char **s) {
1662
1663         struct bus_container *c;
1664         void *a;
1665
1666         assert_return(m, -EINVAL);
1667         assert_return(s, -EINVAL);
1668         assert_return(!m->sealed, -EPERM);
1669         assert_return(!m->poisoned, -ESTALE);
1670
1671         c = message_get_container(m);
1672
1673         if (c->signature && c->signature[c->index]) {
1674                 /* Container signature is already set */
1675
1676                 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1677                         return -ENXIO;
1678         } else {
1679                 char *e;
1680
1681                 /* Maybe we can append to the signature? But only if this is the top-level container */
1682                 if (c->enclosing != 0)
1683                         return -ENXIO;
1684
1685                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1686                 if (!e) {
1687                         m->poisoned = true;
1688                         return -ENOMEM;
1689                 }
1690         }
1691
1692         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1693                 a = message_extend_body(m, 1, size + 1, true, false);
1694                 if (!a)
1695                         return -ENOMEM;
1696
1697                 *s = a;
1698         } else {
1699                 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1700                 if (!a)
1701                         return -ENOMEM;
1702
1703                 *(uint32_t*) a = size;
1704                 *s = (char*) a + 4;
1705         }
1706
1707         (*s)[size] = 0;
1708
1709         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1710                 c->index++;
1711
1712         return 0;
1713 }
1714
1715 _public_ int sd_bus_message_append_string_iovec(
1716                 sd_bus_message *m,
1717                 const struct iovec *iov,
1718                 unsigned n) {
1719
1720         size_t size;
1721         unsigned i;
1722         char *p;
1723         int r;
1724
1725         assert_return(m, -EINVAL);
1726         assert_return(!m->sealed, -EPERM);
1727         assert_return(iov || n == 0, -EINVAL);
1728         assert_return(!m->poisoned, -ESTALE);
1729
1730         size = IOVEC_TOTAL_SIZE(iov, n);
1731
1732         r = sd_bus_message_append_string_space(m, size, &p);
1733         if (r < 0)
1734                 return r;
1735
1736         for (i = 0; i < n; i++) {
1737
1738                 if (iov[i].iov_base)
1739                         memcpy(p, iov[i].iov_base, iov[i].iov_len);
1740                 else
1741                         memset(p, ' ', iov[i].iov_len);
1742
1743                 p += iov[i].iov_len;
1744         }
1745
1746         return 0;
1747 }
1748
1749 static int bus_message_open_array(
1750                 sd_bus_message *m,
1751                 struct bus_container *c,
1752                 const char *contents,
1753                 uint32_t **array_size,
1754                 size_t *begin,
1755                 bool *need_offsets) {
1756
1757         unsigned nindex;
1758         int alignment, r;
1759
1760         assert(m);
1761         assert(c);
1762         assert(contents);
1763         assert(array_size);
1764         assert(begin);
1765         assert(need_offsets);
1766
1767         if (!signature_is_single(contents, true))
1768                 return -EINVAL;
1769
1770         if (c->signature && c->signature[c->index]) {
1771
1772                 /* Verify the existing signature */
1773
1774                 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1775                         return -ENXIO;
1776
1777                 if (!startswith(c->signature + c->index + 1, contents))
1778                         return -ENXIO;
1779
1780                 nindex = c->index + 1 + strlen(contents);
1781         } else {
1782                 char *e;
1783
1784                 if (c->enclosing != 0)
1785                         return -ENXIO;
1786
1787                 /* Extend the existing signature */
1788
1789                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1790                 if (!e) {
1791                         m->poisoned = true;
1792                         return -ENOMEM;
1793                 }
1794
1795                 nindex = e - c->signature;
1796         }
1797
1798         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1799                 alignment = bus_gvariant_get_alignment(contents);
1800                 if (alignment < 0)
1801                         return alignment;
1802
1803                 /* Add alignment padding and add to offset list */
1804                 if (!message_extend_body(m, alignment, 0, false, false))
1805                         return -ENOMEM;
1806
1807                 r = bus_gvariant_is_fixed_size(contents);
1808                 if (r < 0)
1809                         return r;
1810
1811                 *begin = m->body_size;
1812                 *need_offsets = r == 0;
1813         } else {
1814                 void *a, *op;
1815                 size_t os;
1816                 struct bus_body_part *o;
1817
1818                 alignment = bus_type_get_alignment(contents[0]);
1819                 if (alignment < 0)
1820                         return alignment;
1821
1822                 a = message_extend_body(m, 4, 4, false, false);
1823                 if (!a)
1824                         return -ENOMEM;
1825
1826                 o = m->body_end;
1827                 op = m->body_end->data;
1828                 os = m->body_end->size;
1829
1830                 /* Add alignment between size and first element */
1831                 if (!message_extend_body(m, alignment, 0, false, false))
1832                         return -ENOMEM;
1833
1834                 /* location of array size might have changed so let's readjust a */
1835                 if (o == m->body_end)
1836                         a = adjust_pointer(a, op, os, m->body_end->data);
1837
1838                 *(uint32_t*) a = 0;
1839                 *array_size = a;
1840         }
1841
1842         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1843                 c->index = nindex;
1844
1845         return 0;
1846 }
1847
1848 static int bus_message_open_variant(
1849                 sd_bus_message *m,
1850                 struct bus_container *c,
1851                 const char *contents) {
1852
1853         assert(m);
1854         assert(c);
1855         assert(contents);
1856
1857         if (!signature_is_single(contents, false))
1858                 return -EINVAL;
1859
1860         if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1861                 return -EINVAL;
1862
1863         if (c->signature && c->signature[c->index]) {
1864
1865                 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1866                         return -ENXIO;
1867
1868         } else {
1869                 char *e;
1870
1871                 if (c->enclosing != 0)
1872                         return -ENXIO;
1873
1874                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1875                 if (!e) {
1876                         m->poisoned = true;
1877                         return -ENOMEM;
1878                 }
1879         }
1880
1881         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1882                 /* Variants are always aligned to 8 */
1883
1884                 if (!message_extend_body(m, 8, 0, false, false))
1885                         return -ENOMEM;
1886
1887         } else {
1888                 size_t l;
1889                 void *a;
1890
1891                 l = strlen(contents);
1892                 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1893                 if (!a)
1894                         return -ENOMEM;
1895
1896                 *(uint8_t*) a = l;
1897                 memcpy((uint8_t*) a + 1, contents, l + 1);
1898         }
1899
1900         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1901                 c->index++;
1902
1903         return 0;
1904 }
1905
1906 static int bus_message_open_struct(
1907                 sd_bus_message *m,
1908                 struct bus_container *c,
1909                 const char *contents,
1910                 size_t *begin,
1911                 bool *need_offsets) {
1912
1913         size_t nindex;
1914         int r;
1915
1916         assert(m);
1917         assert(c);
1918         assert(contents);
1919         assert(begin);
1920         assert(need_offsets);
1921
1922         if (!signature_is_valid(contents, false))
1923                 return -EINVAL;
1924
1925         if (c->signature && c->signature[c->index]) {
1926                 size_t l;
1927
1928                 l = strlen(contents);
1929
1930                 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1931                     !startswith(c->signature + c->index + 1, contents) ||
1932                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1933                         return -ENXIO;
1934
1935                 nindex = c->index + 1 + l + 1;
1936         } else {
1937                 char *e;
1938
1939                 if (c->enclosing != 0)
1940                         return -ENXIO;
1941
1942                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1943                 if (!e) {
1944                         m->poisoned = true;
1945                         return -ENOMEM;
1946                 }
1947
1948                 nindex = e - c->signature;
1949         }
1950
1951         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1952                 int alignment;
1953
1954                 alignment = bus_gvariant_get_alignment(contents);
1955                 if (alignment < 0)
1956                         return alignment;
1957
1958                 if (!message_extend_body(m, alignment, 0, false, false))
1959                         return -ENOMEM;
1960
1961                 r = bus_gvariant_is_fixed_size(contents);
1962                 if (r < 0)
1963                         return r;
1964
1965                 *begin = m->body_size;
1966                 *need_offsets = r == 0;
1967         } else {
1968                 /* Align contents to 8 byte boundary */
1969                 if (!message_extend_body(m, 8, 0, false, false))
1970                         return -ENOMEM;
1971         }
1972
1973         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1974                 c->index = nindex;
1975
1976         return 0;
1977 }
1978
1979 static int bus_message_open_dict_entry(
1980                 sd_bus_message *m,
1981                 struct bus_container *c,
1982                 const char *contents,
1983                 size_t *begin,
1984                 bool *need_offsets) {
1985
1986         int r;
1987
1988         assert(m);
1989         assert(c);
1990         assert(contents);
1991         assert(begin);
1992         assert(need_offsets);
1993
1994         if (!signature_is_pair(contents))
1995                 return -EINVAL;
1996
1997         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1998                 return -ENXIO;
1999
2000         if (c->signature && c->signature[c->index]) {
2001                 size_t l;
2002
2003                 l = strlen(contents);
2004
2005                 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2006                     !startswith(c->signature + c->index + 1, contents) ||
2007                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2008                         return -ENXIO;
2009         } else
2010                 return -ENXIO;
2011
2012         if (BUS_MESSAGE_IS_GVARIANT(m)) {
2013                 int alignment;
2014
2015                 alignment = bus_gvariant_get_alignment(contents);
2016                 if (alignment < 0)
2017                         return alignment;
2018
2019                 if (!message_extend_body(m, alignment, 0, false, false))
2020                         return -ENOMEM;
2021
2022                 r = bus_gvariant_is_fixed_size(contents);
2023                 if (r < 0)
2024                         return r;
2025
2026                 *begin = m->body_size;
2027                 *need_offsets = r == 0;
2028         } else {
2029                 /* Align contents to 8 byte boundary */
2030                 if (!message_extend_body(m, 8, 0, false, false))
2031                         return -ENOMEM;
2032         }
2033
2034         return 0;
2035 }
2036
2037 _public_ int sd_bus_message_open_container(
2038                 sd_bus_message *m,
2039                 char type,
2040                 const char *contents) {
2041
2042         struct bus_container *c, *w;
2043         uint32_t *array_size = NULL;
2044         char *signature;
2045         size_t before, begin = 0;
2046         bool need_offsets = false;
2047         int r;
2048
2049         assert_return(m, -EINVAL);
2050         assert_return(!m->sealed, -EPERM);
2051         assert_return(contents, -EINVAL);
2052         assert_return(!m->poisoned, -ESTALE);
2053
2054         /* Make sure we have space for one more container */
2055         if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2056                 m->poisoned = true;
2057                 return -ENOMEM;
2058         }
2059
2060         c = message_get_container(m);
2061
2062         signature = strdup(contents);
2063         if (!signature) {
2064                 m->poisoned = true;
2065                 return -ENOMEM;
2066         }
2067
2068         /* Save old index in the parent container, in case we have to
2069          * abort this container */
2070         c->saved_index = c->index;
2071         before = m->body_size;
2072
2073         if (type == SD_BUS_TYPE_ARRAY)
2074                 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2075         else if (type == SD_BUS_TYPE_VARIANT)
2076                 r = bus_message_open_variant(m, c, contents);
2077         else if (type == SD_BUS_TYPE_STRUCT)
2078                 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2079         else if (type == SD_BUS_TYPE_DICT_ENTRY)
2080                 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2081         else
2082                 r = -EINVAL;
2083
2084         if (r < 0) {
2085                 free(signature);
2086                 return r;
2087         }
2088
2089         /* OK, let's fill it in */
2090         w = m->containers + m->n_containers++;
2091         w->enclosing = type;
2092         w->signature = signature;
2093         w->index = 0;
2094         w->array_size = array_size;
2095         w->before = before;
2096         w->begin = begin;
2097         w->n_offsets = w->offsets_allocated = 0;
2098         w->offsets = NULL;
2099         w->need_offsets = need_offsets;
2100
2101         return 0;
2102 }
2103
2104 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2105
2106         assert(m);
2107         assert(c);
2108
2109         if (!BUS_MESSAGE_IS_GVARIANT(m))
2110                 return 0;
2111
2112         if (c->need_offsets) {
2113                 size_t payload, sz, i;
2114                 uint8_t *a;
2115
2116                 /* Variable-width arrays */
2117
2118                 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2119                 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2120
2121                 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2122                 if (!a)
2123                         return -ENOMEM;
2124
2125                 for (i = 0; i < c->n_offsets; i++)
2126                         bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2127         } else {
2128                 void *a;
2129
2130                 /* Fixed-width or empty arrays */
2131
2132                 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2133                 if (!a)
2134                         return -ENOMEM;
2135         }
2136
2137         return 0;
2138 }
2139
2140 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2141         uint8_t *a;
2142         size_t l;
2143
2144         assert(m);
2145         assert(c);
2146         assert(c->signature);
2147
2148         if (!BUS_MESSAGE_IS_GVARIANT(m))
2149                 return 0;
2150
2151         l = strlen(c->signature);
2152
2153         a = message_extend_body(m, 1, 1 + l, true, false);
2154         if (!a)
2155                 return -ENOMEM;
2156
2157         a[0] = 0;
2158         memcpy(a+1, c->signature, l);
2159
2160         return 0;
2161 }
2162
2163 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2164         size_t n_variable = 0;
2165         unsigned i = 0;
2166         const char *p;
2167         uint8_t *a;
2168         int r;
2169
2170         assert(m);
2171         assert(c);
2172
2173         if (!BUS_MESSAGE_IS_GVARIANT(m))
2174                 return 0;
2175
2176         p = strempty(c->signature);
2177         while (*p != 0) {
2178                 size_t n;
2179
2180                 r = signature_element_length(p, &n);
2181                 if (r < 0)
2182                         return r;
2183                 else {
2184                         char t[n+1];
2185
2186                         memcpy(t, p, n);
2187                         t[n] = 0;
2188
2189                         r = bus_gvariant_is_fixed_size(t);
2190                         if (r < 0)
2191                                 return r;
2192                 }
2193
2194                 assert(!c->need_offsets || i <= c->n_offsets);
2195
2196                 /* We need to add an offset for each item that has a
2197                  * variable size and that is not the last one in the
2198                  * list */
2199                 if (r == 0 && p[n] != 0)
2200                         n_variable++;
2201
2202                 i++;
2203                 p += n;
2204         }
2205
2206         assert(!c->need_offsets || i == c->n_offsets);
2207         assert(c->need_offsets || n_variable == 0);
2208
2209         if (n_variable <= 0) {
2210                 a = message_extend_body(m, 1, 0, add_offset, false);
2211                 if (!a)
2212                         return -ENOMEM;
2213         } else {
2214                 size_t sz;
2215                 unsigned j;
2216
2217                 assert(c->offsets[c->n_offsets-1] == m->body_size);
2218
2219                 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2220
2221                 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2222                 if (!a)
2223                         return -ENOMEM;
2224
2225                 p = strempty(c->signature);
2226                 for (i = 0, j = 0; i < c->n_offsets; i++) {
2227                         unsigned k;
2228                         size_t n;
2229
2230                         r = signature_element_length(p, &n);
2231                         if (r < 0)
2232                                 return r;
2233                         else {
2234                                 char t[n+1];
2235
2236                                 memcpy(t, p, n);
2237                                 t[n] = 0;
2238
2239                                 p += n;
2240
2241                                 r = bus_gvariant_is_fixed_size(t);
2242                                 if (r < 0)
2243                                         return r;
2244                                 if (r > 0 || p[0] == 0)
2245                                         continue;
2246                         }
2247
2248                         k = n_variable - 1 - j;
2249
2250                         bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2251
2252                         j++;
2253                 }
2254         }
2255
2256         return 0;
2257 }
2258
2259 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2260         struct bus_container *c;
2261         int r;
2262
2263         assert_return(m, -EINVAL);
2264         assert_return(!m->sealed, -EPERM);
2265         assert_return(m->n_containers > 0, -EINVAL);
2266         assert_return(!m->poisoned, -ESTALE);
2267
2268         c = message_get_container(m);
2269
2270         if (c->enclosing != SD_BUS_TYPE_ARRAY)
2271                 if (c->signature && c->signature[c->index] != 0)
2272                         return -EINVAL;
2273
2274         m->n_containers--;
2275
2276         if (c->enclosing == SD_BUS_TYPE_ARRAY)
2277                 r = bus_message_close_array(m, c);
2278         else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2279                 r = bus_message_close_variant(m, c);
2280         else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2281                 r = bus_message_close_struct(m, c, true);
2282         else
2283                 assert_not_reached("Unknown container type");
2284
2285         free(c->signature);
2286         free(c->offsets);
2287
2288         return r;
2289 }
2290
2291 typedef struct {
2292         const char *types;
2293         unsigned n_struct;
2294         unsigned n_array;
2295 } TypeStack;
2296
2297 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2298         assert(stack);
2299         assert(max > 0);
2300
2301         if (*i >= max)
2302                 return -EINVAL;
2303
2304         stack[*i].types = types;
2305         stack[*i].n_struct = n_struct;
2306         stack[*i].n_array = n_array;
2307         (*i)++;
2308
2309         return 0;
2310 }
2311
2312 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2313         assert(stack);
2314         assert(max > 0);
2315         assert(types);
2316         assert(n_struct);
2317         assert(n_array);
2318
2319         if (*i <= 0)
2320                 return 0;
2321
2322         (*i)--;
2323         *types = stack[*i].types;
2324         *n_struct = stack[*i].n_struct;
2325         *n_array = stack[*i].n_array;
2326
2327         return 1;
2328 }
2329
2330 int bus_message_append_ap(
2331                 sd_bus_message *m,
2332                 const char *types,
2333                 va_list ap) {
2334
2335         unsigned n_array, n_struct;
2336         TypeStack stack[BUS_CONTAINER_DEPTH];
2337         unsigned stack_ptr = 0;
2338         int r;
2339
2340         assert(m);
2341
2342         if (!types)
2343                 return 0;
2344
2345         n_array = (unsigned) -1;
2346         n_struct = strlen(types);
2347
2348         for (;;) {
2349                 const char *t;
2350
2351                 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2352                         r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2353                         if (r < 0)
2354                                 return r;
2355                         if (r == 0)
2356                                 break;
2357
2358                         r = sd_bus_message_close_container(m);
2359                         if (r < 0)
2360                                 return r;
2361
2362                         continue;
2363                 }
2364
2365                 t = types;
2366                 if (n_array != (unsigned) -1)
2367                         n_array --;
2368                 else {
2369                         types ++;
2370                         n_struct--;
2371                 }
2372
2373                 switch (*t) {
2374
2375                 case SD_BUS_TYPE_BYTE: {
2376                         uint8_t x;
2377
2378                         x = (uint8_t) va_arg(ap, int);
2379                         r = sd_bus_message_append_basic(m, *t, &x);
2380                         break;
2381                 }
2382
2383                 case SD_BUS_TYPE_BOOLEAN:
2384                 case SD_BUS_TYPE_INT32:
2385                 case SD_BUS_TYPE_UINT32:
2386                 case SD_BUS_TYPE_UNIX_FD: {
2387                         uint32_t x;
2388
2389                         /* We assume a boolean is the same as int32_t */
2390                         assert_cc(sizeof(int32_t) == sizeof(int));
2391
2392                         x = va_arg(ap, uint32_t);
2393                         r = sd_bus_message_append_basic(m, *t, &x);
2394                         break;
2395                 }
2396
2397                 case SD_BUS_TYPE_INT16:
2398                 case SD_BUS_TYPE_UINT16: {
2399                         uint16_t x;
2400
2401                         x = (uint16_t) va_arg(ap, int);
2402                         r = sd_bus_message_append_basic(m, *t, &x);
2403                         break;
2404                 }
2405
2406                 case SD_BUS_TYPE_INT64:
2407                 case SD_BUS_TYPE_UINT64: {
2408                         uint64_t x;
2409
2410                         x = va_arg(ap, uint64_t);
2411                         r = sd_bus_message_append_basic(m, *t, &x);
2412                         break;
2413                 }
2414
2415                 case SD_BUS_TYPE_DOUBLE: {
2416                         double x;
2417
2418                         x = va_arg(ap, double);
2419                         r = sd_bus_message_append_basic(m, *t, &x);
2420                         break;
2421                 }
2422
2423                 case SD_BUS_TYPE_STRING:
2424                 case SD_BUS_TYPE_OBJECT_PATH:
2425                 case SD_BUS_TYPE_SIGNATURE: {
2426                         const char *x;
2427
2428                         x = va_arg(ap, const char*);
2429                         r = sd_bus_message_append_basic(m, *t, x);
2430                         break;
2431                 }
2432
2433                 case SD_BUS_TYPE_ARRAY: {
2434                         size_t k;
2435
2436                         r = signature_element_length(t + 1, &k);
2437                         if (r < 0)
2438                                 return r;
2439
2440                         {
2441                                 char s[k + 1];
2442                                 memcpy(s, t + 1, k);
2443                                 s[k] = 0;
2444
2445                                 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2446                                 if (r < 0)
2447                                         return r;
2448                         }
2449
2450                         if (n_array == (unsigned) -1) {
2451                                 types += k;
2452                                 n_struct -= k;
2453                         }
2454
2455                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2456                         if (r < 0)
2457                                 return r;
2458
2459                         types = t + 1;
2460                         n_struct = k;
2461                         n_array = va_arg(ap, unsigned);
2462
2463                         break;
2464                 }
2465
2466                 case SD_BUS_TYPE_VARIANT: {
2467                         const char *s;
2468
2469                         s = va_arg(ap, const char*);
2470                         if (!s)
2471                                 return -EINVAL;
2472
2473                         r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2474                         if (r < 0)
2475                                 return r;
2476
2477                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2478                         if (r < 0)
2479                                 return r;
2480
2481                         types = s;
2482                         n_struct = strlen(s);
2483                         n_array = (unsigned) -1;
2484
2485                         break;
2486                 }
2487
2488                 case SD_BUS_TYPE_STRUCT_BEGIN:
2489                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2490                         size_t k;
2491
2492                         r = signature_element_length(t, &k);
2493                         if (r < 0)
2494                                 return r;
2495
2496                         {
2497                                 char s[k - 1];
2498
2499                                 memcpy(s, t + 1, k - 2);
2500                                 s[k - 2] = 0;
2501
2502                                 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2503                                 if (r < 0)
2504                                         return r;
2505                         }
2506
2507                         if (n_array == (unsigned) -1) {
2508                                 types += k - 1;
2509                                 n_struct -= k - 1;
2510                         }
2511
2512                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2513                         if (r < 0)
2514                                 return r;
2515
2516                         types = t + 1;
2517                         n_struct = k - 2;
2518                         n_array = (unsigned) -1;
2519
2520                         break;
2521                 }
2522
2523                 default:
2524                         r = -EINVAL;
2525                 }
2526
2527                 if (r < 0)
2528                         return r;
2529         }
2530
2531         return 1;
2532 }
2533
2534 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2535         va_list ap;
2536         int r;
2537
2538         assert_return(m, -EINVAL);
2539         assert_return(types, -EINVAL);
2540         assert_return(!m->sealed, -EPERM);
2541         assert_return(!m->poisoned, -ESTALE);
2542
2543         va_start(ap, types);
2544         r = bus_message_append_ap(m, types, ap);
2545         va_end(ap);
2546
2547         return r;
2548 }
2549
2550 _public_ int sd_bus_message_append_array_space(
2551                 sd_bus_message *m,
2552                 char type,
2553                 size_t size,
2554                 void **ptr) {
2555
2556         ssize_t align, sz;
2557         void *a;
2558         int r;
2559
2560         assert_return(m, -EINVAL);
2561         assert_return(!m->sealed, -EPERM);
2562         assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2563         assert_return(ptr || size == 0, -EINVAL);
2564         assert_return(!m->poisoned, -ESTALE);
2565
2566         /* alignment and size of the trivial types (except bool) is
2567          * identical for gvariant and dbus1 marshalling */
2568         align = bus_type_get_alignment(type);
2569         sz = bus_type_get_size(type);
2570
2571         assert_se(align > 0);
2572         assert_se(sz > 0);
2573
2574         if (size % sz != 0)
2575                 return -EINVAL;
2576
2577         r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2578         if (r < 0)
2579                 return r;
2580
2581         a = message_extend_body(m, align, size, false, false);
2582         if (!a)
2583                 return -ENOMEM;
2584
2585         r = sd_bus_message_close_container(m);
2586         if (r < 0)
2587                 return r;
2588
2589         *ptr = a;
2590         return 0;
2591 }
2592
2593 _public_ int sd_bus_message_append_array(
2594                 sd_bus_message *m,
2595                 char type,
2596                 const void *ptr,
2597                 size_t size) {
2598         int r;
2599         void *p;
2600
2601         assert_return(m, -EINVAL);
2602         assert_return(!m->sealed, -EPERM);
2603         assert_return(bus_type_is_trivial(type), -EINVAL);
2604         assert_return(ptr || size == 0, -EINVAL);
2605         assert_return(!m->poisoned, -ESTALE);
2606
2607         r = sd_bus_message_append_array_space(m, type, size, &p);
2608         if (r < 0)
2609                 return r;
2610
2611         if (size > 0)
2612                 memcpy(p, ptr, size);
2613
2614         return 0;
2615 }
2616
2617 _public_ int sd_bus_message_append_array_iovec(
2618                 sd_bus_message *m,
2619                 char type,
2620                 const struct iovec *iov,
2621                 unsigned n) {
2622
2623         size_t size;
2624         unsigned i;
2625         void *p;
2626         int r;
2627
2628         assert_return(m, -EINVAL);
2629         assert_return(!m->sealed, -EPERM);
2630         assert_return(bus_type_is_trivial(type), -EINVAL);
2631         assert_return(iov || n == 0, -EINVAL);
2632         assert_return(!m->poisoned, -ESTALE);
2633
2634         size = IOVEC_TOTAL_SIZE(iov, n);
2635
2636         r = sd_bus_message_append_array_space(m, type, size, &p);
2637         if (r < 0)
2638                 return r;
2639
2640         for (i = 0; i < n; i++) {
2641
2642                 if (iov[i].iov_base)
2643                         memcpy(p, iov[i].iov_base, iov[i].iov_len);
2644                 else
2645                         memzero(p, iov[i].iov_len);
2646
2647                 p = (uint8_t*) p + iov[i].iov_len;
2648         }
2649
2650         return 0;
2651 }
2652
2653 _public_ int sd_bus_message_append_array_memfd(
2654                 sd_bus_message *m,
2655                 char type,
2656                 int memfd,
2657                 uint64_t offset,
2658                 uint64_t size) {
2659
2660         _cleanup_close_ int copy_fd = -1;
2661         struct bus_body_part *part;
2662         ssize_t align, sz;
2663         uint64_t real_size;
2664         void *a;
2665         int r;
2666
2667         assert_return(m, -EINVAL);
2668         assert_return(memfd >= 0, -EINVAL);
2669         assert_return(bus_type_is_trivial(type), -EINVAL);
2670         assert_return(size > 0, -EINVAL);
2671         assert_return(!m->sealed, -EPERM);
2672         assert_return(!m->poisoned, -ESTALE);
2673
2674         r = memfd_set_sealed(memfd);
2675         if (r < 0)
2676                 return r;
2677
2678         copy_fd = dup(memfd);
2679         if (copy_fd < 0)
2680                 return copy_fd;
2681
2682         r = memfd_get_size(memfd, &real_size);
2683         if (r < 0)
2684                 return r;
2685
2686         if (offset == 0 && size == (uint64_t) -1)
2687                 size = real_size;
2688         else if (offset + size > real_size)
2689                 return -EMSGSIZE;
2690
2691         align = bus_type_get_alignment(type);
2692         sz = bus_type_get_size(type);
2693
2694         assert_se(align > 0);
2695         assert_se(sz > 0);
2696
2697         if (offset % align != 0)
2698                 return -EINVAL;
2699
2700         if (size % sz != 0)
2701                 return -EINVAL;
2702
2703         if (size > (uint64_t) (uint32_t) -1)
2704                 return -EINVAL;
2705
2706         r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2707         if (r < 0)
2708                 return r;
2709
2710         a = message_extend_body(m, align, 0, false, false);
2711         if (!a)
2712                 return -ENOMEM;
2713
2714         part = message_append_part(m);
2715         if (!part)
2716                 return -ENOMEM;
2717
2718         part->memfd = copy_fd;
2719         part->memfd_offset = offset;
2720         part->sealed = true;
2721         part->size = size;
2722         copy_fd = -1;
2723
2724         m->body_size += size;
2725         message_extend_containers(m, size);
2726
2727         return sd_bus_message_close_container(m);
2728 }
2729
2730 _public_ int sd_bus_message_append_string_memfd(
2731                 sd_bus_message *m,
2732                 int memfd,
2733                 uint64_t offset,
2734                 uint64_t size) {
2735
2736         _cleanup_close_ int copy_fd = -1;
2737         struct bus_body_part *part;
2738         struct bus_container *c;
2739         uint64_t real_size;
2740         void *a;
2741         int r;
2742
2743         assert_return(m, -EINVAL);
2744         assert_return(memfd >= 0, -EINVAL);
2745         assert_return(size > 0, -EINVAL);
2746         assert_return(!m->sealed, -EPERM);
2747         assert_return(!m->poisoned, -ESTALE);
2748
2749         r = memfd_set_sealed(memfd);
2750         if (r < 0)
2751                 return r;
2752
2753         copy_fd = dup(memfd);
2754         if (copy_fd < 0)
2755                 return copy_fd;
2756
2757         r = memfd_get_size(memfd, &real_size);
2758         if (r < 0)
2759                 return r;
2760
2761         if (offset == 0 && size == (uint64_t) -1)
2762                 size = real_size;
2763         else if (offset + size > real_size)
2764                 return -EMSGSIZE;
2765
2766         /* We require this to be NUL terminated */
2767         if (size == 0)
2768                 return -EINVAL;
2769
2770         if (size > (uint64_t) (uint32_t) -1)
2771                 return -EINVAL;
2772
2773         c = message_get_container(m);
2774         if (c->signature && c->signature[c->index]) {
2775                 /* Container signature is already set */
2776
2777                 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2778                         return -ENXIO;
2779         } else {
2780                 char *e;
2781
2782                 /* Maybe we can append to the signature? But only if this is the top-level container */
2783                 if (c->enclosing != 0)
2784                         return -ENXIO;
2785
2786                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2787                 if (!e) {
2788                         m->poisoned = true;
2789                         return -ENOMEM;
2790                 }
2791         }
2792
2793         if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2794                 a = message_extend_body(m, 4, 4, false, false);
2795                 if (!a)
2796                         return -ENOMEM;
2797
2798                 *(uint32_t*) a = size - 1;
2799         }
2800
2801         part = message_append_part(m);
2802         if (!part)
2803                 return -ENOMEM;
2804
2805         part->memfd = copy_fd;
2806         part->memfd_offset = offset;
2807         part->sealed = true;
2808         part->size = size;
2809         copy_fd = -1;
2810
2811         m->body_size += size;
2812         message_extend_containers(m, size);
2813
2814         if (BUS_MESSAGE_IS_GVARIANT(m)) {
2815                 r = message_add_offset(m, m->body_size);
2816                 if (r < 0) {
2817                         m->poisoned = true;
2818                         return -ENOMEM;
2819                 }
2820         }
2821
2822         if (c->enclosing != SD_BUS_TYPE_ARRAY)
2823                 c->index++;
2824
2825         return 0;
2826 }
2827
2828 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2829         char **i;
2830         int r;
2831
2832         assert_return(m, -EINVAL);
2833         assert_return(!m->sealed, -EPERM);
2834         assert_return(!m->poisoned, -ESTALE);
2835
2836         r = sd_bus_message_open_container(m, 'a', "s");
2837         if (r < 0)
2838                 return r;
2839
2840         STRV_FOREACH(i, l) {
2841                 r = sd_bus_message_append_basic(m, 's', *i);
2842                 if (r < 0)
2843                         return r;
2844         }
2845
2846         return sd_bus_message_close_container(m);
2847 }
2848
2849 static int bus_message_close_header(sd_bus_message *m) {
2850
2851         assert(m);
2852
2853         /* The actual user data is finished now, we just complete the
2854            variant and struct now (at least on gvariant). Remember
2855            this position, so that during parsing we know where to to
2856            put the outer container end. */
2857         m->user_body_size = m->body_size;
2858
2859         if (BUS_MESSAGE_IS_GVARIANT(m)) {
2860                 const char *signature;
2861                 size_t sz, l;
2862                 void *d;
2863
2864                 /* Add offset table to end of fields array */
2865                 if (m->n_header_offsets >= 1) {
2866                         uint8_t *a;
2867                         unsigned i;
2868
2869                         assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2870
2871                         sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2872                         a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2873                         if (!a)
2874                                 return -ENOMEM;
2875
2876                         for (i = 0; i < m->n_header_offsets; i++)
2877                                 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2878                 }
2879
2880                 /* Add gvariant NUL byte plus signature to the end of
2881                  * the body, followed by the final offset pointing to
2882                  * the end of the fields array */
2883
2884                 signature = strempty(m->root_container.signature);
2885                 l = strlen(signature);
2886
2887                 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l, 1);
2888                 d = message_extend_body(m, 1, 1 + l + sz, false, true);
2889                 if (!d)
2890                         return -ENOMEM;
2891
2892                 *(uint8_t*) d = 0;
2893                 memcpy((uint8_t*) d + 1, signature, l);
2894
2895                 bus_gvariant_write_word_le((uint8_t*) d + 1 + l, sz, sizeof(struct bus_header) + m->fields_size);
2896
2897                 m->footer = d;
2898                 m->footer_accessible = 1 + l + sz;
2899         } else {
2900                 m->header->dbus1.fields_size = m->fields_size;
2901                 m->header->dbus1.body_size = m->body_size;
2902         }
2903
2904         return 0;
2905 }
2906
2907 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2908         struct bus_body_part *part;
2909         size_t a;
2910         unsigned i;
2911         int r;
2912
2913         assert(m);
2914
2915         if (m->sealed)
2916                 return -EPERM;
2917
2918         if (m->n_containers > 0)
2919                 return -EBADMSG;
2920
2921         if (m->poisoned)
2922                 return -ESTALE;
2923
2924         if (cookie > 0xffffffffULL &&
2925             !BUS_MESSAGE_IS_GVARIANT(m))
2926                 return -EOPNOTSUPP;
2927
2928         /* In vtables the return signature of method calls is listed,
2929          * let's check if they match if this is a response */
2930         if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2931             m->enforced_reply_signature &&
2932             !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2933                 return -ENOMSG;
2934
2935         /* If gvariant marshalling is used we need to close the body structure */
2936         r = bus_message_close_struct(m, &m->root_container, false);
2937         if (r < 0)
2938                 return r;
2939
2940         /* If there's a non-trivial signature set, then add it in
2941          * here, but only on dbus1 */
2942         if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2943                 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2944                 if (r < 0)
2945                         return r;
2946         }
2947
2948         if (m->n_fds > 0) {
2949                 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2950                 if (r < 0)
2951                         return r;
2952         }
2953
2954         r = bus_message_close_header(m);
2955         if (r < 0)
2956                 return r;
2957
2958         if (BUS_MESSAGE_IS_GVARIANT(m))
2959                 m->header->dbus2.cookie = cookie;
2960         else
2961                 m->header->dbus1.serial = (uint32_t) cookie;
2962
2963         m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2964
2965         /* Add padding at the end of the fields part, since we know
2966          * the body needs to start at an 8 byte alignment. We made
2967          * sure we allocated enough space for this, so all we need to
2968          * do here is to zero it out. */
2969         a = ALIGN8(m->fields_size) - m->fields_size;
2970         if (a > 0)
2971                 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2972
2973         /* If this is something we can send as memfd, then let's seal
2974         the memfd now. Note that we can send memfds as payload only
2975         for directed messages, and not for broadcasts. */
2976         if (m->destination && m->bus->use_memfd) {
2977                 MESSAGE_FOREACH_PART(part, i, m)
2978                         if (part->memfd >= 0 &&
2979                             !part->sealed &&
2980                             (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2981                             part != m->body_end) { /* The last part may never be sent as memfd */
2982                                 uint64_t sz;
2983
2984                                 /* Try to seal it if that makes
2985                                  * sense. First, unmap our own map to
2986                                  * make sure we don't keep it busy. */
2987                                 bus_body_part_unmap(part);
2988
2989                                 /* Then, sync up real memfd size */
2990                                 sz = part->size;
2991                                 r = memfd_set_size(part->memfd, sz);
2992                                 if (r < 0)
2993                                         return r;
2994
2995                                 /* Finally, try to seal */
2996                                 if (memfd_set_sealed(part->memfd) >= 0)
2997                                         part->sealed = true;
2998                         }
2999         }
3000
3001         m->root_container.end = m->user_body_size;
3002         m->root_container.index = 0;
3003         m->root_container.offset_index = 0;
3004         m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3005
3006         m->sealed = true;
3007
3008         return 0;
3009 }
3010
3011 int bus_body_part_map(struct bus_body_part *part) {
3012         void *p;
3013         size_t psz, shift;
3014
3015         assert_se(part);
3016
3017         if (part->data)
3018                 return 0;
3019
3020         if (part->size <= 0)
3021                 return 0;
3022
3023         /* For smaller zero parts (as used for padding) we don't need to map anything... */
3024         if (part->memfd < 0 && part->is_zero && part->size < 8) {
3025                 static const uint8_t zeroes[7] = { };
3026                 part->data = (void*) zeroes;
3027                 return 0;
3028         }
3029
3030         shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3031         psz = PAGE_ALIGN(part->size + shift);
3032
3033         if (part->memfd >= 0)
3034                 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3035         else if (part->is_zero)
3036                 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3037         else
3038                 return -EINVAL;
3039
3040         if (p == MAP_FAILED)
3041                 return -errno;
3042
3043         part->mapped = psz;
3044         part->mmap_begin = p;
3045         part->data = (uint8_t*) p + shift;
3046         part->munmap_this = true;
3047
3048         return 0;
3049 }
3050
3051 void bus_body_part_unmap(struct bus_body_part *part) {
3052
3053         assert_se(part);
3054
3055         if (part->memfd < 0)
3056                 return;
3057
3058         if (!part->mmap_begin)
3059                 return;
3060
3061         if (!part->munmap_this)
3062                 return;
3063
3064         assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3065
3066         part->mmap_begin = NULL;
3067         part->data = NULL;
3068         part->mapped = 0;
3069         part->munmap_this = false;
3070
3071         return;
3072 }
3073
3074 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3075         size_t k, start, end;
3076
3077         assert(rindex);
3078         assert(align > 0);
3079
3080         start = ALIGN_TO((size_t) *rindex, align);
3081         end = start + nbytes;
3082
3083         if (end > sz)
3084                 return -EBADMSG;
3085
3086         /* Verify that padding is 0 */
3087         for (k = *rindex; k < start; k++)
3088                 if (((const uint8_t*) p)[k] != 0)
3089                         return -EBADMSG;
3090
3091         if (r)
3092                 *r = (uint8_t*) p + start;
3093
3094         *rindex = end;
3095
3096         return 1;
3097 }
3098
3099 static bool message_end_of_signature(sd_bus_message *m) {
3100         struct bus_container *c;
3101
3102         assert(m);
3103
3104         c = message_get_container(m);
3105         return !c->signature || c->signature[c->index] == 0;
3106 }
3107
3108 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3109         struct bus_container *c;
3110
3111         assert(m);
3112
3113         c = message_get_container(m);
3114         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3115                 return false;
3116
3117         if (BUS_MESSAGE_IS_GVARIANT(m))
3118                 return index >= c->end;
3119         else {
3120                 assert(c->array_size);
3121                 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3122         }
3123 }
3124
3125 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3126         assert_return(m, -EINVAL);
3127         assert_return(m->sealed, -EPERM);
3128
3129         if (complete && m->n_containers > 0)
3130                 return false;
3131
3132         if (message_end_of_signature(m))
3133                 return true;
3134
3135         if (message_end_of_array(m, m->rindex))
3136                 return true;
3137
3138         return false;
3139 }
3140
3141 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3142         struct bus_body_part *part;
3143         size_t begin;
3144         int r;
3145
3146         assert(m);
3147
3148         if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3149                 part = m->cached_rindex_part;
3150                 begin = m->cached_rindex_part_begin;
3151         } else {
3152                 part = &m->body;
3153                 begin = 0;
3154         }
3155
3156         while (part) {
3157                 if (index < begin)
3158                         return NULL;
3159
3160                 if (index + sz <= begin + part->size) {
3161
3162                         r = bus_body_part_map(part);
3163                         if (r < 0)
3164                                 return NULL;
3165
3166                         if (p)
3167                                 *p = (uint8_t*) part->data + index - begin;
3168
3169                         m->cached_rindex_part = part;
3170                         m->cached_rindex_part_begin = begin;
3171
3172                         return part;
3173                 }
3174
3175                 begin += part->size;
3176                 part = part->next;
3177         }
3178
3179         return NULL;
3180 }
3181
3182 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3183         int r;
3184
3185         assert(m);
3186         assert(c);
3187         assert(rindex);
3188
3189         if (!BUS_MESSAGE_IS_GVARIANT(m))
3190                 return 0;