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