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