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
);
117 m
->containers
= NULL
;
119 m
->n_containers
= m
->containers_allocated
= 0;
120 m
->root_container
.index
= 0;
123 static void message_free(sd_bus_message
*m
) {
129 message_reset_parts(m
);
131 if (m
->release_kdbus
)
132 bus_kernel_cmd_free(m
->bus
, (uint8_t *) m
->kdbus
- (uint8_t *) m
->bus
->kdbus_buffer
);
137 sd_bus_unref(m
->bus
);
140 close_many(m
->fds
, m
->n_fds
);
144 if (m
->iovec
!= m
->iovec_fixed
)
147 m
->destination_ptr
= mfree(m
->destination_ptr
);
148 message_reset_containers(m
);
149 free(m
->root_container
.signature
);
150 free(m
->root_container
.offsets
);
152 free(m
->root_container
.peeked_signature
);
154 bus_creds_done(&m
->creds
);
158 static void *message_extend_fields(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
160 size_t old_size
, new_size
, start
;
167 old_size
= sizeof(struct bus_header
) + m
->fields_size
;
168 start
= ALIGN_TO(old_size
, align
);
169 new_size
= start
+ sz
;
171 if (new_size
< start
||
172 new_size
> (size_t) ((uint32_t) -1))
175 if (old_size
== new_size
)
176 return (uint8_t*) m
->header
+ old_size
;
178 if (m
->free_header
) {
179 np
= realloc(m
->header
, ALIGN8(new_size
));
183 /* Initially, the header is allocated as part of of
184 * the sd_bus_message itself, let's replace it by
187 np
= malloc(ALIGN8(new_size
));
191 memcpy(np
, m
->header
, sizeof(struct bus_header
));
194 /* Zero out padding */
195 if (start
> old_size
)
196 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
200 m
->fields_size
= new_size
- sizeof(struct bus_header
);
202 /* Adjust quick access pointers */
203 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
204 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
205 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
206 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
207 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
208 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
210 m
->free_header
= true;
213 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
216 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
219 return (uint8_t*) np
+ start
;
226 static int message_append_field_string(
238 /* dbus1 only allows 8bit header field ids */
242 /* dbus1 doesn't allow strings over 32bit, let's enforce this
243 * globally, to not risk convertability */
245 if (l
> (size_t) (uint32_t) -1)
248 /* Signature "(yv)" where the variant contains "s" */
250 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
252 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
253 p
= message_extend_fields(m
, 8, 8 + l
+ 1 + 1 + 1, true);
257 *((uint64_t*) p
) = h
;
264 *ret
= (char*) p
+ 8;
267 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
268 p
= message_extend_fields(m
, 8, 4 + 4 + l
+ 1, false);
277 ((uint32_t*) p
)[1] = l
;
278 memcpy(p
+ 8, s
, l
+ 1);
281 *ret
= (char*) p
+ 8;
287 static int message_append_field_signature(
298 /* dbus1 only allows 8bit header field ids */
302 /* dbus1 doesn't allow signatures over 8bit, let's enforce
303 * this globally, to not risk convertability */
308 /* Signature "(yv)" where the variant contains "g" */
310 if (BUS_MESSAGE_IS_GVARIANT(m
))
311 /* For gvariant the serialization is the same as for normal strings */
312 return message_append_field_string(m
, h
, 'g', s
, ret
);
314 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
315 p
= message_extend_fields(m
, 8, 4 + 1 + l
+ 1, false);
321 p
[2] = SD_BUS_TYPE_SIGNATURE
;
324 memcpy(p
+ 5, s
, l
+ 1);
327 *ret
= (const char*) p
+ 5;
333 static int message_append_field_uint32(sd_bus_message
*m
, uint64_t h
, uint32_t x
) {
338 /* dbus1 only allows 8bit header field ids */
342 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
343 /* (field id 64bit + ((value + NUL + signature string 'u') */
345 p
= message_extend_fields(m
, 8, 8 + 4 + 1 + 1, true);
349 *((uint64_t*) p
) = h
;
350 *((uint32_t*) (p
+ 8)) = x
;
354 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
355 p
= message_extend_fields(m
, 8, 4 + 4, false);
364 ((uint32_t*) p
)[1] = x
;
370 static int message_append_field_uint64(sd_bus_message
*m
, uint64_t h
, uint64_t x
) {
375 /* dbus1 only allows 8bit header field ids */
379 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
380 /* (field id 64bit + ((value + NUL + signature string 't') */
382 p
= message_extend_fields(m
, 8, 8 + 8 + 1 + 1, true);
386 *((uint64_t*) p
) = h
;
387 *((uint64_t*) (p
+ 8)) = x
;
391 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
392 p
= message_extend_fields(m
, 8, 4 + 4 + 8, false);
405 ((uint64_t*) p
)[1] = x
;
411 static int message_append_reply_cookie(sd_bus_message
*m
, uint64_t cookie
) {
414 if (BUS_MESSAGE_IS_GVARIANT(m
))
415 return message_append_field_uint64(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, cookie
);
417 /* 64bit cookies are not supported on dbus1 */
418 if (cookie
> 0xffffffffUL
)
421 return message_append_field_uint32(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) cookie
);
425 int bus_message_from_header(
428 size_t header_accessible
,
430 size_t footer_accessible
,
436 sd_bus_message
**ret
) {
438 _cleanup_free_ sd_bus_message
*m
= NULL
;
439 struct bus_header
*h
;
443 assert(header
|| header_accessible
<= 0);
444 assert(footer
|| footer_accessible
<= 0);
445 assert(fds
|| n_fds
<= 0);
448 if (header_accessible
< sizeof(struct bus_header
))
451 if (header_accessible
> message_size
)
453 if (footer_accessible
> message_size
)
457 if (!IN_SET(h
->version
, 1, 2))
460 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
463 if (!IN_SET(h
->endian
, BUS_LITTLE_ENDIAN
, BUS_BIG_ENDIAN
))
466 /* Note that we are happy with unknown flags in the flags header! */
468 a
= ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
471 label_sz
= strlen(label
);
482 m
->header_accessible
= header_accessible
;
484 m
->footer_accessible
= footer_accessible
;
486 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
489 if (h
->dbus2
.cookie
== 0)
492 /* dbus2 derives the sizes from the message size and
493 the offset table at the end, since it is formatted as
494 gvariant "yyyyuta{tv}v". Since the message itself is a
495 structure with precisely to variable sized entries,
496 there's only one offset in the table, which marks the
497 end of the fields array. */
499 ws
= bus_gvariant_determine_word_size(message_size
, 0);
500 if (footer_accessible
< ws
)
503 m
->fields_size
= bus_gvariant_read_word_le((uint8_t*) footer
+ footer_accessible
- ws
, ws
);
504 if (ALIGN8(m
->fields_size
) > message_size
- ws
)
506 if (m
->fields_size
< sizeof(struct bus_header
))
509 m
->fields_size
-= sizeof(struct bus_header
);
510 m
->body_size
= message_size
- (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
));
512 if (h
->dbus1
.serial
== 0)
515 /* dbus1 has the sizes in the header */
516 m
->fields_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.fields_size
);
517 m
->body_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.body_size
);
519 if (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
!= message_size
)
527 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
528 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
530 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
533 m
->bus
= sd_bus_ref(bus
);
540 int bus_message_from_malloc(
547 sd_bus_message
**ret
) {
553 r
= bus_message_from_header(
555 buffer
, length
, /* in this case the initial bytes and the final bytes are the same */
564 sz
= length
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
);
567 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(m
->fields_size
);
569 m
->body
.sealed
= true;
574 m
->iovec
= m
->iovec_fixed
;
575 m
->iovec
[0].iov_base
= buffer
;
576 m
->iovec
[0].iov_len
= length
;
578 r
= bus_message_parse_fields(m
);
582 /* We take possession of the memory and fds now */
583 m
->free_header
= true;
594 static sd_bus_message
*message_new(sd_bus
*bus
, uint8_t type
) {
599 m
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
604 m
->header
= (struct bus_header
*) ((uint8_t*) m
+ ALIGN(sizeof(struct sd_bus_message
)));
605 m
->header
->endian
= BUS_NATIVE_ENDIAN
;
606 m
->header
->type
= type
;
607 m
->header
->version
= bus
->message_version
;
608 m
->allow_fds
= bus
->can_fds
|| (bus
->state
!= BUS_HELLO
&& bus
->state
!= BUS_RUNNING
);
609 m
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(m
);
610 m
->bus
= sd_bus_ref(bus
);
612 if (bus
->allow_interactive_authorization
)
613 m
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
618 _public_
int sd_bus_message_new_signal(
622 const char *interface
,
623 const char *member
) {
628 assert_return(bus
, -ENOTCONN
);
629 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
630 assert_return(object_path_is_valid(path
), -EINVAL
);
631 assert_return(interface_name_is_valid(interface
), -EINVAL
);
632 assert_return(member_name_is_valid(member
), -EINVAL
);
633 assert_return(m
, -EINVAL
);
635 t
= message_new(bus
, SD_BUS_MESSAGE_SIGNAL
);
639 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
641 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
644 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
647 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
655 sd_bus_message_unref(t
);
659 _public_
int sd_bus_message_new_method_call(
662 const char *destination
,
664 const char *interface
,
665 const char *member
) {
670 assert_return(bus
, -ENOTCONN
);
671 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
672 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
673 assert_return(object_path_is_valid(path
), -EINVAL
);
674 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
675 assert_return(member_name_is_valid(member
), -EINVAL
);
676 assert_return(m
, -EINVAL
);
678 t
= message_new(bus
, SD_BUS_MESSAGE_METHOD_CALL
);
682 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
685 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
690 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
696 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
709 static int message_new_reply(
710 sd_bus_message
*call
,
712 sd_bus_message
**m
) {
717 assert_return(call
, -EINVAL
);
718 assert_return(call
->sealed
, -EPERM
);
719 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
720 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
721 assert_return(m
, -EINVAL
);
723 t
= message_new(call
->bus
, type
);
727 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
728 t
->reply_cookie
= BUS_MESSAGE_COOKIE(call
);
729 if (t
->reply_cookie
== 0)
732 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
737 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
742 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
743 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
753 _public_
int sd_bus_message_new_method_return(
754 sd_bus_message
*call
,
755 sd_bus_message
**m
) {
757 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
760 _public_
int sd_bus_message_new_method_error(
761 sd_bus_message
*call
,
763 const sd_bus_error
*e
) {
768 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
769 assert_return(m
, -EINVAL
);
771 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
775 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
780 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
785 t
->error
._need_free
= -1;
795 _public_
int sd_bus_message_new_method_errorf(
796 sd_bus_message
*call
,
802 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
805 assert_return(name
, -EINVAL
);
806 assert_return(m
, -EINVAL
);
808 va_start(ap
, format
);
809 bus_error_setfv(&error
, name
, format
, ap
);
812 return sd_bus_message_new_method_error(call
, m
, &error
);
815 _public_
int sd_bus_message_new_method_errno(
816 sd_bus_message
*call
,
819 const sd_bus_error
*p
) {
821 _cleanup_bus_error_free_ sd_bus_error berror
= SD_BUS_ERROR_NULL
;
823 if (sd_bus_error_is_set(p
))
824 return sd_bus_message_new_method_error(call
, m
, p
);
826 sd_bus_error_set_errno(&berror
, error
);
828 return sd_bus_message_new_method_error(call
, m
, &berror
);
831 _public_
int sd_bus_message_new_method_errnof(
832 sd_bus_message
*call
,
838 _cleanup_bus_error_free_ sd_bus_error berror
= SD_BUS_ERROR_NULL
;
841 va_start(ap
, format
);
842 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
845 return sd_bus_message_new_method_error(call
, m
, &berror
);
848 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
852 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
853 m
->creds
.well_known_names_local
= true;
854 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
857 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
861 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
862 m
->creds
.well_known_names_driver
= true;
863 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
866 int bus_message_new_synthetic_error(
869 const sd_bus_error
*e
,
870 sd_bus_message
**m
) {
876 assert(sd_bus_error_is_set(e
));
879 t
= message_new(bus
, SD_BUS_MESSAGE_METHOD_ERROR
);
883 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
884 t
->reply_cookie
= cookie
;
886 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
890 if (bus
&& bus
->unique_name
) {
891 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
896 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
901 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
906 t
->error
._need_free
= -1;
908 bus_message_set_sender_driver(bus
, t
);
918 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
919 assert_return(m
, NULL
);
921 assert(m
->n_ref
> 0);
927 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
932 assert(m
->n_ref
> 0);
942 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
943 assert_return(m
, -EINVAL
);
944 assert_return(type
, -EINVAL
);
946 *type
= m
->header
->type
;
950 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
953 assert_return(m
, -EINVAL
);
954 assert_return(cookie
, -EINVAL
);
956 c
= BUS_MESSAGE_COOKIE(m
);
960 *cookie
= BUS_MESSAGE_COOKIE(m
);
964 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
965 assert_return(m
, -EINVAL
);
966 assert_return(cookie
, -EINVAL
);
968 if (m
->reply_cookie
== 0)
971 *cookie
= m
->reply_cookie
;
975 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
976 assert_return(m
, -EINVAL
);
978 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
979 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
982 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
983 assert_return(m
, -EINVAL
);
985 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
988 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
989 assert_return(m
, -EINVAL
);
991 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
992 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
995 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
996 assert_return(m
, NULL
);
1001 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
1002 assert_return(m
, NULL
);
1004 return m
->interface
;
1007 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
1008 assert_return(m
, NULL
);
1013 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
1014 assert_return(m
, NULL
);
1016 return m
->destination
;
1019 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
1020 assert_return(m
, NULL
);
1025 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
1026 assert_return(m
, NULL
);
1027 assert_return(sd_bus_error_is_set(&m
->error
), NULL
);
1032 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
1033 assert_return(m
, -EINVAL
);
1034 assert_return(usec
, -EINVAL
);
1036 if (m
->monotonic
<= 0)
1039 *usec
= m
->monotonic
;
1043 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1044 assert_return(m
, -EINVAL
);
1045 assert_return(usec
, -EINVAL
);
1047 if (m
->realtime
<= 0)
1050 *usec
= m
->realtime
;
1054 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1055 assert_return(m
, -EINVAL
);
1056 assert_return(seqnum
, -EINVAL
);
1061 *seqnum
= m
->seqnum
;
1065 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1066 assert_return(m
, NULL
);
1068 if (m
->creds
.mask
== 0)
1074 _public_
int sd_bus_message_is_signal(
1076 const char *interface
,
1077 const char *member
) {
1079 assert_return(m
, -EINVAL
);
1081 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1084 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1087 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1093 _public_
int sd_bus_message_is_method_call(
1095 const char *interface
,
1096 const char *member
) {
1098 assert_return(m
, -EINVAL
);
1100 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1103 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1106 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1112 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1113 assert_return(m
, -EINVAL
);
1115 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1118 if (name
&& (!m
->error
.name
|| !streq(m
->error
.name
, name
)))
1124 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1125 assert_return(m
, -EINVAL
);
1126 assert_return(!m
->sealed
, -EPERM
);
1127 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1130 m
->header
->flags
&= ~BUS_MESSAGE_NO_REPLY_EXPECTED
;
1132 m
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
1137 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1138 assert_return(m
, -EINVAL
);
1139 assert_return(!m
->sealed
, -EPERM
);
1142 m
->header
->flags
&= ~BUS_MESSAGE_NO_AUTO_START
;
1144 m
->header
->flags
|= BUS_MESSAGE_NO_AUTO_START
;
1149 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1150 assert_return(m
, -EINVAL
);
1151 assert_return(!m
->sealed
, -EPERM
);
1154 m
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
1156 m
->header
->flags
&= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
1161 static struct bus_container
*message_get_container(sd_bus_message
*m
) {
1164 if (m
->n_containers
== 0)
1165 return &m
->root_container
;
1167 assert(m
->containers
);
1168 return m
->containers
+ m
->n_containers
- 1;
1171 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1172 struct bus_body_part
*part
;
1179 if (m
->n_body_parts
<= 0) {
1183 assert(m
->body_end
);
1185 part
= new0(struct bus_body_part
, 1);
1191 m
->body_end
->next
= part
;
1201 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1206 /* All other fields can be left in their defaults */
1207 assert(!part
->data
);
1208 assert(part
->memfd
< 0);
1211 part
->is_zero
= true;
1212 part
->sealed
= true;
1215 static int part_make_space(
1216 struct sd_bus_message
*m
,
1217 struct bus_body_part
*part
,
1226 assert(!part
->sealed
);
1231 if (!part
->data
&& part
->memfd
< 0) {
1232 part
->memfd
= bus_kernel_pop_memfd(m
->bus
, &part
->data
, &part
->mapped
, &part
->allocated
);
1233 part
->mmap_begin
= part
->data
;
1236 if (part
->memfd
>= 0) {
1238 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1239 uint64_t new_allocated
;
1241 new_allocated
= PAGE_ALIGN(sz
> 0 ? 2 * sz
: 1);
1242 r
= memfd_set_size(part
->memfd
, new_allocated
);
1248 part
->allocated
= new_allocated
;
1251 if (!part
->data
|| sz
> part
->mapped
) {
1254 psz
= PAGE_ALIGN(sz
> 0 ? sz
: 1);
1255 if (part
->mapped
<= 0)
1256 n
= mmap(NULL
, psz
, PROT_READ
|PROT_WRITE
, MAP_SHARED
, part
->memfd
, 0);
1258 n
= mremap(part
->mmap_begin
, part
->mapped
, psz
, MREMAP_MAYMOVE
);
1260 if (n
== MAP_FAILED
) {
1265 part
->mmap_begin
= part
->data
= n
;
1267 part
->memfd_offset
= 0;
1270 part
->munmap_this
= true;
1272 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1273 size_t new_allocated
;
1275 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1276 n
= realloc(part
->data
, new_allocated
);
1283 part
->allocated
= new_allocated
;
1284 part
->free_this
= true;
1289 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1295 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1296 struct bus_container
*c
;
1299 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1301 /* Add offset to current container, unless this is the first
1302 * item in it, which will have the 0 offset, which we can
1304 c
= message_get_container(m
);
1306 if (!c
->need_offsets
)
1309 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1312 c
->offsets
[c
->n_offsets
++] = offset
;
1316 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1317 struct bus_container
*c
;
1324 /* Update counters */
1325 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++) {
1328 *c
->array_size
+= expand
;
1332 static void *message_extend_body(
1337 bool force_inline
) {
1339 size_t start_body
, end_body
, padding
, added
;
1350 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1351 end_body
= start_body
+ sz
;
1353 padding
= start_body
- m
->body_size
;
1354 added
= padding
+ sz
;
1356 /* Check for 32bit overflows */
1357 if (end_body
> (size_t) ((uint32_t) -1) ||
1358 end_body
< start_body
) {
1364 struct bus_body_part
*part
= NULL
;
1368 m
->n_body_parts
<= 0 ||
1369 m
->body_end
->sealed
||
1370 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1371 (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 */
1375 part
= message_append_part(m
);
1379 part_zero(part
, padding
);
1382 part
= message_append_part(m
);
1386 r
= part_make_space(m
, part
, sz
, &p
);
1390 struct bus_container
*c
;
1392 size_t os
, start_part
, end_part
;
1398 start_part
= ALIGN_TO(part
->size
, align
);
1399 end_part
= start_part
+ sz
;
1401 r
= part_make_space(m
, part
, end_part
, &p
);
1406 memzero(p
, padding
);
1407 p
= (uint8_t*) p
+ padding
;
1410 /* Readjust pointers */
1411 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1412 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1414 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1417 /* Return something that is not NULL and is aligned */
1418 p
= (uint8_t *) NULL
+ align
;
1420 m
->body_size
= end_body
;
1421 message_extend_containers(m
, added
);
1424 r
= message_add_offset(m
, end_body
);
1434 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1445 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1449 f
= realloc(m
->fds
, sizeof(int) * (m
->n_fds
+ 1));
1457 m
->fds
[m
->n_fds
] = copy
;
1463 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1464 _cleanup_close_
int fd
= -1;
1465 struct bus_container
*c
;
1469 assert_return(m
, -EINVAL
);
1470 assert_return(!m
->sealed
, -EPERM
);
1471 assert_return(bus_type_is_basic(type
), -EINVAL
);
1472 assert_return(!m
->poisoned
, -ESTALE
);
1474 c
= message_get_container(m
);
1476 if (c
->signature
&& c
->signature
[c
->index
]) {
1477 /* Container signature is already set */
1479 if (c
->signature
[c
->index
] != type
)
1484 /* Maybe we can append to the signature? But only if this is the top-level container */
1485 if (c
->enclosing
!= 0)
1488 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1495 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1501 case SD_BUS_TYPE_SIGNATURE
:
1502 case SD_BUS_TYPE_STRING
:
1505 /* Fall through... */
1506 case SD_BUS_TYPE_OBJECT_PATH
:
1514 case SD_BUS_TYPE_BOOLEAN
:
1516 u8
= p
&& *(int*) p
;
1522 case SD_BUS_TYPE_UNIX_FD
:
1527 fd
= message_push_fd(m
, *(int*) p
);
1538 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1539 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1546 a
= message_extend_body(m
, align
, sz
, true, false);
1553 *stored
= (const uint8_t*) a
;
1560 case SD_BUS_TYPE_STRING
:
1561 /* To make things easy we'll serialize a NULL string
1562 * into the empty string */
1565 /* Fall through... */
1566 case SD_BUS_TYPE_OBJECT_PATH
:
1572 sz
= 4 + strlen(p
) + 1;
1575 case SD_BUS_TYPE_SIGNATURE
:
1580 sz
= 1 + strlen(p
) + 1;
1583 case SD_BUS_TYPE_BOOLEAN
:
1585 u32
= p
&& *(int*) p
;
1591 case SD_BUS_TYPE_UNIX_FD
:
1596 fd
= message_push_fd(m
, *(int*) p
);
1607 align
= bus_type_get_alignment(type
);
1608 sz
= bus_type_get_size(type
);
1615 a
= message_extend_body(m
, align
, sz
, false, false);
1619 if (type
== SD_BUS_TYPE_STRING
|| type
== SD_BUS_TYPE_OBJECT_PATH
) {
1620 *(uint32_t*) a
= sz
- 5;
1621 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1624 *stored
= (const uint8_t*) a
+ 4;
1626 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1627 *(uint8_t*) a
= sz
- 2;
1628 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1631 *stored
= (const uint8_t*) a
+ 1;
1640 if (type
== SD_BUS_TYPE_UNIX_FD
)
1643 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1650 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1651 return message_append_basic(m
, type
, p
, NULL
);
1654 _public_
int sd_bus_message_append_string_space(
1659 struct bus_container
*c
;
1662 assert_return(m
, -EINVAL
);
1663 assert_return(s
, -EINVAL
);
1664 assert_return(!m
->sealed
, -EPERM
);
1665 assert_return(!m
->poisoned
, -ESTALE
);
1667 c
= message_get_container(m
);
1669 if (c
->signature
&& c
->signature
[c
->index
]) {
1670 /* Container signature is already set */
1672 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1677 /* Maybe we can append to the signature? But only if this is the top-level container */
1678 if (c
->enclosing
!= 0)
1681 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1688 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1689 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1695 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1699 *(uint32_t*) a
= size
;
1705 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1711 _public_
int sd_bus_message_append_string_iovec(
1713 const struct iovec
*iov
,
1721 assert_return(m
, -EINVAL
);
1722 assert_return(!m
->sealed
, -EPERM
);
1723 assert_return(iov
|| n
== 0, -EINVAL
);
1724 assert_return(!m
->poisoned
, -ESTALE
);
1726 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1728 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1732 for (i
= 0; i
< n
; i
++) {
1734 if (iov
[i
].iov_base
)
1735 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1737 memset(p
, ' ', iov
[i
].iov_len
);
1739 p
+= iov
[i
].iov_len
;
1745 static int bus_message_open_array(
1747 struct bus_container
*c
,
1748 const char *contents
,
1749 uint32_t **array_size
,
1751 bool *need_offsets
) {
1761 assert(need_offsets
);
1763 if (!signature_is_single(contents
, true))
1766 if (c
->signature
&& c
->signature
[c
->index
]) {
1768 /* Verify the existing signature */
1770 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1773 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1776 nindex
= c
->index
+ 1 + strlen(contents
);
1780 if (c
->enclosing
!= 0)
1783 /* Extend the existing signature */
1785 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1791 nindex
= e
- c
->signature
;
1794 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1795 alignment
= bus_gvariant_get_alignment(contents
);
1799 /* Add alignment padding and add to offset list */
1800 if (!message_extend_body(m
, alignment
, 0, false, false))
1803 r
= bus_gvariant_is_fixed_size(contents
);
1807 *begin
= m
->body_size
;
1808 *need_offsets
= r
== 0;
1812 struct bus_body_part
*o
;
1814 alignment
= bus_type_get_alignment(contents
[0]);
1818 a
= message_extend_body(m
, 4, 4, false, false);
1823 op
= m
->body_end
->data
;
1824 os
= m
->body_end
->size
;
1826 /* Add alignment between size and first element */
1827 if (!message_extend_body(m
, alignment
, 0, false, false))
1830 /* location of array size might have changed so let's readjust a */
1831 if (o
== m
->body_end
)
1832 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1838 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1844 static int bus_message_open_variant(
1846 struct bus_container
*c
,
1847 const char *contents
) {
1853 if (!signature_is_single(contents
, false))
1856 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1859 if (c
->signature
&& c
->signature
[c
->index
]) {
1861 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1867 if (c
->enclosing
!= 0)
1870 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1877 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1878 /* Variants are always aligned to 8 */
1880 if (!message_extend_body(m
, 8, 0, false, false))
1887 l
= strlen(contents
);
1888 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1893 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1896 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1902 static int bus_message_open_struct(
1904 struct bus_container
*c
,
1905 const char *contents
,
1907 bool *need_offsets
) {
1916 assert(need_offsets
);
1918 if (!signature_is_valid(contents
, false))
1921 if (c
->signature
&& c
->signature
[c
->index
]) {
1924 l
= strlen(contents
);
1926 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1927 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1928 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1931 nindex
= c
->index
+ 1 + l
+ 1;
1935 if (c
->enclosing
!= 0)
1938 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1944 nindex
= e
- c
->signature
;
1947 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1950 alignment
= bus_gvariant_get_alignment(contents
);
1954 if (!message_extend_body(m
, alignment
, 0, false, false))
1957 r
= bus_gvariant_is_fixed_size(contents
);
1961 *begin
= m
->body_size
;
1962 *need_offsets
= r
== 0;
1964 /* Align contents to 8 byte boundary */
1965 if (!message_extend_body(m
, 8, 0, false, false))
1969 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1975 static int bus_message_open_dict_entry(
1977 struct bus_container
*c
,
1978 const char *contents
,
1980 bool *need_offsets
) {
1988 assert(need_offsets
);
1990 if (!signature_is_pair(contents
))
1993 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1996 if (c
->signature
&& c
->signature
[c
->index
]) {
1999 l
= strlen(contents
);
2001 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
2002 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
2003 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
2008 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2011 alignment
= bus_gvariant_get_alignment(contents
);
2015 if (!message_extend_body(m
, alignment
, 0, false, false))
2018 r
= bus_gvariant_is_fixed_size(contents
);
2022 *begin
= m
->body_size
;
2023 *need_offsets
= r
== 0;
2025 /* Align contents to 8 byte boundary */
2026 if (!message_extend_body(m
, 8, 0, false, false))
2033 _public_
int sd_bus_message_open_container(
2036 const char *contents
) {
2038 struct bus_container
*c
, *w
;
2039 uint32_t *array_size
= NULL
;
2041 size_t before
, begin
= 0;
2042 bool need_offsets
= false;
2045 assert_return(m
, -EINVAL
);
2046 assert_return(!m
->sealed
, -EPERM
);
2047 assert_return(contents
, -EINVAL
);
2048 assert_return(!m
->poisoned
, -ESTALE
);
2050 /* Make sure we have space for one more container */
2051 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
2056 c
= message_get_container(m
);
2058 signature
= strdup(contents
);
2064 /* Save old index in the parent container, in case we have to
2065 * abort this container */
2066 c
->saved_index
= c
->index
;
2067 before
= m
->body_size
;
2069 if (type
== SD_BUS_TYPE_ARRAY
)
2070 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
2071 else if (type
== SD_BUS_TYPE_VARIANT
)
2072 r
= bus_message_open_variant(m
, c
, contents
);
2073 else if (type
== SD_BUS_TYPE_STRUCT
)
2074 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
2075 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
2076 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
2085 /* OK, let's fill it in */
2086 w
= m
->containers
+ m
->n_containers
++;
2087 w
->enclosing
= type
;
2088 w
->signature
= signature
;
2090 w
->array_size
= array_size
;
2093 w
->n_offsets
= w
->offsets_allocated
= 0;
2095 w
->need_offsets
= need_offsets
;
2100 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2105 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2108 if (c
->need_offsets
) {
2109 size_t payload
, sz
, i
;
2112 /* Variable-width arrays */
2114 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2115 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2117 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2121 for (i
= 0; i
< c
->n_offsets
; i
++)
2122 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2126 /* Fixed-width or empty arrays */
2128 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2136 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2142 assert(c
->signature
);
2144 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2147 l
= strlen(c
->signature
);
2149 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2154 memcpy(a
+1, c
->signature
, l
);
2159 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2160 bool fixed_size
= true;
2161 size_t n_variable
= 0;
2170 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2173 p
= strempty(c
->signature
);
2177 r
= signature_element_length(p
, &n
);
2186 r
= bus_gvariant_is_fixed_size(t
);
2191 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2193 /* We need to add an offset for each item that has a
2194 * variable size and that is not the last one in the
2198 if (r
== 0 && p
[n
] != 0)
2205 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2206 assert(c
->need_offsets
|| n_variable
== 0);
2208 if (isempty(c
->signature
)) {
2209 /* The unary type is encoded as fixed 1 byte padding */
2210 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2215 } else if (n_variable
<= 0) {
2218 /* Structures with fixed-size members only have to be
2219 * fixed-size themselves. But gvariant requires all fixed-size
2220 * elements to be sized a multiple of their alignment. Hence,
2221 * we must *always* add final padding after the last member so
2222 * the overall size of the structure is properly aligned. */
2224 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2226 assert(alignment
> 0);
2228 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2235 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2237 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2239 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2243 p
= strempty(c
->signature
);
2244 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2248 r
= signature_element_length(p
, &n
);
2259 r
= bus_gvariant_is_fixed_size(t
);
2262 if (r
> 0 || p
[0] == 0)
2266 k
= n_variable
- 1 - j
;
2268 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2277 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2278 struct bus_container
*c
;
2281 assert_return(m
, -EINVAL
);
2282 assert_return(!m
->sealed
, -EPERM
);
2283 assert_return(m
->n_containers
> 0, -EINVAL
);
2284 assert_return(!m
->poisoned
, -ESTALE
);
2286 c
= message_get_container(m
);
2288 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2289 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2294 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2295 r
= bus_message_close_array(m
, c
);
2296 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2297 r
= bus_message_close_variant(m
, c
);
2298 else if (c
->enclosing
== SD_BUS_TYPE_STRUCT
|| c
->enclosing
== SD_BUS_TYPE_DICT_ENTRY
)
2299 r
= bus_message_close_struct(m
, c
, true);
2301 assert_not_reached("Unknown container type");
2315 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2322 stack
[*i
].types
= types
;
2323 stack
[*i
].n_struct
= n_struct
;
2324 stack
[*i
].n_array
= n_array
;
2330 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2341 *types
= stack
[*i
].types
;
2342 *n_struct
= stack
[*i
].n_struct
;
2343 *n_array
= stack
[*i
].n_array
;
2348 int bus_message_append_ap(
2353 unsigned n_array
, n_struct
;
2354 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2355 unsigned stack_ptr
= 0;
2363 n_array
= (unsigned) -1;
2364 n_struct
= strlen(types
);
2369 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2370 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2376 r
= sd_bus_message_close_container(m
);
2384 if (n_array
!= (unsigned) -1)
2393 case SD_BUS_TYPE_BYTE
: {
2396 x
= (uint8_t) va_arg(ap
, int);
2397 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2401 case SD_BUS_TYPE_BOOLEAN
:
2402 case SD_BUS_TYPE_INT32
:
2403 case SD_BUS_TYPE_UINT32
:
2404 case SD_BUS_TYPE_UNIX_FD
: {
2407 /* We assume a boolean is the same as int32_t */
2408 assert_cc(sizeof(int32_t) == sizeof(int));
2410 x
= va_arg(ap
, uint32_t);
2411 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2415 case SD_BUS_TYPE_INT16
:
2416 case SD_BUS_TYPE_UINT16
: {
2419 x
= (uint16_t) va_arg(ap
, int);
2420 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2424 case SD_BUS_TYPE_INT64
:
2425 case SD_BUS_TYPE_UINT64
: {
2428 x
= va_arg(ap
, uint64_t);
2429 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2433 case SD_BUS_TYPE_DOUBLE
: {
2436 x
= va_arg(ap
, double);
2437 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2441 case SD_BUS_TYPE_STRING
:
2442 case SD_BUS_TYPE_OBJECT_PATH
:
2443 case SD_BUS_TYPE_SIGNATURE
: {
2446 x
= va_arg(ap
, const char*);
2447 r
= sd_bus_message_append_basic(m
, *t
, x
);
2451 case SD_BUS_TYPE_ARRAY
: {
2454 r
= signature_element_length(t
+ 1, &k
);
2460 memcpy(s
, t
+ 1, k
);
2463 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2468 if (n_array
== (unsigned) -1) {
2473 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2479 n_array
= va_arg(ap
, unsigned);
2484 case SD_BUS_TYPE_VARIANT
: {
2487 s
= va_arg(ap
, const char*);
2491 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2495 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2500 n_struct
= strlen(s
);
2501 n_array
= (unsigned) -1;
2506 case SD_BUS_TYPE_STRUCT_BEGIN
:
2507 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2510 r
= signature_element_length(t
, &k
);
2517 memcpy(s
, t
+ 1, k
- 2);
2520 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2525 if (n_array
== (unsigned) -1) {
2530 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2536 n_array
= (unsigned) -1;
2552 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2556 assert_return(m
, -EINVAL
);
2557 assert_return(types
, -EINVAL
);
2558 assert_return(!m
->sealed
, -EPERM
);
2559 assert_return(!m
->poisoned
, -ESTALE
);
2561 va_start(ap
, types
);
2562 r
= bus_message_append_ap(m
, types
, ap
);
2568 _public_
int sd_bus_message_append_array_space(
2578 assert_return(m
, -EINVAL
);
2579 assert_return(!m
->sealed
, -EPERM
);
2580 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2581 assert_return(ptr
|| size
== 0, -EINVAL
);
2582 assert_return(!m
->poisoned
, -ESTALE
);
2584 /* alignment and size of the trivial types (except bool) is
2585 * identical for gvariant and dbus1 marshalling */
2586 align
= bus_type_get_alignment(type
);
2587 sz
= bus_type_get_size(type
);
2589 assert_se(align
> 0);
2595 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2599 a
= message_extend_body(m
, align
, size
, false, false);
2603 r
= sd_bus_message_close_container(m
);
2611 _public_
int sd_bus_message_append_array(
2619 assert_return(m
, -EINVAL
);
2620 assert_return(!m
->sealed
, -EPERM
);
2621 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2622 assert_return(ptr
|| size
== 0, -EINVAL
);
2623 assert_return(!m
->poisoned
, -ESTALE
);
2625 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2630 memcpy(p
, ptr
, size
);
2635 _public_
int sd_bus_message_append_array_iovec(
2638 const struct iovec
*iov
,
2646 assert_return(m
, -EINVAL
);
2647 assert_return(!m
->sealed
, -EPERM
);
2648 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2649 assert_return(iov
|| n
== 0, -EINVAL
);
2650 assert_return(!m
->poisoned
, -ESTALE
);
2652 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2654 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2658 for (i
= 0; i
< n
; i
++) {
2660 if (iov
[i
].iov_base
)
2661 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2663 memzero(p
, iov
[i
].iov_len
);
2665 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2671 _public_
int sd_bus_message_append_array_memfd(
2678 _cleanup_close_
int copy_fd
= -1;
2679 struct bus_body_part
*part
;
2685 assert_return(m
, -EINVAL
);
2686 assert_return(memfd
>= 0, -EBADF
);
2687 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2688 assert_return(size
> 0, -EINVAL
);
2689 assert_return(!m
->sealed
, -EPERM
);
2690 assert_return(!m
->poisoned
, -ESTALE
);
2692 r
= memfd_set_sealed(memfd
);
2696 copy_fd
= dup(memfd
);
2700 r
= memfd_get_size(memfd
, &real_size
);
2704 if (offset
== 0 && size
== (uint64_t) -1)
2706 else if (offset
+ size
> real_size
)
2709 align
= bus_type_get_alignment(type
);
2710 sz
= bus_type_get_size(type
);
2712 assert_se(align
> 0);
2715 if (offset
% align
!= 0)
2721 if (size
> (uint64_t) (uint32_t) -1)
2724 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2728 a
= message_extend_body(m
, align
, 0, false, false);
2732 part
= message_append_part(m
);
2736 part
->memfd
= copy_fd
;
2737 part
->memfd_offset
= offset
;
2738 part
->sealed
= true;
2742 m
->body_size
+= size
;
2743 message_extend_containers(m
, size
);
2745 return sd_bus_message_close_container(m
);
2748 _public_
int sd_bus_message_append_string_memfd(
2754 _cleanup_close_
int copy_fd
= -1;
2755 struct bus_body_part
*part
;
2756 struct bus_container
*c
;
2761 assert_return(m
, -EINVAL
);
2762 assert_return(memfd
>= 0, -EBADF
);
2763 assert_return(size
> 0, -EINVAL
);
2764 assert_return(!m
->sealed
, -EPERM
);
2765 assert_return(!m
->poisoned
, -ESTALE
);
2767 r
= memfd_set_sealed(memfd
);
2771 copy_fd
= dup(memfd
);
2775 r
= memfd_get_size(memfd
, &real_size
);
2779 if (offset
== 0 && size
== (uint64_t) -1)
2781 else if (offset
+ size
> real_size
)
2784 /* We require this to be NUL terminated */
2788 if (size
> (uint64_t) (uint32_t) -1)
2791 c
= message_get_container(m
);
2792 if (c
->signature
&& c
->signature
[c
->index
]) {
2793 /* Container signature is already set */
2795 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2800 /* Maybe we can append to the signature? But only if this is the top-level container */
2801 if (c
->enclosing
!= 0)
2804 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2811 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2812 a
= message_extend_body(m
, 4, 4, false, false);
2816 *(uint32_t*) a
= size
- 1;
2819 part
= message_append_part(m
);
2823 part
->memfd
= copy_fd
;
2824 part
->memfd_offset
= offset
;
2825 part
->sealed
= true;
2829 m
->body_size
+= size
;
2830 message_extend_containers(m
, size
);
2832 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2833 r
= message_add_offset(m
, m
->body_size
);
2840 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2846 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2850 assert_return(m
, -EINVAL
);
2851 assert_return(!m
->sealed
, -EPERM
);
2852 assert_return(!m
->poisoned
, -ESTALE
);
2854 r
= sd_bus_message_open_container(m
, 'a', "s");
2858 STRV_FOREACH(i
, l
) {
2859 r
= sd_bus_message_append_basic(m
, 's', *i
);
2864 return sd_bus_message_close_container(m
);
2867 static int bus_message_close_header(sd_bus_message
*m
) {
2871 /* The actual user data is finished now, we just complete the
2872 variant and struct now (at least on gvariant). Remember
2873 this position, so that during parsing we know where to to
2874 put the outer container end. */
2875 m
->user_body_size
= m
->body_size
;
2877 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2878 const char *signature
;
2882 /* Add offset table to end of fields array */
2883 if (m
->n_header_offsets
>= 1) {
2887 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2889 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2890 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2894 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2895 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2898 /* Add gvariant NUL byte plus signature to the end of
2899 * the body, followed by the final offset pointing to
2900 * the end of the fields array */
2902 signature
= strempty(m
->root_container
.signature
);
2903 l
= strlen(signature
);
2905 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2906 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2911 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2912 memcpy((uint8_t*) d
+ 2, signature
, l
);
2913 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2915 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2918 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2920 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2921 m
->header
->dbus1
.body_size
= m
->body_size
;
2927 int bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, usec_t timeout
) {
2928 struct bus_body_part
*part
;
2938 if (m
->n_containers
> 0)
2944 if (cookie
> 0xffffffffULL
&&
2945 !BUS_MESSAGE_IS_GVARIANT(m
))
2948 /* In vtables the return signature of method calls is listed,
2949 * let's check if they match if this is a response */
2950 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2951 m
->enforced_reply_signature
&&
2952 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2955 /* If gvariant marshalling is used we need to close the body structure */
2956 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2960 /* If there's a non-trivial signature set, then add it in
2961 * here, but only on dbus1 */
2962 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2963 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2969 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2974 r
= bus_message_close_header(m
);
2978 if (BUS_MESSAGE_IS_GVARIANT(m
))
2979 m
->header
->dbus2
.cookie
= cookie
;
2981 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2983 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout
;
2985 /* Add padding at the end of the fields part, since we know
2986 * the body needs to start at an 8 byte alignment. We made
2987 * sure we allocated enough space for this, so all we need to
2988 * do here is to zero it out. */
2989 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2991 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2993 /* If this is something we can send as memfd, then let's seal
2994 the memfd now. Note that we can send memfds as payload only
2995 for directed messages, and not for broadcasts. */
2996 if (m
->destination
&& m
->bus
->use_memfd
) {
2997 MESSAGE_FOREACH_PART(part
, i
, m
)
2998 if (part
->memfd
>= 0 &&
3000 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
3001 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
3004 /* Try to seal it if that makes
3005 * sense. First, unmap our own map to
3006 * make sure we don't keep it busy. */
3007 bus_body_part_unmap(part
);
3009 /* Then, sync up real memfd size */
3011 r
= memfd_set_size(part
->memfd
, sz
);
3015 /* Finally, try to seal */
3016 if (memfd_set_sealed(part
->memfd
) >= 0)
3017 part
->sealed
= true;
3021 m
->root_container
.end
= m
->user_body_size
;
3022 m
->root_container
.index
= 0;
3023 m
->root_container
.offset_index
= 0;
3024 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
3031 int bus_body_part_map(struct bus_body_part
*part
) {
3040 if (part
->size
<= 0)
3043 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3044 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
3045 static const uint8_t zeroes
[7] = { };
3046 part
->data
= (void*) zeroes
;
3050 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
3051 psz
= PAGE_ALIGN(part
->size
+ shift
);
3053 if (part
->memfd
>= 0)
3054 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
3055 else if (part
->is_zero
)
3056 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
3060 if (p
== MAP_FAILED
)
3064 part
->mmap_begin
= p
;
3065 part
->data
= (uint8_t*) p
+ shift
;
3066 part
->munmap_this
= true;
3071 void bus_body_part_unmap(struct bus_body_part
*part
) {
3075 if (part
->memfd
< 0)
3078 if (!part
->mmap_begin
)
3081 if (!part
->munmap_this
)
3084 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
3086 part
->mmap_begin
= NULL
;
3089 part
->munmap_this
= false;
3094 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3095 size_t k
, start
, end
;
3100 start
= ALIGN_TO((size_t) *rindex
, align
);
3101 end
= start
+ nbytes
;
3106 /* Verify that padding is 0 */
3107 for (k
= *rindex
; k
< start
; k
++)
3108 if (((const uint8_t*) p
)[k
] != 0)
3112 *r
= (uint8_t*) p
+ start
;
3119 static bool message_end_of_signature(sd_bus_message
*m
) {
3120 struct bus_container
*c
;
3124 c
= message_get_container(m
);
3125 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3128 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3129 struct bus_container
*c
;
3133 c
= message_get_container(m
);
3134 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3137 if (BUS_MESSAGE_IS_GVARIANT(m
))
3138 return index
>= c
->end
;
3140 assert(c
->array_size
);
3141 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3145 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3146 assert_return(m
, -EINVAL
);
3147 assert_return(m
->sealed
, -EPERM
);
3149 if (complete
&& m
->n_containers
> 0)
3152 if (message_end_of_signature(m
))
3155 if (message_end_of_array(m
, m
->rindex
))
3161 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3162 struct bus_body_part
*part
;
3168 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3169 part
= m
->cached_rindex_part
;
3170 begin
= m
->cached_rindex_part_begin
;
3180 if (index
+ sz
<= begin
+ part
->size
) {
3182 r
= bus_body_part_map(part
);
3187 *p
= (uint8_t*) part
->data
+ index
- begin
;
3189 m
->cached_rindex_part
= part
;
3190 m
->cached_rindex_part_begin
= begin
;
3195 begin
+= part
->size
;
3202 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3209 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3212 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3215 sz
= bus_gvariant_get_size(c
->signature
);
3219 if (c
->offset_index
+1 >= c
->n_offsets
)
3222 /* Variable-size array */
3224 alignment
= bus_gvariant_get_alignment(c
->signature
);
3225 assert(alignment
> 0);
3227 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3228 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3231 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3234 /* Fixed-size array */
3235 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3241 } else if (c
->enclosing
== 0 ||
3242 c
->enclosing
== SD_BUS_TYPE_STRUCT
||
3243 c
->enclosing
== SD_BUS_TYPE_DICT_ENTRY
) {
3248 if (c
->offset_index
+1 >= c
->n_offsets
)
3251 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3255 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3260 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3263 alignment
= bus_gvariant_get_alignment(t
);
3266 assert(alignment
> 0);
3268 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3269 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3273 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3276 assert_not_reached("Unknown container type");
3281 /* Reached the end */
3288 static int message_peek_body(
3295 size_t k
, start
, end
, padding
;
3296 struct bus_body_part
*part
;
3303 start
= ALIGN_TO((size_t) *rindex
, align
);
3304 padding
= start
- *rindex
;
3305 end
= start
+ nbytes
;
3307 if (end
> m
->user_body_size
)
3310 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3315 /* Verify padding */
3316 for (k
= 0; k
< padding
; k
++)
3321 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3322 if (!part
|| (nbytes
> 0 && !q
))
3333 static bool validate_nul(const char *s
, size_t l
) {
3335 /* Check for NUL chars in the string */
3336 if (memchr(s
, 0, l
))
3339 /* Check for NUL termination */
3346 static bool validate_string(const char *s
, size_t l
) {
3348 if (!validate_nul(s
, l
))
3351 /* Check if valid UTF8 */
3352 if (!utf8_is_valid(s
))
3358 static bool validate_signature(const char *s
, size_t l
) {
3360 if (!validate_nul(s
, l
))
3363 /* Check if valid signature */
3364 if (!signature_is_valid(s
, true))
3370 static bool validate_object_path(const char *s
, size_t l
) {
3372 if (!validate_nul(s
, l
))
3375 if (!object_path_is_valid(s
))
3381 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3382 struct bus_container
*c
;
3387 assert_return(m
, -EINVAL
);
3388 assert_return(m
->sealed
, -EPERM
);
3389 assert_return(bus_type_is_basic(type
), -EINVAL
);
3391 if (message_end_of_signature(m
))
3394 if (message_end_of_array(m
, m
->rindex
))
3397 c
= message_get_container(m
);
3398 if (c
->signature
[c
->index
] != type
)
3403 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3405 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3408 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3412 if (type
== SD_BUS_TYPE_STRING
)
3413 ok
= validate_string(q
, c
->item_size
-1);
3414 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3415 ok
= validate_object_path(q
, c
->item_size
-1);
3417 ok
= validate_signature(q
, c
->item_size
-1);
3423 *(const char**) p
= q
;
3427 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3429 if ((size_t) sz
!= c
->item_size
)
3432 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3435 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3441 case SD_BUS_TYPE_BYTE
:
3443 *(uint8_t*) p
= *(uint8_t*) q
;
3446 case SD_BUS_TYPE_BOOLEAN
:
3448 *(int*) p
= !!*(uint8_t*) q
;
3451 case SD_BUS_TYPE_INT16
:
3452 case SD_BUS_TYPE_UINT16
:
3454 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3457 case SD_BUS_TYPE_INT32
:
3458 case SD_BUS_TYPE_UINT32
:
3460 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3463 case SD_BUS_TYPE_INT64
:
3464 case SD_BUS_TYPE_UINT64
:
3465 case SD_BUS_TYPE_DOUBLE
:
3467 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3470 case SD_BUS_TYPE_UNIX_FD
: {
3473 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3478 *(int*) p
= m
->fds
[j
];
3484 assert_not_reached("unexpected type");
3488 r
= container_next_item(m
, c
, &rindex
);
3493 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3497 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3501 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3502 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3506 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3507 ok
= validate_object_path(q
, l
);
3509 ok
= validate_string(q
, l
);
3514 *(const char**) p
= q
;
3516 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3519 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3524 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3528 if (!validate_signature(q
, l
))
3532 *(const char**) p
= q
;
3537 align
= bus_type_get_alignment(type
);
3540 sz
= bus_type_get_size(type
);
3543 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3549 case SD_BUS_TYPE_BYTE
:
3551 *(uint8_t*) p
= *(uint8_t*) q
;
3554 case SD_BUS_TYPE_BOOLEAN
:
3556 *(int*) p
= !!*(uint32_t*) q
;
3559 case SD_BUS_TYPE_INT16
:
3560 case SD_BUS_TYPE_UINT16
:
3562 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3565 case SD_BUS_TYPE_INT32
:
3566 case SD_BUS_TYPE_UINT32
:
3568 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3571 case SD_BUS_TYPE_INT64
:
3572 case SD_BUS_TYPE_UINT64
:
3573 case SD_BUS_TYPE_DOUBLE
:
3575 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3578 case SD_BUS_TYPE_UNIX_FD
: {
3581 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3586 *(int*) p
= m
->fds
[j
];
3591 assert_not_reached("Unknown basic type...");
3598 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3604 static int bus_message_enter_array(
3606 struct bus_container
*c
,
3607 const char *contents
,
3608 uint32_t **array_size
,
3611 size_t *n_offsets
) {
3625 if (!signature_is_single(contents
, true))
3628 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3631 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3634 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3639 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3642 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3646 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3649 alignment
= bus_type_get_alignment(contents
[0]);
3653 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3657 *array_size
= (uint32_t*) q
;
3659 } else if (c
->item_size
<= 0) {
3661 /* gvariant: empty array */
3666 } else if (bus_gvariant_is_fixed_size(contents
)) {
3668 /* gvariant: fixed length array */
3669 *item_size
= bus_gvariant_get_size(contents
);
3674 size_t where
, p
= 0, framing
, sz
;
3677 /* gvariant: variable length array */
3678 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3680 where
= rindex
+ c
->item_size
- sz
;
3681 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3685 framing
= bus_gvariant_read_word_le(q
, sz
);
3686 if (framing
> c
->item_size
- sz
)
3688 if ((c
->item_size
- framing
) % sz
!= 0)
3691 *n_offsets
= (c
->item_size
- framing
) / sz
;
3693 where
= rindex
+ framing
;
3694 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3698 *offsets
= new(size_t, *n_offsets
);
3702 for (i
= 0; i
< *n_offsets
; i
++) {
3705 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3706 if (x
> c
->item_size
- sz
)
3711 (*offsets
)[i
] = rindex
+ x
;
3715 *item_size
= (*offsets
)[0] - rindex
;
3720 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3721 c
->index
+= 1 + strlen(contents
);
3726 static int bus_message_enter_variant(
3728 struct bus_container
*c
,
3729 const char *contents
,
3730 size_t *item_size
) {
3742 if (!signature_is_single(contents
, false))
3745 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3748 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3751 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3756 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3759 k
= strlen(contents
);
3760 if (1+k
> c
->item_size
)
3763 where
= rindex
+ c
->item_size
- (1+k
);
3764 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3768 if (*(char*) q
!= 0)
3771 if (memcmp((uint8_t*) q
+1, contents
, k
))
3774 *item_size
= c
->item_size
- (1+k
);
3777 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3782 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3786 if (!validate_signature(q
, l
))
3789 if (!streq(q
, contents
))
3795 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3801 static int build_struct_offsets(
3803 const char *signature
,
3807 size_t *n_offsets
) {
3809 unsigned n_variable
= 0, n_total
= 0, v
;
3810 size_t previous
= 0, where
;
3821 if (isempty(signature
)) {
3822 /* Unary type is encoded as *fixed* 1 byte padding */
3823 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3827 if (*(uint8_t *) q
!= 0)
3836 sz
= bus_gvariant_determine_word_size(size
, 0);
3840 /* First, loop over signature and count variable elements and
3841 * elements in general. We use this to know how large the
3842 * offset array is at the end of the structure. Note that
3843 * GVariant only stores offsets for all variable size elements
3844 * that are not the last item. */
3850 r
= signature_element_length(p
, &n
);
3859 r
= bus_gvariant_is_fixed_size(t
);
3864 if (r
== 0 && p
[n
] != 0) /* except the last item */
3871 if (size
< n_variable
* sz
)
3874 where
= m
->rindex
+ size
- (n_variable
* sz
);
3875 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3881 *offsets
= new(size_t, n_total
);
3887 /* Second, loop again and build an offset table */
3893 r
= signature_element_length(p
, &n
);
3902 k
= bus_gvariant_get_size(t
);
3910 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3913 if (m
->rindex
+ x
< previous
)
3916 /* The last item's end
3917 * is determined from
3920 x
= size
- (n_variable
* sz
);
3922 offset
= m
->rindex
+ x
;
3928 align
= bus_gvariant_get_alignment(t
);
3931 offset
= (*n_offsets
== 0 ? m
->rindex
: ALIGN_TO((*offsets
)[*n_offsets
-1], align
)) + k
;
3935 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3940 assert(*n_offsets
== n_total
);
3942 *item_size
= (*offsets
)[0] - m
->rindex
;
3946 static int enter_struct_or_dict_entry(
3948 struct bus_container
*c
,
3949 const char *contents
,
3952 size_t *n_offsets
) {
3963 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3966 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3971 /* gvariant with contents */
3972 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3977 static int bus_message_enter_struct(
3979 struct bus_container
*c
,
3980 const char *contents
,
3983 size_t *n_offsets
) {
3995 if (!signature_is_valid(contents
, false))
3998 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4001 l
= strlen(contents
);
4003 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
4004 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4005 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
4008 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4012 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4013 c
->index
+= 1 + l
+ 1;
4018 static int bus_message_enter_dict_entry(
4020 struct bus_container
*c
,
4021 const char *contents
,
4024 size_t *n_offsets
) {
4033 if (!signature_is_pair(contents
))
4036 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4039 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4042 l
= strlen(contents
);
4044 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
4045 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4046 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
4049 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4053 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4054 c
->index
+= 1 + l
+ 1;
4059 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
4061 const char *contents
) {
4062 struct bus_container
*c
, *w
;
4063 uint32_t *array_size
= NULL
;
4066 size_t *offsets
= NULL
;
4067 size_t n_offsets
= 0, item_size
= 0;
4070 assert_return(m
, -EINVAL
);
4071 assert_return(m
->sealed
, -EPERM
);
4072 assert_return(type
!= 0 || !contents
, -EINVAL
);
4074 if (type
== 0 || !contents
) {
4078 /* Allow entering into anonymous containers */
4079 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
4083 if (type
!= 0 && type
!= tt
)
4086 if (contents
&& !streq(contents
, cc
))
4094 * We enforce a global limit on container depth, that is much
4095 * higher than the 32 structs and 32 arrays the specification
4096 * mandates. This is simpler to implement for us, and we need
4097 * this only to ensure our container array doesn't grow
4098 * without bounds. We are happy to return any data from a
4099 * message as long as the data itself is valid, even if the
4100 * overall message might be not.
4102 * Note that the message signature is validated when
4103 * parsing the headers, and that validation does check the
4106 * Note that the specification defines no limits on the depth
4107 * of stacked variants, but we do.
4109 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4112 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4115 if (message_end_of_signature(m
))
4118 if (message_end_of_array(m
, m
->rindex
))
4121 c
= message_get_container(m
);
4123 signature
= strdup(contents
);
4127 c
->saved_index
= c
->index
;
4130 if (type
== SD_BUS_TYPE_ARRAY
)
4131 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4132 else if (type
== SD_BUS_TYPE_VARIANT
)
4133 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4134 else if (type
== SD_BUS_TYPE_STRUCT
)
4135 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4136 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4137 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4147 /* OK, let's fill it in */
4148 w
= m
->containers
+ m
->n_containers
++;
4149 w
->enclosing
= type
;
4150 w
->signature
= signature
;
4151 w
->peeked_signature
= NULL
;
4155 w
->begin
= m
->rindex
;
4157 /* Unary type has fixed size of 1, but virtual size of 0 */
4158 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4159 type
== SD_BUS_TYPE_STRUCT
&&
4161 w
->end
= m
->rindex
+ 0;
4163 w
->end
= m
->rindex
+ c
->item_size
;
4165 w
->array_size
= array_size
;
4166 w
->item_size
= item_size
;
4167 w
->offsets
= offsets
;
4168 w
->n_offsets
= n_offsets
;
4169 w
->offset_index
= 0;
4174 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4175 struct bus_container
*c
;
4179 assert_return(m
, -EINVAL
);
4180 assert_return(m
->sealed
, -EPERM
);
4181 assert_return(m
->n_containers
> 0, -ENXIO
);
4183 c
= message_get_container(m
);
4185 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4186 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4190 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4191 if (m
->rindex
< c
->end
)
4194 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4197 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4198 if (c
->begin
+ l
!= m
->rindex
)
4203 free(c
->peeked_signature
);
4207 c
= message_get_container(m
);
4210 c
->index
= c
->saved_index
;
4211 r
= container_next_item(m
, c
, &m
->rindex
);
4219 static void message_quit_container(sd_bus_message
*m
) {
4220 struct bus_container
*c
;
4224 assert(m
->n_containers
> 0);
4226 c
= message_get_container(m
);
4229 assert(m
->rindex
>= c
->before
);
4230 m
->rindex
= c
->before
;
4232 /* Free container */
4237 /* Correct index of new top-level container */
4238 c
= message_get_container(m
);
4239 c
->index
= c
->saved_index
;
4242 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4243 struct bus_container
*c
;
4246 assert_return(m
, -EINVAL
);
4247 assert_return(m
->sealed
, -EPERM
);
4249 if (message_end_of_signature(m
))
4252 if (message_end_of_array(m
, m
->rindex
))
4255 c
= message_get_container(m
);
4257 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4261 *type
= c
->signature
[c
->index
];
4265 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4271 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4277 sig
= strndup(c
->signature
+ c
->index
+ 1, l
);
4281 free(c
->peeked_signature
);
4282 *contents
= c
->peeked_signature
= sig
;
4286 *type
= SD_BUS_TYPE_ARRAY
;
4291 if (c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
||
4292 c
->signature
[c
->index
] == SD_BUS_TYPE_DICT_ENTRY_BEGIN
) {
4298 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4303 sig
= strndup(c
->signature
+ c
->index
+ 1, l
- 2);
4307 free(c
->peeked_signature
);
4308 *contents
= c
->peeked_signature
= sig
;
4312 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4317 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4321 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4324 if (c
->item_size
< 2)
4327 /* Look for the NUL delimiter that
4328 separates the payload from the
4329 signature. Since the body might be
4330 in a different part that then the
4331 signature we map byte by byte. */
4333 for (k
= 2; k
<= c
->item_size
; k
++) {
4336 where
= m
->rindex
+ c
->item_size
- k
;
4337 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4341 if (*(char*) q
== 0)
4345 if (k
> c
->item_size
)
4348 free(c
->peeked_signature
);
4349 c
->peeked_signature
= strndup((char*) q
+ 1, k
- 1);
4350 if (!c
->peeked_signature
)
4353 if (!signature_is_valid(c
->peeked_signature
, true))
4356 *contents
= c
->peeked_signature
;
4361 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4366 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4370 if (!validate_signature(q
, l
))
4378 *type
= SD_BUS_TYPE_VARIANT
;
4393 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4394 struct bus_container
*c
;
4396 assert_return(m
, -EINVAL
);
4397 assert_return(m
->sealed
, -EPERM
);
4400 message_reset_containers(m
);
4403 c
= message_get_container(m
);
4405 c
= message_get_container(m
);
4407 c
->offset_index
= 0;
4409 m
->rindex
= c
->begin
;
4412 c
->offset_index
= 0;
4413 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4415 return !isempty(c
->signature
);
4418 static int message_read_ap(
4423 unsigned n_array
, n_struct
;
4424 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4425 unsigned stack_ptr
= 0;
4426 unsigned n_loop
= 0;
4434 /* Ideally, we'd just call ourselves recursively on every
4435 * complex type. However, the state of a va_list that is
4436 * passed to a function is undefined after that function
4437 * returns. This means we need to docode the va_list linearly
4438 * in a single stackframe. We hence implement our own
4439 * home-grown stack in an array. */
4441 n_array
= (unsigned) -1; /* length of current array entries */
4442 n_struct
= strlen(types
); /* length of current struct contents signature */
4449 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4450 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4456 r
= sd_bus_message_exit_container(m
);
4464 if (n_array
!= (unsigned) -1)
4473 case SD_BUS_TYPE_BYTE
:
4474 case SD_BUS_TYPE_BOOLEAN
:
4475 case SD_BUS_TYPE_INT16
:
4476 case SD_BUS_TYPE_UINT16
:
4477 case SD_BUS_TYPE_INT32
:
4478 case SD_BUS_TYPE_UINT32
:
4479 case SD_BUS_TYPE_INT64
:
4480 case SD_BUS_TYPE_UINT64
:
4481 case SD_BUS_TYPE_DOUBLE
:
4482 case SD_BUS_TYPE_STRING
:
4483 case SD_BUS_TYPE_OBJECT_PATH
:
4484 case SD_BUS_TYPE_SIGNATURE
:
4485 case SD_BUS_TYPE_UNIX_FD
: {
4488 p
= va_arg(ap
, void*);
4489 r
= sd_bus_message_read_basic(m
, *t
, p
);
4502 case SD_BUS_TYPE_ARRAY
: {
4505 r
= signature_element_length(t
+ 1, &k
);
4511 memcpy(s
, t
+ 1, k
);
4514 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4525 if (n_array
== (unsigned) -1) {
4530 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4536 n_array
= va_arg(ap
, unsigned);
4541 case SD_BUS_TYPE_VARIANT
: {
4544 s
= va_arg(ap
, const char *);
4548 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4558 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4563 n_struct
= strlen(s
);
4564 n_array
= (unsigned) -1;
4569 case SD_BUS_TYPE_STRUCT_BEGIN
:
4570 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4573 r
= signature_element_length(t
, &k
);
4579 memcpy(s
, t
+ 1, k
- 2);
4582 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4592 if (n_array
== (unsigned) -1) {
4597 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4603 n_array
= (unsigned) -1;
4616 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4620 assert_return(m
, -EINVAL
);
4621 assert_return(m
->sealed
, -EPERM
);
4622 assert_return(types
, -EINVAL
);
4624 va_start(ap
, types
);
4625 r
= message_read_ap(m
, types
, ap
);
4631 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4634 assert_return(m
, -EINVAL
);
4635 assert_return(m
->sealed
, -EPERM
);
4637 /* If types is NULL, read exactly one element */
4639 struct bus_container
*c
;
4642 if (message_end_of_signature(m
))
4645 if (message_end_of_array(m
, m
->rindex
))
4648 c
= message_get_container(m
);
4650 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4654 types
= strndupa(c
->signature
+ c
->index
, l
);
4659 case 0: /* Nothing to drop */
4662 case SD_BUS_TYPE_BYTE
:
4663 case SD_BUS_TYPE_BOOLEAN
:
4664 case SD_BUS_TYPE_INT16
:
4665 case SD_BUS_TYPE_UINT16
:
4666 case SD_BUS_TYPE_INT32
:
4667 case SD_BUS_TYPE_UINT32
:
4668 case SD_BUS_TYPE_INT64
:
4669 case SD_BUS_TYPE_UINT64
:
4670 case SD_BUS_TYPE_DOUBLE
:
4671 case SD_BUS_TYPE_STRING
:
4672 case SD_BUS_TYPE_OBJECT_PATH
:
4673 case SD_BUS_TYPE_SIGNATURE
:
4674 case SD_BUS_TYPE_UNIX_FD
:
4676 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4680 r
= sd_bus_message_skip(m
, types
+ 1);
4686 case SD_BUS_TYPE_ARRAY
: {
4689 r
= signature_element_length(types
+ 1, &k
);
4695 memcpy(s
, types
+1, k
);
4698 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4703 r
= sd_bus_message_skip(m
, s
);
4710 r
= sd_bus_message_exit_container(m
);
4715 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4722 case SD_BUS_TYPE_VARIANT
: {
4723 const char *contents
;
4726 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4730 if (x
!= SD_BUS_TYPE_VARIANT
)
4733 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4737 r
= sd_bus_message_skip(m
, contents
);
4742 r
= sd_bus_message_exit_container(m
);
4746 r
= sd_bus_message_skip(m
, types
+ 1);
4753 case SD_BUS_TYPE_STRUCT_BEGIN
:
4754 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4757 r
= signature_element_length(types
, &k
);
4763 memcpy(s
, types
+1, k
-2);
4766 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4770 r
= sd_bus_message_skip(m
, s
);
4774 r
= sd_bus_message_exit_container(m
);
4779 r
= sd_bus_message_skip(m
, types
+ k
);
4791 _public_
int sd_bus_message_read_array(
4797 struct bus_container
*c
;
4803 assert_return(m
, -EINVAL
);
4804 assert_return(m
->sealed
, -EPERM
);
4805 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4806 assert_return(ptr
, -EINVAL
);
4807 assert_return(size
, -EINVAL
);
4808 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4810 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4814 c
= message_get_container(m
);
4816 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4817 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4821 sz
= c
->end
- c
->begin
;
4823 align
= bus_type_get_alignment(type
);
4827 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4831 /* Zero length array, let's return some aligned
4832 * pointer that is not NULL */
4833 p
= (uint8_t*) NULL
+ align
;
4835 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4840 r
= sd_bus_message_exit_container(m
);
4844 *ptr
= (const void*) p
;
4850 message_quit_container(m
);
4854 static int message_peek_fields(
4865 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4868 static int message_peek_field_uint32(
4880 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4883 /* identical for gvariant and dbus1 */
4885 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4890 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4895 static int message_peek_field_uint64(
4907 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4910 /* identical for gvariant and dbus1 */
4912 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4917 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4922 static int message_peek_field_string(
4924 bool (*validate
)(const char *p
),
4936 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4941 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4947 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4951 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4957 if (!validate_nul(q
, l
))
4963 if (!validate_string(q
, l
))
4973 static int message_peek_field_signature(
4986 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4991 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4997 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
5002 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
5007 if (!validate_signature(q
, l
))
5016 static int message_skip_fields(
5019 uint32_t array_size
,
5020 const char **signature
) {
5022 size_t original_index
;
5028 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
5030 original_index
= *ri
;
5036 if (array_size
!= (uint32_t) -1 &&
5037 array_size
<= *ri
- original_index
)
5044 if (t
== SD_BUS_TYPE_STRING
) {
5046 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
5052 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
5054 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
5060 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
5062 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
5068 } else if (bus_type_is_basic(t
)) {
5071 align
= bus_type_get_alignment(t
);
5072 k
= bus_type_get_size(t
);
5073 assert(align
> 0 && k
> 0);
5075 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
5081 } else if (t
== SD_BUS_TYPE_ARRAY
) {
5083 r
= signature_element_length(*signature
+1, &l
);
5093 strncpy(sig
, *signature
+ 1, l
-1);
5096 alignment
= bus_type_get_alignment(sig
[0]);
5100 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5103 if (nas
> BUS_ARRAY_MAX_SIZE
)
5106 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5110 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5115 (*signature
) += 1 + l
;
5117 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5120 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5124 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5130 } else if (t
== SD_BUS_TYPE_STRUCT
||
5131 t
== SD_BUS_TYPE_DICT_ENTRY
) {
5133 r
= signature_element_length(*signature
, &l
);
5140 strncpy(sig
, *signature
+ 1, l
-1);
5143 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5154 int bus_message_parse_fields(sd_bus_message
*m
) {
5157 uint32_t unix_fds
= 0;
5158 bool unix_fds_set
= false;
5159 void *offsets
= NULL
;
5160 unsigned n_offsets
= 0;
5166 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5169 /* Read the signature from the end of the body variant first */
5170 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5171 if (m
->footer_accessible
< 1 + sz
)
5174 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5176 if (p
< (char*) m
->footer
)
5183 /* We found the beginning of the signature
5184 * string, yay! We require the body to be a
5185 * structure, so verify it and then strip the
5186 * opening/closing brackets. */
5188 l
= ((char*) m
->footer
+ m
->footer_accessible
) - p
- (1 + sz
);
5190 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5191 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5194 c
= strndup(p
+ 1 + 1, l
- 2);
5198 free(m
->root_container
.signature
);
5199 m
->root_container
.signature
= c
;
5206 /* Calculate the actual user body size, by removing
5207 * the trailing variant signature and struct offset
5209 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5211 /* Pull out the offset table for the fields array */
5212 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5217 ri
= m
->fields_size
- sz
;
5218 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5222 framing
= bus_gvariant_read_word_le(q
, sz
);
5223 if (framing
>= m
->fields_size
- sz
)
5225 if ((m
->fields_size
- framing
) % sz
!= 0)
5229 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5233 n_offsets
= (m
->fields_size
- framing
) / sz
;
5236 m
->user_body_size
= m
->body_size
;
5239 while (ri
< m
->fields_size
) {
5240 _cleanup_free_
char *sig
= NULL
;
5241 const char *signature
;
5242 uint64_t field_type
;
5243 size_t item_size
= (size_t) -1;
5245 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5254 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5256 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5260 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5264 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5271 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5276 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5281 where
= ri
= ALIGN_TO(ri
, 8);
5282 item_size
= end
- ri
;
5283 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5287 b
= memrchr(q
, 0, item_size
);
5291 sig
= strndup(b
+1, item_size
- (b
+1-(char*) q
));
5296 item_size
= b
- (char*) q
;
5298 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5303 switch (field_type
) {
5305 case _BUS_MESSAGE_HEADER_INVALID
:
5308 case BUS_MESSAGE_HEADER_PATH
:
5313 if (!streq(signature
, "o"))
5316 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5319 case BUS_MESSAGE_HEADER_INTERFACE
:
5324 if (!streq(signature
, "s"))
5327 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5330 case BUS_MESSAGE_HEADER_MEMBER
:
5335 if (!streq(signature
, "s"))
5338 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5341 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5346 if (!streq(signature
, "s"))
5349 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5351 m
->error
._need_free
= -1;
5355 case BUS_MESSAGE_HEADER_DESTINATION
:
5360 if (!streq(signature
, "s"))
5363 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5366 case BUS_MESSAGE_HEADER_SENDER
:
5371 if (!streq(signature
, "s"))
5374 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5376 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
&& !m
->bus
->is_kernel
) {
5377 m
->creds
.unique_name
= (char*) m
->sender
;
5378 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5384 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5388 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5391 if (m
->root_container
.signature
)
5394 if (!streq(signature
, "g"))
5397 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5405 free(m
->root_container
.signature
);
5406 m
->root_container
.signature
= c
;
5410 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5412 if (m
->reply_cookie
!= 0)
5415 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5416 /* 64bit on dbus2 */
5418 if (!streq(signature
, "t"))
5421 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5425 /* 32bit on dbus1 */
5428 if (!streq(signature
, "u"))
5431 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5435 m
->reply_cookie
= serial
;
5438 if (m
->reply_cookie
== 0)
5443 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5447 if (!streq(signature
, "u"))
5450 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5454 unix_fds_set
= true;
5458 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5459 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5468 if (m
->n_fds
!= unix_fds
)
5471 switch (m
->header
->type
) {
5473 case SD_BUS_MESSAGE_SIGNAL
:
5474 if (!m
->path
|| !m
->interface
|| !m
->member
)
5477 if (m
->reply_cookie
!= 0)
5482 case SD_BUS_MESSAGE_METHOD_CALL
:
5484 if (!m
->path
|| !m
->member
)
5487 if (m
->reply_cookie
!= 0)
5492 case SD_BUS_MESSAGE_METHOD_RETURN
:
5494 if (m
->reply_cookie
== 0)
5498 case SD_BUS_MESSAGE_METHOD_ERROR
:
5500 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5505 /* Refuse non-local messages that claim they are local */
5506 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5508 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5510 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5513 m
->root_container
.end
= m
->user_body_size
;
5515 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5516 r
= build_struct_offsets(
5518 m
->root_container
.signature
,
5520 &m
->root_container
.item_size
,
5521 &m
->root_container
.offsets
,
5522 &m
->root_container
.n_offsets
);
5527 /* Try to read the error message, but if we can't it's a non-issue */
5528 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5529 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5534 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5535 assert_return(m
, -EINVAL
);
5536 assert_return(destination
, -EINVAL
);
5537 assert_return(!m
->sealed
, -EPERM
);
5538 assert_return(!m
->destination
, -EEXIST
);
5540 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5543 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5547 struct bus_body_part
*part
;
5553 total
= BUS_MESSAGE_SIZE(m
);
5559 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5560 MESSAGE_FOREACH_PART(part
, i
, m
)
5561 e
= mempcpy(e
, part
->data
, part
->size
);
5563 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5571 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5578 r
= sd_bus_message_enter_container(m
, 'a', "s");
5582 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5583 r
= strv_extend(l
, s
);
5590 r
= sd_bus_message_exit_container(m
);
5597 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5601 assert_return(m
, -EINVAL
);
5602 assert_return(m
->sealed
, -EPERM
);
5603 assert_return(l
, -EINVAL
);
5605 r
= bus_message_read_strv_extend(m
, &strv
);
5615 static int bus_message_get_arg_skip(
5619 const char **_contents
) {
5624 r
= sd_bus_message_rewind(m
, true);
5629 const char *contents
;
5632 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5638 /* Don't match against arguments after the first one we don't understand */
5639 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5640 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5645 *_contents
= contents
;
5651 r
= sd_bus_message_skip(m
, NULL
);
5658 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5665 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5669 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5672 return sd_bus_message_read_basic(m
, type
, str
);
5675 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5676 const char *contents
;
5683 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5687 if (type
!= SD_BUS_TYPE_ARRAY
)
5689 if (!STR_IN_SET(contents
, "s", "o", "g"))
5692 return sd_bus_message_read_strv(m
, strv
);
5695 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5696 assert_return(m
, EINVAL
);
5698 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5701 return sd_bus_error_get_errno(&m
->error
);
5704 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5705 struct bus_container
*c
;
5707 assert_return(m
, NULL
);
5709 c
= complete
? &m
->root_container
: message_get_container(m
);
5710 return strempty(c
->signature
);
5713 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5714 assert_return(m
, -EINVAL
);
5716 return isempty(m
->root_container
.signature
);
5719 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5720 assert_return(m
, -EINVAL
);
5722 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5725 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5726 bool done_something
= false;
5729 assert_return(m
, -EINVAL
);
5730 assert_return(source
, -EINVAL
);
5731 assert_return(!m
->sealed
, -EPERM
);
5732 assert_return(source
->sealed
, -EPERM
);
5735 const char *contents
;
5750 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5756 done_something
= true;
5758 if (bus_type_is_container(type
) > 0) {
5760 r
= sd_bus_message_enter_container(source
, type
, contents
);
5764 r
= sd_bus_message_open_container(m
, type
, contents
);
5768 r
= sd_bus_message_copy(m
, source
, true);
5772 r
= sd_bus_message_close_container(m
);
5776 r
= sd_bus_message_exit_container(source
);
5783 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5789 if (type
== SD_BUS_TYPE_OBJECT_PATH
||
5790 type
== SD_BUS_TYPE_SIGNATURE
||
5791 type
== SD_BUS_TYPE_STRING
)
5792 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5794 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5801 return done_something
;
5804 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5809 assert_return(m
, -EINVAL
);
5810 assert_return(m
->sealed
, -EPERM
);
5811 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5812 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5813 assert_return(type
|| contents
, -EINVAL
);
5814 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5816 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5820 if (type
!= 0 && type
!= t
)
5823 if (contents
&& !streq_ptr(contents
, c
))
5829 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5830 assert_return(m
, NULL
);
5835 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5836 _cleanup_bus_message_unref_ sd_bus_message
*n
= NULL
;
5844 switch ((*m
)->header
->type
) {
5846 case SD_BUS_MESSAGE_SIGNAL
:
5847 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5853 case SD_BUS_MESSAGE_METHOD_CALL
:
5854 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5860 case SD_BUS_MESSAGE_METHOD_RETURN
:
5861 case SD_BUS_MESSAGE_METHOD_ERROR
:
5863 n
= message_new(bus
, (*m
)->header
->type
);
5867 n
->reply_cookie
= (*m
)->reply_cookie
;
5869 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5873 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5874 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5878 n
->error
._need_free
= -1;
5887 if ((*m
)->destination
&& !n
->destination
) {
5888 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5893 if ((*m
)->sender
&& !n
->sender
) {
5894 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5899 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5901 r
= sd_bus_message_copy(n
, *m
, true);
5905 timeout
= (*m
)->timeout
;
5906 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
))
5907 timeout
= BUS_DEFAULT_TIMEOUT
;
5909 r
= bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5913 sd_bus_message_unref(*m
);
5920 int bus_message_append_sender(sd_bus_message
*m
, const char *sender
) {
5924 assert_return(!m
->sealed
, -EPERM
);
5925 assert_return(!m
->sender
, -EPERM
);
5927 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5930 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5931 assert_return(m
, -EINVAL
);
5932 assert_return(priority
, -EINVAL
);
5934 *priority
= m
->priority
;
5938 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5939 assert_return(m
, -EINVAL
);
5940 assert_return(!m
->sealed
, -EPERM
);
5942 m
->priority
= priority
;