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