1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
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.
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.
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/>.
29 #include "time-util.h"
30 #include "memfd-util.h"
33 #include "bus-message.h"
34 #include "bus-internal.h"
36 #include "bus-signature.h"
37 #include "bus-gvariant.h"
40 static int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
);
42 static void *adjust_pointer(const void *p
, void *old_base
, size_t sz
, void *new_base
) {
47 if (old_base
== new_base
)
50 if ((uint8_t*) p
< (uint8_t*) old_base
)
53 if ((uint8_t*) p
>= (uint8_t*) old_base
+ sz
)
56 return (uint8_t*) new_base
+ ((uint8_t*) p
- (uint8_t*) old_base
);
59 static void message_free_part(sd_bus_message
*m
, struct bus_body_part
*part
) {
63 if (part
->memfd
>= 0) {
64 /* If we can reuse the memfd, try that. For that it
65 * can't be sealed yet. */
68 assert(part
->memfd_offset
== 0);
69 assert(part
->data
== part
->mmap_begin
);
70 bus_kernel_push_memfd(m
->bus
, part
->memfd
, part
->data
, part
->mapped
, part
->allocated
);
73 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
75 safe_close(part
->memfd
);
78 } else if (part
->munmap_this
)
79 munmap(part
->mmap_begin
, part
->mapped
);
80 else if (part
->free_this
)
87 static void message_reset_parts(sd_bus_message
*m
) {
88 struct bus_body_part
*part
;
93 while (m
->n_body_parts
> 0) {
94 struct bus_body_part
*next
= part
->next
;
95 message_free_part(m
, part
);
102 m
->cached_rindex_part
= NULL
;
103 m
->cached_rindex_part_begin
= 0;
106 static void message_reset_containers(sd_bus_message
*m
) {
111 for (i
= 0; i
< m
->n_containers
; i
++) {
112 free(m
->containers
[i
].signature
);
113 free(m
->containers
[i
].offsets
);
116 m
->containers
= mfree(m
->containers
);
118 m
->n_containers
= m
->containers_allocated
= 0;
119 m
->root_container
.index
= 0;
122 static void message_free(sd_bus_message
*m
) {
128 message_reset_parts(m
);
130 if (m
->release_kdbus
)
131 bus_kernel_cmd_free(m
->bus
, (uint8_t *) m
->kdbus
- (uint8_t *) m
->bus
->kdbus_buffer
);
136 sd_bus_unref(m
->bus
);
139 close_many(m
->fds
, m
->n_fds
);
143 if (m
->iovec
!= m
->iovec_fixed
)
146 m
->destination_ptr
= mfree(m
->destination_ptr
);
147 message_reset_containers(m
);
148 free(m
->root_container
.signature
);
149 free(m
->root_container
.offsets
);
151 free(m
->root_container
.peeked_signature
);
153 bus_creds_done(&m
->creds
);
157 static void *message_extend_fields(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
159 size_t old_size
, new_size
, start
;
166 old_size
= sizeof(struct bus_header
) + m
->fields_size
;
167 start
= ALIGN_TO(old_size
, align
);
168 new_size
= start
+ sz
;
170 if (new_size
< start
||
171 new_size
> (size_t) ((uint32_t) -1))
174 if (old_size
== new_size
)
175 return (uint8_t*) m
->header
+ old_size
;
177 if (m
->free_header
) {
178 np
= realloc(m
->header
, ALIGN8(new_size
));
182 /* Initially, the header is allocated as part of of
183 * the sd_bus_message itself, let's replace it by
186 np
= malloc(ALIGN8(new_size
));
190 memcpy(np
, m
->header
, sizeof(struct bus_header
));
193 /* Zero out padding */
194 if (start
> old_size
)
195 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
199 m
->fields_size
= new_size
- sizeof(struct bus_header
);
201 /* Adjust quick access pointers */
202 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
203 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
204 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
205 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
206 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
207 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
209 m
->free_header
= true;
212 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
215 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
218 return (uint8_t*) np
+ start
;
225 static int message_append_field_string(
237 /* dbus1 only allows 8bit header field ids */
241 /* dbus1 doesn't allow strings over 32bit, let's enforce this
242 * globally, to not risk convertability */
244 if (l
> (size_t) (uint32_t) -1)
247 /* Signature "(yv)" where the variant contains "s" */
249 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
251 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
252 p
= message_extend_fields(m
, 8, 8 + l
+ 1 + 1 + 1, true);
256 *((uint64_t*) p
) = h
;
263 *ret
= (char*) p
+ 8;
266 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
267 p
= message_extend_fields(m
, 8, 4 + 4 + l
+ 1, false);
276 ((uint32_t*) p
)[1] = l
;
277 memcpy(p
+ 8, s
, l
+ 1);
280 *ret
= (char*) p
+ 8;
286 static int message_append_field_signature(
297 /* dbus1 only allows 8bit header field ids */
301 /* dbus1 doesn't allow signatures over 8bit, let's enforce
302 * this globally, to not risk convertability */
307 /* Signature "(yv)" where the variant contains "g" */
309 if (BUS_MESSAGE_IS_GVARIANT(m
))
310 /* For gvariant the serialization is the same as for normal strings */
311 return message_append_field_string(m
, h
, 'g', s
, ret
);
313 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
314 p
= message_extend_fields(m
, 8, 4 + 1 + l
+ 1, false);
320 p
[2] = SD_BUS_TYPE_SIGNATURE
;
323 memcpy(p
+ 5, s
, l
+ 1);
326 *ret
= (const char*) p
+ 5;
332 static int message_append_field_uint32(sd_bus_message
*m
, uint64_t h
, uint32_t x
) {
337 /* dbus1 only allows 8bit header field ids */
341 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
342 /* (field id 64bit + ((value + NUL + signature string 'u') */
344 p
= message_extend_fields(m
, 8, 8 + 4 + 1 + 1, true);
348 *((uint64_t*) p
) = h
;
349 *((uint32_t*) (p
+ 8)) = x
;
353 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
354 p
= message_extend_fields(m
, 8, 4 + 4, false);
363 ((uint32_t*) p
)[1] = x
;
369 static int message_append_field_uint64(sd_bus_message
*m
, uint64_t h
, uint64_t x
) {
374 /* dbus1 only allows 8bit header field ids */
378 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
379 /* (field id 64bit + ((value + NUL + signature string 't') */
381 p
= message_extend_fields(m
, 8, 8 + 8 + 1 + 1, true);
385 *((uint64_t*) p
) = h
;
386 *((uint64_t*) (p
+ 8)) = x
;
390 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
391 p
= message_extend_fields(m
, 8, 4 + 4 + 8, false);
404 ((uint64_t*) p
)[1] = x
;
410 static int message_append_reply_cookie(sd_bus_message
*m
, uint64_t cookie
) {
413 if (BUS_MESSAGE_IS_GVARIANT(m
))
414 return message_append_field_uint64(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, cookie
);
416 /* 64bit cookies are not supported on dbus1 */
417 if (cookie
> 0xffffffffUL
)
420 return message_append_field_uint32(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) cookie
);
424 int bus_message_from_header(
427 size_t header_accessible
,
429 size_t footer_accessible
,
435 sd_bus_message
**ret
) {
437 _cleanup_free_ sd_bus_message
*m
= NULL
;
438 struct bus_header
*h
;
442 assert(header
|| header_accessible
<= 0);
443 assert(footer
|| footer_accessible
<= 0);
444 assert(fds
|| n_fds
<= 0);
447 if (header_accessible
< sizeof(struct bus_header
))
450 if (header_accessible
> message_size
)
452 if (footer_accessible
> message_size
)
456 if (!IN_SET(h
->version
, 1, 2))
459 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
462 if (!IN_SET(h
->endian
, BUS_LITTLE_ENDIAN
, BUS_BIG_ENDIAN
))
465 /* Note that we are happy with unknown flags in the flags header! */
467 a
= ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
470 label_sz
= strlen(label
);
481 m
->header_accessible
= header_accessible
;
483 m
->footer_accessible
= footer_accessible
;
485 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
488 if (h
->dbus2
.cookie
== 0)
491 /* dbus2 derives the sizes from the message size and
492 the offset table at the end, since it is formatted as
493 gvariant "yyyyuta{tv}v". Since the message itself is a
494 structure with precisely to variable sized entries,
495 there's only one offset in the table, which marks the
496 end of the fields array. */
498 ws
= bus_gvariant_determine_word_size(message_size
, 0);
499 if (footer_accessible
< ws
)
502 m
->fields_size
= bus_gvariant_read_word_le((uint8_t*) footer
+ footer_accessible
- ws
, ws
);
503 if (ALIGN8(m
->fields_size
) > message_size
- ws
)
505 if (m
->fields_size
< sizeof(struct bus_header
))
508 m
->fields_size
-= sizeof(struct bus_header
);
509 m
->body_size
= message_size
- (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
));
511 if (h
->dbus1
.serial
== 0)
514 /* dbus1 has the sizes in the header */
515 m
->fields_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.fields_size
);
516 m
->body_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.body_size
);
518 if (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
!= message_size
)
526 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
527 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
529 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
532 m
->bus
= sd_bus_ref(bus
);
539 int bus_message_from_malloc(
546 sd_bus_message
**ret
) {
552 r
= bus_message_from_header(
554 buffer
, length
, /* in this case the initial bytes and the final bytes are the same */
563 sz
= length
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
);
566 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(m
->fields_size
);
568 m
->body
.sealed
= true;
573 m
->iovec
= m
->iovec_fixed
;
574 m
->iovec
[0].iov_base
= buffer
;
575 m
->iovec
[0].iov_len
= length
;
577 r
= bus_message_parse_fields(m
);
581 /* We take possession of the memory and fds now */
582 m
->free_header
= true;
593 static sd_bus_message
*message_new(sd_bus
*bus
, uint8_t type
) {
598 m
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
603 m
->header
= (struct bus_header
*) ((uint8_t*) m
+ ALIGN(sizeof(struct sd_bus_message
)));
604 m
->header
->endian
= BUS_NATIVE_ENDIAN
;
605 m
->header
->type
= type
;
606 m
->header
->version
= bus
->message_version
;
607 m
->allow_fds
= bus
->can_fds
|| (bus
->state
!= BUS_HELLO
&& bus
->state
!= BUS_RUNNING
);
608 m
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(m
);
609 m
->bus
= sd_bus_ref(bus
);
611 if (bus
->allow_interactive_authorization
)
612 m
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
617 _public_
int sd_bus_message_new_signal(
621 const char *interface
,
622 const char *member
) {
627 assert_return(bus
, -ENOTCONN
);
628 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
629 assert_return(object_path_is_valid(path
), -EINVAL
);
630 assert_return(interface_name_is_valid(interface
), -EINVAL
);
631 assert_return(member_name_is_valid(member
), -EINVAL
);
632 assert_return(m
, -EINVAL
);
634 t
= message_new(bus
, SD_BUS_MESSAGE_SIGNAL
);
638 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
640 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
643 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
646 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
654 sd_bus_message_unref(t
);
658 _public_
int sd_bus_message_new_method_call(
661 const char *destination
,
663 const char *interface
,
664 const char *member
) {
669 assert_return(bus
, -ENOTCONN
);
670 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
671 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
672 assert_return(object_path_is_valid(path
), -EINVAL
);
673 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
674 assert_return(member_name_is_valid(member
), -EINVAL
);
675 assert_return(m
, -EINVAL
);
677 t
= message_new(bus
, SD_BUS_MESSAGE_METHOD_CALL
);
681 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
684 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
689 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
695 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
708 static int message_new_reply(
709 sd_bus_message
*call
,
711 sd_bus_message
**m
) {
716 assert_return(call
, -EINVAL
);
717 assert_return(call
->sealed
, -EPERM
);
718 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
719 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
720 assert_return(m
, -EINVAL
);
722 t
= message_new(call
->bus
, type
);
726 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
727 t
->reply_cookie
= BUS_MESSAGE_COOKIE(call
);
728 if (t
->reply_cookie
== 0)
731 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
736 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
741 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
742 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
752 _public_
int sd_bus_message_new_method_return(
753 sd_bus_message
*call
,
754 sd_bus_message
**m
) {
756 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
759 _public_
int sd_bus_message_new_method_error(
760 sd_bus_message
*call
,
762 const sd_bus_error
*e
) {
767 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
768 assert_return(m
, -EINVAL
);
770 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
774 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
779 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
784 t
->error
._need_free
= -1;
794 _public_
int sd_bus_message_new_method_errorf(
795 sd_bus_message
*call
,
801 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
804 assert_return(name
, -EINVAL
);
805 assert_return(m
, -EINVAL
);
807 va_start(ap
, format
);
808 bus_error_setfv(&error
, name
, format
, ap
);
811 return sd_bus_message_new_method_error(call
, m
, &error
);
814 _public_
int sd_bus_message_new_method_errno(
815 sd_bus_message
*call
,
818 const sd_bus_error
*p
) {
820 _cleanup_bus_error_free_ sd_bus_error berror
= SD_BUS_ERROR_NULL
;
822 if (sd_bus_error_is_set(p
))
823 return sd_bus_message_new_method_error(call
, m
, p
);
825 sd_bus_error_set_errno(&berror
, error
);
827 return sd_bus_message_new_method_error(call
, m
, &berror
);
830 _public_
int sd_bus_message_new_method_errnof(
831 sd_bus_message
*call
,
837 _cleanup_bus_error_free_ sd_bus_error berror
= SD_BUS_ERROR_NULL
;
840 va_start(ap
, format
);
841 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
844 return sd_bus_message_new_method_error(call
, m
, &berror
);
847 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
851 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
852 m
->creds
.well_known_names_local
= true;
853 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
856 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
860 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
861 m
->creds
.well_known_names_driver
= true;
862 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
865 int bus_message_new_synthetic_error(
868 const sd_bus_error
*e
,
869 sd_bus_message
**m
) {
875 assert(sd_bus_error_is_set(e
));
878 t
= message_new(bus
, SD_BUS_MESSAGE_METHOD_ERROR
);
882 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
883 t
->reply_cookie
= cookie
;
885 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
889 if (bus
&& bus
->unique_name
) {
890 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
895 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
900 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
905 t
->error
._need_free
= -1;
907 bus_message_set_sender_driver(bus
, t
);
917 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
918 assert_return(m
, NULL
);
920 assert(m
->n_ref
> 0);
926 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
931 assert(m
->n_ref
> 0);
941 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
942 assert_return(m
, -EINVAL
);
943 assert_return(type
, -EINVAL
);
945 *type
= m
->header
->type
;
949 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
952 assert_return(m
, -EINVAL
);
953 assert_return(cookie
, -EINVAL
);
955 c
= BUS_MESSAGE_COOKIE(m
);
959 *cookie
= BUS_MESSAGE_COOKIE(m
);
963 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
964 assert_return(m
, -EINVAL
);
965 assert_return(cookie
, -EINVAL
);
967 if (m
->reply_cookie
== 0)
970 *cookie
= m
->reply_cookie
;
974 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
975 assert_return(m
, -EINVAL
);
977 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
978 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
981 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
982 assert_return(m
, -EINVAL
);
984 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
987 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
988 assert_return(m
, -EINVAL
);
990 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
991 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
994 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
995 assert_return(m
, NULL
);
1000 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
1001 assert_return(m
, NULL
);
1003 return m
->interface
;
1006 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
1007 assert_return(m
, NULL
);
1012 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
1013 assert_return(m
, NULL
);
1015 return m
->destination
;
1018 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
1019 assert_return(m
, NULL
);
1024 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
1025 assert_return(m
, NULL
);
1027 if (!sd_bus_error_is_set(&m
->error
))
1033 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
1034 assert_return(m
, -EINVAL
);
1035 assert_return(usec
, -EINVAL
);
1037 if (m
->monotonic
<= 0)
1040 *usec
= m
->monotonic
;
1044 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1045 assert_return(m
, -EINVAL
);
1046 assert_return(usec
, -EINVAL
);
1048 if (m
->realtime
<= 0)
1051 *usec
= m
->realtime
;
1055 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1056 assert_return(m
, -EINVAL
);
1057 assert_return(seqnum
, -EINVAL
);
1062 *seqnum
= m
->seqnum
;
1066 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1067 assert_return(m
, NULL
);
1069 if (m
->creds
.mask
== 0)
1075 _public_
int sd_bus_message_is_signal(
1077 const char *interface
,
1078 const char *member
) {
1080 assert_return(m
, -EINVAL
);
1082 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1085 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1088 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1094 _public_
int sd_bus_message_is_method_call(
1096 const char *interface
,
1097 const char *member
) {
1099 assert_return(m
, -EINVAL
);
1101 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1104 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1107 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1113 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1114 assert_return(m
, -EINVAL
);
1116 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1119 if (name
&& (!m
->error
.name
|| !streq(m
->error
.name
, name
)))
1125 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1126 assert_return(m
, -EINVAL
);
1127 assert_return(!m
->sealed
, -EPERM
);
1128 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1131 m
->header
->flags
&= ~BUS_MESSAGE_NO_REPLY_EXPECTED
;
1133 m
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
1138 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1139 assert_return(m
, -EINVAL
);
1140 assert_return(!m
->sealed
, -EPERM
);
1143 m
->header
->flags
&= ~BUS_MESSAGE_NO_AUTO_START
;
1145 m
->header
->flags
|= BUS_MESSAGE_NO_AUTO_START
;
1150 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1151 assert_return(m
, -EINVAL
);
1152 assert_return(!m
->sealed
, -EPERM
);
1155 m
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
1157 m
->header
->flags
&= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
1162 static struct bus_container
*message_get_container(sd_bus_message
*m
) {
1165 if (m
->n_containers
== 0)
1166 return &m
->root_container
;
1168 assert(m
->containers
);
1169 return m
->containers
+ m
->n_containers
- 1;
1172 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1173 struct bus_body_part
*part
;
1180 if (m
->n_body_parts
<= 0) {
1184 assert(m
->body_end
);
1186 part
= new0(struct bus_body_part
, 1);
1192 m
->body_end
->next
= part
;
1202 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1207 /* All other fields can be left in their defaults */
1208 assert(!part
->data
);
1209 assert(part
->memfd
< 0);
1212 part
->is_zero
= true;
1213 part
->sealed
= true;
1216 static int part_make_space(
1217 struct sd_bus_message
*m
,
1218 struct bus_body_part
*part
,
1227 assert(!part
->sealed
);
1232 if (!part
->data
&& part
->memfd
< 0) {
1233 part
->memfd
= bus_kernel_pop_memfd(m
->bus
, &part
->data
, &part
->mapped
, &part
->allocated
);
1234 part
->mmap_begin
= part
->data
;
1237 if (part
->memfd
>= 0) {
1239 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1240 uint64_t new_allocated
;
1242 new_allocated
= PAGE_ALIGN(sz
> 0 ? 2 * sz
: 1);
1243 r
= memfd_set_size(part
->memfd
, new_allocated
);
1249 part
->allocated
= new_allocated
;
1252 if (!part
->data
|| sz
> part
->mapped
) {
1255 psz
= PAGE_ALIGN(sz
> 0 ? sz
: 1);
1256 if (part
->mapped
<= 0)
1257 n
= mmap(NULL
, psz
, PROT_READ
|PROT_WRITE
, MAP_SHARED
, part
->memfd
, 0);
1259 n
= mremap(part
->mmap_begin
, part
->mapped
, psz
, MREMAP_MAYMOVE
);
1261 if (n
== MAP_FAILED
) {
1266 part
->mmap_begin
= part
->data
= n
;
1268 part
->memfd_offset
= 0;
1271 part
->munmap_this
= true;
1273 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1274 size_t new_allocated
;
1276 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1277 n
= realloc(part
->data
, new_allocated
);
1284 part
->allocated
= new_allocated
;
1285 part
->free_this
= true;
1290 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1296 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1297 struct bus_container
*c
;
1300 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1302 /* Add offset to current container, unless this is the first
1303 * item in it, which will have the 0 offset, which we can
1305 c
= message_get_container(m
);
1307 if (!c
->need_offsets
)
1310 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1313 c
->offsets
[c
->n_offsets
++] = offset
;
1317 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1318 struct bus_container
*c
;
1325 /* Update counters */
1326 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++) {
1329 *c
->array_size
+= expand
;
1333 static void *message_extend_body(
1338 bool force_inline
) {
1340 size_t start_body
, end_body
, padding
, added
;
1351 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1352 end_body
= start_body
+ sz
;
1354 padding
= start_body
- m
->body_size
;
1355 added
= padding
+ sz
;
1357 /* Check for 32bit overflows */
1358 if (end_body
> (size_t) ((uint32_t) -1) ||
1359 end_body
< start_body
) {
1365 struct bus_body_part
*part
= NULL
;
1369 m
->n_body_parts
<= 0 ||
1370 m
->body_end
->sealed
||
1371 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1372 (force_inline
&& m
->body_end
->size
> MEMFD_MIN_SIZE
); /* if this must be an inlined extension, let's create a new part if the previous part is large enough to be inlined */
1376 part
= message_append_part(m
);
1380 part_zero(part
, padding
);
1383 part
= message_append_part(m
);
1387 r
= part_make_space(m
, part
, sz
, &p
);
1391 struct bus_container
*c
;
1393 size_t os
, start_part
, end_part
;
1399 start_part
= ALIGN_TO(part
->size
, align
);
1400 end_part
= start_part
+ sz
;
1402 r
= part_make_space(m
, part
, end_part
, &p
);
1407 memzero(p
, padding
);
1408 p
= (uint8_t*) p
+ padding
;
1411 /* Readjust pointers */
1412 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1413 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1415 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1418 /* Return something that is not NULL and is aligned */
1419 p
= (uint8_t *) NULL
+ align
;
1421 m
->body_size
= end_body
;
1422 message_extend_containers(m
, added
);
1425 r
= message_add_offset(m
, end_body
);
1435 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1446 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1450 f
= realloc(m
->fds
, sizeof(int) * (m
->n_fds
+ 1));
1458 m
->fds
[m
->n_fds
] = copy
;
1464 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1465 _cleanup_close_
int fd
= -1;
1466 struct bus_container
*c
;
1470 assert_return(m
, -EINVAL
);
1471 assert_return(!m
->sealed
, -EPERM
);
1472 assert_return(bus_type_is_basic(type
), -EINVAL
);
1473 assert_return(!m
->poisoned
, -ESTALE
);
1475 c
= message_get_container(m
);
1477 if (c
->signature
&& c
->signature
[c
->index
]) {
1478 /* Container signature is already set */
1480 if (c
->signature
[c
->index
] != type
)
1485 /* Maybe we can append to the signature? But only if this is the top-level container */
1486 if (c
->enclosing
!= 0)
1489 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1496 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1502 case SD_BUS_TYPE_SIGNATURE
:
1503 case SD_BUS_TYPE_STRING
:
1506 /* Fall through... */
1507 case SD_BUS_TYPE_OBJECT_PATH
:
1515 case SD_BUS_TYPE_BOOLEAN
:
1517 u8
= p
&& *(int*) p
;
1523 case SD_BUS_TYPE_UNIX_FD
:
1528 fd
= message_push_fd(m
, *(int*) p
);
1539 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1540 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1547 a
= message_extend_body(m
, align
, sz
, true, false);
1554 *stored
= (const uint8_t*) a
;
1561 case SD_BUS_TYPE_STRING
:
1562 /* To make things easy we'll serialize a NULL string
1563 * into the empty string */
1566 /* Fall through... */
1567 case SD_BUS_TYPE_OBJECT_PATH
:
1573 sz
= 4 + strlen(p
) + 1;
1576 case SD_BUS_TYPE_SIGNATURE
:
1581 sz
= 1 + strlen(p
) + 1;
1584 case SD_BUS_TYPE_BOOLEAN
:
1586 u32
= p
&& *(int*) p
;
1592 case SD_BUS_TYPE_UNIX_FD
:
1597 fd
= message_push_fd(m
, *(int*) p
);
1608 align
= bus_type_get_alignment(type
);
1609 sz
= bus_type_get_size(type
);
1616 a
= message_extend_body(m
, align
, sz
, false, false);
1620 if (type
== SD_BUS_TYPE_STRING
|| type
== SD_BUS_TYPE_OBJECT_PATH
) {
1621 *(uint32_t*) a
= sz
- 5;
1622 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1625 *stored
= (const uint8_t*) a
+ 4;
1627 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1628 *(uint8_t*) a
= sz
- 2;
1629 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1632 *stored
= (const uint8_t*) a
+ 1;
1641 if (type
== SD_BUS_TYPE_UNIX_FD
)
1644 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1651 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1652 return message_append_basic(m
, type
, p
, NULL
);
1655 _public_
int sd_bus_message_append_string_space(
1660 struct bus_container
*c
;
1663 assert_return(m
, -EINVAL
);
1664 assert_return(s
, -EINVAL
);
1665 assert_return(!m
->sealed
, -EPERM
);
1666 assert_return(!m
->poisoned
, -ESTALE
);
1668 c
= message_get_container(m
);
1670 if (c
->signature
&& c
->signature
[c
->index
]) {
1671 /* Container signature is already set */
1673 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1678 /* Maybe we can append to the signature? But only if this is the top-level container */
1679 if (c
->enclosing
!= 0)
1682 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1689 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1690 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1696 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1700 *(uint32_t*) a
= size
;
1706 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1712 _public_
int sd_bus_message_append_string_iovec(
1714 const struct iovec
*iov
,
1722 assert_return(m
, -EINVAL
);
1723 assert_return(!m
->sealed
, -EPERM
);
1724 assert_return(iov
|| n
== 0, -EINVAL
);
1725 assert_return(!m
->poisoned
, -ESTALE
);
1727 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1729 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1733 for (i
= 0; i
< n
; i
++) {
1735 if (iov
[i
].iov_base
)
1736 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1738 memset(p
, ' ', iov
[i
].iov_len
);
1740 p
+= iov
[i
].iov_len
;
1746 static int bus_message_open_array(
1748 struct bus_container
*c
,
1749 const char *contents
,
1750 uint32_t **array_size
,
1752 bool *need_offsets
) {
1762 assert(need_offsets
);
1764 if (!signature_is_single(contents
, true))
1767 if (c
->signature
&& c
->signature
[c
->index
]) {
1769 /* Verify the existing signature */
1771 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1774 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1777 nindex
= c
->index
+ 1 + strlen(contents
);
1781 if (c
->enclosing
!= 0)
1784 /* Extend the existing signature */
1786 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1792 nindex
= e
- c
->signature
;
1795 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1796 alignment
= bus_gvariant_get_alignment(contents
);
1800 /* Add alignment padding and add to offset list */
1801 if (!message_extend_body(m
, alignment
, 0, false, false))
1804 r
= bus_gvariant_is_fixed_size(contents
);
1808 *begin
= m
->body_size
;
1809 *need_offsets
= r
== 0;
1813 struct bus_body_part
*o
;
1815 alignment
= bus_type_get_alignment(contents
[0]);
1819 a
= message_extend_body(m
, 4, 4, false, false);
1824 op
= m
->body_end
->data
;
1825 os
= m
->body_end
->size
;
1827 /* Add alignment between size and first element */
1828 if (!message_extend_body(m
, alignment
, 0, false, false))
1831 /* location of array size might have changed so let's readjust a */
1832 if (o
== m
->body_end
)
1833 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1839 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1845 static int bus_message_open_variant(
1847 struct bus_container
*c
,
1848 const char *contents
) {
1854 if (!signature_is_single(contents
, false))
1857 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1860 if (c
->signature
&& c
->signature
[c
->index
]) {
1862 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1868 if (c
->enclosing
!= 0)
1871 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1878 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1879 /* Variants are always aligned to 8 */
1881 if (!message_extend_body(m
, 8, 0, false, false))
1888 l
= strlen(contents
);
1889 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1894 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1897 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1903 static int bus_message_open_struct(
1905 struct bus_container
*c
,
1906 const char *contents
,
1908 bool *need_offsets
) {
1917 assert(need_offsets
);
1919 if (!signature_is_valid(contents
, false))
1922 if (c
->signature
&& c
->signature
[c
->index
]) {
1925 l
= strlen(contents
);
1927 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1928 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1929 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1932 nindex
= c
->index
+ 1 + l
+ 1;
1936 if (c
->enclosing
!= 0)
1939 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1945 nindex
= e
- c
->signature
;
1948 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1951 alignment
= bus_gvariant_get_alignment(contents
);
1955 if (!message_extend_body(m
, alignment
, 0, false, false))
1958 r
= bus_gvariant_is_fixed_size(contents
);
1962 *begin
= m
->body_size
;
1963 *need_offsets
= r
== 0;
1965 /* Align contents to 8 byte boundary */
1966 if (!message_extend_body(m
, 8, 0, false, false))
1970 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1976 static int bus_message_open_dict_entry(
1978 struct bus_container
*c
,
1979 const char *contents
,
1981 bool *need_offsets
) {
1989 assert(need_offsets
);
1991 if (!signature_is_pair(contents
))
1994 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1997 if (c
->signature
&& c
->signature
[c
->index
]) {
2000 l
= strlen(contents
);
2002 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
2003 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
2004 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
2009 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2012 alignment
= bus_gvariant_get_alignment(contents
);
2016 if (!message_extend_body(m
, alignment
, 0, false, false))
2019 r
= bus_gvariant_is_fixed_size(contents
);
2023 *begin
= m
->body_size
;
2024 *need_offsets
= r
== 0;
2026 /* Align contents to 8 byte boundary */
2027 if (!message_extend_body(m
, 8, 0, false, false))
2034 _public_
int sd_bus_message_open_container(
2037 const char *contents
) {
2039 struct bus_container
*c
, *w
;
2040 uint32_t *array_size
= NULL
;
2042 size_t before
, begin
= 0;
2043 bool need_offsets
= false;
2046 assert_return(m
, -EINVAL
);
2047 assert_return(!m
->sealed
, -EPERM
);
2048 assert_return(contents
, -EINVAL
);
2049 assert_return(!m
->poisoned
, -ESTALE
);
2051 /* Make sure we have space for one more container */
2052 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
2057 c
= message_get_container(m
);
2059 signature
= strdup(contents
);
2065 /* Save old index in the parent container, in case we have to
2066 * abort this container */
2067 c
->saved_index
= c
->index
;
2068 before
= m
->body_size
;
2070 if (type
== SD_BUS_TYPE_ARRAY
)
2071 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
2072 else if (type
== SD_BUS_TYPE_VARIANT
)
2073 r
= bus_message_open_variant(m
, c
, contents
);
2074 else if (type
== SD_BUS_TYPE_STRUCT
)
2075 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
2076 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
2077 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
2086 /* OK, let's fill it in */
2087 w
= m
->containers
+ m
->n_containers
++;
2088 w
->enclosing
= type
;
2089 w
->signature
= signature
;
2091 w
->array_size
= array_size
;
2094 w
->n_offsets
= w
->offsets_allocated
= 0;
2096 w
->need_offsets
= need_offsets
;
2101 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2106 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2109 if (c
->need_offsets
) {
2110 size_t payload
, sz
, i
;
2113 /* Variable-width arrays */
2115 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2116 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2118 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2122 for (i
= 0; i
< c
->n_offsets
; i
++)
2123 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2127 /* Fixed-width or empty arrays */
2129 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2137 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2143 assert(c
->signature
);
2145 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2148 l
= strlen(c
->signature
);
2150 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2155 memcpy(a
+1, c
->signature
, l
);
2160 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2161 bool fixed_size
= true;
2162 size_t n_variable
= 0;
2171 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2174 p
= strempty(c
->signature
);
2178 r
= signature_element_length(p
, &n
);
2187 r
= bus_gvariant_is_fixed_size(t
);
2192 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2194 /* We need to add an offset for each item that has a
2195 * variable size and that is not the last one in the
2199 if (r
== 0 && p
[n
] != 0)
2206 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2207 assert(c
->need_offsets
|| n_variable
== 0);
2209 if (isempty(c
->signature
)) {
2210 /* The unary type is encoded as fixed 1 byte padding */
2211 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2216 } else if (n_variable
<= 0) {
2219 /* Structures with fixed-size members only have to be
2220 * fixed-size themselves. But gvariant requires all fixed-size
2221 * elements to be sized a multiple of their alignment. Hence,
2222 * we must *always* add final padding after the last member so
2223 * the overall size of the structure is properly aligned. */
2225 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2227 assert(alignment
> 0);
2229 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2236 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2238 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2240 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2244 p
= strempty(c
->signature
);
2245 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2249 r
= signature_element_length(p
, &n
);
2260 r
= bus_gvariant_is_fixed_size(t
);
2263 if (r
> 0 || p
[0] == 0)
2267 k
= n_variable
- 1 - j
;
2269 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2278 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2279 struct bus_container
*c
;
2282 assert_return(m
, -EINVAL
);
2283 assert_return(!m
->sealed
, -EPERM
);
2284 assert_return(m
->n_containers
> 0, -EINVAL
);
2285 assert_return(!m
->poisoned
, -ESTALE
);
2287 c
= message_get_container(m
);
2289 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2290 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2295 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2296 r
= bus_message_close_array(m
, c
);
2297 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2298 r
= bus_message_close_variant(m
, c
);
2299 else if (c
->enclosing
== SD_BUS_TYPE_STRUCT
|| c
->enclosing
== SD_BUS_TYPE_DICT_ENTRY
)
2300 r
= bus_message_close_struct(m
, c
, true);
2302 assert_not_reached("Unknown container type");
2316 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2323 stack
[*i
].types
= types
;
2324 stack
[*i
].n_struct
= n_struct
;
2325 stack
[*i
].n_array
= n_array
;
2331 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2342 *types
= stack
[*i
].types
;
2343 *n_struct
= stack
[*i
].n_struct
;
2344 *n_array
= stack
[*i
].n_array
;
2349 int bus_message_append_ap(
2354 unsigned n_array
, n_struct
;
2355 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2356 unsigned stack_ptr
= 0;
2364 n_array
= (unsigned) -1;
2365 n_struct
= strlen(types
);
2370 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2371 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2377 r
= sd_bus_message_close_container(m
);
2385 if (n_array
!= (unsigned) -1)
2394 case SD_BUS_TYPE_BYTE
: {
2397 x
= (uint8_t) va_arg(ap
, int);
2398 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2402 case SD_BUS_TYPE_BOOLEAN
:
2403 case SD_BUS_TYPE_INT32
:
2404 case SD_BUS_TYPE_UINT32
:
2405 case SD_BUS_TYPE_UNIX_FD
: {
2408 /* We assume a boolean is the same as int32_t */
2409 assert_cc(sizeof(int32_t) == sizeof(int));
2411 x
= va_arg(ap
, uint32_t);
2412 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2416 case SD_BUS_TYPE_INT16
:
2417 case SD_BUS_TYPE_UINT16
: {
2420 x
= (uint16_t) va_arg(ap
, int);
2421 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2425 case SD_BUS_TYPE_INT64
:
2426 case SD_BUS_TYPE_UINT64
: {
2429 x
= va_arg(ap
, uint64_t);
2430 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2434 case SD_BUS_TYPE_DOUBLE
: {
2437 x
= va_arg(ap
, double);
2438 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2442 case SD_BUS_TYPE_STRING
:
2443 case SD_BUS_TYPE_OBJECT_PATH
:
2444 case SD_BUS_TYPE_SIGNATURE
: {
2447 x
= va_arg(ap
, const char*);
2448 r
= sd_bus_message_append_basic(m
, *t
, x
);
2452 case SD_BUS_TYPE_ARRAY
: {
2455 r
= signature_element_length(t
+ 1, &k
);
2461 memcpy(s
, t
+ 1, k
);
2464 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2469 if (n_array
== (unsigned) -1) {
2474 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2480 n_array
= va_arg(ap
, unsigned);
2485 case SD_BUS_TYPE_VARIANT
: {
2488 s
= va_arg(ap
, const char*);
2492 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2496 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2501 n_struct
= strlen(s
);
2502 n_array
= (unsigned) -1;
2507 case SD_BUS_TYPE_STRUCT_BEGIN
:
2508 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2511 r
= signature_element_length(t
, &k
);
2518 memcpy(s
, t
+ 1, k
- 2);
2521 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2526 if (n_array
== (unsigned) -1) {
2531 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2537 n_array
= (unsigned) -1;
2553 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2557 assert_return(m
, -EINVAL
);
2558 assert_return(types
, -EINVAL
);
2559 assert_return(!m
->sealed
, -EPERM
);
2560 assert_return(!m
->poisoned
, -ESTALE
);
2562 va_start(ap
, types
);
2563 r
= bus_message_append_ap(m
, types
, ap
);
2569 _public_
int sd_bus_message_append_array_space(
2579 assert_return(m
, -EINVAL
);
2580 assert_return(!m
->sealed
, -EPERM
);
2581 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2582 assert_return(ptr
|| size
== 0, -EINVAL
);
2583 assert_return(!m
->poisoned
, -ESTALE
);
2585 /* alignment and size of the trivial types (except bool) is
2586 * identical for gvariant and dbus1 marshalling */
2587 align
= bus_type_get_alignment(type
);
2588 sz
= bus_type_get_size(type
);
2590 assert_se(align
> 0);
2596 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2600 a
= message_extend_body(m
, align
, size
, false, false);
2604 r
= sd_bus_message_close_container(m
);
2612 _public_
int sd_bus_message_append_array(
2620 assert_return(m
, -EINVAL
);
2621 assert_return(!m
->sealed
, -EPERM
);
2622 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2623 assert_return(ptr
|| size
== 0, -EINVAL
);
2624 assert_return(!m
->poisoned
, -ESTALE
);
2626 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2631 memcpy(p
, ptr
, size
);
2636 _public_
int sd_bus_message_append_array_iovec(
2639 const struct iovec
*iov
,
2647 assert_return(m
, -EINVAL
);
2648 assert_return(!m
->sealed
, -EPERM
);
2649 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2650 assert_return(iov
|| n
== 0, -EINVAL
);
2651 assert_return(!m
->poisoned
, -ESTALE
);
2653 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2655 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2659 for (i
= 0; i
< n
; i
++) {
2661 if (iov
[i
].iov_base
)
2662 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2664 memzero(p
, iov
[i
].iov_len
);
2666 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2672 _public_
int sd_bus_message_append_array_memfd(
2679 _cleanup_close_
int copy_fd
= -1;
2680 struct bus_body_part
*part
;
2686 assert_return(m
, -EINVAL
);
2687 assert_return(memfd
>= 0, -EBADF
);
2688 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2689 assert_return(size
> 0, -EINVAL
);
2690 assert_return(!m
->sealed
, -EPERM
);
2691 assert_return(!m
->poisoned
, -ESTALE
);
2693 r
= memfd_set_sealed(memfd
);
2697 copy_fd
= dup(memfd
);
2701 r
= memfd_get_size(memfd
, &real_size
);
2705 if (offset
== 0 && size
== (uint64_t) -1)
2707 else if (offset
+ size
> real_size
)
2710 align
= bus_type_get_alignment(type
);
2711 sz
= bus_type_get_size(type
);
2713 assert_se(align
> 0);
2716 if (offset
% align
!= 0)
2722 if (size
> (uint64_t) (uint32_t) -1)
2725 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2729 a
= message_extend_body(m
, align
, 0, false, false);
2733 part
= message_append_part(m
);
2737 part
->memfd
= copy_fd
;
2738 part
->memfd_offset
= offset
;
2739 part
->sealed
= true;
2743 m
->body_size
+= size
;
2744 message_extend_containers(m
, size
);
2746 return sd_bus_message_close_container(m
);
2749 _public_
int sd_bus_message_append_string_memfd(
2755 _cleanup_close_
int copy_fd
= -1;
2756 struct bus_body_part
*part
;
2757 struct bus_container
*c
;
2762 assert_return(m
, -EINVAL
);
2763 assert_return(memfd
>= 0, -EBADF
);
2764 assert_return(size
> 0, -EINVAL
);
2765 assert_return(!m
->sealed
, -EPERM
);
2766 assert_return(!m
->poisoned
, -ESTALE
);
2768 r
= memfd_set_sealed(memfd
);
2772 copy_fd
= dup(memfd
);
2776 r
= memfd_get_size(memfd
, &real_size
);
2780 if (offset
== 0 && size
== (uint64_t) -1)
2782 else if (offset
+ size
> real_size
)
2785 /* We require this to be NUL terminated */
2789 if (size
> (uint64_t) (uint32_t) -1)
2792 c
= message_get_container(m
);
2793 if (c
->signature
&& c
->signature
[c
->index
]) {
2794 /* Container signature is already set */
2796 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2801 /* Maybe we can append to the signature? But only if this is the top-level container */
2802 if (c
->enclosing
!= 0)
2805 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2812 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2813 a
= message_extend_body(m
, 4, 4, false, false);
2817 *(uint32_t*) a
= size
- 1;
2820 part
= message_append_part(m
);
2824 part
->memfd
= copy_fd
;
2825 part
->memfd_offset
= offset
;
2826 part
->sealed
= true;
2830 m
->body_size
+= size
;
2831 message_extend_containers(m
, size
);
2833 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2834 r
= message_add_offset(m
, m
->body_size
);
2841 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2847 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2851 assert_return(m
, -EINVAL
);
2852 assert_return(!m
->sealed
, -EPERM
);
2853 assert_return(!m
->poisoned
, -ESTALE
);
2855 r
= sd_bus_message_open_container(m
, 'a', "s");
2859 STRV_FOREACH(i
, l
) {
2860 r
= sd_bus_message_append_basic(m
, 's', *i
);
2865 return sd_bus_message_close_container(m
);
2868 static int bus_message_close_header(sd_bus_message
*m
) {
2872 /* The actual user data is finished now, we just complete the
2873 variant and struct now (at least on gvariant). Remember
2874 this position, so that during parsing we know where to to
2875 put the outer container end. */
2876 m
->user_body_size
= m
->body_size
;
2878 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2879 const char *signature
;
2883 /* Add offset table to end of fields array */
2884 if (m
->n_header_offsets
>= 1) {
2888 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2890 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2891 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2895 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2896 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2899 /* Add gvariant NUL byte plus signature to the end of
2900 * the body, followed by the final offset pointing to
2901 * the end of the fields array */
2903 signature
= strempty(m
->root_container
.signature
);
2904 l
= strlen(signature
);
2906 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2907 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2912 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2913 memcpy((uint8_t*) d
+ 2, signature
, l
);
2914 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2916 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2919 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2921 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2922 m
->header
->dbus1
.body_size
= m
->body_size
;
2928 int bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, usec_t timeout
) {
2929 struct bus_body_part
*part
;
2939 if (m
->n_containers
> 0)
2945 if (cookie
> 0xffffffffULL
&&
2946 !BUS_MESSAGE_IS_GVARIANT(m
))
2949 /* In vtables the return signature of method calls is listed,
2950 * let's check if they match if this is a response */
2951 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2952 m
->enforced_reply_signature
&&
2953 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2956 /* If gvariant marshalling is used we need to close the body structure */
2957 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2961 /* If there's a non-trivial signature set, then add it in
2962 * here, but only on dbus1 */
2963 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2964 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2970 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2975 r
= bus_message_close_header(m
);
2979 if (BUS_MESSAGE_IS_GVARIANT(m
))
2980 m
->header
->dbus2
.cookie
= cookie
;
2982 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2984 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout
;
2986 /* Add padding at the end of the fields part, since we know
2987 * the body needs to start at an 8 byte alignment. We made
2988 * sure we allocated enough space for this, so all we need to
2989 * do here is to zero it out. */
2990 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2992 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2994 /* If this is something we can send as memfd, then let's seal
2995 the memfd now. Note that we can send memfds as payload only
2996 for directed messages, and not for broadcasts. */
2997 if (m
->destination
&& m
->bus
->use_memfd
) {
2998 MESSAGE_FOREACH_PART(part
, i
, m
)
2999 if (part
->memfd
>= 0 &&
3001 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
3002 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
3005 /* Try to seal it if that makes
3006 * sense. First, unmap our own map to
3007 * make sure we don't keep it busy. */
3008 bus_body_part_unmap(part
);
3010 /* Then, sync up real memfd size */
3012 r
= memfd_set_size(part
->memfd
, sz
);
3016 /* Finally, try to seal */
3017 if (memfd_set_sealed(part
->memfd
) >= 0)
3018 part
->sealed
= true;
3022 m
->root_container
.end
= m
->user_body_size
;
3023 m
->root_container
.index
= 0;
3024 m
->root_container
.offset_index
= 0;
3025 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
3032 int bus_body_part_map(struct bus_body_part
*part
) {
3041 if (part
->size
<= 0)
3044 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3045 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
3046 static const uint8_t zeroes
[7] = { };
3047 part
->data
= (void*) zeroes
;
3051 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
3052 psz
= PAGE_ALIGN(part
->size
+ shift
);
3054 if (part
->memfd
>= 0)
3055 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
3056 else if (part
->is_zero
)
3057 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
3061 if (p
== MAP_FAILED
)
3065 part
->mmap_begin
= p
;
3066 part
->data
= (uint8_t*) p
+ shift
;
3067 part
->munmap_this
= true;
3072 void bus_body_part_unmap(struct bus_body_part
*part
) {
3076 if (part
->memfd
< 0)
3079 if (!part
->mmap_begin
)
3082 if (!part
->munmap_this
)
3085 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
3087 part
->mmap_begin
= NULL
;
3090 part
->munmap_this
= false;
3095 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3096 size_t k
, start
, end
;
3101 start
= ALIGN_TO((size_t) *rindex
, align
);
3102 end
= start
+ nbytes
;
3107 /* Verify that padding is 0 */
3108 for (k
= *rindex
; k
< start
; k
++)
3109 if (((const uint8_t*) p
)[k
] != 0)
3113 *r
= (uint8_t*) p
+ start
;
3120 static bool message_end_of_signature(sd_bus_message
*m
) {
3121 struct bus_container
*c
;
3125 c
= message_get_container(m
);
3126 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3129 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3130 struct bus_container
*c
;
3134 c
= message_get_container(m
);
3135 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3138 if (BUS_MESSAGE_IS_GVARIANT(m
))
3139 return index
>= c
->end
;
3141 assert(c
->array_size
);
3142 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3146 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3147 assert_return(m
, -EINVAL
);
3148 assert_return(m
->sealed
, -EPERM
);
3150 if (complete
&& m
->n_containers
> 0)
3153 if (message_end_of_signature(m
))
3156 if (message_end_of_array(m
, m
->rindex
))
3162 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3163 struct bus_body_part
*part
;
3169 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3170 part
= m
->cached_rindex_part
;
3171 begin
= m
->cached_rindex_part_begin
;
3181 if (index
+ sz
<= begin
+ part
->size
) {
3183 r
= bus_body_part_map(part
);
3188 *p
= (uint8_t*) part
->data
+ index
- begin
;
3190 m
->cached_rindex_part
= part
;
3191 m
->cached_rindex_part_begin
= begin
;
3196 begin
+= part
->size
;
3203 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3210 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3213 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3216 sz
= bus_gvariant_get_size(c
->signature
);
3220 if (c
->offset_index
+1 >= c
->n_offsets
)
3223 /* Variable-size array */
3225 alignment
= bus_gvariant_get_alignment(c
->signature
);
3226 assert(alignment
> 0);
3228 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3229 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3232 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3235 /* Fixed-size array */
3236 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3242 } else if (c
->enclosing
== 0 ||
3243 c
->enclosing
== SD_BUS_TYPE_STRUCT
||
3244 c
->enclosing
== SD_BUS_TYPE_DICT_ENTRY
) {
3249 if (c
->offset_index
+1 >= c
->n_offsets
)
3252 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3256 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3261 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3264 alignment
= bus_gvariant_get_alignment(t
);
3267 assert(alignment
> 0);
3269 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3270 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3274 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3277 assert_not_reached("Unknown container type");
3282 /* Reached the end */
3289 static int message_peek_body(
3296 size_t k
, start
, end
, padding
;
3297 struct bus_body_part
*part
;
3304 start
= ALIGN_TO((size_t) *rindex
, align
);
3305 padding
= start
- *rindex
;
3306 end
= start
+ nbytes
;
3308 if (end
> m
->user_body_size
)
3311 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3316 /* Verify padding */
3317 for (k
= 0; k
< padding
; k
++)
3322 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3323 if (!part
|| (nbytes
> 0 && !q
))
3334 static bool validate_nul(const char *s
, size_t l
) {
3336 /* Check for NUL chars in the string */
3337 if (memchr(s
, 0, l
))
3340 /* Check for NUL termination */
3347 static bool validate_string(const char *s
, size_t l
) {
3349 if (!validate_nul(s
, l
))
3352 /* Check if valid UTF8 */
3353 if (!utf8_is_valid(s
))
3359 static bool validate_signature(const char *s
, size_t l
) {
3361 if (!validate_nul(s
, l
))
3364 /* Check if valid signature */
3365 if (!signature_is_valid(s
, true))
3371 static bool validate_object_path(const char *s
, size_t l
) {
3373 if (!validate_nul(s
, l
))
3376 if (!object_path_is_valid(s
))
3382 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3383 struct bus_container
*c
;
3388 assert_return(m
, -EINVAL
);
3389 assert_return(m
->sealed
, -EPERM
);
3390 assert_return(bus_type_is_basic(type
), -EINVAL
);
3392 if (message_end_of_signature(m
))
3395 if (message_end_of_array(m
, m
->rindex
))
3398 c
= message_get_container(m
);
3399 if (c
->signature
[c
->index
] != type
)
3404 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3406 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3409 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3413 if (type
== SD_BUS_TYPE_STRING
)
3414 ok
= validate_string(q
, c
->item_size
-1);
3415 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3416 ok
= validate_object_path(q
, c
->item_size
-1);
3418 ok
= validate_signature(q
, c
->item_size
-1);
3424 *(const char**) p
= q
;
3428 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3430 if ((size_t) sz
!= c
->item_size
)
3433 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3436 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3442 case SD_BUS_TYPE_BYTE
:
3444 *(uint8_t*) p
= *(uint8_t*) q
;
3447 case SD_BUS_TYPE_BOOLEAN
:
3449 *(int*) p
= !!*(uint8_t*) q
;
3452 case SD_BUS_TYPE_INT16
:
3453 case SD_BUS_TYPE_UINT16
:
3455 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3458 case SD_BUS_TYPE_INT32
:
3459 case SD_BUS_TYPE_UINT32
:
3461 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3464 case SD_BUS_TYPE_INT64
:
3465 case SD_BUS_TYPE_UINT64
:
3466 case SD_BUS_TYPE_DOUBLE
:
3468 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3471 case SD_BUS_TYPE_UNIX_FD
: {
3474 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3479 *(int*) p
= m
->fds
[j
];
3485 assert_not_reached("unexpected type");
3489 r
= container_next_item(m
, c
, &rindex
);
3494 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3498 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3502 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3503 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3507 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3508 ok
= validate_object_path(q
, l
);
3510 ok
= validate_string(q
, l
);
3515 *(const char**) p
= q
;
3517 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3520 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3525 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3529 if (!validate_signature(q
, l
))
3533 *(const char**) p
= q
;
3538 align
= bus_type_get_alignment(type
);
3541 sz
= bus_type_get_size(type
);
3544 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3550 case SD_BUS_TYPE_BYTE
:
3552 *(uint8_t*) p
= *(uint8_t*) q
;
3555 case SD_BUS_TYPE_BOOLEAN
:
3557 *(int*) p
= !!*(uint32_t*) q
;
3560 case SD_BUS_TYPE_INT16
:
3561 case SD_BUS_TYPE_UINT16
:
3563 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3566 case SD_BUS_TYPE_INT32
:
3567 case SD_BUS_TYPE_UINT32
:
3569 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3572 case SD_BUS_TYPE_INT64
:
3573 case SD_BUS_TYPE_UINT64
:
3574 case SD_BUS_TYPE_DOUBLE
:
3576 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3579 case SD_BUS_TYPE_UNIX_FD
: {
3582 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3587 *(int*) p
= m
->fds
[j
];
3592 assert_not_reached("Unknown basic type...");
3599 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3605 static int bus_message_enter_array(
3607 struct bus_container
*c
,
3608 const char *contents
,
3609 uint32_t **array_size
,
3612 size_t *n_offsets
) {
3626 if (!signature_is_single(contents
, true))
3629 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3632 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3635 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3640 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3643 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3647 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3650 alignment
= bus_type_get_alignment(contents
[0]);
3654 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3658 *array_size
= (uint32_t*) q
;
3660 } else if (c
->item_size
<= 0) {
3662 /* gvariant: empty array */
3667 } else if (bus_gvariant_is_fixed_size(contents
)) {
3669 /* gvariant: fixed length array */
3670 *item_size
= bus_gvariant_get_size(contents
);
3675 size_t where
, p
= 0, framing
, sz
;
3678 /* gvariant: variable length array */
3679 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3681 where
= rindex
+ c
->item_size
- sz
;
3682 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3686 framing
= bus_gvariant_read_word_le(q
, sz
);
3687 if (framing
> c
->item_size
- sz
)
3689 if ((c
->item_size
- framing
) % sz
!= 0)
3692 *n_offsets
= (c
->item_size
- framing
) / sz
;
3694 where
= rindex
+ framing
;
3695 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3699 *offsets
= new(size_t, *n_offsets
);
3703 for (i
= 0; i
< *n_offsets
; i
++) {
3706 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3707 if (x
> c
->item_size
- sz
)
3712 (*offsets
)[i
] = rindex
+ x
;
3716 *item_size
= (*offsets
)[0] - rindex
;
3721 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3722 c
->index
+= 1 + strlen(contents
);
3727 static int bus_message_enter_variant(
3729 struct bus_container
*c
,
3730 const char *contents
,
3731 size_t *item_size
) {
3743 if (!signature_is_single(contents
, false))
3746 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3749 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3752 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3757 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3760 k
= strlen(contents
);
3761 if (1+k
> c
->item_size
)
3764 where
= rindex
+ c
->item_size
- (1+k
);
3765 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3769 if (*(char*) q
!= 0)
3772 if (memcmp((uint8_t*) q
+1, contents
, k
))
3775 *item_size
= c
->item_size
- (1+k
);
3778 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3783 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3787 if (!validate_signature(q
, l
))
3790 if (!streq(q
, contents
))
3796 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3802 static int build_struct_offsets(
3804 const char *signature
,
3808 size_t *n_offsets
) {
3810 unsigned n_variable
= 0, n_total
= 0, v
;
3811 size_t previous
= 0, where
;
3822 if (isempty(signature
)) {
3823 /* Unary type is encoded as *fixed* 1 byte padding */
3824 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3828 if (*(uint8_t *) q
!= 0)
3837 sz
= bus_gvariant_determine_word_size(size
, 0);
3841 /* First, loop over signature and count variable elements and
3842 * elements in general. We use this to know how large the
3843 * offset array is at the end of the structure. Note that
3844 * GVariant only stores offsets for all variable size elements
3845 * that are not the last item. */
3851 r
= signature_element_length(p
, &n
);
3860 r
= bus_gvariant_is_fixed_size(t
);
3865 if (r
== 0 && p
[n
] != 0) /* except the last item */
3872 if (size
< n_variable
* sz
)
3875 where
= m
->rindex
+ size
- (n_variable
* sz
);
3876 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3882 *offsets
= new(size_t, n_total
);
3888 /* Second, loop again and build an offset table */
3894 r
= signature_element_length(p
, &n
);
3903 k
= bus_gvariant_get_size(t
);
3911 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3914 if (m
->rindex
+ x
< previous
)
3917 /* The last item's end
3918 * is determined from
3921 x
= size
- (n_variable
* sz
);
3923 offset
= m
->rindex
+ x
;
3929 align
= bus_gvariant_get_alignment(t
);
3932 offset
= (*n_offsets
== 0 ? m
->rindex
: ALIGN_TO((*offsets
)[*n_offsets
-1], align
)) + k
;
3936 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3941 assert(*n_offsets
== n_total
);
3943 *item_size
= (*offsets
)[0] - m
->rindex
;
3947 static int enter_struct_or_dict_entry(
3949 struct bus_container
*c
,
3950 const char *contents
,
3953 size_t *n_offsets
) {
3964 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3967 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3972 /* gvariant with contents */
3973 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3978 static int bus_message_enter_struct(
3980 struct bus_container
*c
,
3981 const char *contents
,
3984 size_t *n_offsets
) {
3996 if (!signature_is_valid(contents
, false))
3999 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4002 l
= strlen(contents
);
4004 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
4005 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4006 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
4009 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4013 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4014 c
->index
+= 1 + l
+ 1;
4019 static int bus_message_enter_dict_entry(
4021 struct bus_container
*c
,
4022 const char *contents
,
4025 size_t *n_offsets
) {
4034 if (!signature_is_pair(contents
))
4037 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4040 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4043 l
= strlen(contents
);
4045 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
4046 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4047 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
4050 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4054 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4055 c
->index
+= 1 + l
+ 1;
4060 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
4062 const char *contents
) {
4063 struct bus_container
*c
, *w
;
4064 uint32_t *array_size
= NULL
;
4067 size_t *offsets
= NULL
;
4068 size_t n_offsets
= 0, item_size
= 0;
4071 assert_return(m
, -EINVAL
);
4072 assert_return(m
->sealed
, -EPERM
);
4073 assert_return(type
!= 0 || !contents
, -EINVAL
);
4075 if (type
== 0 || !contents
) {
4079 /* Allow entering into anonymous containers */
4080 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
4084 if (type
!= 0 && type
!= tt
)
4087 if (contents
&& !streq(contents
, cc
))
4095 * We enforce a global limit on container depth, that is much
4096 * higher than the 32 structs and 32 arrays the specification
4097 * mandates. This is simpler to implement for us, and we need
4098 * this only to ensure our container array doesn't grow
4099 * without bounds. We are happy to return any data from a
4100 * message as long as the data itself is valid, even if the
4101 * overall message might be not.
4103 * Note that the message signature is validated when
4104 * parsing the headers, and that validation does check the
4107 * Note that the specification defines no limits on the depth
4108 * of stacked variants, but we do.
4110 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4113 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4116 if (message_end_of_signature(m
))
4119 if (message_end_of_array(m
, m
->rindex
))
4122 c
= message_get_container(m
);
4124 signature
= strdup(contents
);
4128 c
->saved_index
= c
->index
;
4131 if (type
== SD_BUS_TYPE_ARRAY
)
4132 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4133 else if (type
== SD_BUS_TYPE_VARIANT
)
4134 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4135 else if (type
== SD_BUS_TYPE_STRUCT
)
4136 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4137 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4138 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4148 /* OK, let's fill it in */
4149 w
= m
->containers
+ m
->n_containers
++;
4150 w
->enclosing
= type
;
4151 w
->signature
= signature
;
4152 w
->peeked_signature
= NULL
;
4156 w
->begin
= m
->rindex
;
4158 /* Unary type has fixed size of 1, but virtual size of 0 */
4159 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4160 type
== SD_BUS_TYPE_STRUCT
&&
4162 w
->end
= m
->rindex
+ 0;
4164 w
->end
= m
->rindex
+ c
->item_size
;
4166 w
->array_size
= array_size
;
4167 w
->item_size
= item_size
;
4168 w
->offsets
= offsets
;
4169 w
->n_offsets
= n_offsets
;
4170 w
->offset_index
= 0;
4175 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4176 struct bus_container
*c
;
4180 assert_return(m
, -EINVAL
);
4181 assert_return(m
->sealed
, -EPERM
);
4182 assert_return(m
->n_containers
> 0, -ENXIO
);
4184 c
= message_get_container(m
);
4186 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4187 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4191 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4192 if (m
->rindex
< c
->end
)
4195 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4198 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4199 if (c
->begin
+ l
!= m
->rindex
)
4204 free(c
->peeked_signature
);
4208 c
= message_get_container(m
);
4211 c
->index
= c
->saved_index
;
4212 r
= container_next_item(m
, c
, &m
->rindex
);
4220 static void message_quit_container(sd_bus_message
*m
) {
4221 struct bus_container
*c
;
4225 assert(m
->n_containers
> 0);
4227 c
= message_get_container(m
);
4230 assert(m
->rindex
>= c
->before
);
4231 m
->rindex
= c
->before
;
4233 /* Free container */
4238 /* Correct index of new top-level container */
4239 c
= message_get_container(m
);
4240 c
->index
= c
->saved_index
;
4243 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4244 struct bus_container
*c
;
4247 assert_return(m
, -EINVAL
);
4248 assert_return(m
->sealed
, -EPERM
);
4250 if (message_end_of_signature(m
))
4253 if (message_end_of_array(m
, m
->rindex
))
4256 c
= message_get_container(m
);
4258 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4262 *type
= c
->signature
[c
->index
];
4266 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4272 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4278 sig
= strndup(c
->signature
+ c
->index
+ 1, l
);
4282 free(c
->peeked_signature
);
4283 *contents
= c
->peeked_signature
= sig
;
4287 *type
= SD_BUS_TYPE_ARRAY
;
4292 if (c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
||
4293 c
->signature
[c
->index
] == SD_BUS_TYPE_DICT_ENTRY_BEGIN
) {
4299 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4304 sig
= strndup(c
->signature
+ c
->index
+ 1, l
- 2);
4308 free(c
->peeked_signature
);
4309 *contents
= c
->peeked_signature
= sig
;
4313 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4318 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4322 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4325 if (c
->item_size
< 2)
4328 /* Look for the NUL delimiter that
4329 separates the payload from the
4330 signature. Since the body might be
4331 in a different part that then the
4332 signature we map byte by byte. */
4334 for (k
= 2; k
<= c
->item_size
; k
++) {
4337 where
= m
->rindex
+ c
->item_size
- k
;
4338 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4342 if (*(char*) q
== 0)
4346 if (k
> c
->item_size
)
4349 free(c
->peeked_signature
);
4350 c
->peeked_signature
= strndup((char*) q
+ 1, k
- 1);
4351 if (!c
->peeked_signature
)
4354 if (!signature_is_valid(c
->peeked_signature
, true))
4357 *contents
= c
->peeked_signature
;
4362 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4367 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4371 if (!validate_signature(q
, l
))
4379 *type
= SD_BUS_TYPE_VARIANT
;
4394 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4395 struct bus_container
*c
;
4397 assert_return(m
, -EINVAL
);
4398 assert_return(m
->sealed
, -EPERM
);
4401 message_reset_containers(m
);
4404 c
= message_get_container(m
);
4406 c
= message_get_container(m
);
4408 c
->offset_index
= 0;
4410 m
->rindex
= c
->begin
;
4413 c
->offset_index
= 0;
4414 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4416 return !isempty(c
->signature
);
4419 static int message_read_ap(
4424 unsigned n_array
, n_struct
;
4425 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4426 unsigned stack_ptr
= 0;
4427 unsigned n_loop
= 0;
4435 /* Ideally, we'd just call ourselves recursively on every
4436 * complex type. However, the state of a va_list that is
4437 * passed to a function is undefined after that function
4438 * returns. This means we need to docode the va_list linearly
4439 * in a single stackframe. We hence implement our own
4440 * home-grown stack in an array. */
4442 n_array
= (unsigned) -1; /* length of current array entries */
4443 n_struct
= strlen(types
); /* length of current struct contents signature */
4450 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4451 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4457 r
= sd_bus_message_exit_container(m
);
4465 if (n_array
!= (unsigned) -1)
4474 case SD_BUS_TYPE_BYTE
:
4475 case SD_BUS_TYPE_BOOLEAN
:
4476 case SD_BUS_TYPE_INT16
:
4477 case SD_BUS_TYPE_UINT16
:
4478 case SD_BUS_TYPE_INT32
:
4479 case SD_BUS_TYPE_UINT32
:
4480 case SD_BUS_TYPE_INT64
:
4481 case SD_BUS_TYPE_UINT64
:
4482 case SD_BUS_TYPE_DOUBLE
:
4483 case SD_BUS_TYPE_STRING
:
4484 case SD_BUS_TYPE_OBJECT_PATH
:
4485 case SD_BUS_TYPE_SIGNATURE
:
4486 case SD_BUS_TYPE_UNIX_FD
: {
4489 p
= va_arg(ap
, void*);
4490 r
= sd_bus_message_read_basic(m
, *t
, p
);
4503 case SD_BUS_TYPE_ARRAY
: {
4506 r
= signature_element_length(t
+ 1, &k
);
4512 memcpy(s
, t
+ 1, k
);
4515 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4526 if (n_array
== (unsigned) -1) {
4531 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4537 n_array
= va_arg(ap
, unsigned);
4542 case SD_BUS_TYPE_VARIANT
: {
4545 s
= va_arg(ap
, const char *);
4549 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4559 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4564 n_struct
= strlen(s
);
4565 n_array
= (unsigned) -1;
4570 case SD_BUS_TYPE_STRUCT_BEGIN
:
4571 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4574 r
= signature_element_length(t
, &k
);
4580 memcpy(s
, t
+ 1, k
- 2);
4583 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4593 if (n_array
== (unsigned) -1) {
4598 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4604 n_array
= (unsigned) -1;
4617 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4621 assert_return(m
, -EINVAL
);
4622 assert_return(m
->sealed
, -EPERM
);
4623 assert_return(types
, -EINVAL
);
4625 va_start(ap
, types
);
4626 r
= message_read_ap(m
, types
, ap
);
4632 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4635 assert_return(m
, -EINVAL
);
4636 assert_return(m
->sealed
, -EPERM
);
4638 /* If types is NULL, read exactly one element */
4640 struct bus_container
*c
;
4643 if (message_end_of_signature(m
))
4646 if (message_end_of_array(m
, m
->rindex
))
4649 c
= message_get_container(m
);
4651 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4655 types
= strndupa(c
->signature
+ c
->index
, l
);
4660 case 0: /* Nothing to drop */
4663 case SD_BUS_TYPE_BYTE
:
4664 case SD_BUS_TYPE_BOOLEAN
:
4665 case SD_BUS_TYPE_INT16
:
4666 case SD_BUS_TYPE_UINT16
:
4667 case SD_BUS_TYPE_INT32
:
4668 case SD_BUS_TYPE_UINT32
:
4669 case SD_BUS_TYPE_INT64
:
4670 case SD_BUS_TYPE_UINT64
:
4671 case SD_BUS_TYPE_DOUBLE
:
4672 case SD_BUS_TYPE_STRING
:
4673 case SD_BUS_TYPE_OBJECT_PATH
:
4674 case SD_BUS_TYPE_SIGNATURE
:
4675 case SD_BUS_TYPE_UNIX_FD
:
4677 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4681 r
= sd_bus_message_skip(m
, types
+ 1);
4687 case SD_BUS_TYPE_ARRAY
: {
4690 r
= signature_element_length(types
+ 1, &k
);
4696 memcpy(s
, types
+1, k
);
4699 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4704 r
= sd_bus_message_skip(m
, s
);
4711 r
= sd_bus_message_exit_container(m
);
4716 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4723 case SD_BUS_TYPE_VARIANT
: {
4724 const char *contents
;
4727 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4731 if (x
!= SD_BUS_TYPE_VARIANT
)
4734 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4738 r
= sd_bus_message_skip(m
, contents
);
4743 r
= sd_bus_message_exit_container(m
);
4747 r
= sd_bus_message_skip(m
, types
+ 1);
4754 case SD_BUS_TYPE_STRUCT_BEGIN
:
4755 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4758 r
= signature_element_length(types
, &k
);
4764 memcpy(s
, types
+1, k
-2);
4767 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4771 r
= sd_bus_message_skip(m
, s
);
4775 r
= sd_bus_message_exit_container(m
);
4780 r
= sd_bus_message_skip(m
, types
+ k
);
4792 _public_
int sd_bus_message_read_array(
4798 struct bus_container
*c
;
4804 assert_return(m
, -EINVAL
);
4805 assert_return(m
->sealed
, -EPERM
);
4806 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4807 assert_return(ptr
, -EINVAL
);
4808 assert_return(size
, -EINVAL
);
4809 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4811 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4815 c
= message_get_container(m
);
4817 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4818 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4822 sz
= c
->end
- c
->begin
;
4824 align
= bus_type_get_alignment(type
);
4828 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4832 /* Zero length array, let's return some aligned
4833 * pointer that is not NULL */
4834 p
= (uint8_t*) NULL
+ align
;
4836 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4841 r
= sd_bus_message_exit_container(m
);
4845 *ptr
= (const void*) p
;
4851 message_quit_container(m
);
4855 static int message_peek_fields(
4866 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4869 static int message_peek_field_uint32(
4881 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4884 /* identical for gvariant and dbus1 */
4886 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4891 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4896 static int message_peek_field_uint64(
4908 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4911 /* identical for gvariant and dbus1 */
4913 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4918 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4923 static int message_peek_field_string(
4925 bool (*validate
)(const char *p
),
4937 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4942 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4948 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4952 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4958 if (!validate_nul(q
, l
))
4964 if (!validate_string(q
, l
))
4974 static int message_peek_field_signature(
4987 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4992 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4998 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
5003 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
5008 if (!validate_signature(q
, l
))
5017 static int message_skip_fields(
5020 uint32_t array_size
,
5021 const char **signature
) {
5023 size_t original_index
;
5029 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
5031 original_index
= *ri
;
5037 if (array_size
!= (uint32_t) -1 &&
5038 array_size
<= *ri
- original_index
)
5045 if (t
== SD_BUS_TYPE_STRING
) {
5047 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
5053 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
5055 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
5061 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
5063 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
5069 } else if (bus_type_is_basic(t
)) {
5072 align
= bus_type_get_alignment(t
);
5073 k
= bus_type_get_size(t
);
5074 assert(align
> 0 && k
> 0);
5076 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
5082 } else if (t
== SD_BUS_TYPE_ARRAY
) {
5084 r
= signature_element_length(*signature
+1, &l
);
5094 strncpy(sig
, *signature
+ 1, l
-1);
5097 alignment
= bus_type_get_alignment(sig
[0]);
5101 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5104 if (nas
> BUS_ARRAY_MAX_SIZE
)
5107 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5111 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5116 (*signature
) += 1 + l
;
5118 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5121 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5125 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5131 } else if (t
== SD_BUS_TYPE_STRUCT
||
5132 t
== SD_BUS_TYPE_DICT_ENTRY
) {
5134 r
= signature_element_length(*signature
, &l
);
5141 strncpy(sig
, *signature
+ 1, l
-1);
5144 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5155 int bus_message_parse_fields(sd_bus_message
*m
) {
5158 uint32_t unix_fds
= 0;
5159 bool unix_fds_set
= false;
5160 void *offsets
= NULL
;
5161 unsigned n_offsets
= 0;
5167 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5170 /* Read the signature from the end of the body variant first */
5171 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5172 if (m
->footer_accessible
< 1 + sz
)
5175 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5177 if (p
< (char*) m
->footer
)
5184 /* We found the beginning of the signature
5185 * string, yay! We require the body to be a
5186 * structure, so verify it and then strip the
5187 * opening/closing brackets. */
5189 l
= ((char*) m
->footer
+ m
->footer_accessible
) - p
- (1 + sz
);
5191 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5192 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5195 c
= strndup(p
+ 1 + 1, l
- 2);
5199 free(m
->root_container
.signature
);
5200 m
->root_container
.signature
= c
;
5207 /* Calculate the actual user body size, by removing
5208 * the trailing variant signature and struct offset
5210 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5212 /* Pull out the offset table for the fields array */
5213 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5218 ri
= m
->fields_size
- sz
;
5219 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5223 framing
= bus_gvariant_read_word_le(q
, sz
);
5224 if (framing
>= m
->fields_size
- sz
)
5226 if ((m
->fields_size
- framing
) % sz
!= 0)
5230 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5234 n_offsets
= (m
->fields_size
- framing
) / sz
;
5237 m
->user_body_size
= m
->body_size
;
5240 while (ri
< m
->fields_size
) {
5241 _cleanup_free_
char *sig
= NULL
;
5242 const char *signature
;
5243 uint64_t field_type
;
5244 size_t item_size
= (size_t) -1;
5246 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5255 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5257 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5261 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5265 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5272 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5277 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5282 where
= ri
= ALIGN_TO(ri
, 8);
5283 item_size
= end
- ri
;
5284 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5288 b
= memrchr(q
, 0, item_size
);
5292 sig
= strndup(b
+1, item_size
- (b
+1-(char*) q
));
5297 item_size
= b
- (char*) q
;
5299 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5304 switch (field_type
) {
5306 case _BUS_MESSAGE_HEADER_INVALID
:
5309 case BUS_MESSAGE_HEADER_PATH
:
5314 if (!streq(signature
, "o"))
5317 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5320 case BUS_MESSAGE_HEADER_INTERFACE
:
5325 if (!streq(signature
, "s"))
5328 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5331 case BUS_MESSAGE_HEADER_MEMBER
:
5336 if (!streq(signature
, "s"))
5339 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5342 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5347 if (!streq(signature
, "s"))
5350 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5352 m
->error
._need_free
= -1;
5356 case BUS_MESSAGE_HEADER_DESTINATION
:
5361 if (!streq(signature
, "s"))
5364 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5367 case BUS_MESSAGE_HEADER_SENDER
:
5372 if (!streq(signature
, "s"))
5375 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5377 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
&& !m
->bus
->is_kernel
) {
5378 m
->creds
.unique_name
= (char*) m
->sender
;
5379 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5385 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5389 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5392 if (m
->root_container
.signature
)
5395 if (!streq(signature
, "g"))
5398 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5406 free(m
->root_container
.signature
);
5407 m
->root_container
.signature
= c
;
5411 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5413 if (m
->reply_cookie
!= 0)
5416 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5417 /* 64bit on dbus2 */
5419 if (!streq(signature
, "t"))
5422 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5426 /* 32bit on dbus1 */
5429 if (!streq(signature
, "u"))
5432 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5436 m
->reply_cookie
= serial
;
5439 if (m
->reply_cookie
== 0)
5444 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5448 if (!streq(signature
, "u"))
5451 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5455 unix_fds_set
= true;
5459 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5460 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5469 if (m
->n_fds
!= unix_fds
)
5472 switch (m
->header
->type
) {
5474 case SD_BUS_MESSAGE_SIGNAL
:
5475 if (!m
->path
|| !m
->interface
|| !m
->member
)
5478 if (m
->reply_cookie
!= 0)
5483 case SD_BUS_MESSAGE_METHOD_CALL
:
5485 if (!m
->path
|| !m
->member
)
5488 if (m
->reply_cookie
!= 0)
5493 case SD_BUS_MESSAGE_METHOD_RETURN
:
5495 if (m
->reply_cookie
== 0)
5499 case SD_BUS_MESSAGE_METHOD_ERROR
:
5501 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5506 /* Refuse non-local messages that claim they are local */
5507 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5509 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5511 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5514 m
->root_container
.end
= m
->user_body_size
;
5516 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5517 r
= build_struct_offsets(
5519 m
->root_container
.signature
,
5521 &m
->root_container
.item_size
,
5522 &m
->root_container
.offsets
,
5523 &m
->root_container
.n_offsets
);
5528 /* Try to read the error message, but if we can't it's a non-issue */
5529 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5530 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5535 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5536 assert_return(m
, -EINVAL
);
5537 assert_return(destination
, -EINVAL
);
5538 assert_return(!m
->sealed
, -EPERM
);
5539 assert_return(!m
->destination
, -EEXIST
);
5541 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5544 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5548 struct bus_body_part
*part
;
5554 total
= BUS_MESSAGE_SIZE(m
);
5560 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5561 MESSAGE_FOREACH_PART(part
, i
, m
)
5562 e
= mempcpy(e
, part
->data
, part
->size
);
5564 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5572 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5579 r
= sd_bus_message_enter_container(m
, 'a', "s");
5583 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5584 r
= strv_extend(l
, s
);
5591 r
= sd_bus_message_exit_container(m
);
5598 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5602 assert_return(m
, -EINVAL
);
5603 assert_return(m
->sealed
, -EPERM
);
5604 assert_return(l
, -EINVAL
);
5606 r
= bus_message_read_strv_extend(m
, &strv
);
5616 static int bus_message_get_arg_skip(
5620 const char **_contents
) {
5625 r
= sd_bus_message_rewind(m
, true);
5630 const char *contents
;
5633 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5639 /* Don't match against arguments after the first one we don't understand */
5640 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5641 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5646 *_contents
= contents
;
5652 r
= sd_bus_message_skip(m
, NULL
);
5659 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5666 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5670 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5673 return sd_bus_message_read_basic(m
, type
, str
);
5676 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5677 const char *contents
;
5684 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5688 if (type
!= SD_BUS_TYPE_ARRAY
)
5690 if (!STR_IN_SET(contents
, "s", "o", "g"))
5693 return sd_bus_message_read_strv(m
, strv
);
5696 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5697 assert_return(m
, EINVAL
);
5699 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5702 return sd_bus_error_get_errno(&m
->error
);
5705 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5706 struct bus_container
*c
;
5708 assert_return(m
, NULL
);
5710 c
= complete
? &m
->root_container
: message_get_container(m
);
5711 return strempty(c
->signature
);
5714 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5715 assert_return(m
, -EINVAL
);
5717 return isempty(m
->root_container
.signature
);
5720 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5721 assert_return(m
, -EINVAL
);
5723 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5726 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5727 bool done_something
= false;
5730 assert_return(m
, -EINVAL
);
5731 assert_return(source
, -EINVAL
);
5732 assert_return(!m
->sealed
, -EPERM
);
5733 assert_return(source
->sealed
, -EPERM
);
5736 const char *contents
;
5751 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5757 done_something
= true;
5759 if (bus_type_is_container(type
) > 0) {
5761 r
= sd_bus_message_enter_container(source
, type
, contents
);
5765 r
= sd_bus_message_open_container(m
, type
, contents
);
5769 r
= sd_bus_message_copy(m
, source
, true);
5773 r
= sd_bus_message_close_container(m
);
5777 r
= sd_bus_message_exit_container(source
);
5784 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5790 if (type
== SD_BUS_TYPE_OBJECT_PATH
||
5791 type
== SD_BUS_TYPE_SIGNATURE
||
5792 type
== SD_BUS_TYPE_STRING
)
5793 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5795 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5802 return done_something
;
5805 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5810 assert_return(m
, -EINVAL
);
5811 assert_return(m
->sealed
, -EPERM
);
5812 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5813 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5814 assert_return(type
|| contents
, -EINVAL
);
5815 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5817 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5821 if (type
!= 0 && type
!= t
)
5824 if (contents
&& !streq_ptr(contents
, c
))
5830 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5831 assert_return(m
, NULL
);
5836 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5837 _cleanup_bus_message_unref_ sd_bus_message
*n
= NULL
;
5845 switch ((*m
)->header
->type
) {
5847 case SD_BUS_MESSAGE_SIGNAL
:
5848 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5854 case SD_BUS_MESSAGE_METHOD_CALL
:
5855 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5861 case SD_BUS_MESSAGE_METHOD_RETURN
:
5862 case SD_BUS_MESSAGE_METHOD_ERROR
:
5864 n
= message_new(bus
, (*m
)->header
->type
);
5868 n
->reply_cookie
= (*m
)->reply_cookie
;
5870 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5874 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5875 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5879 n
->error
._need_free
= -1;
5888 if ((*m
)->destination
&& !n
->destination
) {
5889 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5894 if ((*m
)->sender
&& !n
->sender
) {
5895 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5900 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5902 r
= sd_bus_message_copy(n
, *m
, true);
5906 timeout
= (*m
)->timeout
;
5907 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
))
5908 timeout
= BUS_DEFAULT_TIMEOUT
;
5910 r
= bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5914 sd_bus_message_unref(*m
);
5921 int bus_message_append_sender(sd_bus_message
*m
, const char *sender
) {
5925 assert_return(!m
->sealed
, -EPERM
);
5926 assert_return(!m
->sender
, -EPERM
);
5928 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5931 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5932 assert_return(m
, -EINVAL
);
5933 assert_return(priority
, -EINVAL
);
5935 *priority
= m
->priority
;
5939 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5940 assert_return(m
, -EINVAL
);
5941 assert_return(!m
->sealed
, -EPERM
);
5943 m
->priority
= priority
;