chiark / gitweb /
c0a0242fd612dfd7b2ce2e082f0ebaa069abb20e
[elogind.git] / src / libsystemd-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
24 #include "util.h"
25 #include "utf8.h"
26 #include "strv.h"
27
28 #include "sd-bus.h"
29 #include "bus-message.h"
30 #include "bus-internal.h"
31 #include "bus-type.h"
32 #include "bus-signature.h"
33
34 static int message_parse_fields(sd_bus_message *m);
35 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
36
37 static void reset_containers(sd_bus_message *m) {
38         unsigned i;
39
40         assert(m);
41
42         for (i = 0; i < m->n_containers; i++)
43                 free(m->containers[i].signature);
44
45         free(m->containers);
46         m->containers = NULL;
47
48         m->n_containers = 0;
49         m->root_container.index = 0;
50 }
51
52 static void message_free(sd_bus_message *m) {
53         unsigned i;
54
55         assert(m);
56
57         if (m->free_header)
58                 free(m->header);
59
60         if (m->free_fields)
61                 free(m->fields);
62
63         if (m->free_body)
64                 free(m->body);
65
66         for (i = 0; i < m->n_fds; i++)
67                 close_nointr_nofail(m->fds[i]);
68
69         reset_containers(m);
70         free(m->root_container.signature);
71
72         free(m->peeked_signature);
73         free(m);
74 }
75
76 static void* buffer_extend(void **p, uint32_t *sz, size_t align, size_t extend) {
77         size_t start, n;
78         void *k;
79
80         assert(p);
81         assert(sz);
82         assert(align > 0);
83
84         start = ALIGN_TO((size_t) *sz, align);
85         n = start + extend;
86
87         if (n == *sz)
88                 return (uint8_t*) *p + start;
89
90         if (n > (size_t) ((uint32_t) -1))
91                 return NULL;
92
93         k = realloc(*p, n);
94         if (!k)
95                 return NULL;
96
97         /* Zero out padding */
98         if (start > *sz)
99                 memset((uint8_t*) k + *sz, 0, start - *sz);
100
101         *p = k;
102         *sz = n;
103
104         return (uint8_t*) k + start;
105 }
106
107 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz) {
108         void *p, *o;
109
110         assert(m);
111
112         o = m->fields;
113         p = buffer_extend(&m->fields, &m->header->fields_size, align, sz);
114         if (!p)
115                 return NULL;
116
117         if (o != m->fields) {
118                 /* Adjust quick access pointers */
119
120                 if (m->path)
121                         m->path = (const char*) m->fields + (m->path - (const char*) o);
122                 if (m->interface)
123                         m->interface = (const char*) m->fields + (m->interface - (const char*) o);
124                 if (m->member)
125                         m->member = (const char*) m->fields + (m->member - (const char*) o);
126                 if (m->destination)
127                         m->destination = (const char*) m->fields + (m->destination - (const char*) o);
128                 if (m->sender)
129                         m->sender = (const char*) m->fields + (m->sender - (const char*) o);
130                 if (m->error.name)
131                         m->error.name = (const char*) m->fields + (m->error.name - (const char*) o);
132         }
133
134         m->free_fields = true;
135
136         return p;
137 }
138
139 static int message_append_field_string(
140                 sd_bus_message *m,
141                 uint8_t h,
142                 char type,
143                 const char *s,
144                 const char **ret) {
145
146         size_t l;
147         uint8_t *p;
148
149         assert(m);
150
151         l = strlen(s);
152         if (l > (size_t) (uint32_t) -1)
153                 return -EINVAL;
154
155         /* field id byte + signature length + signature 's' + NUL + string length + string + NUL */
156         p = message_extend_fields(m, 8, 4 + 4 + l + 1);
157         if (!p)
158                 return -ENOMEM;
159
160         p[0] = h;
161         p[1] = 1;
162         p[2] = type;
163         p[3] = 0;
164
165         ((uint32_t*) p)[1] = l;
166         memcpy(p + 8, s, l + 1);
167
168         if (ret)
169                 *ret = (const char*) p + 8;
170
171         return 0;
172 }
173
174 static int message_append_field_signature(
175                 sd_bus_message *m,
176                 uint8_t h,
177                 const char *s,
178                 const char **ret) {
179
180         size_t l;
181         uint8_t *p;
182
183         assert(m);
184
185         l = strlen(s);
186         if (l > 255)
187                 return -EINVAL;
188
189         /* field id byte + signature length + signature 'g' + NUL + string length + string + NUL */
190         p = message_extend_fields(m, 8, 4 + 1 + l + 1);
191         if (!p)
192                 return -ENOMEM;
193
194         p[0] = h;
195         p[1] = 1;
196         p[2] = SD_BUS_TYPE_SIGNATURE;
197         p[3] = 0;
198         p[4] = l;
199         memcpy(p + 5, s, l + 1);
200
201         if (ret)
202                 *ret = (const char*) p + 5;
203
204         return 0;
205 }
206
207 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
208         uint8_t *p;
209
210         assert(m);
211
212         /* field id byte + signature length + signature 'u' + NUL + value */
213         p = message_extend_fields(m, 8, 4 + 4);
214         if (!p)
215                 return -ENOMEM;
216
217         p[0] = h;
218         p[1] = 1;
219         p[2] = SD_BUS_TYPE_UINT32;
220         p[3] = 0;
221
222         ((uint32_t*) p)[1] = x;
223
224         return 0;
225 }
226
227 int bus_message_from_malloc(void *buffer, size_t length, sd_bus_message **ret) {
228         sd_bus_message *m;
229         struct bus_header *h;
230         size_t total, fs, bs;
231         int r;
232
233         assert(buffer || length <= 0);
234         assert(ret);
235
236         if (length < sizeof(struct bus_header))
237                 return -EBADMSG;
238
239         h = buffer;
240         if (h->version != 1)
241                 return -EBADMSG;
242
243         if (h->serial == 0)
244                 return -EBADMSG;
245
246         if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
247                 return -EBADMSG;
248
249         if (h->endian == SD_BUS_NATIVE_ENDIAN) {
250                 fs = h->fields_size;
251                 bs = h->body_size;
252         } else if (h->endian == SD_BUS_REVERSE_ENDIAN) {
253                 fs = bswap_32(h->fields_size);
254                 bs = bswap_32(h->body_size);
255         } else
256                 return -EBADMSG;
257
258         total = sizeof(struct bus_header) + ALIGN_TO(fs, 8) + bs;
259         if (length != total)
260                 return -EBADMSG;
261
262         m = new0(sd_bus_message, 1);
263         if (!m)
264                 return -ENOMEM;
265
266         m->n_ref = 1;
267         m->header = h;
268         m->free_header = true;
269         m->fields = (uint8_t*) buffer + sizeof(struct bus_header);
270         m->body = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN_TO(fs, 8);
271         m->sealed = true;
272
273         m->n_iovec = 1;
274         m->iovec[0].iov_base = buffer;
275         m->iovec[0].iov_len = length;
276
277         r = message_parse_fields(m);
278         if (r < 0) {
279                 message_free(m);
280                 return r;
281         }
282
283         *ret = m;
284         return 0;
285 }
286
287 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
288         sd_bus_message *m;
289
290         m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
291         if (!m)
292                 return NULL;
293
294         m->n_ref = 1;
295         m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
296         m->header->endian = SD_BUS_NATIVE_ENDIAN;
297         m->header->type = type;
298         m->header->version = bus ? bus->message_version : 1;
299
300         return m;
301 }
302
303 int sd_bus_message_new_signal(
304                 sd_bus *bus,
305                 const char *path,
306                 const char *interface,
307                 const char *member,
308                 sd_bus_message **m) {
309
310         sd_bus_message *t;
311         int r;
312
313         if (!path)
314                 return -EINVAL;
315         if (!interface)
316                 return -EINVAL;
317         if (!member)
318                 return -EINVAL;
319         if (!m)
320                 return -EINVAL;
321
322         t = message_new(bus, SD_BUS_MESSAGE_TYPE_SIGNAL);
323         if (!t)
324                 return -ENOMEM;
325
326         t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
327
328         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
329         if (r < 0)
330                 goto fail;
331         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
332         if (r < 0)
333                 goto fail;
334         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
335         if (r < 0)
336                 goto fail;
337
338         *m = t;
339         return 0;
340
341 fail:
342         sd_bus_message_unref(t);
343         return r;
344 }
345
346 int sd_bus_message_new_method_call(
347                 sd_bus *bus,
348                 const char *destination,
349                 const char *path,
350                 const char *interface,
351                 const char *member,
352                 sd_bus_message **m) {
353
354         sd_bus_message *t;
355         int r;
356
357         if (!path)
358                 return -EINVAL;
359         if (!member)
360                 return -EINVAL;
361         if (!m)
362                 return -EINVAL;
363
364         t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_CALL);
365         if (!t)
366                 return -ENOMEM;
367
368         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
369         if (r < 0)
370                 goto fail;
371         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
372         if (r < 0)
373                 goto fail;
374
375         if (interface) {
376                 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
377                 if (r < 0)
378                         goto fail;
379         }
380
381         if (destination) {
382                 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
383                 if (r < 0)
384                         goto fail;
385         }
386
387         *m = t;
388         return 0;
389
390 fail:
391         message_free(t);
392         return r;
393 }
394
395 static int message_new_reply(
396                 sd_bus *bus,
397                 sd_bus_message *call,
398                 uint8_t type,
399                 sd_bus_message **m) {
400
401         sd_bus_message *t;
402         int r;
403
404         if (!call)
405                 return -EINVAL;
406         if (!call->sealed)
407                 return -EPERM;
408         if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
409                 return -EINVAL;
410         if (!m)
411                 return -EINVAL;
412
413         t = message_new(bus, type);
414         if (!t)
415                 return -ENOMEM;
416
417         t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
418         t->reply_serial = BUS_MESSAGE_SERIAL(call);
419
420         r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
421         if (r < 0)
422                 goto fail;
423
424         if (call->sender) {
425                 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->sender);
426                 if (r < 0)
427                         goto fail;
428         }
429
430         t->dont_send = !!(call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED);
431
432         *m = t;
433         return 0;
434
435 fail:
436         message_free(t);
437         return r;
438 }
439
440 int sd_bus_message_new_method_return(
441                 sd_bus *bus,
442                 sd_bus_message *call,
443                 sd_bus_message **m) {
444
445         return message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_RETURN, m);
446 }
447
448 int sd_bus_message_new_method_error(
449                 sd_bus *bus,
450                 sd_bus_message *call,
451                 const sd_bus_error *e,
452                 sd_bus_message **m) {
453
454         sd_bus_message *t;
455         int r;
456
457         if (!sd_bus_error_is_set(e))
458                 return -EINVAL;
459         if (!m)
460                 return -EINVAL;
461
462         r = message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_ERROR, &t);
463         if (r < 0)
464                 return r;
465
466         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
467         if (r < 0)
468                 goto fail;
469
470         if (e->message) {
471                 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
472                 if (r < 0)
473                         goto fail;
474         }
475
476         *m = t;
477         return 0;
478
479 fail:
480         message_free(t);
481         return r;
482 }
483
484 sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
485         if (!m)
486                 return NULL;
487
488         assert(m->n_ref > 0);
489         m->n_ref++;
490
491         return m;
492 }
493
494 sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
495         if (!m)
496                 return NULL;
497
498         assert(m->n_ref > 0);
499         m->n_ref--;
500
501         if (m->n_ref <= 0)
502                 message_free(m);
503
504         return NULL;
505 }
506
507 int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
508         if (!m)
509                 return -EINVAL;
510         if (!type)
511                 return -EINVAL;
512
513         *type = m->header->type;
514         return 0;
515 }
516
517 int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
518         if (!m)
519                 return -EINVAL;
520         if (!serial)
521                 return -EINVAL;
522         if (m->header->serial == 0)
523                 return -ENOENT;
524
525         *serial = BUS_MESSAGE_SERIAL(m);
526         return 0;
527 }
528
529 int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
530         if (!m)
531                 return -EINVAL;
532         if (!serial)
533                 return -EINVAL;
534         if (m->reply_serial == 0)
535                 return -ENOENT;
536
537         *serial = m->reply_serial;
538         return 0;
539 }
540
541 int sd_bus_message_get_no_reply(sd_bus_message *m) {
542         if (!m)
543                 return -EINVAL;
544
545         return m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL ? !!(m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
546 }
547
548 const char *sd_bus_message_get_path(sd_bus_message *m) {
549         if (!m)
550                 return NULL;
551
552         return m->path;
553 }
554
555 const char *sd_bus_message_get_interface(sd_bus_message *m) {
556         if (!m)
557                 return NULL;
558
559         return m->interface;
560 }
561
562 const char *sd_bus_message_get_member(sd_bus_message *m) {
563         if (!m)
564                 return NULL;
565
566         return m->member;
567 }
568 const char *sd_bus_message_get_destination(sd_bus_message *m) {
569         if (!m)
570                 return NULL;
571
572         return m->destination;
573 }
574
575 const char *sd_bus_message_get_sender(sd_bus_message *m) {
576         if (!m)
577                 return NULL;
578
579         return m->sender;
580 }
581
582 const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
583         if (!m)
584                 return NULL;
585
586         if (!sd_bus_error_is_set(&m->error))
587                 return NULL;
588
589         return &m->error;
590 }
591
592 int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) {
593         if (!m)
594                 return -EINVAL;
595         if (!m->uid_valid)
596                 return -ENOENT;
597
598         *uid = m->uid;
599         return 0;
600 }
601
602 int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) {
603         if (!m)
604                 return -EINVAL;
605         if (!m->gid_valid)
606                 return -ENOENT;
607
608         *gid = m->gid;
609         return 0;
610 }
611
612 int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) {
613         if (!m)
614                 return -EINVAL;
615         if (m->pid <= 0)
616                 return -ENOENT;
617
618         *pid = m->pid;
619         return 0;
620 }
621
622 int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) {
623         if (!m)
624                 return -EINVAL;
625         if (m->tid <= 0)
626                 return -ENOENT;
627
628         *tid = m->tid;
629         return 0;
630 }
631
632 int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member) {
633         if (!m)
634                 return -EINVAL;
635
636         if (m->header->type != SD_BUS_MESSAGE_TYPE_SIGNAL)
637                 return 0;
638
639         if (interface && (!m->interface || !streq(m->interface, interface)))
640                 return 0;
641
642         if (member &&  (!m->member || !streq(m->member, member)))
643                 return 0;
644
645         return 1;
646 }
647
648 int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member) {
649         if (!m)
650                 return -EINVAL;
651
652         if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
653                 return 0;
654
655         if (interface && (!m->interface || !streq(m->interface, interface)))
656                 return 0;
657
658         if (member &&  (!m->member || !streq(m->member, member)))
659                 return 0;
660
661         return 1;
662 }
663
664 int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
665         if (!m)
666                 return -EINVAL;
667
668         if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
669                 return 0;
670
671         if (name && (!m->error.name || !streq(m->error.name, name)))
672                 return 0;
673
674         return 1;
675 }
676
677 int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
678         if (!m)
679                 return -EINVAL;
680         if (m->sealed)
681                 return -EPERM;
682         if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
683                 return -EPERM;
684
685         if (b)
686                 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
687         else
688                 m->header->flags &= ~SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
689
690         return 0;
691 }
692
693 static struct bus_container *message_get_container(sd_bus_message *m) {
694         assert(m);
695
696         if (m->n_containers == 0)
697                 return &m->root_container;
698
699         assert(m->containers);
700         return m->containers + m->n_containers - 1;
701 }
702
703 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
704         void *p, *o;
705         size_t added;
706         struct bus_container *c;
707
708         assert(m);
709         assert(align > 0);
710
711         o = m->body;
712         added = m->header->body_size;
713
714         p = buffer_extend(&m->body, &m->header->body_size, align, sz);
715         if (!p)
716                 return NULL;
717
718         added = m->header->body_size - added;
719
720         for (c = m->containers; c < m->containers + m->n_containers; c++)
721                 if (c->array_size) {
722                         c->array_size = (uint32_t*) ((uint8_t*) m->body + ((uint8_t*) c->array_size - (uint8_t*) o));
723                         *c->array_size += added;
724                 }
725
726         if (o != m->body) {
727                 if (m->error.message)
728                         m->error.message = (const char*) m->body + (m->error.message - (const char*) o);
729         }
730
731         m->free_body = true;
732
733         return p;
734 }
735
736 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
737         struct bus_container *c;
738         size_t sz, align;
739         uint32_t k;
740         void *a;
741         char *e = NULL;
742
743         if (!m)
744                 return -EINVAL;
745         if (m->sealed)
746                 return -EPERM;
747         if (!bus_type_is_basic(type))
748                 return -EINVAL;
749
750         c = message_get_container(m);
751
752         if (c->signature && c->signature[c->index]) {
753                 /* Container signature is already set */
754
755                 if (c->signature[c->index] != type)
756                         return -ENXIO;
757         } else {
758                 /* Maybe we can append to the signature? But only if this is the top-level container*/
759                 if (c->enclosing != 0)
760                         return -ENXIO;
761
762                 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
763                 if (!e)
764                         return -ENOMEM;
765         }
766
767         switch (type) {
768
769         case SD_BUS_TYPE_STRING:
770         case SD_BUS_TYPE_OBJECT_PATH:
771                 align = 4;
772                 sz = 4 + strlen(p) + 1;
773                 break;
774
775         case SD_BUS_TYPE_SIGNATURE:
776                 align = 1;
777                 sz = 1 + strlen(p) + 1;
778                 break;
779
780         case SD_BUS_TYPE_BOOLEAN:
781                 align = sz = 4;
782
783                 assert_cc(sizeof(int) == sizeof(uint32_t));
784                 memcpy(&k, p, 4);
785                 k = !!k;
786                 p = &k;
787                 break;
788
789         default:
790                 align = bus_type_get_alignment(type);
791                 sz = bus_type_get_size(type);
792                 break;
793         }
794
795         assert(align > 0);
796         assert(sz > 0);
797
798         a = message_extend_body(m, align, sz);
799         if (!a) {
800                 /* Truncate extended signature again */
801                 if (e)
802                         c->signature[c->index] = 0;
803
804                 return -ENOMEM;
805         }
806
807         if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
808                 *(uint32_t*) a = sz - 5;
809                 memcpy((uint8_t*) a + 4, p, sz - 4);
810
811                 if (stored)
812                         *stored = (const uint8_t*) a + 4;
813
814         } else if (type == SD_BUS_TYPE_SIGNATURE) {
815                 *(uint8_t*) a = sz - 1;
816                 memcpy((uint8_t*) a + 1, p, sz - 1);
817
818                 if (stored)
819                         *stored = (const uint8_t*) a + 1;
820
821         } else {
822                 memcpy(a, p, sz);
823
824                 if (stored)
825                         *stored = a;
826         }
827
828         if (c->enclosing != SD_BUS_TYPE_ARRAY)
829                 c->index++;
830
831         return 0;
832 }
833
834 int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
835         return message_append_basic(m, type, p, NULL);
836 }
837
838 static int bus_message_open_array(
839                 sd_bus_message *m,
840                 struct bus_container *c,
841                 const char *contents,
842                 uint32_t **array_size) {
843
844         unsigned nindex;
845         char *e = NULL;
846         void *a, *b;
847         int alignment;
848         size_t saved;
849
850         assert(m);
851         assert(c);
852         assert(contents);
853         assert(array_size);
854
855         if (!signature_is_single(contents))
856                 return -EINVAL;
857
858         alignment = bus_type_get_alignment(contents[0]);
859         if (alignment < 0)
860                 return alignment;
861
862         if (c->signature && c->signature[c->index]) {
863
864                 /* Verify the existing signature */
865
866                 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
867                         return -ENXIO;
868
869                 if (!startswith(c->signature + c->index + 1, contents))
870                         return -ENXIO;
871
872                 nindex = c->index + 1 + strlen(contents);
873         } else {
874                 if (c->enclosing != 0)
875                         return -ENXIO;
876
877                 /* Extend the existing signature */
878
879                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
880                 if (!e)
881                         return -ENOMEM;
882
883                 nindex = e - c->signature;
884         }
885
886         saved = m->header->body_size;
887         a = message_extend_body(m, 4, 4);
888         if (!a) {
889                 /* Truncate extended signature again */
890                 if (e)
891                         c->signature[c->index] = 0;
892
893                 return -ENOMEM;
894         }
895         b = m->body;
896
897         if (!message_extend_body(m, alignment, 0)) {
898                 /* Add alignment between size and first element */
899                 if (e)
900                         c->signature[c->index] = 0;
901
902                 m->header->body_size = saved;
903                 return -ENOMEM;
904         }
905
906         if (c->enclosing != SD_BUS_TYPE_ARRAY)
907                 c->index = nindex;
908
909         /* m->body might have changed so let's readjust a */
910         a = (uint8_t*) m->body + ((uint8_t*) a - (uint8_t*) b);
911         *(uint32_t*) a = 0;
912
913         *array_size = a;
914         return 0;
915 }
916
917 static int bus_message_open_variant(
918                 sd_bus_message *m,
919                 struct bus_container *c,
920                 const char *contents) {
921
922         char *e = NULL;
923         size_t l;
924         void *a;
925
926         assert(m);
927         assert(c);
928         assert(contents);
929
930         if (!signature_is_single(contents))
931                 return -EINVAL;
932
933         if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
934                 return -EINVAL;
935
936         if (c->signature && c->signature[c->index]) {
937
938                 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
939                         return -ENXIO;
940
941         } else {
942                 if (c->enclosing != 0)
943                         return -ENXIO;
944
945                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
946                 if (!e)
947                         return -ENOMEM;
948         }
949
950         l = strlen(contents);
951         a = message_extend_body(m, 1, 1 + l + 1);
952         if (!a) {
953                 /* Truncate extended signature again */
954                 if (e)
955                         c->signature[c->index] = 0;
956
957                 return -ENOMEM;
958         }
959
960         *(uint8_t*) a = l;
961         memcpy((uint8_t*) a + 1, contents, l + 1);
962
963         if (c->enclosing != SD_BUS_TYPE_ARRAY)
964                 c->index++;
965
966         return 0;
967 }
968
969 static int bus_message_open_struct(
970                 sd_bus_message *m,
971                 struct bus_container *c,
972                 const char *contents) {
973
974         size_t nindex;
975         char *e = NULL;
976
977         assert(m);
978         assert(c);
979         assert(contents);
980
981         if (!signature_is_valid(contents, false))
982                 return -EINVAL;
983
984         if (c->signature && c->signature[c->index]) {
985                 size_t l;
986
987                 l = strlen(contents);
988
989                 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
990                     !startswith(c->signature + c->index + 1, contents) ||
991                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
992                         return -ENXIO;
993
994                 nindex = c->index + 1 + l + 1;
995         } else {
996                 if (c->enclosing != 0)
997                         return -ENXIO;
998
999                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1000                 if (!e)
1001                         return -ENOMEM;
1002
1003                 nindex = e - c->signature;
1004         }
1005
1006         /* Align contents to 8 byte boundary */
1007         if (!message_extend_body(m, 8, 0)) {
1008                 if (e)
1009                         c->signature[c->index] = 0;
1010
1011                 return -ENOMEM;
1012         }
1013
1014         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1015                 c->index = nindex;
1016
1017         return 0;
1018 }
1019
1020 static int bus_message_open_dict_entry(
1021                 sd_bus_message *m,
1022                 struct bus_container *c,
1023                 const char *contents) {
1024
1025         size_t nindex;
1026
1027         assert(m);
1028         assert(c);
1029         assert(contents);
1030
1031         if (!signature_is_pair(contents))
1032                 return -EINVAL;
1033
1034         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1035                 return -ENXIO;
1036
1037         if (c->signature && c->signature[c->index]) {
1038                 size_t l;
1039
1040                 l = strlen(contents);
1041
1042                 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1043                     !startswith(c->signature + c->index + 1, contents) ||
1044                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1045                         return -ENXIO;
1046
1047                 nindex = c->index + 1 + l + 1;
1048         } else
1049                 return -ENXIO;
1050
1051         /* Align contents to 8 byte boundary */
1052         if (!message_extend_body(m, 8, 0))
1053                 return -ENOMEM;
1054
1055         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1056                 c->index = nindex;
1057
1058         return 0;
1059 }
1060
1061 int sd_bus_message_open_container(
1062                 sd_bus_message *m,
1063                 char type,
1064                 const char *contents) {
1065
1066         struct bus_container *c, *w;
1067         uint32_t *array_size = NULL;
1068         char *signature;
1069         int r;
1070
1071         if (!m)
1072                 return -EINVAL;
1073         if (m->sealed)
1074                 return -EPERM;
1075         if (!contents)
1076                 return -EINVAL;
1077
1078         /* Make sure we have space for one more container */
1079         w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1080         if (!w)
1081                 return -ENOMEM;
1082         m->containers = w;
1083
1084         c = message_get_container(m);
1085
1086         signature = strdup(contents);
1087         if (!signature)
1088                 return -ENOMEM;
1089
1090         if (type == SD_BUS_TYPE_ARRAY)
1091                 r = bus_message_open_array(m, c, contents, &array_size);
1092         else if (type == SD_BUS_TYPE_VARIANT)
1093                 r = bus_message_open_variant(m, c, contents);
1094         else if (type == SD_BUS_TYPE_STRUCT)
1095                 r = bus_message_open_struct(m, c, contents);
1096         else if (type == SD_BUS_TYPE_DICT_ENTRY)
1097                 r = bus_message_open_dict_entry(m, c, contents);
1098         else
1099                 r = -EINVAL;
1100
1101         if (r < 0) {
1102                 free(signature);
1103                 return r;
1104         }
1105
1106         /* OK, let's fill it in */
1107         w += m->n_containers++;
1108         w->enclosing = type;
1109         w->signature = signature;
1110         w->index = 0;
1111         w->array_size = array_size;
1112         w->begin = 0;
1113
1114         return 0;
1115 }
1116
1117 int sd_bus_message_close_container(sd_bus_message *m) {
1118         struct bus_container *c;
1119
1120         if (!m)
1121                 return -EINVAL;
1122         if (m->sealed)
1123                 return -EPERM;
1124         if (m->n_containers <= 0)
1125                 return -EINVAL;
1126
1127         c = message_get_container(m);
1128         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1129                 if (c->signature && c->signature[c->index] != 0)
1130                         return -EINVAL;
1131
1132         free(c->signature);
1133         m->n_containers--;
1134
1135         return 0;
1136 }
1137
1138 static int message_append_ap(
1139                 sd_bus_message *m,
1140                 const char *types,
1141                 va_list ap) {
1142
1143         const char *t;
1144         int r;
1145
1146         assert(m);
1147         assert(types);
1148
1149         for (t = types; *t; t++) {
1150                 switch (*t) {
1151
1152                 case SD_BUS_TYPE_BYTE: {
1153                         uint8_t x;
1154
1155                         x = (uint8_t) va_arg(ap, int);
1156                         r = sd_bus_message_append_basic(m, *t, &x);
1157                         break;
1158                 }
1159
1160                 case SD_BUS_TYPE_BOOLEAN:
1161                 case SD_BUS_TYPE_INT32:
1162                 case SD_BUS_TYPE_UINT32:
1163                 case SD_BUS_TYPE_UNIX_FD: {
1164                         uint32_t x;
1165
1166                         /* We assume a boolean is the same as int32_t */
1167                         assert_cc(sizeof(int32_t) == sizeof(int));
1168
1169                         x = va_arg(ap, uint32_t);
1170                         r = sd_bus_message_append_basic(m, *t, &x);
1171                         break;
1172                 }
1173
1174                 case SD_BUS_TYPE_INT16:
1175                 case SD_BUS_TYPE_UINT16: {
1176                         uint16_t x;
1177
1178                         x = (uint16_t) va_arg(ap, int);
1179                         r = sd_bus_message_append_basic(m, *t, &x);
1180                         break;
1181                 }
1182
1183                 case SD_BUS_TYPE_INT64:
1184                 case SD_BUS_TYPE_UINT64:
1185                 case SD_BUS_TYPE_DOUBLE: {
1186                         uint64_t x;
1187
1188                         x = va_arg(ap, uint64_t);
1189                         r = sd_bus_message_append_basic(m, *t, &x);
1190                         break;
1191                 }
1192
1193                 case SD_BUS_TYPE_STRING:
1194                 case SD_BUS_TYPE_OBJECT_PATH:
1195                 case SD_BUS_TYPE_SIGNATURE: {
1196                         const char *x;
1197
1198                         x = va_arg(ap, const char*);
1199                         r = sd_bus_message_append_basic(m, *t, x);
1200                         break;
1201                 }
1202
1203                 case SD_BUS_TYPE_ARRAY: {
1204                         size_t k;
1205
1206                         r = signature_element_length(t + 1, &k);
1207                         if (r < 0)
1208                                 return r;
1209
1210                         {
1211                                 unsigned i, n;
1212                                 char s[k + 1];
1213
1214                                 memcpy(s, t + 1, k);
1215                                 s[k] = 0;
1216                                 t += k;
1217
1218                                 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1219                                 if (r < 0)
1220                                         return r;
1221
1222                                 n = va_arg(ap, unsigned);
1223                                 for (i = 0; i < n; i++) {
1224                                         r = message_append_ap(m, s, ap);
1225                                         if (r < 0)
1226                                                 return r;
1227                                 }
1228
1229                                 r = sd_bus_message_close_container(m);
1230                         }
1231
1232                         break;
1233                 }
1234
1235                 case SD_BUS_TYPE_VARIANT: {
1236                         const char *s;
1237
1238                         s = va_arg(ap, const char*);
1239                         if (!s)
1240                                 return -EINVAL;
1241
1242                         r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
1243                         if (r < 0)
1244                                 return r;
1245
1246                         r = message_append_ap(m, s, ap);
1247                         if (r < 0)
1248                                 return r;
1249
1250                         r = sd_bus_message_close_container(m);
1251                         break;
1252                 }
1253
1254                 case SD_BUS_TYPE_STRUCT_BEGIN:
1255                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
1256                         size_t k;
1257
1258                         r = signature_element_length(t, &k);
1259                         if (r < 0)
1260                                 return r;
1261
1262                         {
1263                                 char s[k - 1];
1264
1265                                 memcpy(s, t + 1, k - 2);
1266                                 s[k - 2] = 0;
1267
1268                                 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
1269                                 if (r < 0)
1270                                         return r;
1271
1272                                 t += k - 1;
1273
1274                                 r = message_append_ap(m, s, ap);
1275                                 if (r < 0)
1276                                         return r;
1277
1278                                 r = sd_bus_message_close_container(m);
1279                         }
1280
1281                         break;
1282                 }
1283
1284                 default:
1285                         r = -EINVAL;
1286                 }
1287
1288                 if (r < 0)
1289                         return r;
1290         }
1291
1292         return 0;
1293 }
1294
1295 int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
1296         va_list ap;
1297         int r;
1298
1299         if (!m)
1300                 return -EINVAL;
1301         if (m->sealed)
1302                 return -EPERM;
1303         if (!types)
1304                 return -EINVAL;
1305
1306         va_start(ap, types);
1307         r = message_append_ap(m, types, ap);
1308         va_end(ap);
1309
1310         return r;
1311 }
1312
1313 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
1314         size_t k, start, n;
1315
1316         assert(rindex);
1317         assert(align > 0);
1318
1319         start = ALIGN_TO((size_t) *rindex, align);
1320         n = start + nbytes;
1321
1322         if (n > sz)
1323                 return -EBADMSG;
1324
1325         /* Verify that padding is 0 */
1326         for (k = *rindex; k < start; k++)
1327                 if (((const uint8_t*) p)[k] != 0)
1328                         return -EBADMSG;
1329
1330         if (r)
1331                 *r = (uint8_t*) p + start;
1332
1333         *rindex = n;
1334
1335         return 1;
1336 }
1337
1338 static bool message_end_of_array(sd_bus_message *m, size_t index) {
1339         struct bus_container *c;
1340
1341         assert(m);
1342
1343         c = message_get_container(m);
1344         if (!c->array_size)
1345                 return false;
1346
1347         return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
1348 }
1349
1350 static int message_peek_body(sd_bus_message *m, size_t *rindex, size_t align, size_t nbytes, void **ret) {
1351         assert(m);
1352         assert(rindex);
1353         assert(align > 0);
1354
1355         if (message_end_of_array(m, *rindex))
1356                 return 0;
1357
1358         return buffer_peek(m->body, BUS_MESSAGE_BODY_SIZE(m), rindex, align, nbytes, ret);
1359 }
1360
1361 static bool validate_string(const char *s, size_t l) {
1362         assert(s);
1363
1364         /* Check for NUL chars in the string */
1365         if (memchr(s, 0, l))
1366                 return false;
1367
1368         /* Check for NUL termination */
1369         if (s[l] != 0)
1370                 return false;
1371
1372         /* Check if valid UTF8 */
1373         if (!utf8_is_valid(s))
1374                 return false;
1375
1376         return true;
1377 }
1378
1379 static bool validate_signature(const char *s, size_t l) {
1380         /* Check for NUL chars in the signature */
1381         if (memchr(s, 0, l))
1382                 return false;
1383
1384         /* Check for NUL termination */
1385         if (s[l] != 0)
1386                 return false;
1387
1388         /* Check if valid signature */
1389         if (!signature_is_valid(s, true))
1390                 return false;
1391
1392         return true;
1393 }
1394
1395 int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
1396         struct bus_container *c;
1397         int r;
1398         void *q;
1399
1400         if (!m)
1401                 return -EINVAL;
1402         if (!m->sealed)
1403                 return -EPERM;
1404         if (!bus_type_is_basic(type))
1405                 return -EINVAL;
1406
1407         c = message_get_container(m);
1408
1409         if (!c->signature || c->signature[c->index] == 0)
1410                 return 0;
1411
1412         if (c->signature[c->index] != type)
1413                 return -ENXIO;
1414
1415         switch (type) {
1416
1417         case SD_BUS_TYPE_STRING:
1418         case SD_BUS_TYPE_OBJECT_PATH: {
1419                 uint32_t l;
1420                 size_t rindex;
1421
1422                 rindex = m->rindex;
1423                 r = message_peek_body(m, &rindex, 4, 4, &q);
1424                 if (r <= 0)
1425                         return r;
1426
1427                 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1428                 r = message_peek_body(m, &rindex, 1, l+1, &q);
1429                 if (r < 0)
1430                         return r;
1431                 if (r == 0)
1432                         return -EBADMSG;
1433
1434                 if (!validate_string(q, l))
1435                         return -EBADMSG;
1436
1437                 m->rindex = rindex;
1438                 *(const char**) p = q;
1439                 break;
1440         }
1441
1442         case SD_BUS_TYPE_SIGNATURE: {
1443                 uint8_t l;
1444                 size_t rindex;
1445
1446                 rindex = m->rindex;
1447                 r = message_peek_body(m, &rindex, 1, 1, &q);
1448                 if (r <= 0)
1449                         return r;
1450
1451                 l = *(uint8_t*) q;
1452                 r = message_peek_body(m, &rindex, 1, l+1, &q);
1453                 if (r < 0)
1454                         return r;
1455                 if (r == 0)
1456                         return -EBADMSG;
1457
1458                 if (!validate_signature(q, l))
1459                         return -EBADMSG;
1460
1461                 m->rindex = rindex;
1462                 *(const char**) p = q;
1463                 break;
1464         }
1465
1466         default: {
1467                 size_t sz, align;
1468
1469                 align = bus_type_get_alignment(type);
1470                 sz = bus_type_get_size(type);
1471
1472                 r = message_peek_body(m, &m->rindex, align, sz, &q);
1473                 if (r <= 0)
1474                         return r;
1475
1476                 switch (type) {
1477
1478                 case SD_BUS_TYPE_BYTE:
1479                         *(uint8_t*) p = *(uint8_t*) q;
1480                         break;
1481
1482                 case SD_BUS_TYPE_BOOLEAN:
1483                         *(int*) p = !!*(uint32_t*) q;
1484                         break;
1485
1486                 case SD_BUS_TYPE_INT16:
1487                 case SD_BUS_TYPE_UINT16:
1488                         *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
1489                         break;
1490
1491                 case SD_BUS_TYPE_INT32:
1492                 case SD_BUS_TYPE_UINT32:
1493                         *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1494                         break;
1495
1496                 case SD_BUS_TYPE_INT64:
1497                 case SD_BUS_TYPE_UINT64:
1498                 case SD_BUS_TYPE_DOUBLE:
1499                         *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
1500                         break;
1501
1502                 default:
1503                         assert_not_reached("Unknown basic type...");
1504                 }
1505
1506                 break;
1507         }
1508         }
1509
1510         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1511                 c->index++;
1512
1513         return 1;
1514 }
1515
1516 static int bus_message_enter_array(
1517                 sd_bus_message *m,
1518                 struct bus_container *c,
1519                 const char *contents,
1520                 uint32_t **array_size) {
1521
1522         size_t rindex;
1523         void *q;
1524         int r, alignment;
1525
1526         assert(m);
1527         assert(c);
1528         assert(contents);
1529         assert(array_size);
1530
1531         if (!signature_is_single(contents))
1532                 return -EINVAL;
1533
1534         alignment = bus_type_get_alignment(contents[0]);
1535         if (alignment < 0)
1536                 return alignment;
1537
1538         if (!c->signature || c->signature[c->index] == 0)
1539                 return 0;
1540
1541         if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1542                 return -ENXIO;
1543
1544         if (!startswith(c->signature + c->index + 1, contents))
1545                 return -ENXIO;
1546
1547         rindex = m->rindex;
1548         r = message_peek_body(m, &rindex, 4, 4, &q);
1549         if (r <= 0)
1550                 return r;
1551
1552         if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > 67108864)
1553                 return -EBADMSG;
1554
1555         r = message_peek_body(m, &rindex, alignment, 0, NULL);
1556         if (r < 0)
1557                 return r;
1558         if (r == 0)
1559                 return -EBADMSG;
1560
1561         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1562                 c->index += 1 + strlen(contents);
1563
1564         m->rindex = rindex;
1565
1566         *array_size = (uint32_t*) q;
1567
1568         return 1;
1569 }
1570
1571 static int bus_message_enter_variant(
1572                 sd_bus_message *m,
1573                 struct bus_container *c,
1574                 const char *contents) {
1575
1576         size_t rindex;
1577         uint8_t l;
1578         void *q;
1579         int r;
1580
1581         assert(m);
1582         assert(c);
1583         assert(contents);
1584
1585         if (!signature_is_single(contents))
1586                 return -EINVAL;
1587
1588         if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1589                 return -EINVAL;
1590
1591         if (!c->signature || c->signature[c->index] == 0)
1592                 return 0;
1593
1594         if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1595                 return -ENXIO;
1596
1597         rindex = m->rindex;
1598         r = message_peek_body(m, &rindex, 1, 1, &q);
1599         if (r <= 0)
1600                 return r;
1601
1602         l = *(uint8_t*) q;
1603         r = message_peek_body(m, &rindex, 1, l+1, &q);
1604         if (r < 0)
1605                 return r;
1606         if (r == 0)
1607                 return -EBADMSG;
1608
1609         if (!validate_signature(q, l))
1610                 return -EBADMSG;
1611
1612         if (!streq(q, contents))
1613                 return -ENXIO;
1614
1615         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1616                 c->index++;
1617
1618         m->rindex = rindex;
1619
1620         return 1;
1621 }
1622
1623 static int bus_message_enter_struct(
1624                 sd_bus_message *m,
1625                 struct bus_container *c,
1626                 const char *contents) {
1627
1628         size_t l;
1629         int r;
1630
1631         assert(m);
1632         assert(c);
1633         assert(contents);
1634
1635         if (!signature_is_valid(contents, false))
1636                 return -EINVAL;
1637
1638         if (!c->signature || c->signature[c->index] == 0)
1639                 return 0;
1640
1641         l = strlen(contents);
1642
1643         if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1644             !startswith(c->signature + c->index + 1, contents) ||
1645             c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1646                 return -ENXIO;
1647
1648         r = message_peek_body(m, &m->rindex, 8, 0, NULL);
1649         if (r <= 0)
1650                 return r;
1651
1652         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1653                 c->index += 1 + l + 1;
1654
1655         return 1;
1656 }
1657
1658 static int bus_message_enter_dict_entry(
1659                 sd_bus_message *m,
1660                 struct bus_container *c,
1661                 const char *contents) {
1662
1663         size_t l;
1664         int r;
1665
1666         assert(m);
1667         assert(c);
1668         assert(contents);
1669
1670         if (!signature_is_pair(contents))
1671                 return -EINVAL;
1672
1673         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1674                 return -ENXIO;
1675
1676         if (!c->signature || c->signature[c->index] == 0)
1677                 return 0;
1678
1679         l = strlen(contents);
1680
1681         if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1682             !startswith(c->signature + c->index + 1, contents) ||
1683             c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1684                 return -ENXIO;
1685
1686         r = message_peek_body(m, &m->rindex, 8, 0, NULL);
1687         if (r <= 0)
1688                 return r;
1689
1690         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1691                 c->index += 1 + l + 1;
1692
1693         return 1;
1694 }
1695
1696 int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents) {
1697         struct bus_container *c, *w;
1698         uint32_t *array_size = NULL;
1699         char *signature;
1700         int r;
1701
1702         if (!m)
1703                 return -EINVAL;
1704         if (!m->sealed)
1705                 return -EPERM;
1706         if (!contents)
1707                 return -EINVAL;
1708
1709         w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1710         if (!w)
1711                 return -ENOMEM;
1712         m->containers = w;
1713
1714         c = message_get_container(m);
1715
1716         if (!c->signature || c->signature[c->index] == 0)
1717                 return 0;
1718
1719         signature = strdup(contents);
1720         if (!signature)
1721                 return -ENOMEM;
1722
1723         if (type == SD_BUS_TYPE_ARRAY)
1724                 r = bus_message_enter_array(m, c, contents, &array_size);
1725         else if (type == SD_BUS_TYPE_VARIANT)
1726                 r = bus_message_enter_variant(m, c, contents);
1727         else if (type == SD_BUS_TYPE_STRUCT)
1728                 r = bus_message_enter_struct(m, c, contents);
1729         else if (type == SD_BUS_TYPE_DICT_ENTRY)
1730                 r = bus_message_enter_dict_entry(m, c, contents);
1731         else
1732                 r = -EINVAL;
1733
1734         if (r <= 0) {
1735                 free(signature);
1736                 return r;
1737         }
1738
1739         /* OK, let's fill it in */
1740         w += m->n_containers++;
1741         w->enclosing = type;
1742         w->signature = signature;
1743         w->index = 0;
1744         w->array_size = array_size;
1745         w->begin = m->rindex;
1746
1747         return 1;
1748 }
1749
1750 int sd_bus_message_exit_container(sd_bus_message *m) {
1751         struct bus_container *c;
1752
1753         if (!m)
1754                 return -EINVAL;
1755         if (!m->sealed)
1756                 return -EPERM;
1757         if (m->n_containers <= 0)
1758                 return -EINVAL;
1759
1760         c = message_get_container(m);
1761         if (c->enclosing == SD_BUS_TYPE_ARRAY) {
1762                 uint32_t l;
1763
1764                 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
1765                 if (c->begin + l != m->rindex)
1766                         return -EBUSY;
1767
1768         } else {
1769                 if (c->signature && c->signature[c->index] != 0)
1770                         return -EINVAL;
1771         }
1772
1773         free(c->signature);
1774         m->n_containers--;
1775
1776         return 1;
1777 }
1778
1779 int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
1780         struct bus_container *c;
1781         int r;
1782
1783         if (!m)
1784                 return -EINVAL;
1785         if (!m->sealed)
1786                 return -EPERM;
1787
1788         c = message_get_container(m);
1789
1790         if (!c->signature || c->signature[c->index] == 0)
1791                 goto eof;
1792
1793         if (message_end_of_array(m, m->rindex))
1794                 goto eof;
1795
1796         if (bus_type_is_basic(c->signature[c->index])) {
1797                 if (contents)
1798                         *contents = NULL;
1799                 if (type)
1800                         *type = c->signature[c->index];
1801                 return 1;
1802         }
1803
1804         if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
1805
1806                 if (contents) {
1807                         size_t l;
1808                         char *sig;
1809
1810                         r = signature_element_length(c->signature+c->index+1, &l);
1811                         if (r < 0)
1812                                 return r;
1813
1814                         assert(l >= 1);
1815
1816                         sig = strndup(c->signature + c->index + 1, l);
1817                         if (!sig)
1818                                 return -ENOMEM;
1819
1820                         free(m->peeked_signature);
1821                         m->peeked_signature = sig;
1822
1823                         *contents = sig;
1824                 }
1825
1826                 if (type)
1827                         *type = SD_BUS_TYPE_ARRAY;
1828
1829                 return 1;
1830         }
1831
1832         if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
1833             c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
1834
1835                 if (contents) {
1836                         size_t l;
1837                         char *sig;
1838
1839                         r = signature_element_length(c->signature+c->index, &l);
1840                         if (r < 0)
1841                                 return r;
1842
1843                         assert(l >= 2);
1844                         sig = strndup(c->signature + c->index + 1, l - 2);
1845                         if (!sig)
1846                                 return -ENOMEM;
1847
1848                         free(m->peeked_signature);
1849                         m->peeked_signature = sig;
1850
1851                         *contents = sig;
1852                 }
1853
1854                 if (type)
1855                         *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
1856
1857                 return 1;
1858         }
1859
1860         if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
1861                 if (contents) {
1862                         size_t rindex, l;
1863                         void *q;
1864
1865                         rindex = m->rindex;
1866                         r = message_peek_body(m, &rindex, 1, 1, &q);
1867                         if (r < 0)
1868                                 return r;
1869                         if (r == 0)
1870                                 goto eof;
1871
1872                         l = *(uint8_t*) q;
1873                         r = message_peek_body(m, &rindex, 1, l+1, &q);
1874                         if (r < 0)
1875                                 return r;
1876                         if (r == 0)
1877                                 return -EBADMSG;
1878
1879                         if (!validate_signature(q, l))
1880                                 return -EBADMSG;
1881
1882                         *contents = q;
1883                 }
1884
1885                 if (type)
1886                         *type = SD_BUS_TYPE_VARIANT;
1887
1888                 return 1;
1889         }
1890
1891         return -EINVAL;
1892
1893 eof:
1894         if (type)
1895                 *type = c->enclosing;
1896         if (contents)
1897                 *contents = NULL;
1898         return 0;
1899 }
1900
1901 int sd_bus_message_rewind(sd_bus_message *m, int complete) {
1902         struct bus_container *c;
1903
1904         if (!m)
1905                 return -EINVAL;
1906         if (!m->sealed)
1907                 return -EPERM;
1908
1909         if (complete) {
1910                 reset_containers(m);
1911                 m->rindex = 0;
1912                 m->root_container.index = 0;
1913
1914                 c = message_get_container(m);
1915         } else {
1916                 c = message_get_container(m);
1917
1918                 c->index = 0;
1919                 m->rindex = c->begin;
1920         }
1921
1922         return !isempty(c->signature);
1923 }
1924
1925 static int message_read_ap(sd_bus_message *m, const char *types, va_list ap) {
1926         const char *t;
1927         int r;
1928
1929         assert(m);
1930         assert(types);
1931
1932         for (t = types; *t; t++) {
1933                 switch (*t) {
1934
1935                 case SD_BUS_TYPE_BYTE:
1936                 case SD_BUS_TYPE_BOOLEAN:
1937                 case SD_BUS_TYPE_INT16:
1938                 case SD_BUS_TYPE_UINT16:
1939                 case SD_BUS_TYPE_INT32:
1940                 case SD_BUS_TYPE_UINT32:
1941                 case SD_BUS_TYPE_INT64:
1942                 case SD_BUS_TYPE_UINT64:
1943                 case SD_BUS_TYPE_DOUBLE:
1944                 case SD_BUS_TYPE_STRING:
1945                 case SD_BUS_TYPE_OBJECT_PATH:
1946                 case SD_BUS_TYPE_SIGNATURE: {
1947                         void *p;
1948
1949                         p = va_arg(ap, void*);
1950                         r = sd_bus_message_read_basic(m, *t, p);
1951                         break;
1952                 }
1953
1954                 case SD_BUS_TYPE_ARRAY: {
1955                         size_t k;
1956
1957                         r = signature_element_length(t + 1, &k);
1958                         if (r < 0)
1959                                 return r;
1960
1961                         {
1962                                 unsigned i, n;
1963                                 char s[k + 1];
1964
1965                                 memcpy(s, t + 1, k);
1966                                 s[k] = 0;
1967                                 t += k;
1968
1969                                 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
1970                                 if (r < 0)
1971                                         return r;
1972                                 if (r == 0)
1973                                         return -ENXIO;
1974
1975                                 n = va_arg(ap, unsigned);
1976                                 for (i = 0; i < n; i++) {
1977                                         r = message_read_ap(m, s, ap);
1978                                         if (r < 0)
1979                                                 return r;
1980                                 }
1981
1982                                 r = sd_bus_message_exit_container(m);
1983                         }
1984
1985                         break;
1986                 }
1987
1988                 case SD_BUS_TYPE_VARIANT: {
1989                         const char *s;
1990
1991                         s = va_arg(ap, const char *);
1992                         if (!s)
1993                                 return -EINVAL;
1994
1995                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
1996                         if (r < 0)
1997                                 return r;
1998                         if (r == 0)
1999                                 return -ENXIO;
2000
2001                         r = message_read_ap(m, s, ap);
2002                         if (r < 0)
2003                                 return r;
2004                         if (r == 0)
2005                                 return -ENXIO;
2006
2007                         r = sd_bus_message_exit_container(m);
2008                         break;
2009                 }
2010
2011                 case SD_BUS_TYPE_STRUCT_BEGIN:
2012                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2013                         size_t k;
2014
2015                         r = signature_element_length(t, &k);
2016                         if (r < 0)
2017                                 return r;
2018
2019                         {
2020                                 char s[k - 1];
2021                                 memcpy(s, t + 1, k - 2);
2022                                 s[k - 2] = 0;
2023
2024                                 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2025                                 if (r < 0)
2026                                         return r;
2027                                 if (r == 0)
2028                                         return -ENXIO;
2029
2030                                 t += k - 1;
2031
2032                                 r = message_read_ap(m, s, ap);
2033                                 if (r < 0)
2034                                         return r;
2035                                 if (r == 0)
2036                                         return -ENXIO;
2037
2038                                 r = sd_bus_message_exit_container(m);
2039                         }
2040
2041                         break;
2042                 }
2043
2044                 default:
2045                         r = -EINVAL;
2046                 }
2047
2048                 if (r < 0)
2049                         return r;
2050                 if (r == 0)
2051                         return -ENXIO;
2052         }
2053
2054         return 1;
2055 }
2056
2057 int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
2058         va_list ap;
2059         int r;
2060
2061         if (!m)
2062                 return -EINVAL;
2063         if (!m->sealed)
2064                 return -EPERM;
2065         if (!types)
2066                 return -EINVAL;
2067
2068         va_start(ap, types);
2069         r = message_read_ap(m, types, ap);
2070         va_end(ap);
2071
2072         return r;
2073 }
2074
2075 static int message_peek_fields(
2076                 sd_bus_message *m,
2077                 size_t *rindex,
2078                 size_t align,
2079                 size_t nbytes,
2080                 void **ret) {
2081
2082         assert(m);
2083         assert(rindex);
2084         assert(align > 0);
2085
2086         return buffer_peek(m->fields, BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
2087 }
2088
2089 static int message_peek_field_string(
2090                 sd_bus_message *m,
2091                 size_t *ri,
2092                 const char **ret) {
2093
2094         size_t l;
2095         int r;
2096         void *q;
2097
2098         assert(m);
2099         assert(ri);
2100
2101         r = message_peek_fields(m, ri, 4, 4, &q);
2102         if (r < 0)
2103                 return r;
2104
2105         l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2106         r = message_peek_fields(m, ri, 1, l+1, &q);
2107         if (r < 0)
2108                 return r;
2109
2110         if (!validate_string(q, l))
2111                 return -EBADMSG;
2112
2113         if (ret)
2114                 *ret = q;
2115
2116         return 0;
2117 }
2118
2119 static int message_peek_field_signature(
2120                 sd_bus_message *m,
2121                 size_t *ri,
2122                 const char **ret) {
2123
2124         size_t l;
2125         int r;
2126         void *q;
2127
2128         assert(m);
2129         assert(ri);
2130
2131         r = message_peek_fields(m, ri, 1, 1, &q);
2132         if (r < 0)
2133                 return r;
2134
2135         l = *(uint8_t*) q;
2136         r = message_peek_fields(m, ri, 1, l+1, &q);
2137         if (r < 0)
2138                 return r;
2139
2140         if (!validate_signature(q, l))
2141                 return -EBADMSG;
2142
2143         if (ret)
2144                 *ret = q;
2145
2146         return 0;
2147 }
2148
2149 static int message_peek_field_uint32(
2150                 sd_bus_message *m,
2151                 size_t *ri,
2152                 uint32_t *ret) {
2153
2154         int r;
2155         void *q;
2156
2157         assert(m);
2158         assert(ri);
2159
2160         r = message_peek_fields(m, ri, 4, 4, &q);
2161         if (r < 0)
2162                 return r;
2163
2164         if (ret)
2165                 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2166
2167         return 0;
2168 }
2169
2170 static int message_skip_fields(
2171                 sd_bus_message *m,
2172                 size_t *ri,
2173                 uint32_t array_size,
2174                 const char **signature) {
2175
2176         size_t original_index;
2177         int r;
2178
2179         assert(m);
2180         assert(ri);
2181         assert(signature);
2182
2183         original_index = *ri;
2184
2185         for (;;) {
2186                 char t;
2187                 void *q;
2188                 size_t l;
2189
2190                 if (array_size != (uint32_t) -1 &&
2191                     array_size <= *ri - original_index)
2192                         return 0;
2193
2194                 t = **signature;
2195                 if (!t)
2196                         return 0;
2197
2198                 if (t == SD_BUS_TYPE_STRING ||
2199                     t == SD_BUS_TYPE_OBJECT_PATH) {
2200
2201                         r = message_peek_field_string(m, ri, NULL);
2202                         if (r < 0)
2203                                 return r;
2204
2205                         (*signature)++;
2206
2207                 } else if (t == SD_BUS_TYPE_SIGNATURE) {
2208
2209                         r = message_peek_field_signature(m, ri, NULL);
2210                         if (r < 0)
2211                                 return r;
2212
2213                         (*signature)++;
2214
2215                 } else if (bus_type_is_basic(t)) {
2216                         size_t align, k;
2217
2218                         align = bus_type_get_alignment(t);
2219                         k = bus_type_get_size(t);
2220
2221                         r = message_peek_fields(m, ri, align, k, NULL);
2222                         if (r < 0)
2223                                 return r;
2224
2225                         (*signature)++;
2226
2227                 } else if (t == SD_BUS_TYPE_ARRAY) {
2228
2229                         r = signature_element_length(*signature+1, &l);
2230                         if (r < 0)
2231                                 return r;
2232
2233                         assert(l >= 1);
2234                         {
2235                                 char sig[l-1], *s;
2236                                 size_t nas;
2237                                 int alignment;
2238
2239                                 strncpy(sig, *signature + 1, l-1);
2240                                 s = sig;
2241
2242                                 alignment = bus_type_get_alignment(sig[0]);
2243                                 if (alignment < 0)
2244                                         return alignment;
2245
2246                                 r = message_peek_fields(m, ri, 4, 4, &q);
2247                                 if (r < 0)
2248                                         return r;
2249
2250                                 nas = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2251                                 if (nas > 67108864)
2252                                         return -EBADMSG;
2253
2254                                 r = message_peek_fields(m, ri, alignment, 0, NULL);
2255                                 if (r < 0)
2256                                         return r;
2257
2258                                 r = message_skip_fields(m, ri, nas, (const char**) &s);
2259                                 if (r < 0)
2260                                         return r;
2261                         }
2262
2263                         (*signature) += 1 + l;
2264
2265                 } else if (t == SD_BUS_TYPE_VARIANT) {
2266                         const char *s;
2267
2268                         r = message_peek_field_signature(m, ri, &s);
2269                         if (r < 0)
2270                                 return r;
2271
2272                         r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
2273                         if (r < 0)
2274                                 return r;
2275
2276                         (*signature)++;
2277
2278                 } else if (t == SD_BUS_TYPE_STRUCT ||
2279                            t == SD_BUS_TYPE_DICT_ENTRY) {
2280
2281                         r = signature_element_length(*signature, &l);
2282                         if (r < 0)
2283                                 return r;
2284
2285                         assert(l >= 2);
2286                         {
2287                                 char sig[l-1], *s;
2288                                 strncpy(sig, *signature + 1, l-1);
2289                                 s = sig;
2290
2291                                 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
2292                                 if (r < 0)
2293                                         return r;
2294                         }
2295
2296                         *signature += l;
2297                 } else
2298                         return -EINVAL;
2299         }
2300 }
2301
2302 static int message_parse_fields(sd_bus_message *m) {
2303         size_t ri;
2304         int r;
2305
2306         assert(m);
2307
2308         for (ri = 0; ri < BUS_MESSAGE_FIELDS_SIZE(m); ) {
2309                 const char *signature;
2310                 uint8_t *header;
2311
2312                 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
2313                 if (r < 0)
2314                         return r;
2315
2316                 r = message_peek_field_signature(m, &ri, &signature);
2317                 if (r < 0)
2318                         return r;
2319
2320                 switch (*header) {
2321                 case _SD_BUS_MESSAGE_HEADER_INVALID:
2322                         return -EBADMSG;
2323
2324                 case SD_BUS_MESSAGE_HEADER_PATH:
2325                         if (!streq(signature, "o"))
2326                                 return -EBADMSG;
2327
2328                         r = message_peek_field_string(m, &ri, &m->path);
2329                         break;
2330
2331                 case SD_BUS_MESSAGE_HEADER_INTERFACE:
2332                         if (!streq(signature, "s"))
2333                                 return -EBADMSG;
2334
2335                         r = message_peek_field_string(m, &ri, &m->interface);
2336                         break;
2337
2338                 case SD_BUS_MESSAGE_HEADER_MEMBER:
2339                         if (!streq(signature, "s"))
2340                                 return -EBADMSG;
2341
2342                         r = message_peek_field_string(m, &ri, &m->member);
2343                         break;
2344
2345                 case SD_BUS_MESSAGE_HEADER_ERROR_NAME:
2346                         if (!streq(signature, "s"))
2347                                 return -EBADMSG;
2348
2349                         r = message_peek_field_string(m, &ri, &m->error.name);
2350                         break;
2351
2352                 case SD_BUS_MESSAGE_HEADER_DESTINATION:
2353                         if (!streq(signature, "s"))
2354                                 return -EBADMSG;
2355
2356                         r = message_peek_field_string(m, &ri, &m->destination);
2357                         break;
2358
2359                 case SD_BUS_MESSAGE_HEADER_SENDER:
2360                         if (!streq(signature, "s"))
2361                                 return -EBADMSG;
2362
2363                         r = message_peek_field_string(m, &ri, &m->sender);
2364                         break;
2365
2366
2367                 case SD_BUS_MESSAGE_HEADER_SIGNATURE: {
2368                         const char *s;
2369                         char *c;
2370
2371                         if (!streq(signature, "g"))
2372                                 return -EBADMSG;
2373
2374                         r = message_peek_field_signature(m, &ri, &s);
2375                         if (r < 0)
2376                                 return r;
2377
2378                         c = strdup(s);
2379                         if (!c)
2380                                 return -ENOMEM;
2381
2382                         free(m->root_container.signature);
2383                         m->root_container.signature = c;
2384
2385                         r = 0;
2386                         break;
2387                 }
2388
2389                 case SD_BUS_MESSAGE_HEADER_REPLY_SERIAL:
2390                         if (!streq(signature, "u"))
2391                                 return -EBADMSG;
2392
2393                         r = message_peek_field_uint32(m, &ri, &m->reply_serial);
2394                         break;
2395
2396                 default:
2397                         r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
2398                 }
2399
2400                 if (r < 0)
2401                         return r;
2402         }
2403
2404         if (isempty(m->root_container.signature) != (BUS_MESSAGE_BODY_SIZE(m) == 0))
2405                 return -EBADMSG;
2406
2407         switch (m->header->type) {
2408
2409         case SD_BUS_MESSAGE_TYPE_SIGNAL:
2410                 if (!m->path || !m->interface || !m->member)
2411                         return -EBADMSG;
2412                 break;
2413
2414         case SD_BUS_MESSAGE_TYPE_METHOD_CALL:
2415
2416                 if (!m->path || !m->member)
2417                         return -EBADMSG;
2418
2419                 break;
2420
2421         case SD_BUS_MESSAGE_TYPE_METHOD_RETURN:
2422
2423                 if (m->reply_serial == 0)
2424                         return -EBADMSG;
2425                 break;
2426
2427         case SD_BUS_MESSAGE_TYPE_METHOD_ERROR:
2428
2429                 if (m->reply_serial == 0 || !m->error.name)
2430                         return -EBADMSG;
2431                 break;
2432         }
2433
2434         /* Try to read the error message, but if we can't it's a non-issue */
2435         if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
2436                 sd_bus_message_read(m, "s", &m->error.message);
2437
2438         return 0;
2439 }
2440
2441 static void setup_iovec(sd_bus_message *m) {
2442         assert(m);
2443         assert(m->sealed);
2444
2445         m->n_iovec = 0;
2446         m->size = 0;
2447
2448         m->iovec[m->n_iovec].iov_base = m->header;
2449         m->iovec[m->n_iovec].iov_len = sizeof(*m->header);
2450         m->size += m->iovec[m->n_iovec].iov_len;
2451         m->n_iovec++;
2452
2453         if (m->fields) {
2454                 m->iovec[m->n_iovec].iov_base = m->fields;
2455                 m->iovec[m->n_iovec].iov_len = m->header->fields_size;
2456                 m->size += m->iovec[m->n_iovec].iov_len;
2457                 m->n_iovec++;
2458
2459                 if (m->header->fields_size % 8 != 0) {
2460                         static const uint8_t padding[7] = { 0, 0, 0, 0, 0, 0, 0 };
2461
2462                         m->iovec[m->n_iovec].iov_base = (void*) padding;
2463                         m->iovec[m->n_iovec].iov_len = 8 - m->header->fields_size % 8;
2464                         m->size += m->iovec[m->n_iovec].iov_len;
2465                         m->n_iovec++;
2466                 }
2467         }
2468
2469         if (m->body) {
2470                 m->iovec[m->n_iovec].iov_base = m->body;
2471                 m->iovec[m->n_iovec].iov_len = m->header->body_size;
2472                 m->size += m->iovec[m->n_iovec].iov_len;
2473                 m->n_iovec++;
2474         }
2475 }
2476
2477 int bus_message_seal(sd_bus_message *m, uint64_t serial) {
2478         int r;
2479
2480         assert(m);
2481
2482         if (m->sealed)
2483                 return -EPERM;
2484
2485         if (m->n_containers > 0)
2486                 return -EBADMSG;
2487
2488         /* If there's a non-trivial signature set, then add it in here */
2489         if (!isempty(m->root_container.signature)) {
2490                 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2491                 if (r < 0)
2492                         return r;
2493         }
2494
2495         if (m->n_fds > 0) {
2496                 r = message_append_field_uint32(m, SD_BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2497                 if (r < 0)
2498                         return r;
2499         }
2500
2501         m->header->serial = serial;
2502         m->sealed = true;
2503
2504         setup_iovec(m);
2505
2506         return 0;
2507 }
2508
2509 int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
2510         if (!m)
2511                 return -EINVAL;
2512         if (!destination)
2513                 return -EINVAL;
2514         if (m->sealed)
2515                 return -EPERM;
2516         if (m->destination)
2517                 return -EEXIST;
2518
2519         return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
2520 }
2521
2522 int bus_message_dump(sd_bus_message *m) {
2523         unsigned level = 1;
2524         int r;
2525
2526         assert(m);
2527
2528         printf("Message %p\n"
2529                "\tn_ref=%u\n"
2530                "\tendian=%c\n"
2531                "\ttype=%i\n"
2532                "\tflags=%u\n"
2533                "\tversion=%u\n"
2534                "\tserial=%u\n"
2535                "\tfields_size=%u\n"
2536                "\tbody_size=%u\n"
2537                "\tpath=%s\n"
2538                "\tinterface=%s\n"
2539                "\tmember=%s\n"
2540                "\tdestination=%s\n"
2541                "\tsender=%s\n"
2542                "\tsignature=%s\n"
2543                "\treply_serial=%u\n"
2544                "\terror.name=%s\n"
2545                "\terror.message=%s\n"
2546                "\tsealed=%s\n",
2547                m,
2548                m->n_ref,
2549                m->header->endian,
2550                m->header->type,
2551                m->header->flags,
2552                m->header->version,
2553                BUS_MESSAGE_SERIAL(m),
2554                BUS_MESSAGE_FIELDS_SIZE(m),
2555                BUS_MESSAGE_BODY_SIZE(m),
2556                strna(m->path),
2557                strna(m->interface),
2558                strna(m->member),
2559                strna(m->destination),
2560                strna(m->sender),
2561                strna(m->root_container.signature),
2562                m->reply_serial,
2563                strna(m->error.name),
2564                strna(m->error.message),
2565                yes_no(m->sealed));
2566
2567         r = sd_bus_message_rewind(m, true);
2568         if (r < 0) {
2569                 log_error("Failed to rewind: %s", strerror(-r));
2570                 return r;
2571         }
2572
2573         printf("BEGIN_MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
2574
2575         for(;;) {
2576                 _cleanup_free_ char *prefix = NULL;
2577                 const char *contents = NULL;
2578                 char type;
2579                 union {
2580                         uint8_t u8;
2581                         uint16_t u16;
2582                         int16_t s16;
2583                         uint32_t u32;
2584                         int32_t s32;
2585                         uint64_t u64;
2586                         int64_t s64;
2587                         double d64;
2588                         const char *string;
2589                         int i;
2590                 } basic;
2591
2592                 r = sd_bus_message_peek_type(m, &type, &contents);
2593                 if (r < 0) {
2594                         log_error("Failed to peek type: %s", strerror(-r));
2595                         return r;
2596                 }
2597                 if (r == 0) {
2598                         if (level <= 1)
2599                                 break;
2600
2601                         r = sd_bus_message_exit_container(m);
2602                         if (r < 0) {
2603                                 log_error("Failed to exit container: %s", strerror(-r));
2604                                 return r;
2605                         }
2606
2607                         level--;
2608
2609                         prefix = strrep("\t", level);
2610                         if (!prefix)
2611                                 return log_oom();
2612
2613                         if (type == SD_BUS_TYPE_ARRAY)
2614                                 printf("%s} END_ARRAY \n", prefix);
2615                         else if (type == SD_BUS_TYPE_VARIANT)
2616                                 printf("%s} END_VARIANT\n", prefix);
2617                         else if (type == SD_BUS_TYPE_STRUCT)
2618                                 printf("%s} END_STRUCT\n", prefix);
2619                         else if (type == SD_BUS_TYPE_DICT_ENTRY)
2620                                 printf("%s} END_DICT_ENTRY\n", prefix);
2621
2622                         continue;
2623                 }
2624
2625                 prefix = strrep("\t", level);
2626                 if (!prefix)
2627                         return log_oom();
2628
2629                 if (bus_type_is_container(type) > 0) {
2630                         r = sd_bus_message_enter_container(m, type, contents);
2631                         if (r < 0) {
2632                                 log_error("Failed to enter container: %s", strerror(-r));
2633                                 return r;
2634                         }
2635
2636                         if (type == SD_BUS_TYPE_ARRAY)
2637                                 printf("%sBEGIN_ARRAY \"%s\" {\n", prefix, contents);
2638                         else if (type == SD_BUS_TYPE_VARIANT)
2639                                 printf("%sBEGIN_VARIANT \"%s\" {\n", prefix, contents);
2640                         else if (type == SD_BUS_TYPE_STRUCT)
2641                                 printf("%sBEGIN_STRUCT \"%s\" {\n", prefix, contents);
2642                         else if (type == SD_BUS_TYPE_DICT_ENTRY)
2643                                 printf("%sBEGIN_DICT_ENTRY \"%s\" {\n", prefix, contents);
2644
2645                         level ++;
2646
2647                         continue;
2648                 }
2649
2650                 r = sd_bus_message_read_basic(m, type, &basic);
2651                 if (r < 0) {
2652                         log_error("Failed to get basic: %s", strerror(-r));
2653                         return r;
2654                 }
2655
2656                 switch (type) {
2657
2658                 case SD_BUS_TYPE_BYTE:
2659                         printf("%sBYTE: %u\n", prefix, basic.u8);
2660                         break;
2661
2662                 case SD_BUS_TYPE_BOOLEAN:
2663                         printf("%sBOOLEAN: %s\n", prefix, yes_no(basic.i));
2664                         break;
2665
2666                 case SD_BUS_TYPE_INT16:
2667                         printf("%sINT16: %i\n", prefix, basic.s16);
2668                         break;
2669
2670                 case SD_BUS_TYPE_UINT16:
2671                         printf("%sUINT16: %u\n", prefix, basic.u16);
2672                         break;
2673
2674                 case SD_BUS_TYPE_INT32:
2675                         printf("%sINT32: %i\n", prefix, basic.s32);
2676                         break;
2677
2678                 case SD_BUS_TYPE_UINT32:
2679                         printf("%sUINT32: %u\n", prefix, basic.u32);
2680                         break;
2681
2682                 case SD_BUS_TYPE_INT64:
2683                         printf("%sINT64: %lli\n", prefix, (long long) basic.s64);
2684                         break;
2685
2686                 case SD_BUS_TYPE_UINT64:
2687                         printf("%sUINT64: %llu\n", prefix, (unsigned long long) basic.u64);
2688                         break;
2689
2690                 case SD_BUS_TYPE_DOUBLE:
2691                         printf("%sDOUBLE: %g\n", prefix, basic.d64);
2692                         break;
2693
2694                 case SD_BUS_TYPE_STRING:
2695                         printf("%sSTRING: \"%s\"\n", prefix, basic.string);
2696                         break;
2697
2698                 case SD_BUS_TYPE_OBJECT_PATH:
2699                         printf("%sOBJECT_PATH: \"%s\"\n", prefix, basic.string);
2700                         break;
2701
2702                 case SD_BUS_TYPE_SIGNATURE:
2703                         printf("%sSIGNATURE: \"%s\"\n", prefix, basic.string);
2704                         break;
2705
2706                 case SD_BUS_TYPE_UNIX_FD:
2707                         printf("%sUNIX_FD: %i\n", prefix, basic.i);
2708                         break;
2709
2710                 default:
2711                         assert_not_reached("Unknown basic type.");
2712                 }
2713         }
2714
2715         printf("} END_MESSAGE\n");
2716         return 0;
2717 }
2718
2719 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
2720         size_t total;
2721         unsigned i;
2722         void *p, *e;
2723
2724         assert(m);
2725         assert(buffer);
2726         assert(sz);
2727
2728         for (i = 0, total = 0; i < m->n_iovec; i++)
2729                 total += m->iovec[i].iov_len;
2730
2731         p = malloc(total);
2732         if (!p)
2733                 return -ENOMEM;
2734
2735         for (i = 0, e = p; i < m->n_iovec; i++)
2736                 e = mempcpy(e, m->iovec[i].iov_base, m->iovec[i].iov_len);
2737
2738         *buffer = p;
2739         *sz = total;
2740
2741         return 0;
2742 }
2743
2744 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
2745         int r;
2746
2747         assert(m);
2748         assert(l);
2749
2750         r = sd_bus_message_enter_container(m, 'a', "s");
2751         if (r < 0)
2752                 return r;
2753
2754         for (;;) {
2755                 const char *s;
2756
2757                 r = sd_bus_message_read_basic(m, 's', &s);
2758                 if (r < 0)
2759                         return r;
2760                 if (r == 0)
2761                         break;
2762
2763                 r = strv_extend(l, s);
2764                 if (r < 0)
2765                         return r;
2766         }
2767
2768         r = sd_bus_message_exit_container(m);
2769         if (r < 0)
2770                 return r;
2771
2772         return 0;
2773 }