]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-message.c
net-util: don't use libudev
[thirdparty/systemd.git] / src / libsystemd-bus / bus-message.c
CommitLineData
de1c301e
LP
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>
2c93b4ef 23#include <fcntl.h>
bc7fd8cd 24#include <sys/mman.h>
de1c301e
LP
25
26#include "util.h"
9a17484d 27#include "utf8.h"
89ffcd2a 28#include "strv.h"
6629161f 29#include "time-util.h"
d8d3d8a7 30#include "cgroup-util.h"
de1c301e 31
de1c301e 32#include "sd-bus.h"
9a17484d 33#include "bus-message.h"
de1c301e
LP
34#include "bus-internal.h"
35#include "bus-type.h"
36#include "bus-signature.h"
37
80a46c73 38static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
de1c301e 39
bc7fd8cd
LP
40static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
41
42 if (p == NULL)
43 return NULL;
44
45 if (old_base == new_base)
46 return (void*) p;
47
48 if ((uint8_t*) p < (uint8_t*) old_base)
49 return (void*) p;
50
51 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
52 return (void*) p;
53
54 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
55}
56
57static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
58 assert(m);
59 assert(part);
60
61 if (part->memfd >= 0) {
66b26c5c
LP
62 /* If we can reuse the memfd, try that. For that it
63 * can't be sealed yet. */
bc7fd8cd
LP
64
65 if (!part->sealed)
66 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped);
67 else {
89b4fc46
LP
68 if (part->mapped > 0)
69 assert_se(munmap(part->data, part->mapped) == 0);
bc7fd8cd
LP
70
71 close_nointr_nofail(part->memfd);
72 }
73
453a0c29
LP
74 } else if (part->munmap_this)
75 munmap(part->data, part->mapped);
76 else if (part->free_this)
bc7fd8cd
LP
77 free(part->data);
78
79 if (part != &m->body)
80 free(part);
81}
82
83static void message_reset_parts(sd_bus_message *m) {
84 struct bus_body_part *part;
85
86 assert(m);
87
88 part = &m->body;
89 while (m->n_body_parts > 0) {
90 struct bus_body_part *next = part->next;
91 message_free_part(m, part);
92 part = next;
93 m->n_body_parts--;
94 }
95
96 m->body_end = NULL;
97
98 m->cached_rindex_part = NULL;
99 m->cached_rindex_part_begin = 0;
100}
101
102static void message_reset_containers(sd_bus_message *m) {
9a17484d
LP
103 unsigned i;
104
105 assert(m);
106
107 for (i = 0; i < m->n_containers; i++)
108 free(m->containers[i].signature);
109
110 free(m->containers);
111 m->containers = NULL;
112
113 m->n_containers = 0;
114 m->root_container.index = 0;
115}
116
de1c301e 117static void message_free(sd_bus_message *m) {
de1c301e
LP
118 assert(m);
119
120 if (m->free_header)
121 free(m->header);
122
bc7fd8cd 123 message_reset_parts(m);
de1c301e 124
6629161f
LP
125 if (m->free_kdbus)
126 free(m->kdbus);
127
62b3e928
KS
128 if (m->release_kdbus) {
129 uint64_t off;
130
131 off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
132 ioctl(m->bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
133 }
fd8d62d9 134
f54514f3
LP
135 if (m->bus)
136 sd_bus_unref(m->bus);
137
2c93b4ef
LP
138 if (m->free_fds) {
139 close_many(m->fds, m->n_fds);
140 free(m->fds);
141 }
de1c301e 142
bc7fd8cd
LP
143 if (m->iovec != m->iovec_fixed)
144 free(m->iovec);
145
77930f11
LP
146 free(m->cmdline_array);
147
bc7fd8cd 148 message_reset_containers(m);
9a17484d 149 free(m->root_container.signature);
de1c301e 150
9a17484d 151 free(m->peeked_signature);
d8d3d8a7
LP
152
153 free(m->unit);
154 free(m->user_unit);
155 free(m->session);
de1c301e
LP
156 free(m);
157}
158
c91cb83c
LP
159static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz) {
160 void *op, *np;
161 size_t old_size, new_size, start;
de1c301e 162
c91cb83c 163 assert(m);
de1c301e 164
c91cb83c 165 if (m->poisoned)
de1c301e
LP
166 return NULL;
167
c91cb83c
LP
168 old_size = sizeof(struct bus_header) + m->header->fields_size;
169 start = ALIGN_TO(old_size, align);
170 new_size = start + sz;
de1c301e 171
c91cb83c
LP
172 if (old_size == new_size)
173 return (uint8_t*) m->header + old_size;
de1c301e 174
c91cb83c
LP
175 if (new_size > (size_t) ((uint32_t) -1))
176 goto poison;
de1c301e 177
c91cb83c
LP
178 if (m->free_header) {
179 np = realloc(m->header, ALIGN8(new_size));
180 if (!np)
181 goto poison;
182 } else {
183 /* Initially, the header is allocated as part of of
184 * the sd_bus_message itself, let's replace it by
185 * dynamic data */
de1c301e 186
c91cb83c
LP
187 np = malloc(ALIGN8(new_size));
188 if (!np)
189 goto poison;
de1c301e 190
c91cb83c
LP
191 memcpy(np, m->header, sizeof(struct bus_header));
192 }
de1c301e 193
c91cb83c
LP
194 /* Zero out padding */
195 if (start > old_size)
196 memset((uint8_t*) np + old_size, 0, start - old_size);
bc7fd8cd 197
c91cb83c
LP
198 op = m->header;
199 m->header = np;
200 m->header->fields_size = new_size - sizeof(struct bus_header);
de1c301e 201
bc7fd8cd 202 /* Adjust quick access pointers */
c91cb83c
LP
203 m->path = adjust_pointer(m->path, op, old_size, m->header);
204 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
205 m->member = adjust_pointer(m->member, op, old_size, m->header);
206 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
207 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
208 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
bc7fd8cd 209
c91cb83c 210 m->free_header = true;
de1c301e 211
c91cb83c
LP
212 return (uint8_t*) np + start;
213
214poison:
215 m->poisoned = true;
216 return NULL;
de1c301e
LP
217}
218
219static int message_append_field_string(
220 sd_bus_message *m,
221 uint8_t h,
222 char type,
223 const char *s,
224 const char **ret) {
225
226 size_t l;
227 uint8_t *p;
228
229 assert(m);
230
231 l = strlen(s);
232 if (l > (size_t) (uint32_t) -1)
233 return -EINVAL;
234
235 /* field id byte + signature length + signature 's' + NUL + string length + string + NUL */
236 p = message_extend_fields(m, 8, 4 + 4 + l + 1);
237 if (!p)
238 return -ENOMEM;
239
240 p[0] = h;
241 p[1] = 1;
242 p[2] = type;
243 p[3] = 0;
244
245 ((uint32_t*) p)[1] = l;
246 memcpy(p + 8, s, l + 1);
247
248 if (ret)
bc7fd8cd 249 *ret = (char*) p + 8;
de1c301e
LP
250
251 return 0;
252}
253
254static int message_append_field_signature(
255 sd_bus_message *m,
256 uint8_t h,
257 const char *s,
258 const char **ret) {
259
260 size_t l;
261 uint8_t *p;
262
263 assert(m);
264
265 l = strlen(s);
266 if (l > 255)
267 return -EINVAL;
268
269 /* field id byte + signature length + signature 'g' + NUL + string length + string + NUL */
270 p = message_extend_fields(m, 8, 4 + 1 + l + 1);
271 if (!p)
272 return -ENOMEM;
273
274 p[0] = h;
275 p[1] = 1;
276 p[2] = SD_BUS_TYPE_SIGNATURE;
277 p[3] = 0;
278 p[4] = l;
279 memcpy(p + 5, s, l + 1);
280
281 if (ret)
282 *ret = (const char*) p + 5;
283
284 return 0;
285}
286
287static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
288 uint8_t *p;
289
290 assert(m);
291
292 /* field id byte + signature length + signature 'u' + NUL + value */
293 p = message_extend_fields(m, 8, 4 + 4);
294 if (!p)
295 return -ENOMEM;
296
297 p[0] = h;
298 p[1] = 1;
299 p[2] = SD_BUS_TYPE_UINT32;
300 p[3] = 0;
301
302 ((uint32_t*) p)[1] = x;
303
304 return 0;
305}
306
6629161f 307int bus_message_from_header(
2571ead1
LP
308 void *buffer,
309 size_t length,
2c93b4ef
LP
310 int *fds,
311 unsigned n_fds,
312 const struct ucred *ucred,
2571ead1 313 const char *label,
6629161f 314 size_t extra,
2571ead1
LP
315 sd_bus_message **ret) {
316
80a46c73
LP
317 sd_bus_message *m;
318 struct bus_header *h;
6629161f 319 size_t a, label_sz;
80a46c73
LP
320
321 assert(buffer || length <= 0);
2c93b4ef 322 assert(fds || n_fds <= 0);
80a46c73
LP
323 assert(ret);
324
325 if (length < sizeof(struct bus_header))
326 return -EBADMSG;
327
328 h = buffer;
329 if (h->version != 1)
330 return -EBADMSG;
331
332 if (h->serial == 0)
333 return -EBADMSG;
334
335 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
336 return -EBADMSG;
337
6629161f
LP
338 if (h->endian != SD_BUS_LITTLE_ENDIAN &&
339 h->endian != SD_BUS_BIG_ENDIAN)
80a46c73
LP
340 return -EBADMSG;
341
6629161f 342 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
80a46c73 343
2571ead1
LP
344 if (label) {
345 label_sz = strlen(label);
6629161f
LP
346 a += label_sz + 1;
347 }
2571ead1
LP
348
349 m = malloc0(a);
80a46c73
LP
350 if (!m)
351 return -ENOMEM;
352
353 m->n_ref = 1;
2c93b4ef 354 m->sealed = true;
80a46c73 355 m->header = h;
2c93b4ef
LP
356 m->fds = fds;
357 m->n_fds = n_fds;
80a46c73 358
2571ead1
LP
359 if (ucred) {
360 m->uid = ucred->uid;
361 m->pid = ucred->pid;
362 m->gid = ucred->gid;
363 m->uid_valid = m->gid_valid = true;
364 }
365
366 if (label) {
6629161f 367 m->label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
2571ead1
LP
368 memcpy(m->label, label, label_sz + 1);
369 }
370
6629161f
LP
371 *ret = m;
372 return 0;
373}
374
375int bus_message_from_malloc(
376 void *buffer,
377 size_t length,
378 int *fds,
379 unsigned n_fds,
380 const struct ucred *ucred,
381 const char *label,
382 sd_bus_message **ret) {
383
384 sd_bus_message *m;
385 int r;
386
387 r = bus_message_from_header(buffer, length, fds, n_fds, ucred, label, 0, &m);
388 if (r < 0)
389 return r;
390
391 if (length != BUS_MESSAGE_SIZE(m)) {
392 r = -EBADMSG;
393 goto fail;
394 }
395
bc7fd8cd
LP
396 m->n_body_parts = 1;
397 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
398 m->body.size = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
399 m->body.sealed = true;
400 m->body.memfd = -1;
6629161f 401
80a46c73 402 m->n_iovec = 1;
bc7fd8cd 403 m->iovec = m->iovec_fixed;
80a46c73
LP
404 m->iovec[0].iov_base = buffer;
405 m->iovec[0].iov_len = length;
406
6629161f 407 r = bus_message_parse_fields(m);
2c93b4ef
LP
408 if (r < 0)
409 goto fail;
410
411 /* We take possession of the memory and fds now */
412 m->free_header = true;
413 m->free_fds = true;
80a46c73
LP
414
415 *ret = m;
416 return 0;
2c93b4ef
LP
417
418fail:
419 message_free(m);
420 return r;
80a46c73
LP
421}
422
de1c301e
LP
423static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
424 sd_bus_message *m;
425
80a46c73 426 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
de1c301e
LP
427 if (!m)
428 return NULL;
429
430 m->n_ref = 1;
431 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
80a46c73 432 m->header->endian = SD_BUS_NATIVE_ENDIAN;
de1c301e
LP
433 m->header->type = type;
434 m->header->version = bus ? bus->message_version : 1;
021a1e78 435 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
de1c301e 436
9b05bc48
LP
437 if (bus)
438 m->bus = sd_bus_ref(bus);
439
de1c301e
LP
440 return m;
441}
442
443int sd_bus_message_new_signal(
444 sd_bus *bus,
445 const char *path,
446 const char *interface,
447 const char *member,
448 sd_bus_message **m) {
449
450 sd_bus_message *t;
451 int r;
452
453 if (!path)
454 return -EINVAL;
455 if (!interface)
456 return -EINVAL;
457 if (!member)
458 return -EINVAL;
5407f2de
LP
459 if (!m)
460 return -EINVAL;
021a1e78
LP
461 if (bus && bus->state == BUS_UNSET)
462 return -ENOTCONN;
de1c301e 463
40ca29a1 464 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
de1c301e
LP
465 if (!t)
466 return -ENOMEM;
467
89ffcd2a
LP
468 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
469
de1c301e
LP
470 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
471 if (r < 0)
472 goto fail;
473 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
474 if (r < 0)
475 goto fail;
476 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
477 if (r < 0)
478 goto fail;
479
480 *m = t;
481 return 0;
482
483fail:
484 sd_bus_message_unref(t);
485 return r;
486}
487
488int sd_bus_message_new_method_call(
489 sd_bus *bus,
490 const char *destination,
491 const char *path,
492 const char *interface,
493 const char *member,
494 sd_bus_message **m) {
495
496 sd_bus_message *t;
497 int r;
498
29ddb38f 499 if (destination && !service_name_is_valid(destination))
de1c301e 500 return -EINVAL;
29ddb38f
LP
501 if (!object_path_is_valid(path))
502 return -EINVAL;
503 if (interface && !interface_name_is_valid(interface))
504 return -EINVAL;
505 if (!member_name_is_valid(member))
de1c301e 506 return -EINVAL;
5407f2de
LP
507 if (!m)
508 return -EINVAL;
021a1e78
LP
509 if (bus && bus->state == BUS_UNSET)
510 return -ENOTCONN;
de1c301e 511
40ca29a1 512 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
de1c301e
LP
513 if (!t)
514 return -ENOMEM;
515
516 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
517 if (r < 0)
518 goto fail;
519 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
520 if (r < 0)
521 goto fail;
522
523 if (interface) {
524 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
525 if (r < 0)
526 goto fail;
527 }
528
529 if (destination) {
530 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
531 if (r < 0)
532 goto fail;
533 }
534
535 *m = t;
536 return 0;
537
538fail:
539 message_free(t);
540 return r;
541}
542
5407f2de 543static int message_new_reply(
de1c301e
LP
544 sd_bus *bus,
545 sd_bus_message *call,
5407f2de 546 uint8_t type,
de1c301e
LP
547 sd_bus_message **m) {
548
549 sd_bus_message *t;
550 int r;
551
552 if (!call)
553 return -EINVAL;
e3017af9
LP
554 if (!call->sealed)
555 return -EPERM;
40ca29a1 556 if (call->header->type != SD_BUS_MESSAGE_METHOD_CALL)
de1c301e 557 return -EINVAL;
5407f2de
LP
558 if (!m)
559 return -EINVAL;
021a1e78
LP
560 if (bus && bus->state == BUS_UNSET)
561 return -ENOTCONN;
de1c301e 562
5407f2de 563 t = message_new(bus, type);
de1c301e
LP
564 if (!t)
565 return -ENOMEM;
566
89ffcd2a 567 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
de1c301e 568 t->reply_serial = BUS_MESSAGE_SERIAL(call);
5407f2de 569
de1c301e
LP
570 r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
571 if (r < 0)
572 goto fail;
573
574 if (call->sender) {
8f155917 575 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
de1c301e
LP
576 if (r < 0)
577 goto fail;
578 }
579
5407f2de
LP
580 t->dont_send = !!(call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED);
581
de1c301e 582 *m = t;
89ffcd2a 583 return 0;
de1c301e
LP
584
585fail:
586 message_free(t);
587 return r;
588}
589
5407f2de
LP
590int sd_bus_message_new_method_return(
591 sd_bus *bus,
592 sd_bus_message *call,
593 sd_bus_message **m) {
594
40ca29a1 595 return message_new_reply(bus, call, SD_BUS_MESSAGE_METHOD_RETURN, m);
5407f2de
LP
596}
597
de1c301e
LP
598int sd_bus_message_new_method_error(
599 sd_bus *bus,
600 sd_bus_message *call,
601 const sd_bus_error *e,
602 sd_bus_message **m) {
603
604 sd_bus_message *t;
605 int r;
606
fbfa72b0 607 if (!sd_bus_error_is_set(e))
de1c301e 608 return -EINVAL;
5407f2de
LP
609 if (!m)
610 return -EINVAL;
de1c301e 611
40ca29a1 612 r = message_new_reply(bus, call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
de1c301e 613 if (r < 0)
5407f2de 614 return r;
de1c301e
LP
615
616 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
617 if (r < 0)
618 goto fail;
619
620 if (e->message) {
621 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
622 if (r < 0)
623 goto fail;
624 }
625
626 *m = t;
627 return 0;
628
629fail:
630 message_free(t);
631 return r;
632}
633
29ddb38f
LP
634int sd_bus_message_new_method_errorf(
635 sd_bus *bus,
636 sd_bus_message *call,
637 sd_bus_message **m,
638 const char *name,
639 const char *format,
640 ...) {
641
40ca29a1 642 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
29ddb38f
LP
643 va_list ap;
644 int r;
645
40ca29a1
LP
646 assert_return(name, -EINVAL);
647 assert_return(m, -EINVAL);
648
649 va_start(ap, format);
650 r = bus_error_setfv(&error, name, format, ap);
651 va_end(ap);
29ddb38f 652
29ddb38f
LP
653 if (r < 0)
654 return r;
655
40ca29a1
LP
656 return sd_bus_message_new_method_error(bus, call, &error, m);
657}
29ddb38f 658
40ca29a1
LP
659int sd_bus_message_new_method_errno(
660 sd_bus *bus,
661 sd_bus_message *call,
662 int error,
663 const sd_bus_error *p,
664 sd_bus_message **m) {
29ddb38f 665
40ca29a1 666 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
29ddb38f 667
40ca29a1
LP
668 if (sd_bus_error_is_set(p))
669 return sd_bus_message_new_method_error(bus, call, p, m);
29ddb38f 670
40ca29a1 671 sd_bus_error_set_errno(&berror, error);
29ddb38f 672
40ca29a1
LP
673 return sd_bus_message_new_method_error(bus, call, &berror, m);
674}
29ddb38f 675
40ca29a1
LP
676int sd_bus_message_new_method_errnof(
677 sd_bus *bus,
678 sd_bus_message *call,
679 sd_bus_message **m,
680 int error,
681 const char *format,
682 ...) {
683
684 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
685 va_list ap;
686 int r;
687
688 va_start(ap, format);
689 r = bus_error_set_errnofv(&berror, error, format, ap);
690 va_end(ap);
691
692 if (r < 0)
693 return r;
694
695 return sd_bus_message_new_method_error(bus, call, &berror, m);
29ddb38f
LP
696}
697
eb01ba5d
LP
698int bus_message_new_synthetic_error(
699 sd_bus *bus,
700 uint64_t serial,
701 const sd_bus_error *e,
702 sd_bus_message **m) {
703
704 sd_bus_message *t;
705 int r;
706
707 assert(sd_bus_error_is_set(e));
708 assert(m);
709
40ca29a1 710 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
eb01ba5d
LP
711 if (!t)
712 return -ENOMEM;
713
714 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
715 t->reply_serial = serial;
716
717 r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
718 if (r < 0)
719 goto fail;
720
721 if (bus && bus->unique_name) {
722 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
723 if (r < 0)
724 goto fail;
725 }
726
3a7d4f1b
LP
727 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
728 if (r < 0)
729 goto fail;
730
731 if (e->message) {
732 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
733 if (r < 0)
734 goto fail;
735 }
736
eb01ba5d
LP
737 *m = t;
738 return 0;
739
740fail:
741 message_free(t);
742 return r;
743}
744
de1c301e
LP
745sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
746 if (!m)
747 return NULL;
748
749 assert(m->n_ref > 0);
750 m->n_ref++;
751
752 return m;
753}
754
755sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
756 if (!m)
757 return NULL;
758
759 assert(m->n_ref > 0);
760 m->n_ref--;
761
762 if (m->n_ref <= 0)
763 message_free(m);
764
765 return NULL;
766}
767
768int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
769 if (!m)
770 return -EINVAL;
771 if (!type)
772 return -EINVAL;
773
774 *type = m->header->type;
775 return 0;
776}
777
778int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
779 if (!m)
780 return -EINVAL;
781 if (!serial)
782 return -EINVAL;
783 if (m->header->serial == 0)
784 return -ENOENT;
785
786 *serial = BUS_MESSAGE_SERIAL(m);
787 return 0;
788}
789
790int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
791 if (!m)
792 return -EINVAL;
793 if (!serial)
794 return -EINVAL;
795 if (m->reply_serial == 0)
796 return -ENOENT;
797
798 *serial = m->reply_serial;
799 return 0;
800}
801
802int sd_bus_message_get_no_reply(sd_bus_message *m) {
803 if (!m)
804 return -EINVAL;
805
40ca29a1 806 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL ? !!(m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
de1c301e
LP
807}
808
809const char *sd_bus_message_get_path(sd_bus_message *m) {
810 if (!m)
811 return NULL;
812
813 return m->path;
814}
815
816const char *sd_bus_message_get_interface(sd_bus_message *m) {
817 if (!m)
818 return NULL;
819
820 return m->interface;
821}
822
823const char *sd_bus_message_get_member(sd_bus_message *m) {
824 if (!m)
825 return NULL;
826
827 return m->member;
828}
829const char *sd_bus_message_get_destination(sd_bus_message *m) {
830 if (!m)
831 return NULL;
832
833 return m->destination;
834}
835
836const char *sd_bus_message_get_sender(sd_bus_message *m) {
837 if (!m)
838 return NULL;
839
840 return m->sender;
841}
842
843const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
844 if (!m)
845 return NULL;
846
847 if (!sd_bus_error_is_set(&m->error))
848 return NULL;
849
850 return &m->error;
851}
852
853int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) {
854 if (!m)
855 return -EINVAL;
4a875b61
LP
856 if (!uid)
857 return -EINVAL;
de1c301e 858 if (!m->uid_valid)
4a875b61 859 return -ESRCH;
de1c301e
LP
860
861 *uid = m->uid;
862 return 0;
863}
864
865int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) {
866 if (!m)
867 return -EINVAL;
4a875b61
LP
868 if (!gid)
869 return -EINVAL;
de1c301e 870 if (!m->gid_valid)
4a875b61 871 return -ESRCH;
de1c301e
LP
872
873 *gid = m->gid;
874 return 0;
875}
876
877int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) {
878 if (!m)
879 return -EINVAL;
4a875b61
LP
880 if (!pid)
881 return -EINVAL;
de1c301e 882 if (m->pid <= 0)
4a875b61 883 return -ESRCH;
de1c301e
LP
884
885 *pid = m->pid;
886 return 0;
887}
888
889int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) {
890 if (!m)
891 return -EINVAL;
4a875b61
LP
892 if (!tid)
893 return -EINVAL;
de1c301e 894 if (m->tid <= 0)
4a875b61 895 return -ESRCH;
de1c301e
LP
896
897 *tid = m->tid;
898 return 0;
899}
900
8323bc1f
LP
901int sd_bus_message_get_pid_starttime(sd_bus_message *m, uint64_t *usec) {
902 if (!m)
903 return -EINVAL;
4a875b61
LP
904 if (!usec)
905 return -EINVAL;
8323bc1f 906 if (m->pid_starttime <= 0)
4a875b61 907 return -ESRCH;
8323bc1f
LP
908
909 *usec = m->pid_starttime;
910 return 0;
911}
912
4a875b61 913int sd_bus_message_get_selinux_context(sd_bus_message *m, const char **ret) {
2571ead1 914 if (!m)
4a875b61
LP
915 return -EINVAL;
916 if (!m->label)
917 return -ESRCH;
2571ead1 918
4a875b61
LP
919 *ret = m->label;
920 return 0;
2571ead1
LP
921}
922
69aec65c 923int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
acb5a3cb
LP
924 if (!m)
925 return -EINVAL;
4a875b61
LP
926 if (!usec)
927 return -EINVAL;
69aec65c 928 if (m->monotonic <= 0)
4a875b61 929 return -ESRCH;
acb5a3cb 930
69aec65c 931 *usec = m->monotonic;
acb5a3cb
LP
932 return 0;
933}
934
69aec65c
LP
935int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
936 if (!m)
937 return -EINVAL;
4a875b61
LP
938 if (!usec)
939 return -EINVAL;
69aec65c 940 if (m->realtime <= 0)
4a875b61 941 return -ESRCH;
69aec65c
LP
942
943 *usec = m->realtime;
944 return 0;
945}
946
4a875b61 947int sd_bus_message_get_comm(sd_bus_message *m, const char **ret) {
69aec65c 948 if (!m)
4a875b61
LP
949 return -EINVAL;
950 if (!ret)
951 return -EINVAL;
952 if (!m->comm)
953 return -ESRCH;
69aec65c 954
4a875b61
LP
955 *ret = m->comm;
956 return 0;
69aec65c
LP
957}
958
4a875b61 959int sd_bus_message_get_tid_comm(sd_bus_message *m, const char **ret) {
69aec65c 960 if (!m)
4a875b61
LP
961 return -EINVAL;
962 if (!ret)
963 return -EINVAL;
964 if (!m->tid_comm)
965 return -ESRCH;
69aec65c 966
4a875b61
LP
967 *ret = m->tid_comm;
968 return 0;
69aec65c
LP
969}
970
4a875b61 971int sd_bus_message_get_exe(sd_bus_message *m, const char **ret) {
69aec65c 972 if (!m)
4a875b61
LP
973 return -EINVAL;
974 if (!ret)
975 return -EINVAL;
976 if (!m->exe)
977 return -ESRCH;
69aec65c 978
4a875b61
LP
979 *ret = m->exe;
980 return 0;
981}
982
983int sd_bus_message_get_cgroup(sd_bus_message *m, const char **ret) {
984 if (!m)
985 return -EINVAL;
986 if (!ret)
987 return -EINVAL;
988 if (!m->cgroup)
989 return -ESRCH;
990
991 *ret = m->cgroup;
992 return 0;
69aec65c
LP
993}
994
d8d3d8a7
LP
995int sd_bus_message_get_unit(sd_bus_message *m, const char **ret) {
996 int r;
997
998 if (!m)
999 return -EINVAL;
1000 if (!ret)
1001 return -EINVAL;
1002 if (!m->cgroup)
1003 return -ESRCH;
1004
1005 if (!m->unit) {
1006 r = cg_path_get_unit(m->cgroup, &m->unit);
1007 if (r < 0)
1008 return r;
1009 }
1010
1011 *ret = m->unit;
1012 return 0;
1013}
1014
1015int sd_bus_message_get_user_unit(sd_bus_message *m, const char **ret) {
1016 int r;
1017
1018 if (!m)
1019 return -EINVAL;
1020 if (!ret)
1021 return -EINVAL;
1022 if (!m->cgroup)
1023 return -ESRCH;
1024
1025 if (!m->user_unit) {
1026 r = cg_path_get_user_unit(m->cgroup, &m->user_unit);
1027 if (r < 0)
1028 return r;
1029 }
1030
1031 *ret = m->user_unit;
1032 return 0;
1033}
1034
1035int sd_bus_message_get_session(sd_bus_message *m, const char **ret) {
1036 int r;
1037
1038 if (!m)
1039 return -EINVAL;
1040 if (!ret)
1041 return -EINVAL;
1042 if (!m->cgroup)
1043 return -ESRCH;
1044
1045 if (!m->session) {
1046 r = cg_path_get_session(m->cgroup, &m->session);
1047 if (r < 0)
1048 return r;
1049 }
1050
1051 *ret = m->session;
1052 return 0;
1053}
1054
bc7f3beb
LP
1055int sd_bus_message_get_owner_uid(sd_bus_message *m, uid_t *uid) {
1056 if (!m)
1057 return -EINVAL;
1058 if (!uid)
1059 return -EINVAL;
1060 if (!m->cgroup)
1061 return -ESRCH;
1062
1063 return cg_path_get_owner_uid(m->cgroup, uid);
1064}
1065
77930f11
LP
1066int sd_bus_message_get_cmdline(sd_bus_message *m, char ***cmdline) {
1067 size_t n, i;
1068 const char *p;
1069 bool first;
1070
1071 if (!m)
1072 return -EINVAL;
1073
1074 if (!m->cmdline)
1075 return -ENOENT;
1076
1077 for (p = m->cmdline, n = 0; p < m->cmdline + m->cmdline_length; p++)
1078 if (*p == 0)
1079 n++;
1080
1081 m->cmdline_array = new(char*, n + 1);
1082 if (!m->cmdline_array)
1083 return -ENOMEM;
1084
1085 for (p = m->cmdline, i = 0, first = true; p < m->cmdline + m->cmdline_length; p++) {
1086 if (first)
1087 m->cmdline_array[i++] = (char*) p;
1088
1089 first = *p == 0;
1090 }
1091
1092 m->cmdline_array[i] = NULL;
1093 *cmdline = m->cmdline_array;
1094
1095 return 0;
1096}
1097
120f919e
LP
1098int sd_bus_message_get_audit_sessionid(sd_bus_message *m, uint32_t *sessionid) {
1099 if (!m)
1100 return -EINVAL;
1101 if (!sessionid)
1102 return -EINVAL;
1103 if (!m->audit)
1104 return -ESRCH;
1105
1106 *sessionid = m->audit->sessionid;
1107 return 0;
1108}
1109
1110int sd_bus_message_get_audit_loginuid(sd_bus_message *m, uid_t *uid) {
1111 if (!m)
1112 return -EINVAL;
1113 if (!uid)
1114 return -EINVAL;
1115 if (!m->audit)
1116 return -ESRCH;
1117
1118 *uid = m->audit->loginuid;
1119 return 0;
1120}
1121
102ea8e4
LP
1122int sd_bus_message_has_effective_cap(sd_bus_message *m, int capability) {
1123 unsigned sz;
1124
1125 if (!m)
1126 return -EINVAL;
1127 if (capability < 0)
1128 return -EINVAL;
1129 if (!m->capability)
1130 return -ESRCH;
1131
1132 sz = m->capability_size / 4;
1133 if ((unsigned) capability >= sz*8)
1134 return 0;
1135
1136 return !!(m->capability[2 * sz + (capability / 8)] & (1 << (capability % 8)));
1137}
1138
de1c301e
LP
1139int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member) {
1140 if (!m)
1141 return -EINVAL;
1142
40ca29a1 1143 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
de1c301e
LP
1144 return 0;
1145
1146 if (interface && (!m->interface || !streq(m->interface, interface)))
1147 return 0;
1148
1149 if (member && (!m->member || !streq(m->member, member)))
1150 return 0;
1151
1152 return 1;
1153}
1154
1155int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member) {
1156 if (!m)
1157 return -EINVAL;
1158
40ca29a1 1159 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
de1c301e
LP
1160 return 0;
1161
1162 if (interface && (!m->interface || !streq(m->interface, interface)))
1163 return 0;
1164
1165 if (member && (!m->member || !streq(m->member, member)))
1166 return 0;
1167
1168 return 1;
1169}
1170
1171int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1172 if (!m)
1173 return -EINVAL;
1174
40ca29a1 1175 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
de1c301e
LP
1176 return 0;
1177
1178 if (name && (!m->error.name || !streq(m->error.name, name)))
1179 return 0;
1180
1181 return 1;
1182}
1183
1184int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
1185 if (!m)
1186 return -EINVAL;
1187 if (m->sealed)
1188 return -EPERM;
40ca29a1 1189 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
de1c301e
LP
1190 return -EPERM;
1191
1192 if (b)
1193 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
1194 else
1195 m->header->flags &= ~SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
1196
1197 return 0;
1198}
1199
1200static struct bus_container *message_get_container(sd_bus_message *m) {
1201 assert(m);
1202
1203 if (m->n_containers == 0)
1204 return &m->root_container;
1205
9a17484d
LP
1206 assert(m->containers);
1207 return m->containers + m->n_containers - 1;
de1c301e
LP
1208}
1209
bc7fd8cd
LP
1210struct bus_body_part *message_append_part(sd_bus_message *m) {
1211 struct bus_body_part *part;
1212
1213 assert(m);
1214
1215 if (m->poisoned)
1216 return NULL;
1217
1218 if (m->n_body_parts <= 0) {
1219 part = &m->body;
1220 zero(*part);
1221 } else {
1222 assert(m->body_end);
1223
1224 part = new0(struct bus_body_part, 1);
1225 if (!part) {
1226 m->poisoned = true;
1227 return NULL;
1228 }
1229
1230 m->body_end->next = part;
1231 }
1232
1233 part->memfd = -1;
1234 m->body_end = part;
1235 m->n_body_parts ++;
1236
1237 return part;
1238}
1239
1240static void part_zero(struct bus_body_part *part, size_t sz) {
1241 assert(part);
1242 assert(sz > 0);
1243 assert(sz < 8);
1244
453a0c29
LP
1245 /* All other fields can be left in their defaults */
1246 assert(!part->data);
1247 assert(part->memfd < 0);
1248
bc7fd8cd 1249 part->size = sz;
453a0c29
LP
1250 part->is_zero = true;
1251 part->sealed = true;
bc7fd8cd
LP
1252}
1253
1254static int part_make_space(
1255 struct sd_bus_message *m,
1256 struct bus_body_part *part,
1257 size_t sz,
1258 void **q) {
1259
1260 void *n;
1261 int r;
1262
1263 assert(m);
1264 assert(part);
1265 assert(!part->sealed);
1266
1267 if (m->poisoned)
1268 return -ENOMEM;
1269
1270 if (!part->data && part->memfd < 0)
1271 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped);
1272
1273 if (part->memfd >= 0) {
1274 uint64_t u = sz;
1275
1276 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &u);
1277 if (r < 0) {
1278 m->poisoned = true;
1279 return -errno;
1280 }
1281
453a0c29
LP
1282 if (!part->data || sz > part->mapped) {
1283 size_t psz = PAGE_ALIGN(sz > 0 ? sz : 1);
bc7fd8cd
LP
1284
1285 if (part->mapped <= 0)
1286 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1287 else
1288 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1289
1290 if (n == MAP_FAILED) {
1291 m->poisoned = true;
1292 return -errno;
1293 }
1294
1295 part->mapped = psz;
1296 part->data = n;
1297 }
bf30e48f
KS
1298
1299 part->munmap_this = true;
bc7fd8cd 1300 } else {
23c6f770 1301 n = realloc(part->data, MAX(sz, 1u));
bc7fd8cd
LP
1302 if (!n) {
1303 m->poisoned = true;
1304 return -ENOMEM;
1305 }
1306
1307 part->data = n;
1308 part->free_this = true;
1309 }
1310
1311 if (q)
1312 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1313
1314 part->size = sz;
1315 return 0;
1316}
1317
453a0c29 1318static void message_extend_containers(sd_bus_message *m, size_t expand) {
de1c301e 1319 struct bus_container *c;
453a0c29
LP
1320
1321 assert(m);
1322
1323 if (expand <= 0)
1324 return;
1325
1326 /* Update counters */
1327 for (c = m->containers; c < m->containers + m->n_containers; c++)
1328 if (c->array_size)
1329 *c->array_size += expand;
453a0c29
LP
1330}
1331
1332static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
bc7fd8cd
LP
1333 struct bus_body_part *part = NULL;
1334 size_t start_body, end_body, padding, start_part, end_part, added;
1335 bool add_new_part;
1336 void *p;
1337 int r;
de1c301e
LP
1338
1339 assert(m);
9a17484d 1340 assert(align > 0);
bc7fd8cd 1341 assert(!m->sealed);
de1c301e 1342
bc7fd8cd
LP
1343 if (m->poisoned)
1344 return NULL;
de1c301e 1345
bc7fd8cd
LP
1346 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1347 end_body = start_body + sz;
1348
1349 padding = start_body - m->header->body_size;
1350 added = padding + sz;
1351
1352 /* Check for 32bit overflows */
1353 if (end_body > (size_t) ((uint32_t) -1)) {
1354 m->poisoned = true;
de1c301e 1355 return NULL;
bc7fd8cd 1356 }
de1c301e 1357
bc7fd8cd
LP
1358 add_new_part =
1359 m->n_body_parts <= 0 ||
1360 m->body_end->sealed ||
1361 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
de1c301e 1362
bc7fd8cd
LP
1363 if (add_new_part) {
1364 if (padding > 0) {
1365 part = message_append_part(m);
1366 if (!part)
1367 return NULL;
1368
1369 part_zero(part, padding);
1370 }
1371
1372 part = message_append_part(m);
1373 if (!part)
1374 return NULL;
1375
1376 r = part_make_space(m, part, sz, &p);
1377 if (r < 0)
1378 return NULL;
1379 } else {
453a0c29 1380 struct bus_container *c;
bc7fd8cd
LP
1381 void *op;
1382 size_t os;
1383
1384 part = m->body_end;
1385 op = part->data;
1386 os = part->size;
1387
1388 start_part = ALIGN_TO(part->size, align);
1389 end_part = start_part + sz;
1390
1391 r = part_make_space(m, part, end_part, &p);
1392 if (r < 0)
1393 return NULL;
1394
1395 if (padding > 0) {
1396 memset(p, 0, padding);
1397 p = (uint8_t*) p + padding;
de1c301e
LP
1398 }
1399
bc7fd8cd
LP
1400 /* Readjust pointers */
1401 for (c = m->containers; c < m->containers + m->n_containers; c++)
1402 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1403
1404 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
de1c301e
LP
1405 }
1406
bc7fd8cd 1407 m->header->body_size = end_body;
453a0c29 1408 message_extend_containers(m, added);
de1c301e
LP
1409
1410 return p;
1411}
1412
1413int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1414 struct bus_container *c;
27f6e5c7 1415 ssize_t align, sz;
de1c301e
LP
1416 uint32_t k;
1417 void *a;
2c93b4ef 1418 int fd = -1;
62cfa9da 1419 uint32_t fdi = 0;
2c93b4ef 1420 int r;
de1c301e
LP
1421
1422 if (!m)
1423 return -EINVAL;
2c93b4ef
LP
1424 if (!p)
1425 return -EINVAL;
de1c301e
LP
1426 if (m->sealed)
1427 return -EPERM;
1428 if (!bus_type_is_basic(type))
1429 return -EINVAL;
bc7fd8cd
LP
1430 if (m->poisoned)
1431 return -ESTALE;
de1c301e
LP
1432
1433 c = message_get_container(m);
1434
1435 if (c->signature && c->signature[c->index]) {
1436 /* Container signature is already set */
1437
1438 if (c->signature[c->index] != type)
9a17484d 1439 return -ENXIO;
de1c301e 1440 } else {
5cbe7492
LP
1441 char *e;
1442
de1c301e
LP
1443 /* Maybe we can append to the signature? But only if this is the top-level container*/
1444 if (c->enclosing != 0)
9a17484d 1445 return -ENXIO;
de1c301e
LP
1446
1447 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
bc7fd8cd
LP
1448 if (!e) {
1449 m->poisoned = true;
de1c301e 1450 return -ENOMEM;
bc7fd8cd 1451 }
de1c301e
LP
1452 }
1453
de1c301e
LP
1454 switch (type) {
1455
1456 case SD_BUS_TYPE_STRING:
1457 case SD_BUS_TYPE_OBJECT_PATH:
b8beb278 1458
de1c301e
LP
1459 align = 4;
1460 sz = 4 + strlen(p) + 1;
1461 break;
1462
1463 case SD_BUS_TYPE_SIGNATURE:
b8beb278 1464
de1c301e
LP
1465 align = 1;
1466 sz = 1 + strlen(p) + 1;
1467 break;
1468
1469 case SD_BUS_TYPE_BOOLEAN:
1470 align = sz = 4;
1471
1472 assert_cc(sizeof(int) == sizeof(uint32_t));
1473 memcpy(&k, p, 4);
1474 k = !!k;
1475 p = &k;
1476 break;
1477
2c93b4ef
LP
1478 case SD_BUS_TYPE_UNIX_FD: {
1479 int z, *f;
1480
1481 if (!m->allow_fds) {
1482 r = -ENOTSUP;
1483 goto fail;
1484 }
1485
1486 align = sz = 4;
1487
1488 z = *(int*) p;
1489 if (z < 0) {
1490 r = -EINVAL;
1491 goto fail;
1492 }
1493
1494 fd = fcntl(z, F_DUPFD_CLOEXEC, 3);
1495 if (fd < 0) {
1496 r = -errno;
1497 goto fail;
1498 }
1499
1500 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1501 if (!f) {
bc7fd8cd 1502 m->poisoned = true;
2c93b4ef
LP
1503 r = -ENOMEM;
1504 goto fail;
1505 }
1506
1507 fdi = m->n_fds;
1508 f[fdi] = fd;
1509 m->fds = f;
1510 m->free_fds = true;
1511 break;
1512 }
1513
de1c301e
LP
1514 default:
1515 align = bus_type_get_alignment(type);
1516 sz = bus_type_get_size(type);
1517 break;
1518 }
1519
1520 assert(align > 0);
1521 assert(sz > 0);
1522
1523 a = message_extend_body(m, align, sz);
1524 if (!a) {
2c93b4ef
LP
1525 r = -ENOMEM;
1526 goto fail;
de1c301e
LP
1527 }
1528
1529 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1530 *(uint32_t*) a = sz - 5;
1531 memcpy((uint8_t*) a + 4, p, sz - 4);
1532
1533 if (stored)
1534 *stored = (const uint8_t*) a + 4;
1535
1536 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1537 *(uint8_t*) a = sz - 1;
1538 memcpy((uint8_t*) a + 1, p, sz - 1);
1539
1540 if (stored)
1541 *stored = (const uint8_t*) a + 1;
2c93b4ef
LP
1542 } else if (type == SD_BUS_TYPE_UNIX_FD) {
1543 *(uint32_t*) a = fdi;
1544
1545 if (stored)
1546 *stored = a;
1547
1548 m->n_fds ++;
de1c301e
LP
1549
1550 } else {
1551 memcpy(a, p, sz);
1552
1553 if (stored)
1554 *stored = a;
1555 }
1556
1557 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1558 c->index++;
de1c301e
LP
1559
1560 return 0;
2c93b4ef
LP
1561
1562fail:
2c93b4ef
LP
1563 if (fd >= 0)
1564 close_nointr_nofail(fd);
1565
1566 return r;
de1c301e
LP
1567}
1568
1569int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1570 return message_append_basic(m, type, p, NULL);
1571}
1572
f8e013f8
LP
1573int sd_bus_message_append_string_space(sd_bus_message *m, size_t size, char **s) {
1574 struct bus_container *c;
f8e013f8 1575 void *a;
f8e013f8
LP
1576
1577 if (!m)
1578 return -EINVAL;
1579 if (!s)
1580 return -EINVAL;
1581 if (m->sealed)
1582 return -EPERM;
bc7fd8cd
LP
1583 if (m->poisoned)
1584 return -ESTALE;
f8e013f8
LP
1585
1586 c = message_get_container(m);
1587
1588 if (c->signature && c->signature[c->index]) {
1589 /* Container signature is already set */
1590
1591 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1592 return -ENXIO;
1593 } else {
5cbe7492
LP
1594 char *e;
1595
f8e013f8
LP
1596 /* Maybe we can append to the signature? But only if this is the top-level container*/
1597 if (c->enclosing != 0)
1598 return -ENXIO;
1599
1600 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
bc7fd8cd
LP
1601 if (!e) {
1602 m->poisoned = true;
f8e013f8 1603 return -ENOMEM;
bc7fd8cd 1604 }
f8e013f8
LP
1605 }
1606
f8e013f8 1607 a = message_extend_body(m, 4, 4 + size + 1);
bc7fd8cd
LP
1608 if (!a)
1609 return -ENOMEM;
f8e013f8
LP
1610
1611 *(uint32_t*) a = size;
1612 *s = (char*) a + 4;
1613
1614 (*s)[size] = 0;
1615
1616 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1617 c->index++;
1618
1619 return 0;
f8e013f8
LP
1620}
1621
de1c301e
LP
1622static int bus_message_open_array(
1623 sd_bus_message *m,
1624 struct bus_container *c,
1625 const char *contents,
1626 uint32_t **array_size) {
1627
9a17484d 1628 unsigned nindex;
bc7fd8cd 1629 void *a, *op;
de1c301e 1630 int alignment;
bc7fd8cd
LP
1631 size_t os;
1632 struct bus_body_part *o;
de1c301e
LP
1633
1634 assert(m);
1635 assert(c);
1636 assert(contents);
1637 assert(array_size);
1638
29ddb38f 1639 if (!signature_is_single(contents, true))
de1c301e
LP
1640 return -EINVAL;
1641
1642 alignment = bus_type_get_alignment(contents[0]);
1643 if (alignment < 0)
1644 return alignment;
1645
1646 if (c->signature && c->signature[c->index]) {
1647
1648 /* Verify the existing signature */
1649
1650 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
9a17484d 1651 return -ENXIO;
de1c301e
LP
1652
1653 if (!startswith(c->signature + c->index + 1, contents))
9a17484d 1654 return -ENXIO;
de1c301e
LP
1655
1656 nindex = c->index + 1 + strlen(contents);
1657 } else {
5cbe7492
LP
1658 char *e;
1659
de1c301e 1660 if (c->enclosing != 0)
9a17484d 1661 return -ENXIO;
de1c301e
LP
1662
1663 /* Extend the existing signature */
1664
1665 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
bc7fd8cd
LP
1666 if (!e) {
1667 m->poisoned = true;
de1c301e 1668 return -ENOMEM;
bc7fd8cd 1669 }
de1c301e
LP
1670
1671 nindex = e - c->signature;
1672 }
1673
de1c301e 1674 a = message_extend_body(m, 4, 4);
bc7fd8cd 1675 if (!a)
de1c301e 1676 return -ENOMEM;
de1c301e 1677
bc7fd8cd
LP
1678 o = m->body_end;
1679 op = m->body_end->data;
1680 os = m->body_end->size;
de1c301e 1681
bc7fd8cd
LP
1682 /* Add alignment between size and first element */
1683 if (!message_extend_body(m, alignment, 0))
de1c301e 1684 return -ENOMEM;
de1c301e
LP
1685
1686 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1687 c->index = nindex;
1688
bc7fd8cd
LP
1689 /* location of array size might have changed so let's readjust a */
1690 if (o == m->body_end)
1691 a = adjust_pointer(a, op, os, m->body_end->data);
de1c301e 1692
bc7fd8cd 1693 *(uint32_t*) a = 0;
de1c301e
LP
1694 *array_size = a;
1695 return 0;
1696}
1697
1698static int bus_message_open_variant(
1699 sd_bus_message *m,
1700 struct bus_container *c,
1701 const char *contents) {
1702
9a17484d 1703 size_t l;
de1c301e
LP
1704 void *a;
1705
1706 assert(m);
1707 assert(c);
1708 assert(contents);
1709
29ddb38f 1710 if (!signature_is_single(contents, false))
de1c301e
LP
1711 return -EINVAL;
1712
1713 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1714 return -EINVAL;
1715
1716 if (c->signature && c->signature[c->index]) {
1717
1718 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
9a17484d 1719 return -ENXIO;
de1c301e
LP
1720
1721 } else {
5cbe7492
LP
1722 char *e;
1723
de1c301e 1724 if (c->enclosing != 0)
9a17484d 1725 return -ENXIO;
de1c301e
LP
1726
1727 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
bc7fd8cd
LP
1728 if (!e) {
1729 m->poisoned = true;
de1c301e 1730 return -ENOMEM;
bc7fd8cd 1731 }
de1c301e
LP
1732 }
1733
de1c301e
LP
1734 l = strlen(contents);
1735 a = message_extend_body(m, 1, 1 + l + 1);
bc7fd8cd 1736 if (!a)
de1c301e 1737 return -ENOMEM;
de1c301e
LP
1738
1739 *(uint8_t*) a = l;
1740 memcpy((uint8_t*) a + 1, contents, l + 1);
1741
1742 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1743 c->index++;
de1c301e
LP
1744
1745 return 0;
1746}
1747
1748static int bus_message_open_struct(
1749 sd_bus_message *m,
1750 struct bus_container *c,
1751 const char *contents) {
1752
1753 size_t nindex;
de1c301e
LP
1754
1755 assert(m);
1756 assert(c);
1757 assert(contents);
1758
1759 if (!signature_is_valid(contents, false))
1760 return -EINVAL;
1761
1762 if (c->signature && c->signature[c->index]) {
1763 size_t l;
1764
1765 l = strlen(contents);
1766
1767 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1768 !startswith(c->signature + c->index + 1, contents) ||
1769 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
9a17484d 1770 return -ENXIO;
de1c301e
LP
1771
1772 nindex = c->index + 1 + l + 1;
1773 } else {
5cbe7492
LP
1774 char *e;
1775
de1c301e 1776 if (c->enclosing != 0)
9a17484d 1777 return -ENXIO;
de1c301e
LP
1778
1779 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
bc7fd8cd
LP
1780 if (!e) {
1781 m->poisoned = true;
de1c301e 1782 return -ENOMEM;
bc7fd8cd 1783 }
de1c301e
LP
1784
1785 nindex = e - c->signature;
1786 }
1787
1788 /* Align contents to 8 byte boundary */
bc7fd8cd 1789 if (!message_extend_body(m, 8, 0))
de1c301e 1790 return -ENOMEM;
de1c301e
LP
1791
1792 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1793 c->index = nindex;
1794
1795 return 0;
1796}
1797
1798static int bus_message_open_dict_entry(
1799 sd_bus_message *m,
1800 struct bus_container *c,
1801 const char *contents) {
1802
1803 size_t nindex;
1804
1805 assert(m);
1806 assert(c);
1807 assert(contents);
1808
1809 if (!signature_is_pair(contents))
1810 return -EINVAL;
1811
1812 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1813 return -ENXIO;
de1c301e
LP
1814
1815 if (c->signature && c->signature[c->index]) {
1816 size_t l;
1817
1818 l = strlen(contents);
1819
1820 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1821 !startswith(c->signature + c->index + 1, contents) ||
1822 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
9a17484d 1823 return -ENXIO;
de1c301e
LP
1824
1825 nindex = c->index + 1 + l + 1;
1826 } else
9a17484d 1827 return -ENXIO;
de1c301e
LP
1828
1829 /* Align contents to 8 byte boundary */
1830 if (!message_extend_body(m, 8, 0))
1831 return -ENOMEM;
1832
1833 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1834 c->index = nindex;
1835
1836 return 0;
1837}
1838
1839int sd_bus_message_open_container(
1840 sd_bus_message *m,
1841 char type,
1842 const char *contents) {
1843
9a17484d 1844 struct bus_container *c, *w;
de1c301e 1845 uint32_t *array_size = NULL;
9a17484d 1846 char *signature;
b3af9646 1847 size_t before;
de1c301e
LP
1848 int r;
1849
1850 if (!m)
1851 return -EINVAL;
1852 if (m->sealed)
1853 return -EPERM;
1854 if (!contents)
1855 return -EINVAL;
bc7fd8cd
LP
1856 if (m->poisoned)
1857 return -ESTALE;
de1c301e
LP
1858
1859 /* Make sure we have space for one more container */
9a17484d 1860 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
bc7fd8cd
LP
1861 if (!w) {
1862 m->poisoned = true;
de1c301e 1863 return -ENOMEM;
bc7fd8cd
LP
1864 }
1865
9a17484d 1866 m->containers = w;
de1c301e
LP
1867
1868 c = message_get_container(m);
1869
1870 signature = strdup(contents);
bc7fd8cd
LP
1871 if (!signature) {
1872 m->poisoned = true;
de1c301e 1873 return -ENOMEM;
bc7fd8cd 1874 }
de1c301e 1875
b3af9646
LP
1876 /* Save old index in the parent container, in case we have to
1877 * abort this container */
1878 c->saved_index = c->index;
1879 before = m->header->body_size;
1880
de1c301e
LP
1881 if (type == SD_BUS_TYPE_ARRAY)
1882 r = bus_message_open_array(m, c, contents, &array_size);
1883 else if (type == SD_BUS_TYPE_VARIANT)
1884 r = bus_message_open_variant(m, c, contents);
1885 else if (type == SD_BUS_TYPE_STRUCT)
1886 r = bus_message_open_struct(m, c, contents);
1887 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1888 r = bus_message_open_dict_entry(m, c, contents);
1889 else
1890 r = -EINVAL;
1891
1892 if (r < 0) {
1893 free(signature);
1894 return r;
1895 }
1896
1897 /* OK, let's fill it in */
9a17484d
LP
1898 w += m->n_containers++;
1899 w->enclosing = type;
1900 w->signature = signature;
1901 w->index = 0;
1902 w->array_size = array_size;
b3af9646
LP
1903 w->before = before;
1904 w->begin = m->rindex;
de1c301e
LP
1905
1906 return 0;
1907}
1908
1909int sd_bus_message_close_container(sd_bus_message *m) {
1910 struct bus_container *c;
1911
1912 if (!m)
1913 return -EINVAL;
1914 if (m->sealed)
1915 return -EPERM;
1916 if (m->n_containers <= 0)
1917 return -EINVAL;
bc7fd8cd
LP
1918 if (m->poisoned)
1919 return -ESTALE;
de1c301e
LP
1920
1921 c = message_get_container(m);
de1c301e 1922 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1923 if (c->signature && c->signature[c->index] != 0)
de1c301e
LP
1924 return -EINVAL;
1925
1926 free(c->signature);
1927 m->n_containers--;
1928
1929 return 0;
1930}
1931
1b492614
LP
1932typedef struct {
1933 const char *types;
1934 unsigned n_struct;
1935 unsigned n_array;
1936} TypeStack;
1937
1938static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
1939 assert(stack);
1940 assert(max > 0);
1941
1942 if (*i >= max)
1943 return -EINVAL;
1944
1945 stack[*i].types = types;
1946 stack[*i].n_struct = n_struct;
1947 stack[*i].n_array = n_array;
1948 (*i)++;
1949
1950 return 0;
1951}
1952
1953static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
1954 assert(stack);
1955 assert(max > 0);
1956 assert(types);
1957 assert(n_struct);
1958 assert(n_array);
1959
1960 if (*i <= 0)
1961 return 0;
1962
1963 (*i)--;
1964 *types = stack[*i].types;
1965 *n_struct = stack[*i].n_struct;
1966 *n_array = stack[*i].n_array;
1967
1968 return 1;
1969}
1970
917b5dc7 1971int bus_message_append_ap(
de1c301e
LP
1972 sd_bus_message *m,
1973 const char *types,
1974 va_list ap) {
1975
1b492614
LP
1976 unsigned n_array, n_struct;
1977 TypeStack stack[BUS_CONTAINER_DEPTH];
1978 unsigned stack_ptr = 0;
de1c301e
LP
1979 int r;
1980
1981 assert(m);
88d331d5
LP
1982
1983 if (!types)
1984 return 0;
de1c301e 1985
1b492614
LP
1986 n_array = (unsigned) -1;
1987 n_struct = strlen(types);
1988
1989 for (;;) {
1990 const char *t;
1991
1992 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
1993 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
1994 if (r < 0)
1995 return r;
1996 if (r == 0)
1997 break;
1998
1999 r = sd_bus_message_close_container(m);
2000 if (r < 0)
2001 return r;
2002
2003 continue;
2004 }
2005
2006 t = types;
2007 if (n_array != (unsigned) -1)
2008 n_array --;
2009 else {
2010 types ++;
2011 n_struct--;
2012 }
2013
de1c301e
LP
2014 switch (*t) {
2015
2016 case SD_BUS_TYPE_BYTE: {
2017 uint8_t x;
2018
2019 x = (uint8_t) va_arg(ap, int);
2020 r = sd_bus_message_append_basic(m, *t, &x);
2021 break;
2022 }
2023
2024 case SD_BUS_TYPE_BOOLEAN:
2025 case SD_BUS_TYPE_INT32:
9a17484d
LP
2026 case SD_BUS_TYPE_UINT32:
2027 case SD_BUS_TYPE_UNIX_FD: {
de1c301e
LP
2028 uint32_t x;
2029
9a17484d
LP
2030 /* We assume a boolean is the same as int32_t */
2031 assert_cc(sizeof(int32_t) == sizeof(int));
2032
de1c301e
LP
2033 x = va_arg(ap, uint32_t);
2034 r = sd_bus_message_append_basic(m, *t, &x);
2035 break;
2036 }
2037
2038 case SD_BUS_TYPE_INT16:
2039 case SD_BUS_TYPE_UINT16: {
2040 uint16_t x;
2041
2042 x = (uint16_t) va_arg(ap, int);
2043 r = sd_bus_message_append_basic(m, *t, &x);
2044 break;
2045 }
2046
2047 case SD_BUS_TYPE_INT64:
2048 case SD_BUS_TYPE_UINT64:
2049 case SD_BUS_TYPE_DOUBLE: {
2050 uint64_t x;
2051
2052 x = va_arg(ap, uint64_t);
2053 r = sd_bus_message_append_basic(m, *t, &x);
2054 break;
2055 }
2056
2057 case SD_BUS_TYPE_STRING:
2058 case SD_BUS_TYPE_OBJECT_PATH:
2059 case SD_BUS_TYPE_SIGNATURE: {
2060 const char *x;
2061
2062 x = va_arg(ap, const char*);
2063 r = sd_bus_message_append_basic(m, *t, x);
2064 break;
2065 }
2066
de1c301e 2067 case SD_BUS_TYPE_ARRAY: {
de1c301e
LP
2068 size_t k;
2069
2070 r = signature_element_length(t + 1, &k);
2071 if (r < 0)
2072 return r;
2073
2074 {
2075 char s[k + 1];
de1c301e
LP
2076 memcpy(s, t + 1, k);
2077 s[k] = 0;
de1c301e
LP
2078
2079 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2080 if (r < 0)
2081 return r;
1b492614 2082 }
de1c301e 2083
1b492614
LP
2084 if (n_array == (unsigned) -1) {
2085 types += k;
2086 n_struct -= k;
de1c301e
LP
2087 }
2088
1b492614
LP
2089 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2090 if (r < 0)
2091 return r;
2092
2093 types = t + 1;
2094 n_struct = k;
2095 n_array = va_arg(ap, unsigned);
2096
de1c301e
LP
2097 break;
2098 }
2099
2100 case SD_BUS_TYPE_VARIANT: {
2101 const char *s;
2102
2103 s = va_arg(ap, const char*);
2104 if (!s)
2105 return -EINVAL;
2106
2107 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2108 if (r < 0)
2109 return r;
2110
1b492614 2111 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
de1c301e
LP
2112 if (r < 0)
2113 return r;
2114
1b492614
LP
2115 types = s;
2116 n_struct = strlen(s);
2117 n_array = (unsigned) -1;
2118
de1c301e
LP
2119 break;
2120 }
2121
2122 case SD_BUS_TYPE_STRUCT_BEGIN:
2123 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2124 size_t k;
2125
2126 r = signature_element_length(t, &k);
2127 if (r < 0)
2128 return r;
2129
2130 {
2131 char s[k - 1];
2132
2133 memcpy(s, t + 1, k - 2);
2134 s[k - 2] = 0;
2135
2136 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2137 if (r < 0)
2138 return r;
1b492614 2139 }
de1c301e 2140
1b492614
LP
2141 if (n_array == (unsigned) -1) {
2142 types += k - 1;
2143 n_struct -= k - 1;
2144 }
de1c301e 2145
1b492614
LP
2146 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2147 if (r < 0)
2148 return r;
de1c301e 2149
1b492614
LP
2150 types = t + 1;
2151 n_struct = k - 2;
2152 n_array = (unsigned) -1;
de1c301e
LP
2153
2154 break;
2155 }
2156
2157 default:
2158 r = -EINVAL;
2159 }
2160
2161 if (r < 0)
2162 return r;
2163 }
2164
2165 return 0;
2166}
2167
2168int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2169 va_list ap;
2170 int r;
2171
2172 if (!m)
2173 return -EINVAL;
2174 if (m->sealed)
2175 return -EPERM;
bc7fd8cd
LP
2176 if (m->poisoned)
2177 return -ESTALE;
de1c301e 2178 if (!types)
917b5dc7 2179 return 0;
de1c301e
LP
2180
2181 va_start(ap, types);
917b5dc7 2182 r = bus_message_append_ap(m, types, ap);
de1c301e
LP
2183 va_end(ap);
2184
2185 return r;
2186}
2187
f8e013f8 2188int sd_bus_message_append_array_space(sd_bus_message *m, char type, size_t size, void **ptr) {
b3af9646
LP
2189 ssize_t align, sz;
2190 void *a;
2191 int r;
2192
2193 if (!m)
2194 return -EINVAL;
2195 if (m->sealed)
2196 return -EPERM;
2197 if (!bus_type_is_trivial(type))
2198 return -EINVAL;
2199 if (!ptr && size > 0)
2200 return -EINVAL;
bc7fd8cd
LP
2201 if (m->poisoned)
2202 return -ESTALE;
b3af9646
LP
2203
2204 align = bus_type_get_alignment(type);
2205 sz = bus_type_get_size(type);
2206
2207 assert_se(align > 0);
2208 assert_se(sz > 0);
2209
2210 if (size % sz != 0)
2211 return -EINVAL;
2212
2213 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2214 if (r < 0)
2215 return r;
2216
2217 a = message_extend_body(m, align, size);
bc7fd8cd
LP
2218 if (!a)
2219 return -ENOMEM;
b3af9646
LP
2220
2221 r = sd_bus_message_close_container(m);
2222 if (r < 0)
bc7fd8cd 2223 return r;
b3af9646
LP
2224
2225 *ptr = a;
2226 return 0;
b3af9646
LP
2227}
2228
2229int sd_bus_message_append_array(sd_bus_message *m, char type, const void *ptr, size_t size) {
2230 int r;
2231 void *p;
2232
2233 if (!ptr && size > 0)
2234 return -EINVAL;
2235
f8e013f8 2236 r = sd_bus_message_append_array_space(m, type, size, &p);
b3af9646
LP
2237 if (r < 0)
2238 return r;
2239
2240 if (size > 0)
2241 memcpy(p, ptr, size);
2242
2243 return 0;
2244}
2245
453a0c29
LP
2246int sd_bus_message_append_array_memfd(sd_bus_message *m, char type, sd_memfd *memfd) {
2247 _cleanup_close_ int copy_fd = -1;
2248 struct bus_body_part *part;
2249 ssize_t align, sz;
2250 uint64_t size;
2251 void *a;
2252 int r;
2253
2254 if (!m)
2255 return -EINVAL;
2256 if (!memfd)
2257 return -EINVAL;
2258 if (m->sealed)
2259 return -EPERM;
2260 if (!bus_type_is_trivial(type))
2261 return -EINVAL;
2262 if (m->poisoned)
2263 return -ESTALE;
2264
2265 r = sd_memfd_set_sealed(memfd, true);
2266 if (r < 0)
2267 return r;
2268
2269 copy_fd = sd_memfd_dup_fd(memfd);
2270 if (copy_fd < 0)
2271 return copy_fd;
2272
2273 r = sd_memfd_get_size(memfd, &size);
2274 if (r < 0)
2275 return r;
2276
2277 align = bus_type_get_alignment(type);
2278 sz = bus_type_get_size(type);
2279
2280 assert_se(align > 0);
2281 assert_se(sz > 0);
2282
2283 if (size % sz != 0)
2284 return -EINVAL;
2285
5cbe7492 2286 if (size > (uint64_t) (uint32_t) -1)
453a0c29
LP
2287 return -EINVAL;
2288
2289 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2290 if (r < 0)
2291 return r;
2292
2293 a = message_extend_body(m, align, 0);
2294 if (!a)
2295 return -ENOMEM;
2296
2297 part = message_append_part(m);
2298 if (!part)
2299 return -ENOMEM;
2300
2301 part->memfd = copy_fd;
2302 part->sealed = true;
2303 part->size = size;
2304 copy_fd = -1;
2305
2306 message_extend_containers(m, size);
2307 m->header->body_size += size;
2308
2309 return sd_bus_message_close_container(m);
2310}
2311
5cbe7492
LP
2312int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
2313 _cleanup_close_ int copy_fd = -1;
2314 struct bus_body_part *part;
2315 struct bus_container *c;
2316 uint64_t size;
2317 void *a;
2318 int r;
2319
55736ed0
LP
2320 assert_return(m, -EINVAL);
2321 assert_return(memfd, -EINVAL);
2322 assert_return(!m->sealed, -EPERM);
2323 assert_return(!m->poisoned, -ESTALE);
5cbe7492
LP
2324
2325 r = sd_memfd_set_sealed(memfd, true);
2326 if (r < 0)
2327 return r;
2328
2329 copy_fd = sd_memfd_dup_fd(memfd);
2330 if (copy_fd < 0)
2331 return copy_fd;
2332
2333 r = sd_memfd_get_size(memfd, &size);
2334 if (r < 0)
2335 return r;
2336
2337 /* We require this to be NUL terminated */
2338 if (size == 0)
2339 return -EINVAL;
2340
2341 if (size > (uint64_t) (uint32_t) -1)
2342 return -EINVAL;
2343
2344 c = message_get_container(m);
2345 if (c->signature && c->signature[c->index]) {
2346 /* Container signature is already set */
2347
2348 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2349 return -ENXIO;
2350 } else {
2351 char *e;
2352
2353 /* Maybe we can append to the signature? But only if this is the top-level container*/
2354 if (c->enclosing != 0)
2355 return -ENXIO;
2356
2357 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2358 if (!e) {
2359 m->poisoned = true;
2360 return -ENOMEM;
2361 }
2362 }
2363
2364 a = message_extend_body(m, 4, 4);
2365 if (!a)
2366 return -ENOMEM;
2367
2368 *(uint32_t*) a = size - 1;
2369
2370 part = message_append_part(m);
2371 if (!part)
2372 return -ENOMEM;
2373
2374 part->memfd = copy_fd;
2375 part->sealed = true;
2376 part->size = size;
2377 copy_fd = -1;
2378
2379 message_extend_containers(m, size);
2380 m->header->body_size += size;
2381
2382 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2383 c->index++;
2384
2385 return 0;
2386}
2387
55736ed0
LP
2388int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2389 char **i;
2390 int r;
2391
2392 assert_return(m, -EINVAL);
2393 assert_return(!m->sealed, -EPERM);
2394 assert_return(!m->poisoned, -ESTALE);
2395
2396 r = sd_bus_message_open_container(m, 'a', "s");
2397 if (r < 0)
2398 return r;
2399
2400 STRV_FOREACH(i, l) {
2401 r = sd_bus_message_append_basic(m, 's', *i);
2402 if (r < 0)
2403 return r;
2404 }
2405
2406 return sd_bus_message_close_container(m);
2407}
2408
a392d361 2409int bus_body_part_map(struct bus_body_part *part) {
453a0c29
LP
2410 void *p;
2411 size_t psz;
2412
2413 assert_se(part);
2414
2415 if (part->data)
2416 return 0;
2417
2418 if (part->size <= 0)
2419 return 0;
2420
1307c3ff
LP
2421 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2422 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2423 static const uint8_t zeroes[7] = { };
2424 part->data = (void*) zeroes;
2425 return 0;
2426 }
2427
453a0c29
LP
2428 psz = PAGE_ALIGN(part->size);
2429
2430 if (part->memfd >= 0)
2431 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2432 else if (part->is_zero)
2433 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2434 else
2435 return -EINVAL;
2436
2437 if (p == MAP_FAILED)
2438 return -errno;
2439
2440 part->mapped = psz;
2441 part->data = p;
a392d361
LP
2442 part->munmap_this = true;
2443
453a0c29
LP
2444 return 0;
2445}
2446
a392d361
LP
2447void bus_body_part_unmap(struct bus_body_part *part) {
2448
2449 assert_se(part);
2450
2451 if (part->memfd < 0)
2452 return;
2453
a392d361
LP
2454 if (!part->data)
2455 return;
2456
bf30e48f
KS
2457 if (!part->munmap_this)
2458 return;
a392d361
LP
2459
2460 assert_se(munmap(part->data, part->mapped) == 0);
2461
2462 part->data = NULL;
2463 part->mapped = 0;
2464 part->munmap_this = false;
2465
2466 return;
2467}
2468
9a17484d 2469static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
bc7fd8cd 2470 size_t k, start, end;
de1c301e 2471
9a17484d
LP
2472 assert(rindex);
2473 assert(align > 0);
de1c301e 2474
9a17484d 2475 start = ALIGN_TO((size_t) *rindex, align);
bc7fd8cd 2476 end = start + nbytes;
9a17484d 2477
bc7fd8cd 2478 if (end > sz)
9a17484d
LP
2479 return -EBADMSG;
2480
2481 /* Verify that padding is 0 */
2482 for (k = *rindex; k < start; k++)
2483 if (((const uint8_t*) p)[k] != 0)
2484 return -EBADMSG;
2485
2486 if (r)
2487 *r = (uint8_t*) p + start;
2488
bc7fd8cd 2489 *rindex = end;
9a17484d
LP
2490
2491 return 1;
de1c301e
LP
2492}
2493
9a17484d
LP
2494static bool message_end_of_array(sd_bus_message *m, size_t index) {
2495 struct bus_container *c;
de1c301e 2496
9a17484d 2497 assert(m);
de1c301e 2498
9a17484d
LP
2499 c = message_get_container(m);
2500 if (!c->array_size)
2501 return false;
de1c301e 2502
9a17484d 2503 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
de1c301e
LP
2504}
2505
bc7fd8cd
LP
2506static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2507 struct bus_body_part *part;
2508 size_t begin;
453a0c29
LP
2509 int r;
2510
bc7fd8cd
LP
2511 assert(m);
2512
2513 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2514 part = m->cached_rindex_part;
2515 begin = m->cached_rindex_part_begin;
2516 } else {
2517 part = &m->body;
2518 begin = 0;
2519 }
2520
2521 while (part) {
2522 if (index < begin)
2523 return NULL;
2524
2525 if (index + sz <= begin + part->size) {
453a0c29 2526
a392d361 2527 r = bus_body_part_map(part);
453a0c29
LP
2528 if (r < 0)
2529 return NULL;
2530
bc7fd8cd 2531 if (p)
453a0c29 2532 *p = (uint8_t*) part->data + index - begin;
bc7fd8cd
LP
2533
2534 m->cached_rindex_part = part;
2535 m->cached_rindex_part_begin = begin;
2536
2537 return part;
2538 }
2539
453a0c29 2540 begin += part->size;
bc7fd8cd
LP
2541 part = part->next;
2542 }
2543
2544 return NULL;
2545}
2546
2547static int message_peek_body(
2548 sd_bus_message *m,
2549 size_t *rindex,
2550 size_t align,
2551 size_t nbytes,
2552 void **ret) {
2553
2554 size_t k, start, end, padding;
2555 struct bus_body_part *part;
2556 uint8_t *q;
2557
de1c301e 2558 assert(m);
9a17484d
LP
2559 assert(rindex);
2560 assert(align > 0);
de1c301e 2561
9a17484d
LP
2562 if (message_end_of_array(m, *rindex))
2563 return 0;
de1c301e 2564
bc7fd8cd
LP
2565 start = ALIGN_TO((size_t) *rindex, align);
2566 padding = start - *rindex;
2567 end = start + nbytes;
2568
2569 if (end > BUS_MESSAGE_BODY_SIZE(m))
2570 return -EBADMSG;
2571
2572 part = find_part(m, *rindex, padding, (void**) &q);
2573 if (!part)
2574 return -EBADMSG;
2575
2576 if (q) {
2577 /* Verify padding */
2578 for (k = 0; k < padding; k++)
2579 if (q[k] != 0)
2580 return -EBADMSG;
2581 }
2582
2583 part = find_part(m, start, nbytes, (void**) &q);
2584 if (!part || !q)
2585 return -EBADMSG;
2586
2587 *rindex = end;
2588
2589 if (ret)
2590 *ret = q;
2591
2592 return 1;
9a17484d 2593}
de1c301e 2594
ac89bf1d 2595static bool validate_nul(const char *s, size_t l) {
de1c301e 2596
9a17484d
LP
2597 /* Check for NUL chars in the string */
2598 if (memchr(s, 0, l))
2599 return false;
de1c301e 2600
9a17484d
LP
2601 /* Check for NUL termination */
2602 if (s[l] != 0)
2603 return false;
de1c301e 2604
ac89bf1d
LP
2605 return true;
2606}
2607
2608static bool validate_string(const char *s, size_t l) {
2609
2610 if (!validate_nul(s, l))
2611 return false;
2612
9a17484d
LP
2613 /* Check if valid UTF8 */
2614 if (!utf8_is_valid(s))
2615 return false;
2616
2617 return true;
de1c301e
LP
2618}
2619
9a17484d 2620static bool validate_signature(const char *s, size_t l) {
de1c301e 2621
ac89bf1d 2622 if (!validate_nul(s, l))
9a17484d 2623 return false;
de1c301e 2624
9a17484d
LP
2625 /* Check if valid signature */
2626 if (!signature_is_valid(s, true))
2627 return false;
2628
2629 return true;
2630}
2631
ac89bf1d
LP
2632static bool validate_object_path(const char *s, size_t l) {
2633
2634 if (!validate_nul(s, l))
2635 return false;
2636
2637 if (!object_path_is_valid(s))
2638 return false;
2639
2640 return true;
2641}
2642
9a17484d
LP
2643int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
2644 struct bus_container *c;
2645 int r;
2646 void *q;
2647
2648 if (!m)
2649 return -EINVAL;
2650 if (!m->sealed)
de1c301e 2651 return -EPERM;
9a17484d
LP
2652 if (!bus_type_is_basic(type))
2653 return -EINVAL;
2c93b4ef
LP
2654 if (!p)
2655 return -EINVAL;
de1c301e 2656
9a17484d 2657 c = message_get_container(m);
de1c301e 2658
9a17484d 2659 if (!c->signature || c->signature[c->index] == 0)
430fb8fa 2660 return -ENXIO;
9a17484d 2661
1daf8121
LP
2662 if (message_end_of_array(m, m->rindex))
2663 return 0;
2664
9a17484d
LP
2665 if (c->signature[c->index] != type)
2666 return -ENXIO;
2667
2668 switch (type) {
2669
2670 case SD_BUS_TYPE_STRING:
2671 case SD_BUS_TYPE_OBJECT_PATH: {
2672 uint32_t l;
2673 size_t rindex;
2674
2675 rindex = m->rindex;
2676 r = message_peek_body(m, &rindex, 4, 4, &q);
2677 if (r <= 0)
2678 return r;
2679
2680 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2681 r = message_peek_body(m, &rindex, 1, l+1, &q);
de1c301e
LP
2682 if (r < 0)
2683 return r;
9a17484d
LP
2684 if (r == 0)
2685 return -EBADMSG;
2686
ac89bf1d
LP
2687 if (type == SD_BUS_TYPE_OBJECT_PATH) {
2688 if (!validate_object_path(q, l))
2689 return -EBADMSG;
2690 } else {
2691 if (!validate_string(q, l))
2692 return -EBADMSG;
2693 }
9a17484d
LP
2694
2695 m->rindex = rindex;
2696 *(const char**) p = q;
2697 break;
de1c301e
LP
2698 }
2699
9a17484d
LP
2700 case SD_BUS_TYPE_SIGNATURE: {
2701 uint8_t l;
2702 size_t rindex;
2703
2704 rindex = m->rindex;
2705 r = message_peek_body(m, &rindex, 1, 1, &q);
2706 if (r <= 0)
2707 return r;
2708
2709 l = *(uint8_t*) q;
2710 r = message_peek_body(m, &rindex, 1, l+1, &q);
de1c301e
LP
2711 if (r < 0)
2712 return r;
9a17484d
LP
2713 if (r == 0)
2714 return -EBADMSG;
2715
2716 if (!validate_signature(q, l))
2717 return -EBADMSG;
2718
2719 m->rindex = rindex;
2720 *(const char**) p = q;
2721 break;
de1c301e
LP
2722 }
2723
9a17484d 2724 default: {
27f6e5c7
ZJS
2725 ssize_t sz, align;
2726 size_t rindex;
de1c301e 2727
9a17484d
LP
2728 align = bus_type_get_alignment(type);
2729 sz = bus_type_get_size(type);
27f6e5c7 2730 assert(align > 0 && sz > 0);
de1c301e 2731
2c93b4ef
LP
2732 rindex = m->rindex;
2733 r = message_peek_body(m, &rindex, align, sz, &q);
9a17484d
LP
2734 if (r <= 0)
2735 return r;
2736
2737 switch (type) {
2738
2739 case SD_BUS_TYPE_BYTE:
2740 *(uint8_t*) p = *(uint8_t*) q;
2741 break;
2742
2743 case SD_BUS_TYPE_BOOLEAN:
9bcbce42 2744 *(unsigned*) p = !!*(uint32_t*) q;
9a17484d
LP
2745 break;
2746
2747 case SD_BUS_TYPE_INT16:
2748 case SD_BUS_TYPE_UINT16:
2749 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
2750 break;
2751
2752 case SD_BUS_TYPE_INT32:
2753 case SD_BUS_TYPE_UINT32:
2754 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2755 break;
2756
2757 case SD_BUS_TYPE_INT64:
2758 case SD_BUS_TYPE_UINT64:
2759 case SD_BUS_TYPE_DOUBLE:
2760 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
2761 break;
2762
2c93b4ef 2763 case SD_BUS_TYPE_UNIX_FD: {
2c93b4ef
LP
2764 uint32_t j;
2765
2766 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2767 if (j >= m->n_fds)
2768 return -EBADMSG;
2769
1ef2af5a 2770 *(int*) p = m->fds[j];
2c93b4ef
LP
2771 break;
2772 }
2773
9a17484d
LP
2774 default:
2775 assert_not_reached("Unknown basic type...");
2776 }
2777
b3af9646 2778 m->rindex = rindex;
2c93b4ef 2779
9a17484d
LP
2780 break;
2781 }
2782 }
2783
2784 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2785 c->index++;
2786
2787 return 1;
de1c301e
LP
2788}
2789
9a17484d
LP
2790static int bus_message_enter_array(
2791 sd_bus_message *m,
2792 struct bus_container *c,
2793 const char *contents,
2794 uint32_t **array_size) {
2795
2796 size_t rindex;
2797 void *q;
2798 int r, alignment;
2799
2800 assert(m);
2801 assert(c);
2802 assert(contents);
2803 assert(array_size);
2804
29ddb38f 2805 if (!signature_is_single(contents, true))
de1c301e 2806 return -EINVAL;
9a17484d
LP
2807
2808 alignment = bus_type_get_alignment(contents[0]);
2809 if (alignment < 0)
2810 return alignment;
2811
2812 if (!c->signature || c->signature[c->index] == 0)
2813 return 0;
2814
2815 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
2816 return -ENXIO;
2817
2818 if (!startswith(c->signature + c->index + 1, contents))
2819 return -ENXIO;
2820
2821 rindex = m->rindex;
2822 r = message_peek_body(m, &rindex, 4, 4, &q);
2823 if (r <= 0)
2824 return r;
2825
ac89bf1d 2826 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
80a46c73 2827 return -EBADMSG;
9a17484d
LP
2828
2829 r = message_peek_body(m, &rindex, alignment, 0, NULL);
2830 if (r < 0)
2831 return r;
2832 if (r == 0)
2833 return -EBADMSG;
2834
2835 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2836 c->index += 1 + strlen(contents);
2837
2838 m->rindex = rindex;
2839
2840 *array_size = (uint32_t*) q;
2841
2842 return 1;
2843}
2844
2845static int bus_message_enter_variant(
2846 sd_bus_message *m,
2847 struct bus_container *c,
2848 const char *contents) {
2849
2850 size_t rindex;
2851 uint8_t l;
2852 void *q;
2853 int r;
2854
2855 assert(m);
2856 assert(c);
2857 assert(contents);
2858
29ddb38f 2859 if (!signature_is_single(contents, false))
de1c301e 2860 return -EINVAL;
de1c301e 2861
9a17484d
LP
2862 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
2863 return -EINVAL;
2864
2865 if (!c->signature || c->signature[c->index] == 0)
2866 return 0;
2867
2868 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
2869 return -ENXIO;
2870
2871 rindex = m->rindex;
2872 r = message_peek_body(m, &rindex, 1, 1, &q);
2873 if (r <= 0)
2874 return r;
2875
2876 l = *(uint8_t*) q;
2877 r = message_peek_body(m, &rindex, 1, l+1, &q);
2878 if (r < 0)
2879 return r;
2880 if (r == 0)
2881 return -EBADMSG;
2882
2883 if (!validate_signature(q, l))
2884 return -EBADMSG;
2885
2886 if (!streq(q, contents))
2887 return -ENXIO;
2888
2889 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2890 c->index++;
2891
2892 m->rindex = rindex;
2893
2894 return 1;
de1c301e
LP
2895}
2896
9a17484d
LP
2897static int bus_message_enter_struct(
2898 sd_bus_message *m,
2899 struct bus_container *c,
2900 const char *contents) {
2901
2902 size_t l;
2903 int r;
2904
2905 assert(m);
2906 assert(c);
2907 assert(contents);
2908
2909 if (!signature_is_valid(contents, false))
2910 return -EINVAL;
2911
2912 if (!c->signature || c->signature[c->index] == 0)
2913 return 0;
2914
2915 l = strlen(contents);
2916
2917 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
2918 !startswith(c->signature + c->index + 1, contents) ||
2919 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
2920 return -ENXIO;
2921
2922 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
2923 if (r <= 0)
2924 return r;
2925
2926 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2927 c->index += 1 + l + 1;
2928
2929 return 1;
2930}
2931
2932static int bus_message_enter_dict_entry(
2933 sd_bus_message *m,
2934 struct bus_container *c,
2935 const char *contents) {
2936
2937 size_t l;
2938 int r;
2939
2940 assert(m);
2941 assert(c);
2942 assert(contents);
2943
2944 if (!signature_is_pair(contents))
2945 return -EINVAL;
2946
2947 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2948 return -ENXIO;
2949
2950 if (!c->signature || c->signature[c->index] == 0)
2951 return 0;
2952
2953 l = strlen(contents);
2954
2955 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2956 !startswith(c->signature + c->index + 1, contents) ||
2957 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2958 return -ENXIO;
2959
2960 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
2961 if (r <= 0)
2962 return r;
2963
2964 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2965 c->index += 1 + l + 1;
2966
2967 return 1;
2968}
2969
2970int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents) {
2971 struct bus_container *c, *w;
2972 uint32_t *array_size = NULL;
2973 char *signature;
b3af9646 2974 size_t before;
9a17484d
LP
2975 int r;
2976
2977 if (!m)
2978 return -EINVAL;
2979 if (!m->sealed)
2980 return -EPERM;
2981 if (!contents)
2982 return -EINVAL;
2983
ed205a6b
LP
2984 /*
2985 * We enforce a global limit on container depth, that is much
2986 * higher than the 32 structs and 32 arrays the specification
2987 * mandates. This is simpler to implement for us, and we need
2988 * this only to ensure our container array doesn't grow
2989 * without bounds. We are happy to return any data from a
2990 * message as long as the data itself is valid, even if the
2991 * overall message might be not.
2992 *
2993 * Note that the message signature is validated when
2994 * parsing the headers, and that validation does check the
2995 * 32/32 limit.
2996 *
2997 * Note that the specification defines no limits on the depth
2998 * of stacked variants, but we do.
2999 */
3000 if (m->n_containers >= BUS_CONTAINER_DEPTH)
3001 return -EBADMSG;
3002
9a17484d
LP
3003 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
3004 if (!w)
3005 return -ENOMEM;
3006 m->containers = w;
3007
3008 c = message_get_container(m);
3009
3010 if (!c->signature || c->signature[c->index] == 0)
430fb8fa 3011 return -ENXIO;
9a17484d 3012
1daf8121
LP
3013 if (message_end_of_array(m, m->rindex))
3014 return 0;
3015
9a17484d
LP
3016 signature = strdup(contents);
3017 if (!signature)
3018 return -ENOMEM;
3019
b3af9646
LP
3020 c->saved_index = c->index;
3021 before = m->rindex;
3022
9a17484d
LP
3023 if (type == SD_BUS_TYPE_ARRAY)
3024 r = bus_message_enter_array(m, c, contents, &array_size);
3025 else if (type == SD_BUS_TYPE_VARIANT)
3026 r = bus_message_enter_variant(m, c, contents);
3027 else if (type == SD_BUS_TYPE_STRUCT)
3028 r = bus_message_enter_struct(m, c, contents);
3029 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3030 r = bus_message_enter_dict_entry(m, c, contents);
3031 else
3032 r = -EINVAL;
3033
3034 if (r <= 0) {
3035 free(signature);
3036 return r;
3037 }
3038
3039 /* OK, let's fill it in */
3040 w += m->n_containers++;
3041 w->enclosing = type;
3042 w->signature = signature;
3043 w->index = 0;
3044 w->array_size = array_size;
b3af9646 3045 w->before = before;
9a17484d
LP
3046 w->begin = m->rindex;
3047
3048 return 1;
3049}
3050
3051int sd_bus_message_exit_container(sd_bus_message *m) {
3052 struct bus_container *c;
3053
3054 if (!m)
3055 return -EINVAL;
3056 if (!m->sealed)
3057 return -EPERM;
3058 if (m->n_containers <= 0)
3059 return -EINVAL;
3060
3061 c = message_get_container(m);
3062 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3063 uint32_t l;
3064
3065 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3066 if (c->begin + l != m->rindex)
3067 return -EBUSY;
3068
3069 } else {
3070 if (c->signature && c->signature[c->index] != 0)
3071 return -EINVAL;
3072 }
3073
3074 free(c->signature);
3075 m->n_containers--;
3076
3077 return 1;
3078}
3079
b3af9646
LP
3080static void message_quit_container(sd_bus_message *m) {
3081 struct bus_container *c;
3082
3083 assert(m);
3084 assert(m->sealed);
3085 assert(m->n_containers > 0);
3086
3087 c = message_get_container(m);
3088
3089 /* Undo seeks */
3090 assert(m->rindex >= c->before);
3091 m->rindex = c->before;
3092
3093 /* Free container */
3094 free(c->signature);
3095 m->n_containers--;
3096
3097 /* Correct index of new top-level container */
3098 c = message_get_container(m);
3099 c->index = c->saved_index;
3100}
3101
9a17484d
LP
3102int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
3103 struct bus_container *c;
3104 int r;
3105
c430fee6
LP
3106 assert_return(m, -EINVAL);
3107 assert_return(m->sealed, -EPERM);
9a17484d
LP
3108
3109 c = message_get_container(m);
3110
3111 if (!c->signature || c->signature[c->index] == 0)
3112 goto eof;
3113
3114 if (message_end_of_array(m, m->rindex))
3115 goto eof;
3116
3117 if (bus_type_is_basic(c->signature[c->index])) {
3118 if (contents)
3119 *contents = NULL;
3120 if (type)
3121 *type = c->signature[c->index];
3122 return 1;
3123 }
3124
3125 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
3126
3127 if (contents) {
3128 size_t l;
3129 char *sig;
3130
3131 r = signature_element_length(c->signature+c->index+1, &l);
3132 if (r < 0)
3133 return r;
3134
80a46c73
LP
3135 assert(l >= 1);
3136
9a17484d
LP
3137 sig = strndup(c->signature + c->index + 1, l);
3138 if (!sig)
3139 return -ENOMEM;
3140
3141 free(m->peeked_signature);
3142 m->peeked_signature = sig;
3143
3144 *contents = sig;
3145 }
3146
3147 if (type)
3148 *type = SD_BUS_TYPE_ARRAY;
3149
3150 return 1;
3151 }
3152
3153 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
3154 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
3155
3156 if (contents) {
3157 size_t l;
3158 char *sig;
3159
3160 r = signature_element_length(c->signature+c->index, &l);
3161 if (r < 0)
3162 return r;
3163
3164 assert(l >= 2);
3165 sig = strndup(c->signature + c->index + 1, l - 2);
3166 if (!sig)
3167 return -ENOMEM;
3168
3169 free(m->peeked_signature);
3170 m->peeked_signature = sig;
3171
3172 *contents = sig;
3173 }
3174
3175 if (type)
3176 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
3177
3178 return 1;
3179 }
3180
3181 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
3182 if (contents) {
3183 size_t rindex, l;
3184 void *q;
3185
3186 rindex = m->rindex;
3187 r = message_peek_body(m, &rindex, 1, 1, &q);
3188 if (r < 0)
3189 return r;
3190 if (r == 0)
3191 goto eof;
3192
3193 l = *(uint8_t*) q;
3194 r = message_peek_body(m, &rindex, 1, l+1, &q);
3195 if (r < 0)
3196 return r;
3197 if (r == 0)
3198 return -EBADMSG;
3199
3200 if (!validate_signature(q, l))
3201 return -EBADMSG;
3202
3203 *contents = q;
3204 }
3205
3206 if (type)
3207 *type = SD_BUS_TYPE_VARIANT;
3208
3209 return 1;
3210 }
3211
3212 return -EINVAL;
3213
3214eof:
3215 if (type)
3216 *type = c->enclosing;
3217 if (contents)
3218 *contents = NULL;
3219 return 0;
3220}
3221
89ffcd2a 3222int sd_bus_message_rewind(sd_bus_message *m, int complete) {
9a17484d
LP
3223 struct bus_container *c;
3224
3225 if (!m)
3226 return -EINVAL;
3227 if (!m->sealed)
3228 return -EPERM;
3229
3230 if (complete) {
bc7fd8cd 3231 message_reset_containers(m);
9a17484d
LP
3232 m->rindex = 0;
3233 m->root_container.index = 0;
3234
3235 c = message_get_container(m);
3236 } else {
3237 c = message_get_container(m);
3238
3239 c->index = 0;
3240 m->rindex = c->begin;
3241 }
3242
3243 return !isempty(c->signature);
3244}
1b492614
LP
3245static int message_read_ap(
3246 sd_bus_message *m,
3247 const char *types,
3248 va_list ap) {
9a17484d 3249
fe1d424d
LP
3250 unsigned n_array, n_struct;
3251 TypeStack stack[BUS_CONTAINER_DEPTH];
3252 unsigned stack_ptr = 0;
430fb8fa 3253 unsigned n_loop = 0;
9a17484d
LP
3254 int r;
3255
3256 assert(m);
1b492614 3257
430fb8fa 3258 if (isempty(types))
1b492614 3259 return 0;
9a17484d 3260
fe1d424d
LP
3261 /* Ideally, we'd just call ourselves recursively on every
3262 * complex type. However, the state of a va_list that is
3263 * passed to a function is undefined after that function
3264 * returns. This means we need to docode the va_list linearly
3265 * in a single stackframe. We hence implement our own
3266 * home-grown stack in an array. */
3267
430fb8fa
LP
3268 n_array = (unsigned) -1; /* lenght of current array entries */
3269 n_struct = strlen(types); /* length of current struct contents signature */
fe1d424d
LP
3270
3271 for (;;) {
3272 const char *t;
3273
430fb8fa
LP
3274 n_loop++;
3275
1b492614 3276 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
fe1d424d
LP
3277 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
3278 if (r < 0)
3279 return r;
3280 if (r == 0)
3281 break;
3282
3283 r = sd_bus_message_exit_container(m);
3284 if (r < 0)
3285 return r;
3286
3287 continue;
3288 }
3289
3290 t = types;
3291 if (n_array != (unsigned) -1)
3292 n_array --;
3293 else {
3294 types ++;
3295 n_struct--;
3296 }
3297
9a17484d
LP
3298 switch (*t) {
3299
3300 case SD_BUS_TYPE_BYTE:
3301 case SD_BUS_TYPE_BOOLEAN:
3302 case SD_BUS_TYPE_INT16:
3303 case SD_BUS_TYPE_UINT16:
3304 case SD_BUS_TYPE_INT32:
3305 case SD_BUS_TYPE_UINT32:
3306 case SD_BUS_TYPE_INT64:
3307 case SD_BUS_TYPE_UINT64:
3308 case SD_BUS_TYPE_DOUBLE:
3309 case SD_BUS_TYPE_STRING:
3310 case SD_BUS_TYPE_OBJECT_PATH:
2c93b4ef
LP
3311 case SD_BUS_TYPE_SIGNATURE:
3312 case SD_BUS_TYPE_UNIX_FD: {
9a17484d
LP
3313 void *p;
3314
3315 p = va_arg(ap, void*);
3316 r = sd_bus_message_read_basic(m, *t, p);
fe1d424d
LP
3317 if (r < 0)
3318 return r;
430fb8fa
LP
3319
3320 if (r == 0) {
3321 if (n_loop <= 1)
3322 return 0;
3323
fe1d424d 3324 return -ENXIO;
430fb8fa 3325 }
fe1d424d 3326
9a17484d
LP
3327 break;
3328 }
3329
3330 case SD_BUS_TYPE_ARRAY: {
3331 size_t k;
3332
3333 r = signature_element_length(t + 1, &k);
3334 if (r < 0)
3335 return r;
3336
3337 {
9a17484d 3338 char s[k + 1];
9a17484d
LP
3339 memcpy(s, t + 1, k);
3340 s[k] = 0;
9a17484d
LP
3341
3342 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
3343 if (r < 0)
3344 return r;
430fb8fa
LP
3345 if (r == 0) {
3346 if (n_loop <= 1)
3347 return 0;
3348
9a17484d 3349 return -ENXIO;
430fb8fa 3350 }
fe1d424d 3351 }
9a17484d 3352
fe1d424d
LP
3353 if (n_array == (unsigned) -1) {
3354 types += k;
3355 n_struct -= k;
9a17484d
LP
3356 }
3357
fe1d424d
LP
3358 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
3359 if (r < 0)
3360 return r;
3361
3362 types = t + 1;
3363 n_struct = k;
3364 n_array = va_arg(ap, unsigned);
3365
9a17484d
LP
3366 break;
3367 }
3368
3369 case SD_BUS_TYPE_VARIANT: {
3370 const char *s;
3371
3372 s = va_arg(ap, const char *);
3373 if (!s)
3374 return -EINVAL;
3375
3376 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
3377 if (r < 0)
3378 return r;
430fb8fa
LP
3379 if (r == 0) {
3380 if (n_loop <= 1)
3381 return 0;
3382
9a17484d 3383 return -ENXIO;
430fb8fa 3384 }
9a17484d 3385
fe1d424d 3386 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
9a17484d
LP
3387 if (r < 0)
3388 return r;
9a17484d 3389
fe1d424d
LP
3390 types = s;
3391 n_struct = strlen(s);
3392 n_array = (unsigned) -1;
3393
9a17484d
LP
3394 break;
3395 }
3396
3397 case SD_BUS_TYPE_STRUCT_BEGIN:
3398 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
3399 size_t k;
3400
3401 r = signature_element_length(t, &k);
3402 if (r < 0)
3403 return r;
3404
3405 {
3406 char s[k - 1];
3407 memcpy(s, t + 1, k - 2);
3408 s[k - 2] = 0;
3409
3410 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
3411 if (r < 0)
3412 return r;
430fb8fa
LP
3413 if (r == 0) {
3414 if (n_loop <= 1)
3415 return 0;
9a17484d 3416 return -ENXIO;
430fb8fa 3417 }
fe1d424d 3418 }
9a17484d 3419
fe1d424d
LP
3420 if (n_array == (unsigned) -1) {
3421 types += k - 1;
3422 n_struct -= k - 1;
3423 }
9a17484d 3424
fe1d424d
LP
3425 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
3426 if (r < 0)
3427 return r;
9a17484d 3428
fe1d424d
LP
3429 types = t + 1;
3430 n_struct = k - 2;
3431 n_array = (unsigned) -1;
9a17484d
LP
3432
3433 break;
3434 }
3435
3436 default:
fe1d424d 3437 return -EINVAL;
9a17484d 3438 }
9a17484d
LP
3439 }
3440
3441 return 1;
3442}
3443
3444int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
3445 va_list ap;
3446 int r;
3447
3448 if (!m)
3449 return -EINVAL;
3450 if (!m->sealed)
3451 return -EPERM;
3452 if (!types)
3453 return -EINVAL;
3454
3455 va_start(ap, types);
3456 r = message_read_ap(m, types, ap);
3457 va_end(ap);
3458
3459 return r;
3460}
3461
b3af9646
LP
3462int sd_bus_message_read_array(sd_bus_message *m, char type, const void **ptr, size_t *size) {
3463 struct bus_container *c;
3464 void *p;
3465 size_t sz;
3466 ssize_t align;
3467 int r;
3468
3469 if (!m)
3470 return -EINVAL;
3471 if (!m->sealed)
3472 return -EPERM;
3473 if (!bus_type_is_trivial(type))
3474 return -EINVAL;
3475 if (!ptr)
3476 return -EINVAL;
3477 if (!size)
3478 return -EINVAL;
3479 if (BUS_MESSAGE_NEED_BSWAP(m))
3480 return -ENOTSUP;
3481
3482 align = bus_type_get_alignment(type);
3483 if (align < 0)
3484 return align;
3485
3486 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
66b26c5c 3487 if (r <= 0)
b3af9646
LP
3488 return r;
3489
3490 c = message_get_container(m);
3491 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3492
3493 r = message_peek_body(m, &m->rindex, align, sz, &p);
3494 if (r < 0)
3495 goto fail;
3496 if (r == 0) {
3497 r = -EBADMSG;
3498 goto fail;
3499 }
3500
3501 r = sd_bus_message_exit_container(m);
3502 if (r < 0)
3503 goto fail;
3504
3505 *ptr = (const void*) p;
3506 *size = sz;
3507
3508 return 1;
3509
3510fail:
3511 message_quit_container(m);
3512 return r;
3513}
3514
80a46c73
LP
3515static int message_peek_fields(
3516 sd_bus_message *m,
3517 size_t *rindex,
3518 size_t align,
3519 size_t nbytes,
3520 void **ret) {
3521
3522 assert(m);
3523 assert(rindex);
3524 assert(align > 0);
3525
c91cb83c 3526 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
80a46c73
LP
3527}
3528
9f26c90c
LP
3529static int message_peek_field_uint32(
3530 sd_bus_message *m,
3531 size_t *ri,
3532 uint32_t *ret) {
3533
3534 int r;
3535 void *q;
3536
3537 assert(m);
3538 assert(ri);
3539
3540 r = message_peek_fields(m, ri, 4, 4, &q);
3541 if (r < 0)
3542 return r;
3543
3544 if (ret)
3545 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3546
3547 return 0;
3548}
3549
80a46c73
LP
3550static int message_peek_field_string(
3551 sd_bus_message *m,
6693860f 3552 bool (*validate)(const char *p),
80a46c73
LP
3553 size_t *ri,
3554 const char **ret) {
3555
9f26c90c 3556 uint32_t l;
80a46c73
LP
3557 int r;
3558 void *q;
3559
9a17484d 3560 assert(m);
80a46c73
LP
3561 assert(ri);
3562
9f26c90c 3563 r = message_peek_field_uint32(m, ri, &l);
80a46c73
LP
3564 if (r < 0)
3565 return r;
3566
80a46c73
LP
3567 r = message_peek_fields(m, ri, 1, l+1, &q);
3568 if (r < 0)
3569 return r;
9a17484d 3570
6693860f
LP
3571 if (validate) {
3572 if (!validate_nul(q, l))
3573 return -EBADMSG;
3574
3575 if (!validate(q))
ac89bf1d
LP
3576 return -EBADMSG;
3577 } else {
3578 if (!validate_string(q, l))
3579 return -EBADMSG;
3580 }
80a46c73
LP
3581
3582 if (ret)
3583 *ret = q;
3584
3585 return 0;
3586}
3587
3588static int message_peek_field_signature(
3589 sd_bus_message *m,
3590 size_t *ri,
3591 const char **ret) {
3592
3593 size_t l;
3594 int r;
3595 void *q;
3596
3597 assert(m);
3598 assert(ri);
3599
3600 r = message_peek_fields(m, ri, 1, 1, &q);
3601 if (r < 0)
3602 return r;
3603
3604 l = *(uint8_t*) q;
3605 r = message_peek_fields(m, ri, 1, l+1, &q);
3606 if (r < 0)
3607 return r;
3608
3609 if (!validate_signature(q, l))
3610 return -EBADMSG;
3611
3612 if (ret)
3613 *ret = q;
3614
3615 return 0;
3616}
3617
80a46c73
LP
3618static int message_skip_fields(
3619 sd_bus_message *m,
3620 size_t *ri,
3621 uint32_t array_size,
3622 const char **signature) {
3623
3624 size_t original_index;
3625 int r;
3626
3627 assert(m);
3628 assert(ri);
3629 assert(signature);
3630
3631 original_index = *ri;
3632
3633 for (;;) {
3634 char t;
80a46c73
LP
3635 size_t l;
3636
3637 if (array_size != (uint32_t) -1 &&
3638 array_size <= *ri - original_index)
3639 return 0;
3640
3641 t = **signature;
3642 if (!t)
3643 return 0;
3644
6693860f
LP
3645 if (t == SD_BUS_TYPE_STRING) {
3646
3647 r = message_peek_field_string(m, NULL, ri, NULL);
3648 if (r < 0)
3649 return r;
3650
3651 (*signature)++;
3652
3653 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
80a46c73 3654
6693860f 3655 r = message_peek_field_string(m, object_path_is_valid, ri, NULL);
80a46c73
LP
3656 if (r < 0)
3657 return r;
3658
3659 (*signature)++;
3660
3661 } else if (t == SD_BUS_TYPE_SIGNATURE) {
3662
3663 r = message_peek_field_signature(m, ri, NULL);
3664 if (r < 0)
3665 return r;
3666
3667 (*signature)++;
3668
3669 } else if (bus_type_is_basic(t)) {
27f6e5c7 3670 ssize_t align, k;
80a46c73 3671
c66a2e0c
TG
3672 align = bus_type_get_alignment(t);
3673 k = bus_type_get_size(t);
27f6e5c7 3674 assert(align > 0 && k > 0);
80a46c73
LP
3675
3676 r = message_peek_fields(m, ri, align, k, NULL);
3677 if (r < 0)
3678 return r;
9a17484d 3679
80a46c73
LP
3680 (*signature)++;
3681
3682 } else if (t == SD_BUS_TYPE_ARRAY) {
3683
3684 r = signature_element_length(*signature+1, &l);
3685 if (r < 0)
3686 return r;
3687
3688 assert(l >= 1);
3689 {
3690 char sig[l-1], *s;
9f26c90c 3691 uint32_t nas;
80a46c73
LP
3692 int alignment;
3693
3694 strncpy(sig, *signature + 1, l-1);
3695 s = sig;
3696
3697 alignment = bus_type_get_alignment(sig[0]);
3698 if (alignment < 0)
3699 return alignment;
3700
9f26c90c 3701 r = message_peek_field_uint32(m, ri, &nas);
80a46c73
LP
3702 if (r < 0)
3703 return r;
ac89bf1d 3704 if (nas > BUS_ARRAY_MAX_SIZE)
80a46c73
LP
3705 return -EBADMSG;
3706
3707 r = message_peek_fields(m, ri, alignment, 0, NULL);
3708 if (r < 0)
3709 return r;
3710
3711 r = message_skip_fields(m, ri, nas, (const char**) &s);
3712 if (r < 0)
3713 return r;
3714 }
3715
3716 (*signature) += 1 + l;
3717
3718 } else if (t == SD_BUS_TYPE_VARIANT) {
3719 const char *s;
3720
3721 r = message_peek_field_signature(m, ri, &s);
3722 if (r < 0)
3723 return r;
3724
3725 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
3726 if (r < 0)
3727 return r;
3728
3729 (*signature)++;
3730
3731 } else if (t == SD_BUS_TYPE_STRUCT ||
3732 t == SD_BUS_TYPE_DICT_ENTRY) {
3733
3734 r = signature_element_length(*signature, &l);
3735 if (r < 0)
3736 return r;
3737
3738 assert(l >= 2);
3739 {
3740 char sig[l-1], *s;
3741 strncpy(sig, *signature + 1, l-1);
3742 s = sig;
3743
3744 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
3745 if (r < 0)
3746 return r;
3747 }
3748
3749 *signature += l;
3750 } else
3751 return -EINVAL;
3752 }
3753}
3754
6629161f 3755int bus_message_parse_fields(sd_bus_message *m) {
80a46c73
LP
3756 size_t ri;
3757 int r;
2c93b4ef 3758 uint32_t unix_fds = 0;
80a46c73
LP
3759
3760 assert(m);
3761
3762 for (ri = 0; ri < BUS_MESSAGE_FIELDS_SIZE(m); ) {
3763 const char *signature;
3764 uint8_t *header;
3765
3766 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
3767 if (r < 0)
3768 return r;
3769
3770 r = message_peek_field_signature(m, &ri, &signature);
3771 if (r < 0)
3772 return r;
3773
3774 switch (*header) {
3775 case _SD_BUS_MESSAGE_HEADER_INVALID:
3776 return -EBADMSG;
3777
3778 case SD_BUS_MESSAGE_HEADER_PATH:
2c93b4ef
LP
3779
3780 if (m->path)
3781 return -EBADMSG;
3782
80a46c73
LP
3783 if (!streq(signature, "o"))
3784 return -EBADMSG;
3785
6693860f 3786 r = message_peek_field_string(m, object_path_is_valid, &ri, &m->path);
80a46c73
LP
3787 break;
3788
3789 case SD_BUS_MESSAGE_HEADER_INTERFACE:
2c93b4ef
LP
3790
3791 if (m->interface)
3792 return -EBADMSG;
3793
80a46c73
LP
3794 if (!streq(signature, "s"))
3795 return -EBADMSG;
3796
6693860f 3797 r = message_peek_field_string(m, interface_name_is_valid, &ri, &m->interface);
80a46c73
LP
3798 break;
3799
3800 case SD_BUS_MESSAGE_HEADER_MEMBER:
2c93b4ef
LP
3801
3802 if (m->member)
3803 return -EBADMSG;
3804
80a46c73
LP
3805 if (!streq(signature, "s"))
3806 return -EBADMSG;
3807
6693860f 3808 r = message_peek_field_string(m, member_name_is_valid, &ri, &m->member);
80a46c73
LP
3809 break;
3810
3811 case SD_BUS_MESSAGE_HEADER_ERROR_NAME:
2c93b4ef
LP
3812
3813 if (m->error.name)
3814 return -EBADMSG;
3815
80a46c73
LP
3816 if (!streq(signature, "s"))
3817 return -EBADMSG;
3818
6693860f 3819 r = message_peek_field_string(m, error_name_is_valid, &ri, &m->error.name);
80a46c73
LP
3820 break;
3821
3822 case SD_BUS_MESSAGE_HEADER_DESTINATION:
2c93b4ef
LP
3823
3824 if (m->destination)
3825 return -EBADMSG;
3826
80a46c73
LP
3827 if (!streq(signature, "s"))
3828 return -EBADMSG;
3829
6693860f 3830 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->destination);
80a46c73
LP
3831 break;
3832
3833 case SD_BUS_MESSAGE_HEADER_SENDER:
2c93b4ef
LP
3834
3835 if (m->sender)
3836 return -EBADMSG;
3837
80a46c73
LP
3838 if (!streq(signature, "s"))
3839 return -EBADMSG;
3840
6693860f 3841 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->sender);
80a46c73
LP
3842 break;
3843
3844
3845 case SD_BUS_MESSAGE_HEADER_SIGNATURE: {
3846 const char *s;
3847 char *c;
3848
2c93b4ef
LP
3849 if (m->root_container.signature)
3850 return -EBADMSG;
3851
80a46c73
LP
3852 if (!streq(signature, "g"))
3853 return -EBADMSG;
3854
3855 r = message_peek_field_signature(m, &ri, &s);
3856 if (r < 0)
3857 return r;
3858
3859 c = strdup(s);
3860 if (!c)
3861 return -ENOMEM;
3862
3863 free(m->root_container.signature);
3864 m->root_container.signature = c;
80a46c73
LP
3865 break;
3866 }
3867
3868 case SD_BUS_MESSAGE_HEADER_REPLY_SERIAL:
2c93b4ef
LP
3869 if (m->reply_serial != 0)
3870 return -EBADMSG;
3871
80a46c73
LP
3872 if (!streq(signature, "u"))
3873 return -EBADMSG;
3874
3875 r = message_peek_field_uint32(m, &ri, &m->reply_serial);
6693860f
LP
3876 if (r < 0)
3877 return r;
3878
3879 if (m->reply_serial == 0)
3880 return -EBADMSG;
3881
80a46c73
LP
3882 break;
3883
2c93b4ef
LP
3884 case SD_BUS_MESSAGE_HEADER_UNIX_FDS:
3885 if (unix_fds != 0)
3886 return -EBADMSG;
3887
3888 if (!streq(signature, "u"))
3889 return -EBADMSG;
3890
3891 r = message_peek_field_uint32(m, &ri, &unix_fds);
3892 if (r < 0)
3893 return -EBADMSG;
3894
3895 if (unix_fds == 0)
3896 return -EBADMSG;
3897
3898 break;
3899
80a46c73
LP
3900 default:
3901 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
3902 }
3903
3904 if (r < 0)
3905 return r;
3906 }
3907
2c93b4ef
LP
3908 if (m->n_fds != unix_fds)
3909 return -EBADMSG;
3910
80a46c73
LP
3911 if (isempty(m->root_container.signature) != (BUS_MESSAGE_BODY_SIZE(m) == 0))
3912 return -EBADMSG;
3913
3914 switch (m->header->type) {
3915
40ca29a1 3916 case SD_BUS_MESSAGE_SIGNAL:
80a46c73
LP
3917 if (!m->path || !m->interface || !m->member)
3918 return -EBADMSG;
3919 break;
3920
40ca29a1 3921 case SD_BUS_MESSAGE_METHOD_CALL:
80a46c73
LP
3922
3923 if (!m->path || !m->member)
3924 return -EBADMSG;
3925
3926 break;
3927
40ca29a1 3928 case SD_BUS_MESSAGE_METHOD_RETURN:
80a46c73
LP
3929
3930 if (m->reply_serial == 0)
3931 return -EBADMSG;
3932 break;
3933
40ca29a1 3934 case SD_BUS_MESSAGE_METHOD_ERROR:
80a46c73
LP
3935
3936 if (m->reply_serial == 0 || !m->error.name)
3937 return -EBADMSG;
3938 break;
3939 }
9a17484d 3940
89ffcd2a 3941 /* Try to read the error message, but if we can't it's a non-issue */
40ca29a1 3942 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
89ffcd2a
LP
3943 sd_bus_message_read(m, "s", &m->error.message);
3944
9a17484d
LP
3945 return 0;
3946}
3947
9a17484d 3948int bus_message_seal(sd_bus_message *m, uint64_t serial) {
47e6ce32 3949 struct bus_body_part *part;
69aec65c 3950 size_t l, a;
47e6ce32
LP
3951 unsigned i;
3952 int r;
9a17484d
LP
3953
3954 assert(m);
3955
3956 if (m->sealed)
3957 return -EPERM;
3958
3959 if (m->n_containers > 0)
3960 return -EBADMSG;
3961
13c299d3
LP
3962 if (m->poisoned)
3963 return -ESTALE;
3964
9a17484d
LP
3965 /* If there's a non-trivial signature set, then add it in here */
3966 if (!isempty(m->root_container.signature)) {
80a46c73 3967 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
9a17484d
LP
3968 if (r < 0)
3969 return r;
3970 }
3971
3972 if (m->n_fds > 0) {
3973 r = message_append_field_uint32(m, SD_BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
3974 if (r < 0)
3975 return r;
3976 }
3977
66b26c5c
LP
3978 /* Add padding at the end of the fields part, since we know
3979 * the body needs to start at an 8 byte alignment. We made
3980 * sure we allocated enough space for this, so all we need to
3981 * do here is to zero it out. */
69aec65c
LP
3982 l = BUS_MESSAGE_FIELDS_SIZE(m);
3983 a = ALIGN8(l) - l;
c91cb83c
LP
3984 if (a > 0)
3985 memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
69aec65c 3986
66b26c5c
LP
3987 /* If this is something we can send as memfd, then let's seal
3988 the memfd now. Note that we can send memfds as payload only
3989 for directed messages, and not for broadcasts. */
8f155917 3990 if (m->destination && m->bus && m->bus->use_memfd) {
66b26c5c 3991 MESSAGE_FOREACH_PART(part, i, m)
8f155917 3992 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
66b26c5c 3993 bus_body_part_unmap(part);
a392d361 3994
66b26c5c
LP
3995 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
3996 part->sealed = true;
3997 }
3998 }
47e6ce32 3999
9a17484d
LP
4000 m->header->serial = serial;
4001 m->sealed = true;
4002
9a17484d
LP
4003 return 0;
4004}
4005
4006int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
4007 if (!m)
4008 return -EINVAL;
4009 if (!destination)
4010 return -EINVAL;
4011 if (m->sealed)
4012 return -EPERM;
4013 if (m->destination)
4014 return -EEXIST;
4015
4016 return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
4017}
4018
c430fee6 4019int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
d8d3d8a7 4020 const char *u = NULL, *uu = NULL, *s = NULL;
77930f11 4021 char **cmdline = NULL;
9a17484d
LP
4022 unsigned level = 1;
4023 int r;
120f919e
LP
4024 uid_t owner, audit_loginuid;
4025 uint32_t audit_sessionid;
9a17484d
LP
4026
4027 assert(m);
4028
c430fee6
LP
4029 if (!f)
4030 f = stdout;
4031
4032 if (with_header) {
4033 fprintf(f,
4034 "Message %p\n"
4035 "\tn_ref=%u\n"
4036 "\tendian=%c\n"
4037 "\ttype=%i\n"
4038 "\tflags=%u\n"
4039 "\tversion=%u\n"
4040 "\tserial=%u\n"
4041 "\tfields_size=%u\n"
4042 "\tbody_size=%u\n"
4043 "\tpath=%s\n"
4044 "\tinterface=%s\n"
4045 "\tmember=%s\n"
4046 "\tdestination=%s\n"
4047 "\tsender=%s\n"
4048 "\tsignature=%s\n"
4049 "\treply_serial=%u\n"
c430fee6
LP
4050 "\tsealed=%s\n"
4051 "\tn_body_parts=%u\n",
4052 m,
4053 m->n_ref,
4054 m->header->endian,
4055 m->header->type,
4056 m->header->flags,
4057 m->header->version,
4058 BUS_MESSAGE_SERIAL(m),
4059 BUS_MESSAGE_FIELDS_SIZE(m),
4060 BUS_MESSAGE_BODY_SIZE(m),
4061 strna(m->path),
4062 strna(m->interface),
4063 strna(m->member),
4064 strna(m->destination),
4065 strna(m->sender),
4066 strna(m->root_container.signature),
4067 m->reply_serial,
c430fee6
LP
4068 yes_no(m->sealed),
4069 m->n_body_parts);
4070
3fc047f4
LP
4071 if (sd_bus_error_is_set(&m->error))
4072 fprintf(f,
4073 "\terror.name=%s\n"
4074 "\terror.message=%s\n",
4075 strna(m->error.name),
4076 strna(m->error.message));
4077
c430fee6
LP
4078 if (m->pid != 0)
4079 fprintf(f, "\tpid=%lu\n", (unsigned long) m->pid);
4080 if (m->tid != 0)
4081 fprintf(f, "\ttid=%lu\n", (unsigned long) m->tid);
4082 if (m->uid_valid)
4083 fprintf(f, "\tuid=%lu\n", (unsigned long) m->uid);
4084 if (m->gid_valid)
4085 fprintf(f, "\tgid=%lu\n", (unsigned long) m->gid);
4086 if (m->pid_starttime != 0)
4087 fprintf(f, "\tpid_starttime=%llu\n", (unsigned long long) m->pid_starttime);
4088 if (m->monotonic != 0)
4089 fprintf(f, "\tmonotonic=%llu\n", (unsigned long long) m->monotonic);
4090 if (m->realtime != 0)
4091 fprintf(f, "\trealtime=%llu\n", (unsigned long long) m->realtime);
4092 if (m->exe)
4093 fprintf(f, "\texe=[%s]\n", m->exe);
4094 if (m->comm)
4095 fprintf(f, "\tcomm=[%s]\n", m->comm);
4096 if (m->tid_comm)
4097 fprintf(f, "\ttid_comm=[%s]\n", m->tid_comm);
4098 if (m->label)
4099 fprintf(f, "\tlabel=[%s]\n", m->label);
4100 if (m->cgroup)
4101 fprintf(f, "\tcgroup=[%s]\n", m->cgroup);
4102
4103 sd_bus_message_get_unit(m, &u);
4104 if (u)
4105 fprintf(f, "\tunit=[%s]\n", u);
4106 sd_bus_message_get_user_unit(m, &uu);
4107 if (uu)
4108 fprintf(f, "\tuser_unit=[%s]\n", uu);
4109 sd_bus_message_get_session(m, &s);
4110 if (s)
4111 fprintf(f, "\tsession=[%s]\n", s);
4112 if (sd_bus_message_get_owner_uid(m, &owner) >= 0)
4113 fprintf(f, "\towner_uid=%lu\n", (unsigned long) owner);
4114 if (sd_bus_message_get_audit_loginuid(m, &audit_loginuid) >= 0)
4115 fprintf(f, "\taudit_loginuid=%lu\n", (unsigned long) audit_loginuid);
4116 if (sd_bus_message_get_audit_sessionid(m, &audit_sessionid) >= 0)
4117 fprintf(f, "\taudit_sessionid=%lu\n", (unsigned long) audit_sessionid);
4118
3fc047f4
LP
4119 r = sd_bus_message_has_effective_cap(m, 5);
4120 if (r >= 0)
4121 fprintf(f, "\tCAP_KILL=%s\n", yes_no(r));
c430fee6
LP
4122
4123 if (sd_bus_message_get_cmdline(m, &cmdline) >= 0) {
4124 char **c;
4125
4126 fputs("\tcmdline=[", f);
4127 STRV_FOREACH(c, cmdline) {
4128 if (c != cmdline)
4129 fputc(' ', f);
4130
4131 fputs(*c, f);
4132 }
77930f11 4133
c430fee6
LP
4134 fputs("]\n", f);
4135 }
77930f11
LP
4136 }
4137
9a17484d
LP
4138 r = sd_bus_message_rewind(m, true);
4139 if (r < 0) {
4140 log_error("Failed to rewind: %s", strerror(-r));
4141 return r;
4142 }
4143
c430fee6 4144 fprintf(f, "BEGIN_MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
9a17484d
LP
4145
4146 for(;;) {
4147 _cleanup_free_ char *prefix = NULL;
4148 const char *contents = NULL;
4149 char type;
4150 union {
4151 uint8_t u8;
4152 uint16_t u16;
4153 int16_t s16;
4154 uint32_t u32;
4155 int32_t s32;
4156 uint64_t u64;
4157 int64_t s64;
4158 double d64;
4159 const char *string;
4160 int i;
4161 } basic;
4162
4163 r = sd_bus_message_peek_type(m, &type, &contents);
4164 if (r < 0) {
4165 log_error("Failed to peek type: %s", strerror(-r));
4166 return r;
4167 }
4168 if (r == 0) {
4169 if (level <= 1)
4170 break;
4171
4172 r = sd_bus_message_exit_container(m);
4173 if (r < 0) {
4174 log_error("Failed to exit container: %s", strerror(-r));
4175 return r;
4176 }
4177
4178 level--;
4179
4180 prefix = strrep("\t", level);
4181 if (!prefix)
4182 return log_oom();
4183
4184 if (type == SD_BUS_TYPE_ARRAY)
c430fee6 4185 fprintf(f, "%s} END_ARRAY \n", prefix);
9a17484d 4186 else if (type == SD_BUS_TYPE_VARIANT)
c430fee6 4187 fprintf(f, "%s} END_VARIANT\n", prefix);
9a17484d 4188 else if (type == SD_BUS_TYPE_STRUCT)
c430fee6 4189 fprintf(f, "%s} END_STRUCT\n", prefix);
9a17484d 4190 else if (type == SD_BUS_TYPE_DICT_ENTRY)
c430fee6 4191 fprintf(f, "%s} END_DICT_ENTRY\n", prefix);
9a17484d
LP
4192
4193 continue;
4194 }
4195
4196 prefix = strrep("\t", level);
4197 if (!prefix)
4198 return log_oom();
4199
4200 if (bus_type_is_container(type) > 0) {
4201 r = sd_bus_message_enter_container(m, type, contents);
4202 if (r < 0) {
4203 log_error("Failed to enter container: %s", strerror(-r));
4204 return r;
4205 }
4206
4207 if (type == SD_BUS_TYPE_ARRAY)
c430fee6 4208 fprintf(f, "%sBEGIN_ARRAY \"%s\" {\n", prefix, contents);
9a17484d 4209 else if (type == SD_BUS_TYPE_VARIANT)
c430fee6 4210 fprintf(f, "%sBEGIN_VARIANT \"%s\" {\n", prefix, contents);
9a17484d 4211 else if (type == SD_BUS_TYPE_STRUCT)
c430fee6 4212 fprintf(f, "%sBEGIN_STRUCT \"%s\" {\n", prefix, contents);
9a17484d 4213 else if (type == SD_BUS_TYPE_DICT_ENTRY)
c430fee6 4214 fprintf(f, "%sBEGIN_DICT_ENTRY \"%s\" {\n", prefix, contents);
9a17484d
LP
4215
4216 level ++;
4217
4218 continue;
4219 }
4220
4221 r = sd_bus_message_read_basic(m, type, &basic);
4222 if (r < 0) {
4223 log_error("Failed to get basic: %s", strerror(-r));
4224 return r;
4225 }
4226
c430fee6
LP
4227 assert(r > 0);
4228
9a17484d
LP
4229 switch (type) {
4230
4231 case SD_BUS_TYPE_BYTE:
c430fee6 4232 fprintf(f, "%sBYTE: %u\n", prefix, basic.u8);
9a17484d
LP
4233 break;
4234
4235 case SD_BUS_TYPE_BOOLEAN:
c430fee6 4236 fprintf(f, "%sBOOLEAN: %s\n", prefix, yes_no(basic.i));
9a17484d
LP
4237 break;
4238
4239 case SD_BUS_TYPE_INT16:
c430fee6 4240 fprintf(f, "%sINT16: %i\n", prefix, basic.s16);
9a17484d
LP
4241 break;
4242
4243 case SD_BUS_TYPE_UINT16:
c430fee6 4244 fprintf(f, "%sUINT16: %u\n", prefix, basic.u16);
9a17484d
LP
4245 break;
4246
4247 case SD_BUS_TYPE_INT32:
c430fee6 4248 fprintf(f, "%sINT32: %i\n", prefix, basic.s32);
9a17484d
LP
4249 break;
4250
4251 case SD_BUS_TYPE_UINT32:
c430fee6 4252 fprintf(f, "%sUINT32: %u\n", prefix, basic.u32);
9a17484d
LP
4253 break;
4254
4255 case SD_BUS_TYPE_INT64:
c430fee6 4256 fprintf(f, "%sINT64: %lli\n", prefix, (long long) basic.s64);
9a17484d
LP
4257 break;
4258
4259 case SD_BUS_TYPE_UINT64:
c430fee6 4260 fprintf(f, "%sUINT64: %llu\n", prefix, (unsigned long long) basic.u64);
9a17484d
LP
4261 break;
4262
4263 case SD_BUS_TYPE_DOUBLE:
c430fee6 4264 fprintf(f, "%sDOUBLE: %g\n", prefix, basic.d64);
9a17484d
LP
4265 break;
4266
4267 case SD_BUS_TYPE_STRING:
c430fee6 4268 fprintf(f, "%sSTRING: \"%s\"\n", prefix, basic.string);
9a17484d
LP
4269 break;
4270
4271 case SD_BUS_TYPE_OBJECT_PATH:
c430fee6 4272 fprintf(f, "%sOBJECT_PATH: \"%s\"\n", prefix, basic.string);
9a17484d
LP
4273 break;
4274
4275 case SD_BUS_TYPE_SIGNATURE:
c430fee6 4276 fprintf(f, "%sSIGNATURE: \"%s\"\n", prefix, basic.string);
9a17484d
LP
4277 break;
4278
4279 case SD_BUS_TYPE_UNIX_FD:
c430fee6 4280 fprintf(f, "%sUNIX_FD: %i\n", prefix, basic.i);
9a17484d
LP
4281 break;
4282
4283 default:
4284 assert_not_reached("Unknown basic type.");
4285 }
4286 }
4287
c430fee6 4288 fprintf(f, "} END_MESSAGE\n");
9a17484d 4289 return 0;
de1c301e
LP
4290}
4291
4292int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
4293 size_t total;
de1c301e 4294 void *p, *e;
bc7fd8cd
LP
4295 unsigned i;
4296 struct bus_body_part *part;
de1c301e
LP
4297
4298 assert(m);
4299 assert(buffer);
4300 assert(sz);
4301
6629161f 4302 total = BUS_MESSAGE_SIZE(m);
de1c301e
LP
4303
4304 p = malloc(total);
4305 if (!p)
4306 return -ENOMEM;
4307
c91cb83c 4308 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
9b29bb68 4309 MESSAGE_FOREACH_PART(part, i, m)
bc7fd8cd 4310 e = mempcpy(e, part->data, part->size);
2100fa10
LP
4311
4312 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
de1c301e
LP
4313
4314 *buffer = p;
4315 *sz = total;
4316
4317 return 0;
4318}
89ffcd2a
LP
4319
4320int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
4321 int r;
4322
4323 assert(m);
4324 assert(l);
4325
4326 r = sd_bus_message_enter_container(m, 'a', "s");
4327 if (r < 0)
4328 return r;
4329
4330 for (;;) {
4331 const char *s;
4332
4333 r = sd_bus_message_read_basic(m, 's', &s);
4334 if (r < 0)
4335 return r;
4336 if (r == 0)
4337 break;
4338
4339 r = strv_extend(l, s);
4340 if (r < 0)
4341 return r;
4342 }
4343
4344 r = sd_bus_message_exit_container(m);
4345 if (r < 0)
4346 return r;
4347
4348 return 0;
4349}
392d5b37
LP
4350
4351const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
4352 int r;
42c5aaf3
LP
4353 const char *t = NULL;
4354 unsigned j;
392d5b37
LP
4355
4356 assert(m);
4357
4358 r = sd_bus_message_rewind(m, true);
4359 if (r < 0)
4360 return NULL;
4361
42c5aaf3
LP
4362 for (j = 0; j <= i; j++) {
4363 char type;
4364
392d5b37
LP
4365 r = sd_bus_message_peek_type(m, &type, NULL);
4366 if (r < 0)
4367 return NULL;
4368
4369 if (type != SD_BUS_TYPE_STRING &&
4370 type != SD_BUS_TYPE_OBJECT_PATH &&
4371 type != SD_BUS_TYPE_SIGNATURE)
4372 return NULL;
4373
4374 r = sd_bus_message_read_basic(m, type, &t);
4375 if (r < 0)
4376 return NULL;
392d5b37
LP
4377 }
4378
392d5b37
LP
4379 return t;
4380}
2100fa10 4381
c91cb83c
LP
4382bool bus_header_is_complete(struct bus_header *h, size_t size) {
4383 size_t full;
4384
4385 assert(h);
4386 assert(size);
4387
4388 if (size < sizeof(struct bus_header))
4389 return false;
4390
4391 full = sizeof(struct bus_header) +
4392 (h->endian == SD_BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
4393
4394 return size >= full;
4395}
4396
4397int bus_header_message_size(struct bus_header *h, size_t *sum) {
6629161f
LP
4398 size_t fs, bs;
4399
4400 assert(h);
4401 assert(sum);
4402
4403 if (h->endian == SD_BUS_NATIVE_ENDIAN) {
4404 fs = h->fields_size;
4405 bs = h->body_size;
4406 } else if (h->endian == SD_BUS_REVERSE_ENDIAN) {
4407 fs = bswap_32(h->fields_size);
4408 bs = bswap_32(h->body_size);
4409 } else
4410 return -EBADMSG;
2100fa10 4411
6629161f
LP
4412 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
4413 return 0;
2100fa10 4414}
eb01ba5d 4415
40ca29a1
LP
4416int sd_bus_message_get_errno(sd_bus_message *m) {
4417 assert_return(m, -EINVAL);
eb01ba5d 4418
40ca29a1 4419 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
eb01ba5d
LP
4420 return 0;
4421
40ca29a1 4422 return sd_bus_error_get_errno(&m->error);
eb01ba5d 4423}
29ddb38f 4424
40ca29a1 4425const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
29ddb38f
LP
4426 struct bus_container *c;
4427
4428 if (!m)
40ca29a1 4429 return NULL;
29ddb38f
LP
4430
4431 c = complete ? &m->root_container : message_get_container(m);
40ca29a1 4432 return c->signature ?: "";
29ddb38f 4433}
c430fee6
LP
4434
4435int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
4436 bool done_something = false;
4437 int r;
4438
80ba3b84
LP
4439 assert_return(m, -EINVAL);
4440 assert_return(source, -EINVAL);
4441 assert_return(!m->sealed, -EPERM);
4442 assert_return(source->sealed, -EPERM);
4443
c430fee6
LP
4444 do {
4445 const char *contents;
4446 char type;
4447 union {
4448 uint8_t u8;
4449 uint16_t u16;
4450 int16_t s16;
4451 uint32_t u32;
4452 int32_t s32;
4453 uint64_t u64;
4454 int64_t s64;
4455 double d64;
4456 const char *string;
4457 int i;
4458 } basic;
4459
4460 r = sd_bus_message_peek_type(source, &type, &contents);
4461 if (r < 0)
4462 return r;
4463 if (r == 0)
4464 break;
4465
4466 done_something = true;
4467
4468 if (bus_type_is_container(type) > 0) {
4469
4470 r = sd_bus_message_enter_container(source, type, contents);
4471 if (r < 0)
4472 return r;
4473
4474 r = sd_bus_message_open_container(m, type, contents);
4475 if (r < 0)
4476 return r;
4477
4478 r = sd_bus_message_copy(m, source, true);
4479 if (r < 0)
4480 return r;
4481
4482 r = sd_bus_message_close_container(m);
4483 if (r < 0)
4484 return r;
4485
4486 r = sd_bus_message_exit_container(source);
4487 if (r < 0)
4488 return r;
4489
4490 continue;
4491 }
4492
4493 r = sd_bus_message_read_basic(source, type, &basic);
4494 if (r < 0)
4495 return r;
4496
4497 assert(r > 0);
4498
4499 if (type == SD_BUS_TYPE_OBJECT_PATH ||
4500 type == SD_BUS_TYPE_SIGNATURE ||
4501 type == SD_BUS_TYPE_STRING)
4502 r = sd_bus_message_append_basic(m, type, basic.string);
4503 else
4504 r = sd_bus_message_append_basic(m, type, &basic);
4505
4506 if (r < 0)
4507 return r;
4508
4509 } while (all);
4510
4511 return done_something;
4512}
4513
4514int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
4515 const char *c;
4516 char t;
4517 int r;
4518
4519 assert_return(m, -EINVAL);
4520 assert_return(m->sealed, -EPERM);
4521 assert_return(!type || bus_type_is_valid(type), -EINVAL);
4522 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
4523 assert_return(type || contents, -EINVAL);
4524 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
4525
4526 r = sd_bus_message_peek_type(m, &t, &c);
4527 if (r <= 0)
4528 return r;
4529
4530 if (type != 0 && type != t)
4531 return 0;
4532
4533 if (contents && !streq_ptr(contents, c))
4534 return 0;
4535
4536 return 1;
4537}