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/>.
28 #include "bus-gvariant.h"
29 #include "bus-internal.h"
30 #include "bus-signature.h"
33 #include "memfd-util.h"
34 #include "string-util.h"
36 #include "time-util.h"
39 #include "bus-message.h"
41 static int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
);
43 static void *adjust_pointer(const void *p
, void *old_base
, size_t sz
, void *new_base
) {
48 if (old_base
== new_base
)
51 if ((uint8_t*) p
< (uint8_t*) old_base
)
54 if ((uint8_t*) p
>= (uint8_t*) old_base
+ sz
)
57 return (uint8_t*) new_base
+ ((uint8_t*) p
- (uint8_t*) old_base
);
60 static void message_free_part(sd_bus_message
*m
, struct bus_body_part
*part
) {
64 if (part
->memfd
>= 0) {
65 /* If we can reuse the memfd, try that. For that it
66 * can't be sealed yet. */
69 assert(part
->memfd_offset
== 0);
70 assert(part
->data
== part
->mmap_begin
);
71 bus_kernel_push_memfd(m
->bus
, part
->memfd
, part
->data
, part
->mapped
, part
->allocated
);
74 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
76 safe_close(part
->memfd
);
79 } else if (part
->munmap_this
)
80 munmap(part
->mmap_begin
, part
->mapped
);
81 else if (part
->free_this
)
88 static void message_reset_parts(sd_bus_message
*m
) {
89 struct bus_body_part
*part
;
94 while (m
->n_body_parts
> 0) {
95 struct bus_body_part
*next
= part
->next
;
96 message_free_part(m
, part
);
103 m
->cached_rindex_part
= NULL
;
104 m
->cached_rindex_part_begin
= 0;
107 static void message_reset_containers(sd_bus_message
*m
) {
112 for (i
= 0; i
< m
->n_containers
; i
++) {
113 free(m
->containers
[i
].signature
);
114 free(m
->containers
[i
].offsets
);
117 m
->containers
= mfree(m
->containers
);
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
);
1028 if (!sd_bus_error_is_set(&m
->error
))
1034 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
1035 assert_return(m
, -EINVAL
);
1036 assert_return(usec
, -EINVAL
);
1038 if (m
->monotonic
<= 0)
1041 *usec
= m
->monotonic
;
1045 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1046 assert_return(m
, -EINVAL
);
1047 assert_return(usec
, -EINVAL
);
1049 if (m
->realtime
<= 0)
1052 *usec
= m
->realtime
;
1056 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1057 assert_return(m
, -EINVAL
);
1058 assert_return(seqnum
, -EINVAL
);
1063 *seqnum
= m
->seqnum
;
1067 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1068 assert_return(m
, NULL
);
1070 if (m
->creds
.mask
== 0)
1076 _public_
int sd_bus_message_is_signal(
1078 const char *interface
,
1079 const char *member
) {
1081 assert_return(m
, -EINVAL
);
1083 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1086 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1089 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1095 _public_
int sd_bus_message_is_method_call(
1097 const char *interface
,
1098 const char *member
) {
1100 assert_return(m
, -EINVAL
);
1102 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1105 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1108 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1114 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1115 assert_return(m
, -EINVAL
);
1117 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1120 if (name
&& (!m
->error
.name
|| !streq(m
->error
.name
, name
)))
1126 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1127 assert_return(m
, -EINVAL
);
1128 assert_return(!m
->sealed
, -EPERM
);
1129 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1132 m
->header
->flags
&= ~BUS_MESSAGE_NO_REPLY_EXPECTED
;
1134 m
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
1139 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1140 assert_return(m
, -EINVAL
);
1141 assert_return(!m
->sealed
, -EPERM
);
1144 m
->header
->flags
&= ~BUS_MESSAGE_NO_AUTO_START
;
1146 m
->header
->flags
|= BUS_MESSAGE_NO_AUTO_START
;
1151 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1152 assert_return(m
, -EINVAL
);
1153 assert_return(!m
->sealed
, -EPERM
);
1156 m
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
1158 m
->header
->flags
&= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
1163 static struct bus_container
*message_get_container(sd_bus_message
*m
) {
1166 if (m
->n_containers
== 0)
1167 return &m
->root_container
;
1169 assert(m
->containers
);
1170 return m
->containers
+ m
->n_containers
- 1;
1173 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1174 struct bus_body_part
*part
;
1181 if (m
->n_body_parts
<= 0) {
1185 assert(m
->body_end
);
1187 part
= new0(struct bus_body_part
, 1);
1193 m
->body_end
->next
= part
;
1203 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1208 /* All other fields can be left in their defaults */
1209 assert(!part
->data
);
1210 assert(part
->memfd
< 0);
1213 part
->is_zero
= true;
1214 part
->sealed
= true;
1217 static int part_make_space(
1218 struct sd_bus_message
*m
,
1219 struct bus_body_part
*part
,
1228 assert(!part
->sealed
);
1233 if (!part
->data
&& part
->memfd
< 0) {
1234 part
->memfd
= bus_kernel_pop_memfd(m
->bus
, &part
->data
, &part
->mapped
, &part
->allocated
);
1235 part
->mmap_begin
= part
->data
;
1238 if (part
->memfd
>= 0) {
1240 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1241 uint64_t new_allocated
;
1243 new_allocated
= PAGE_ALIGN(sz
> 0 ? 2 * sz
: 1);
1244 r
= memfd_set_size(part
->memfd
, new_allocated
);
1250 part
->allocated
= new_allocated
;
1253 if (!part
->data
|| sz
> part
->mapped
) {
1256 psz
= PAGE_ALIGN(sz
> 0 ? sz
: 1);
1257 if (part
->mapped
<= 0)
1258 n
= mmap(NULL
, psz
, PROT_READ
|PROT_WRITE
, MAP_SHARED
, part
->memfd
, 0);
1260 n
= mremap(part
->mmap_begin
, part
->mapped
, psz
, MREMAP_MAYMOVE
);
1262 if (n
== MAP_FAILED
) {
1267 part
->mmap_begin
= part
->data
= n
;
1269 part
->memfd_offset
= 0;
1272 part
->munmap_this
= true;
1274 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1275 size_t new_allocated
;
1277 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1278 n
= realloc(part
->data
, new_allocated
);
1285 part
->allocated
= new_allocated
;
1286 part
->free_this
= true;
1291 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1297 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1298 struct bus_container
*c
;
1301 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1303 /* Add offset to current container, unless this is the first
1304 * item in it, which will have the 0 offset, which we can
1306 c
= message_get_container(m
);
1308 if (!c
->need_offsets
)
1311 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1314 c
->offsets
[c
->n_offsets
++] = offset
;
1318 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1319 struct bus_container
*c
;
1326 /* Update counters */
1327 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++) {
1330 *c
->array_size
+= expand
;
1334 static void *message_extend_body(
1339 bool force_inline
) {
1341 size_t start_body
, end_body
, padding
, added
;
1352 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1353 end_body
= start_body
+ sz
;
1355 padding
= start_body
- m
->body_size
;
1356 added
= padding
+ sz
;
1358 /* Check for 32bit overflows */
1359 if (end_body
> (size_t) ((uint32_t) -1) ||
1360 end_body
< start_body
) {
1366 struct bus_body_part
*part
= NULL
;
1370 m
->n_body_parts
<= 0 ||
1371 m
->body_end
->sealed
||
1372 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1373 (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 */
1377 part
= message_append_part(m
);
1381 part_zero(part
, padding
);
1384 part
= message_append_part(m
);
1388 r
= part_make_space(m
, part
, sz
, &p
);
1392 struct bus_container
*c
;
1394 size_t os
, start_part
, end_part
;
1400 start_part
= ALIGN_TO(part
->size
, align
);
1401 end_part
= start_part
+ sz
;
1403 r
= part_make_space(m
, part
, end_part
, &p
);
1408 memzero(p
, padding
);
1409 p
= (uint8_t*) p
+ padding
;
1412 /* Readjust pointers */
1413 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1414 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1416 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1419 /* Return something that is not NULL and is aligned */
1420 p
= (uint8_t *) NULL
+ align
;
1422 m
->body_size
= end_body
;
1423 message_extend_containers(m
, added
);
1426 r
= message_add_offset(m
, end_body
);
1436 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1447 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1451 f
= realloc(m
->fds
, sizeof(int) * (m
->n_fds
+ 1));
1459 m
->fds
[m
->n_fds
] = copy
;
1465 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1466 _cleanup_close_
int fd
= -1;
1467 struct bus_container
*c
;
1471 assert_return(m
, -EINVAL
);
1472 assert_return(!m
->sealed
, -EPERM
);
1473 assert_return(bus_type_is_basic(type
), -EINVAL
);
1474 assert_return(!m
->poisoned
, -ESTALE
);
1476 c
= message_get_container(m
);
1478 if (c
->signature
&& c
->signature
[c
->index
]) {
1479 /* Container signature is already set */
1481 if (c
->signature
[c
->index
] != type
)
1486 /* Maybe we can append to the signature? But only if this is the top-level container */
1487 if (c
->enclosing
!= 0)
1490 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1497 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1503 case SD_BUS_TYPE_SIGNATURE
:
1504 case SD_BUS_TYPE_STRING
:
1507 /* Fall through... */
1508 case SD_BUS_TYPE_OBJECT_PATH
:
1516 case SD_BUS_TYPE_BOOLEAN
:
1518 u8
= p
&& *(int*) p
;
1524 case SD_BUS_TYPE_UNIX_FD
:
1529 fd
= message_push_fd(m
, *(int*) p
);
1540 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1541 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1548 a
= message_extend_body(m
, align
, sz
, true, false);
1555 *stored
= (const uint8_t*) a
;
1562 case SD_BUS_TYPE_STRING
:
1563 /* To make things easy we'll serialize a NULL string
1564 * into the empty string */
1567 /* Fall through... */
1568 case SD_BUS_TYPE_OBJECT_PATH
:
1574 sz
= 4 + strlen(p
) + 1;
1577 case SD_BUS_TYPE_SIGNATURE
:
1582 sz
= 1 + strlen(p
) + 1;
1585 case SD_BUS_TYPE_BOOLEAN
:
1587 u32
= p
&& *(int*) p
;
1593 case SD_BUS_TYPE_UNIX_FD
:
1598 fd
= message_push_fd(m
, *(int*) p
);
1609 align
= bus_type_get_alignment(type
);
1610 sz
= bus_type_get_size(type
);
1617 a
= message_extend_body(m
, align
, sz
, false, false);
1621 if (type
== SD_BUS_TYPE_STRING
|| type
== SD_BUS_TYPE_OBJECT_PATH
) {
1622 *(uint32_t*) a
= sz
- 5;
1623 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1626 *stored
= (const uint8_t*) a
+ 4;
1628 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1629 *(uint8_t*) a
= sz
- 2;
1630 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1633 *stored
= (const uint8_t*) a
+ 1;
1642 if (type
== SD_BUS_TYPE_UNIX_FD
)
1645 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1652 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1653 return message_append_basic(m
, type
, p
, NULL
);
1656 _public_
int sd_bus_message_append_string_space(
1661 struct bus_container
*c
;
1664 assert_return(m
, -EINVAL
);
1665 assert_return(s
, -EINVAL
);
1666 assert_return(!m
->sealed
, -EPERM
);
1667 assert_return(!m
->poisoned
, -ESTALE
);
1669 c
= message_get_container(m
);
1671 if (c
->signature
&& c
->signature
[c
->index
]) {
1672 /* Container signature is already set */
1674 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1679 /* Maybe we can append to the signature? But only if this is the top-level container */
1680 if (c
->enclosing
!= 0)
1683 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1690 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1691 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1697 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1701 *(uint32_t*) a
= size
;
1707 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1713 _public_
int sd_bus_message_append_string_iovec(
1715 const struct iovec
*iov
,
1723 assert_return(m
, -EINVAL
);
1724 assert_return(!m
->sealed
, -EPERM
);
1725 assert_return(iov
|| n
== 0, -EINVAL
);
1726 assert_return(!m
->poisoned
, -ESTALE
);
1728 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1730 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1734 for (i
= 0; i
< n
; i
++) {
1736 if (iov
[i
].iov_base
)
1737 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1739 memset(p
, ' ', iov
[i
].iov_len
);
1741 p
+= iov
[i
].iov_len
;
1747 static int bus_message_open_array(
1749 struct bus_container
*c
,
1750 const char *contents
,
1751 uint32_t **array_size
,
1753 bool *need_offsets
) {
1763 assert(need_offsets
);
1765 if (!signature_is_single(contents
, true))
1768 if (c
->signature
&& c
->signature
[c
->index
]) {
1770 /* Verify the existing signature */
1772 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1775 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1778 nindex
= c
->index
+ 1 + strlen(contents
);
1782 if (c
->enclosing
!= 0)
1785 /* Extend the existing signature */
1787 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1793 nindex
= e
- c
->signature
;
1796 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1797 alignment
= bus_gvariant_get_alignment(contents
);
1801 /* Add alignment padding and add to offset list */
1802 if (!message_extend_body(m
, alignment
, 0, false, false))
1805 r
= bus_gvariant_is_fixed_size(contents
);
1809 *begin
= m
->body_size
;
1810 *need_offsets
= r
== 0;
1814 struct bus_body_part
*o
;
1816 alignment
= bus_type_get_alignment(contents
[0]);
1820 a
= message_extend_body(m
, 4, 4, false, false);
1825 op
= m
->body_end
->data
;
1826 os
= m
->body_end
->size
;
1828 /* Add alignment between size and first element */
1829 if (!message_extend_body(m
, alignment
, 0, false, false))
1832 /* location of array size might have changed so let's readjust a */
1833 if (o
== m
->body_end
)
1834 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1840 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1846 static int bus_message_open_variant(
1848 struct bus_container
*c
,
1849 const char *contents
) {
1855 if (!signature_is_single(contents
, false))
1858 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1861 if (c
->signature
&& c
->signature
[c
->index
]) {
1863 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1869 if (c
->enclosing
!= 0)
1872 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1879 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1880 /* Variants are always aligned to 8 */
1882 if (!message_extend_body(m
, 8, 0, false, false))
1889 l
= strlen(contents
);
1890 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1895 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1898 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1904 static int bus_message_open_struct(
1906 struct bus_container
*c
,
1907 const char *contents
,
1909 bool *need_offsets
) {
1918 assert(need_offsets
);
1920 if (!signature_is_valid(contents
, false))
1923 if (c
->signature
&& c
->signature
[c
->index
]) {
1926 l
= strlen(contents
);
1928 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1929 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1930 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1933 nindex
= c
->index
+ 1 + l
+ 1;
1937 if (c
->enclosing
!= 0)
1940 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1946 nindex
= e
- c
->signature
;
1949 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1952 alignment
= bus_gvariant_get_alignment(contents
);
1956 if (!message_extend_body(m
, alignment
, 0, false, false))
1959 r
= bus_gvariant_is_fixed_size(contents
);
1963 *begin
= m
->body_size
;
1964 *need_offsets
= r
== 0;
1966 /* Align contents to 8 byte boundary */
1967 if (!message_extend_body(m
, 8, 0, false, false))
1971 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1977 static int bus_message_open_dict_entry(
1979 struct bus_container
*c
,
1980 const char *contents
,
1982 bool *need_offsets
) {
1990 assert(need_offsets
);
1992 if (!signature_is_pair(contents
))
1995 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1998 if (c
->signature
&& c
->signature
[c
->index
]) {
2001 l
= strlen(contents
);
2003 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
2004 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
2005 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
2010 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2013 alignment
= bus_gvariant_get_alignment(contents
);
2017 if (!message_extend_body(m
, alignment
, 0, false, false))
2020 r
= bus_gvariant_is_fixed_size(contents
);
2024 *begin
= m
->body_size
;
2025 *need_offsets
= r
== 0;
2027 /* Align contents to 8 byte boundary */
2028 if (!message_extend_body(m
, 8, 0, false, false))
2035 _public_
int sd_bus_message_open_container(
2038 const char *contents
) {
2040 struct bus_container
*c
, *w
;
2041 uint32_t *array_size
= NULL
;
2043 size_t before
, begin
= 0;
2044 bool need_offsets
= false;
2047 assert_return(m
, -EINVAL
);
2048 assert_return(!m
->sealed
, -EPERM
);
2049 assert_return(contents
, -EINVAL
);
2050 assert_return(!m
->poisoned
, -ESTALE
);
2052 /* Make sure we have space for one more container */
2053 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
2058 c
= message_get_container(m
);
2060 signature
= strdup(contents
);
2066 /* Save old index in the parent container, in case we have to
2067 * abort this container */
2068 c
->saved_index
= c
->index
;
2069 before
= m
->body_size
;
2071 if (type
== SD_BUS_TYPE_ARRAY
)
2072 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
2073 else if (type
== SD_BUS_TYPE_VARIANT
)
2074 r
= bus_message_open_variant(m
, c
, contents
);
2075 else if (type
== SD_BUS_TYPE_STRUCT
)
2076 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
2077 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
2078 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
2087 /* OK, let's fill it in */
2088 w
= m
->containers
+ m
->n_containers
++;
2089 w
->enclosing
= type
;
2090 w
->signature
= signature
;
2092 w
->array_size
= array_size
;
2095 w
->n_offsets
= w
->offsets_allocated
= 0;
2097 w
->need_offsets
= need_offsets
;
2102 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2107 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2110 if (c
->need_offsets
) {
2111 size_t payload
, sz
, i
;
2114 /* Variable-width arrays */
2116 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2117 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2119 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2123 for (i
= 0; i
< c
->n_offsets
; i
++)
2124 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2128 /* Fixed-width or empty arrays */
2130 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2138 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2144 assert(c
->signature
);
2146 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2149 l
= strlen(c
->signature
);
2151 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2156 memcpy(a
+1, c
->signature
, l
);
2161 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2162 bool fixed_size
= true;
2163 size_t n_variable
= 0;
2172 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2175 p
= strempty(c
->signature
);
2179 r
= signature_element_length(p
, &n
);
2188 r
= bus_gvariant_is_fixed_size(t
);
2193 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2195 /* We need to add an offset for each item that has a
2196 * variable size and that is not the last one in the
2200 if (r
== 0 && p
[n
] != 0)
2207 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2208 assert(c
->need_offsets
|| n_variable
== 0);
2210 if (isempty(c
->signature
)) {
2211 /* The unary type is encoded as fixed 1 byte padding */
2212 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2217 } else if (n_variable
<= 0) {
2220 /* Structures with fixed-size members only have to be
2221 * fixed-size themselves. But gvariant requires all fixed-size
2222 * elements to be sized a multiple of their alignment. Hence,
2223 * we must *always* add final padding after the last member so
2224 * the overall size of the structure is properly aligned. */
2226 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2228 assert(alignment
> 0);
2230 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2237 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2239 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2241 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2245 p
= strempty(c
->signature
);
2246 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2250 r
= signature_element_length(p
, &n
);
2261 r
= bus_gvariant_is_fixed_size(t
);
2264 if (r
> 0 || p
[0] == 0)
2268 k
= n_variable
- 1 - j
;
2270 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2279 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2280 struct bus_container
*c
;
2283 assert_return(m
, -EINVAL
);
2284 assert_return(!m
->sealed
, -EPERM
);
2285 assert_return(m
->n_containers
> 0, -EINVAL
);
2286 assert_return(!m
->poisoned
, -ESTALE
);
2288 c
= message_get_container(m
);
2290 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2291 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2296 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2297 r
= bus_message_close_array(m
, c
);
2298 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2299 r
= bus_message_close_variant(m
, c
);
2300 else if (c
->enclosing
== SD_BUS_TYPE_STRUCT
|| c
->enclosing
== SD_BUS_TYPE_DICT_ENTRY
)
2301 r
= bus_message_close_struct(m
, c
, true);
2303 assert_not_reached("Unknown container type");
2317 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2324 stack
[*i
].types
= types
;
2325 stack
[*i
].n_struct
= n_struct
;
2326 stack
[*i
].n_array
= n_array
;
2332 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2343 *types
= stack
[*i
].types
;
2344 *n_struct
= stack
[*i
].n_struct
;
2345 *n_array
= stack
[*i
].n_array
;
2350 int bus_message_append_ap(
2355 unsigned n_array
, n_struct
;
2356 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2357 unsigned stack_ptr
= 0;
2365 n_array
= (unsigned) -1;
2366 n_struct
= strlen(types
);
2371 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2372 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2378 r
= sd_bus_message_close_container(m
);
2386 if (n_array
!= (unsigned) -1)
2395 case SD_BUS_TYPE_BYTE
: {
2398 x
= (uint8_t) va_arg(ap
, int);
2399 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2403 case SD_BUS_TYPE_BOOLEAN
:
2404 case SD_BUS_TYPE_INT32
:
2405 case SD_BUS_TYPE_UINT32
:
2406 case SD_BUS_TYPE_UNIX_FD
: {
2409 /* We assume a boolean is the same as int32_t */
2410 assert_cc(sizeof(int32_t) == sizeof(int));
2412 x
= va_arg(ap
, uint32_t);
2413 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2417 case SD_BUS_TYPE_INT16
:
2418 case SD_BUS_TYPE_UINT16
: {
2421 x
= (uint16_t) va_arg(ap
, int);
2422 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2426 case SD_BUS_TYPE_INT64
:
2427 case SD_BUS_TYPE_UINT64
: {
2430 x
= va_arg(ap
, uint64_t);
2431 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2435 case SD_BUS_TYPE_DOUBLE
: {
2438 x
= va_arg(ap
, double);
2439 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2443 case SD_BUS_TYPE_STRING
:
2444 case SD_BUS_TYPE_OBJECT_PATH
:
2445 case SD_BUS_TYPE_SIGNATURE
: {
2448 x
= va_arg(ap
, const char*);
2449 r
= sd_bus_message_append_basic(m
, *t
, x
);
2453 case SD_BUS_TYPE_ARRAY
: {
2456 r
= signature_element_length(t
+ 1, &k
);
2462 memcpy(s
, t
+ 1, k
);
2465 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2470 if (n_array
== (unsigned) -1) {
2475 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2481 n_array
= va_arg(ap
, unsigned);
2486 case SD_BUS_TYPE_VARIANT
: {
2489 s
= va_arg(ap
, const char*);
2493 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2497 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2502 n_struct
= strlen(s
);
2503 n_array
= (unsigned) -1;
2508 case SD_BUS_TYPE_STRUCT_BEGIN
:
2509 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2512 r
= signature_element_length(t
, &k
);
2519 memcpy(s
, t
+ 1, k
- 2);
2522 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2527 if (n_array
== (unsigned) -1) {
2532 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2538 n_array
= (unsigned) -1;
2554 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2558 assert_return(m
, -EINVAL
);
2559 assert_return(types
, -EINVAL
);
2560 assert_return(!m
->sealed
, -EPERM
);
2561 assert_return(!m
->poisoned
, -ESTALE
);
2563 va_start(ap
, types
);
2564 r
= bus_message_append_ap(m
, types
, ap
);
2570 _public_
int sd_bus_message_append_array_space(
2580 assert_return(m
, -EINVAL
);
2581 assert_return(!m
->sealed
, -EPERM
);
2582 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2583 assert_return(ptr
|| size
== 0, -EINVAL
);
2584 assert_return(!m
->poisoned
, -ESTALE
);
2586 /* alignment and size of the trivial types (except bool) is
2587 * identical for gvariant and dbus1 marshalling */
2588 align
= bus_type_get_alignment(type
);
2589 sz
= bus_type_get_size(type
);
2591 assert_se(align
> 0);
2597 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2601 a
= message_extend_body(m
, align
, size
, false, false);
2605 r
= sd_bus_message_close_container(m
);
2613 _public_
int sd_bus_message_append_array(
2621 assert_return(m
, -EINVAL
);
2622 assert_return(!m
->sealed
, -EPERM
);
2623 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2624 assert_return(ptr
|| size
== 0, -EINVAL
);
2625 assert_return(!m
->poisoned
, -ESTALE
);
2627 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2632 memcpy(p
, ptr
, size
);
2637 _public_
int sd_bus_message_append_array_iovec(
2640 const struct iovec
*iov
,
2648 assert_return(m
, -EINVAL
);
2649 assert_return(!m
->sealed
, -EPERM
);
2650 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2651 assert_return(iov
|| n
== 0, -EINVAL
);
2652 assert_return(!m
->poisoned
, -ESTALE
);
2654 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2656 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2660 for (i
= 0; i
< n
; i
++) {
2662 if (iov
[i
].iov_base
)
2663 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2665 memzero(p
, iov
[i
].iov_len
);
2667 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2673 _public_
int sd_bus_message_append_array_memfd(
2680 _cleanup_close_
int copy_fd
= -1;
2681 struct bus_body_part
*part
;
2687 assert_return(m
, -EINVAL
);
2688 assert_return(memfd
>= 0, -EBADF
);
2689 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2690 assert_return(size
> 0, -EINVAL
);
2691 assert_return(!m
->sealed
, -EPERM
);
2692 assert_return(!m
->poisoned
, -ESTALE
);
2694 r
= memfd_set_sealed(memfd
);
2698 copy_fd
= dup(memfd
);
2702 r
= memfd_get_size(memfd
, &real_size
);
2706 if (offset
== 0 && size
== (uint64_t) -1)
2708 else if (offset
+ size
> real_size
)
2711 align
= bus_type_get_alignment(type
);
2712 sz
= bus_type_get_size(type
);
2714 assert_se(align
> 0);
2717 if (offset
% align
!= 0)
2723 if (size
> (uint64_t) (uint32_t) -1)
2726 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2730 a
= message_extend_body(m
, align
, 0, false, false);
2734 part
= message_append_part(m
);
2738 part
->memfd
= copy_fd
;
2739 part
->memfd_offset
= offset
;
2740 part
->sealed
= true;
2744 m
->body_size
+= size
;
2745 message_extend_containers(m
, size
);
2747 return sd_bus_message_close_container(m
);
2750 _public_
int sd_bus_message_append_string_memfd(
2756 _cleanup_close_
int copy_fd
= -1;
2757 struct bus_body_part
*part
;
2758 struct bus_container
*c
;
2763 assert_return(m
, -EINVAL
);
2764 assert_return(memfd
>= 0, -EBADF
);
2765 assert_return(size
> 0, -EINVAL
);
2766 assert_return(!m
->sealed
, -EPERM
);
2767 assert_return(!m
->poisoned
, -ESTALE
);
2769 r
= memfd_set_sealed(memfd
);
2773 copy_fd
= dup(memfd
);
2777 r
= memfd_get_size(memfd
, &real_size
);
2781 if (offset
== 0 && size
== (uint64_t) -1)
2783 else if (offset
+ size
> real_size
)
2786 /* We require this to be NUL terminated */
2790 if (size
> (uint64_t) (uint32_t) -1)
2793 c
= message_get_container(m
);
2794 if (c
->signature
&& c
->signature
[c
->index
]) {
2795 /* Container signature is already set */
2797 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2802 /* Maybe we can append to the signature? But only if this is the top-level container */
2803 if (c
->enclosing
!= 0)
2806 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2813 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2814 a
= message_extend_body(m
, 4, 4, false, false);
2818 *(uint32_t*) a
= size
- 1;
2821 part
= message_append_part(m
);
2825 part
->memfd
= copy_fd
;
2826 part
->memfd_offset
= offset
;
2827 part
->sealed
= true;
2831 m
->body_size
+= size
;
2832 message_extend_containers(m
, size
);
2834 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2835 r
= message_add_offset(m
, m
->body_size
);
2842 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2848 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2852 assert_return(m
, -EINVAL
);
2853 assert_return(!m
->sealed
, -EPERM
);
2854 assert_return(!m
->poisoned
, -ESTALE
);
2856 r
= sd_bus_message_open_container(m
, 'a', "s");
2860 STRV_FOREACH(i
, l
) {
2861 r
= sd_bus_message_append_basic(m
, 's', *i
);
2866 return sd_bus_message_close_container(m
);
2869 static int bus_message_close_header(sd_bus_message
*m
) {
2873 /* The actual user data is finished now, we just complete the
2874 variant and struct now (at least on gvariant). Remember
2875 this position, so that during parsing we know where to to
2876 put the outer container end. */
2877 m
->user_body_size
= m
->body_size
;
2879 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2880 const char *signature
;
2884 /* Add offset table to end of fields array */
2885 if (m
->n_header_offsets
>= 1) {
2889 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2891 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2892 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2896 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2897 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2900 /* Add gvariant NUL byte plus signature to the end of
2901 * the body, followed by the final offset pointing to
2902 * the end of the fields array */
2904 signature
= strempty(m
->root_container
.signature
);
2905 l
= strlen(signature
);
2907 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2908 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2913 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2914 memcpy((uint8_t*) d
+ 2, signature
, l
);
2915 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2917 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2920 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2922 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2923 m
->header
->dbus1
.body_size
= m
->body_size
;
2929 int bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, usec_t timeout
) {
2930 struct bus_body_part
*part
;
2940 if (m
->n_containers
> 0)
2946 if (cookie
> 0xffffffffULL
&&
2947 !BUS_MESSAGE_IS_GVARIANT(m
))
2950 /* In vtables the return signature of method calls is listed,
2951 * let's check if they match if this is a response */
2952 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2953 m
->enforced_reply_signature
&&
2954 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2957 /* If gvariant marshalling is used we need to close the body structure */
2958 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2962 /* If there's a non-trivial signature set, then add it in
2963 * here, but only on dbus1 */
2964 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2965 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2971 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2976 r
= bus_message_close_header(m
);
2980 if (BUS_MESSAGE_IS_GVARIANT(m
))
2981 m
->header
->dbus2
.cookie
= cookie
;
2983 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2985 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout
;
2987 /* Add padding at the end of the fields part, since we know
2988 * the body needs to start at an 8 byte alignment. We made
2989 * sure we allocated enough space for this, so all we need to
2990 * do here is to zero it out. */
2991 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2993 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2995 /* If this is something we can send as memfd, then let's seal
2996 the memfd now. Note that we can send memfds as payload only
2997 for directed messages, and not for broadcasts. */
2998 if (m
->destination
&& m
->bus
->use_memfd
) {
2999 MESSAGE_FOREACH_PART(part
, i
, m
)
3000 if (part
->memfd
>= 0 &&
3002 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
3003 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
3006 /* Try to seal it if that makes
3007 * sense. First, unmap our own map to
3008 * make sure we don't keep it busy. */
3009 bus_body_part_unmap(part
);
3011 /* Then, sync up real memfd size */
3013 r
= memfd_set_size(part
->memfd
, sz
);
3017 /* Finally, try to seal */
3018 if (memfd_set_sealed(part
->memfd
) >= 0)
3019 part
->sealed
= true;
3023 m
->root_container
.end
= m
->user_body_size
;
3024 m
->root_container
.index
= 0;
3025 m
->root_container
.offset_index
= 0;
3026 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
3033 int bus_body_part_map(struct bus_body_part
*part
) {
3042 if (part
->size
<= 0)
3045 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3046 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
3047 static const uint8_t zeroes
[7] = { };
3048 part
->data
= (void*) zeroes
;
3052 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
3053 psz
= PAGE_ALIGN(part
->size
+ shift
);
3055 if (part
->memfd
>= 0)
3056 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
3057 else if (part
->is_zero
)
3058 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
3062 if (p
== MAP_FAILED
)
3066 part
->mmap_begin
= p
;
3067 part
->data
= (uint8_t*) p
+ shift
;
3068 part
->munmap_this
= true;
3073 void bus_body_part_unmap(struct bus_body_part
*part
) {
3077 if (part
->memfd
< 0)
3080 if (!part
->mmap_begin
)
3083 if (!part
->munmap_this
)
3086 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
3088 part
->mmap_begin
= NULL
;
3091 part
->munmap_this
= false;
3096 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3097 size_t k
, start
, end
;
3102 start
= ALIGN_TO((size_t) *rindex
, align
);
3103 end
= start
+ nbytes
;
3108 /* Verify that padding is 0 */
3109 for (k
= *rindex
; k
< start
; k
++)
3110 if (((const uint8_t*) p
)[k
] != 0)
3114 *r
= (uint8_t*) p
+ start
;
3121 static bool message_end_of_signature(sd_bus_message
*m
) {
3122 struct bus_container
*c
;
3126 c
= message_get_container(m
);
3127 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3130 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3131 struct bus_container
*c
;
3135 c
= message_get_container(m
);
3136 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3139 if (BUS_MESSAGE_IS_GVARIANT(m
))
3140 return index
>= c
->end
;
3142 assert(c
->array_size
);
3143 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3147 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3148 assert_return(m
, -EINVAL
);
3149 assert_return(m
->sealed
, -EPERM
);
3151 if (complete
&& m
->n_containers
> 0)
3154 if (message_end_of_signature(m
))
3157 if (message_end_of_array(m
, m
->rindex
))
3163 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3164 struct bus_body_part
*part
;
3170 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3171 part
= m
->cached_rindex_part
;
3172 begin
= m
->cached_rindex_part_begin
;
3182 if (index
+ sz
<= begin
+ part
->size
) {
3184 r
= bus_body_part_map(part
);
3189 *p
= (uint8_t*) part
->data
+ index
- begin
;
3191 m
->cached_rindex_part
= part
;
3192 m
->cached_rindex_part_begin
= begin
;
3197 begin
+= part
->size
;
3204 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3211 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3214 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3217 sz
= bus_gvariant_get_size(c
->signature
);
3221 if (c
->offset_index
+1 >= c
->n_offsets
)
3224 /* Variable-size array */
3226 alignment
= bus_gvariant_get_alignment(c
->signature
);
3227 assert(alignment
> 0);
3229 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3230 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3233 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3236 /* Fixed-size array */
3237 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3243 } else if (c
->enclosing
== 0 ||
3244 c
->enclosing
== SD_BUS_TYPE_STRUCT
||
3245 c
->enclosing
== SD_BUS_TYPE_DICT_ENTRY
) {
3250 if (c
->offset_index
+1 >= c
->n_offsets
)
3253 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3257 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3262 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3265 alignment
= bus_gvariant_get_alignment(t
);
3268 assert(alignment
> 0);
3270 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3271 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3275 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3278 assert_not_reached("Unknown container type");
3283 /* Reached the end */
3290 static int message_peek_body(
3297 size_t k
, start
, end
, padding
;
3298 struct bus_body_part
*part
;
3305 start
= ALIGN_TO((size_t) *rindex
, align
);
3306 padding
= start
- *rindex
;
3307 end
= start
+ nbytes
;
3309 if (end
> m
->user_body_size
)
3312 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3317 /* Verify padding */
3318 for (k
= 0; k
< padding
; k
++)
3323 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3324 if (!part
|| (nbytes
> 0 && !q
))
3335 static bool validate_nul(const char *s
, size_t l
) {
3337 /* Check for NUL chars in the string */
3338 if (memchr(s
, 0, l
))
3341 /* Check for NUL termination */
3348 static bool validate_string(const char *s
, size_t l
) {
3350 if (!validate_nul(s
, l
))
3353 /* Check if valid UTF8 */
3354 if (!utf8_is_valid(s
))
3360 static bool validate_signature(const char *s
, size_t l
) {
3362 if (!validate_nul(s
, l
))
3365 /* Check if valid signature */
3366 if (!signature_is_valid(s
, true))
3372 static bool validate_object_path(const char *s
, size_t l
) {
3374 if (!validate_nul(s
, l
))
3377 if (!object_path_is_valid(s
))
3383 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3384 struct bus_container
*c
;
3389 assert_return(m
, -EINVAL
);
3390 assert_return(m
->sealed
, -EPERM
);
3391 assert_return(bus_type_is_basic(type
), -EINVAL
);
3393 if (message_end_of_signature(m
))
3396 if (message_end_of_array(m
, m
->rindex
))
3399 c
= message_get_container(m
);
3400 if (c
->signature
[c
->index
] != type
)
3405 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3407 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3410 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3414 if (type
== SD_BUS_TYPE_STRING
)
3415 ok
= validate_string(q
, c
->item_size
-1);
3416 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3417 ok
= validate_object_path(q
, c
->item_size
-1);
3419 ok
= validate_signature(q
, c
->item_size
-1);
3425 *(const char**) p
= q
;
3429 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3431 if ((size_t) sz
!= c
->item_size
)
3434 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3437 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3443 case SD_BUS_TYPE_BYTE
:
3445 *(uint8_t*) p
= *(uint8_t*) q
;
3448 case SD_BUS_TYPE_BOOLEAN
:
3450 *(int*) p
= !!*(uint8_t*) q
;
3453 case SD_BUS_TYPE_INT16
:
3454 case SD_BUS_TYPE_UINT16
:
3456 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3459 case SD_BUS_TYPE_INT32
:
3460 case SD_BUS_TYPE_UINT32
:
3462 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3465 case SD_BUS_TYPE_INT64
:
3466 case SD_BUS_TYPE_UINT64
:
3467 case SD_BUS_TYPE_DOUBLE
:
3469 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3472 case SD_BUS_TYPE_UNIX_FD
: {
3475 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3480 *(int*) p
= m
->fds
[j
];
3486 assert_not_reached("unexpected type");
3490 r
= container_next_item(m
, c
, &rindex
);
3495 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3499 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3503 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3504 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3508 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3509 ok
= validate_object_path(q
, l
);
3511 ok
= validate_string(q
, l
);
3516 *(const char**) p
= q
;
3518 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3521 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3526 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3530 if (!validate_signature(q
, l
))
3534 *(const char**) p
= q
;
3539 align
= bus_type_get_alignment(type
);
3542 sz
= bus_type_get_size(type
);
3545 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3551 case SD_BUS_TYPE_BYTE
:
3553 *(uint8_t*) p
= *(uint8_t*) q
;
3556 case SD_BUS_TYPE_BOOLEAN
:
3558 *(int*) p
= !!*(uint32_t*) q
;
3561 case SD_BUS_TYPE_INT16
:
3562 case SD_BUS_TYPE_UINT16
:
3564 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3567 case SD_BUS_TYPE_INT32
:
3568 case SD_BUS_TYPE_UINT32
:
3570 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3573 case SD_BUS_TYPE_INT64
:
3574 case SD_BUS_TYPE_UINT64
:
3575 case SD_BUS_TYPE_DOUBLE
:
3577 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3580 case SD_BUS_TYPE_UNIX_FD
: {
3583 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3588 *(int*) p
= m
->fds
[j
];
3593 assert_not_reached("Unknown basic type...");
3600 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3606 static int bus_message_enter_array(
3608 struct bus_container
*c
,
3609 const char *contents
,
3610 uint32_t **array_size
,
3613 size_t *n_offsets
) {
3627 if (!signature_is_single(contents
, true))
3630 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3633 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3636 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3641 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3644 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3648 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3651 alignment
= bus_type_get_alignment(contents
[0]);
3655 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3659 *array_size
= (uint32_t*) q
;
3661 } else if (c
->item_size
<= 0) {
3663 /* gvariant: empty array */
3668 } else if (bus_gvariant_is_fixed_size(contents
)) {
3670 /* gvariant: fixed length array */
3671 *item_size
= bus_gvariant_get_size(contents
);
3676 size_t where
, p
= 0, framing
, sz
;
3679 /* gvariant: variable length array */
3680 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3682 where
= rindex
+ c
->item_size
- sz
;
3683 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3687 framing
= bus_gvariant_read_word_le(q
, sz
);
3688 if (framing
> c
->item_size
- sz
)
3690 if ((c
->item_size
- framing
) % sz
!= 0)
3693 *n_offsets
= (c
->item_size
- framing
) / sz
;
3695 where
= rindex
+ framing
;
3696 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3700 *offsets
= new(size_t, *n_offsets
);
3704 for (i
= 0; i
< *n_offsets
; i
++) {
3707 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3708 if (x
> c
->item_size
- sz
)
3713 (*offsets
)[i
] = rindex
+ x
;
3717 *item_size
= (*offsets
)[0] - rindex
;
3722 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3723 c
->index
+= 1 + strlen(contents
);
3728 static int bus_message_enter_variant(
3730 struct bus_container
*c
,
3731 const char *contents
,
3732 size_t *item_size
) {
3744 if (!signature_is_single(contents
, false))
3747 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3750 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3753 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3758 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3761 k
= strlen(contents
);
3762 if (1+k
> c
->item_size
)
3765 where
= rindex
+ c
->item_size
- (1+k
);
3766 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3770 if (*(char*) q
!= 0)
3773 if (memcmp((uint8_t*) q
+1, contents
, k
))
3776 *item_size
= c
->item_size
- (1+k
);
3779 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3784 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3788 if (!validate_signature(q
, l
))
3791 if (!streq(q
, contents
))
3797 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3803 static int build_struct_offsets(
3805 const char *signature
,
3809 size_t *n_offsets
) {
3811 unsigned n_variable
= 0, n_total
= 0, v
;
3812 size_t previous
= 0, where
;
3823 if (isempty(signature
)) {
3824 /* Unary type is encoded as *fixed* 1 byte padding */
3825 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3829 if (*(uint8_t *) q
!= 0)
3838 sz
= bus_gvariant_determine_word_size(size
, 0);
3842 /* First, loop over signature and count variable elements and
3843 * elements in general. We use this to know how large the
3844 * offset array is at the end of the structure. Note that
3845 * GVariant only stores offsets for all variable size elements
3846 * that are not the last item. */
3852 r
= signature_element_length(p
, &n
);
3861 r
= bus_gvariant_is_fixed_size(t
);
3866 if (r
== 0 && p
[n
] != 0) /* except the last item */
3873 if (size
< n_variable
* sz
)
3876 where
= m
->rindex
+ size
- (n_variable
* sz
);
3877 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3883 *offsets
= new(size_t, n_total
);
3889 /* Second, loop again and build an offset table */
3895 r
= signature_element_length(p
, &n
);
3904 k
= bus_gvariant_get_size(t
);
3912 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3915 if (m
->rindex
+ x
< previous
)
3918 /* The last item's end
3919 * is determined from
3922 x
= size
- (n_variable
* sz
);
3924 offset
= m
->rindex
+ x
;
3930 align
= bus_gvariant_get_alignment(t
);
3933 offset
= (*n_offsets
== 0 ? m
->rindex
: ALIGN_TO((*offsets
)[*n_offsets
-1], align
)) + k
;
3937 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3942 assert(*n_offsets
== n_total
);
3944 *item_size
= (*offsets
)[0] - m
->rindex
;
3948 static int enter_struct_or_dict_entry(
3950 struct bus_container
*c
,
3951 const char *contents
,
3954 size_t *n_offsets
) {
3965 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3968 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3973 /* gvariant with contents */
3974 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3979 static int bus_message_enter_struct(
3981 struct bus_container
*c
,
3982 const char *contents
,
3985 size_t *n_offsets
) {
3997 if (!signature_is_valid(contents
, false))
4000 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4003 l
= strlen(contents
);
4005 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
4006 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4007 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
4010 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4014 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4015 c
->index
+= 1 + l
+ 1;
4020 static int bus_message_enter_dict_entry(
4022 struct bus_container
*c
,
4023 const char *contents
,
4026 size_t *n_offsets
) {
4035 if (!signature_is_pair(contents
))
4038 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4041 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4044 l
= strlen(contents
);
4046 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
4047 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4048 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
4051 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4055 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4056 c
->index
+= 1 + l
+ 1;
4061 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
4063 const char *contents
) {
4064 struct bus_container
*c
, *w
;
4065 uint32_t *array_size
= NULL
;
4068 size_t *offsets
= NULL
;
4069 size_t n_offsets
= 0, item_size
= 0;
4072 assert_return(m
, -EINVAL
);
4073 assert_return(m
->sealed
, -EPERM
);
4074 assert_return(type
!= 0 || !contents
, -EINVAL
);
4076 if (type
== 0 || !contents
) {
4080 /* Allow entering into anonymous containers */
4081 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
4085 if (type
!= 0 && type
!= tt
)
4088 if (contents
&& !streq(contents
, cc
))
4096 * We enforce a global limit on container depth, that is much
4097 * higher than the 32 structs and 32 arrays the specification
4098 * mandates. This is simpler to implement for us, and we need
4099 * this only to ensure our container array doesn't grow
4100 * without bounds. We are happy to return any data from a
4101 * message as long as the data itself is valid, even if the
4102 * overall message might be not.
4104 * Note that the message signature is validated when
4105 * parsing the headers, and that validation does check the
4108 * Note that the specification defines no limits on the depth
4109 * of stacked variants, but we do.
4111 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4114 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4117 if (message_end_of_signature(m
))
4120 if (message_end_of_array(m
, m
->rindex
))
4123 c
= message_get_container(m
);
4125 signature
= strdup(contents
);
4129 c
->saved_index
= c
->index
;
4132 if (type
== SD_BUS_TYPE_ARRAY
)
4133 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4134 else if (type
== SD_BUS_TYPE_VARIANT
)
4135 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4136 else if (type
== SD_BUS_TYPE_STRUCT
)
4137 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4138 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4139 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4149 /* OK, let's fill it in */
4150 w
= m
->containers
+ m
->n_containers
++;
4151 w
->enclosing
= type
;
4152 w
->signature
= signature
;
4153 w
->peeked_signature
= NULL
;
4157 w
->begin
= m
->rindex
;
4159 /* Unary type has fixed size of 1, but virtual size of 0 */
4160 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4161 type
== SD_BUS_TYPE_STRUCT
&&
4163 w
->end
= m
->rindex
+ 0;
4165 w
->end
= m
->rindex
+ c
->item_size
;
4167 w
->array_size
= array_size
;
4168 w
->item_size
= item_size
;
4169 w
->offsets
= offsets
;
4170 w
->n_offsets
= n_offsets
;
4171 w
->offset_index
= 0;
4176 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4177 struct bus_container
*c
;
4181 assert_return(m
, -EINVAL
);
4182 assert_return(m
->sealed
, -EPERM
);
4183 assert_return(m
->n_containers
> 0, -ENXIO
);
4185 c
= message_get_container(m
);
4187 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4188 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4192 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4193 if (m
->rindex
< c
->end
)
4196 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4199 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4200 if (c
->begin
+ l
!= m
->rindex
)
4205 free(c
->peeked_signature
);
4209 c
= message_get_container(m
);
4212 c
->index
= c
->saved_index
;
4213 r
= container_next_item(m
, c
, &m
->rindex
);
4221 static void message_quit_container(sd_bus_message
*m
) {
4222 struct bus_container
*c
;
4226 assert(m
->n_containers
> 0);
4228 c
= message_get_container(m
);
4231 assert(m
->rindex
>= c
->before
);
4232 m
->rindex
= c
->before
;
4234 /* Free container */
4239 /* Correct index of new top-level container */
4240 c
= message_get_container(m
);
4241 c
->index
= c
->saved_index
;
4244 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4245 struct bus_container
*c
;
4248 assert_return(m
, -EINVAL
);
4249 assert_return(m
->sealed
, -EPERM
);
4251 if (message_end_of_signature(m
))
4254 if (message_end_of_array(m
, m
->rindex
))
4257 c
= message_get_container(m
);
4259 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4263 *type
= c
->signature
[c
->index
];
4267 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4273 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4279 sig
= strndup(c
->signature
+ c
->index
+ 1, l
);
4283 free(c
->peeked_signature
);
4284 *contents
= c
->peeked_signature
= sig
;
4288 *type
= SD_BUS_TYPE_ARRAY
;
4293 if (c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
||
4294 c
->signature
[c
->index
] == SD_BUS_TYPE_DICT_ENTRY_BEGIN
) {
4300 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4305 sig
= strndup(c
->signature
+ c
->index
+ 1, l
- 2);
4309 free(c
->peeked_signature
);
4310 *contents
= c
->peeked_signature
= sig
;
4314 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4319 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4323 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4326 if (c
->item_size
< 2)
4329 /* Look for the NUL delimiter that
4330 separates the payload from the
4331 signature. Since the body might be
4332 in a different part that then the
4333 signature we map byte by byte. */
4335 for (k
= 2; k
<= c
->item_size
; k
++) {
4338 where
= m
->rindex
+ c
->item_size
- k
;
4339 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4343 if (*(char*) q
== 0)
4347 if (k
> c
->item_size
)
4350 free(c
->peeked_signature
);
4351 c
->peeked_signature
= strndup((char*) q
+ 1, k
- 1);
4352 if (!c
->peeked_signature
)
4355 if (!signature_is_valid(c
->peeked_signature
, true))
4358 *contents
= c
->peeked_signature
;
4363 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4368 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4372 if (!validate_signature(q
, l
))
4380 *type
= SD_BUS_TYPE_VARIANT
;
4395 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4396 struct bus_container
*c
;
4398 assert_return(m
, -EINVAL
);
4399 assert_return(m
->sealed
, -EPERM
);
4402 message_reset_containers(m
);
4405 c
= message_get_container(m
);
4407 c
= message_get_container(m
);
4409 c
->offset_index
= 0;
4411 m
->rindex
= c
->begin
;
4414 c
->offset_index
= 0;
4415 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4417 return !isempty(c
->signature
);
4420 static int message_read_ap(
4425 unsigned n_array
, n_struct
;
4426 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4427 unsigned stack_ptr
= 0;
4428 unsigned n_loop
= 0;
4436 /* Ideally, we'd just call ourselves recursively on every
4437 * complex type. However, the state of a va_list that is
4438 * passed to a function is undefined after that function
4439 * returns. This means we need to docode the va_list linearly
4440 * in a single stackframe. We hence implement our own
4441 * home-grown stack in an array. */
4443 n_array
= (unsigned) -1; /* length of current array entries */
4444 n_struct
= strlen(types
); /* length of current struct contents signature */
4451 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4452 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4458 r
= sd_bus_message_exit_container(m
);
4466 if (n_array
!= (unsigned) -1)
4475 case SD_BUS_TYPE_BYTE
:
4476 case SD_BUS_TYPE_BOOLEAN
:
4477 case SD_BUS_TYPE_INT16
:
4478 case SD_BUS_TYPE_UINT16
:
4479 case SD_BUS_TYPE_INT32
:
4480 case SD_BUS_TYPE_UINT32
:
4481 case SD_BUS_TYPE_INT64
:
4482 case SD_BUS_TYPE_UINT64
:
4483 case SD_BUS_TYPE_DOUBLE
:
4484 case SD_BUS_TYPE_STRING
:
4485 case SD_BUS_TYPE_OBJECT_PATH
:
4486 case SD_BUS_TYPE_SIGNATURE
:
4487 case SD_BUS_TYPE_UNIX_FD
: {
4490 p
= va_arg(ap
, void*);
4491 r
= sd_bus_message_read_basic(m
, *t
, p
);
4504 case SD_BUS_TYPE_ARRAY
: {
4507 r
= signature_element_length(t
+ 1, &k
);
4513 memcpy(s
, t
+ 1, k
);
4516 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4527 if (n_array
== (unsigned) -1) {
4532 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4538 n_array
= va_arg(ap
, unsigned);
4543 case SD_BUS_TYPE_VARIANT
: {
4546 s
= va_arg(ap
, const char *);
4550 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4560 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4565 n_struct
= strlen(s
);
4566 n_array
= (unsigned) -1;
4571 case SD_BUS_TYPE_STRUCT_BEGIN
:
4572 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4575 r
= signature_element_length(t
, &k
);
4581 memcpy(s
, t
+ 1, k
- 2);
4584 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4594 if (n_array
== (unsigned) -1) {
4599 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4605 n_array
= (unsigned) -1;
4618 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4622 assert_return(m
, -EINVAL
);
4623 assert_return(m
->sealed
, -EPERM
);
4624 assert_return(types
, -EINVAL
);
4626 va_start(ap
, types
);
4627 r
= message_read_ap(m
, types
, ap
);
4633 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4636 assert_return(m
, -EINVAL
);
4637 assert_return(m
->sealed
, -EPERM
);
4639 /* If types is NULL, read exactly one element */
4641 struct bus_container
*c
;
4644 if (message_end_of_signature(m
))
4647 if (message_end_of_array(m
, m
->rindex
))
4650 c
= message_get_container(m
);
4652 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4656 types
= strndupa(c
->signature
+ c
->index
, l
);
4661 case 0: /* Nothing to drop */
4664 case SD_BUS_TYPE_BYTE
:
4665 case SD_BUS_TYPE_BOOLEAN
:
4666 case SD_BUS_TYPE_INT16
:
4667 case SD_BUS_TYPE_UINT16
:
4668 case SD_BUS_TYPE_INT32
:
4669 case SD_BUS_TYPE_UINT32
:
4670 case SD_BUS_TYPE_INT64
:
4671 case SD_BUS_TYPE_UINT64
:
4672 case SD_BUS_TYPE_DOUBLE
:
4673 case SD_BUS_TYPE_STRING
:
4674 case SD_BUS_TYPE_OBJECT_PATH
:
4675 case SD_BUS_TYPE_SIGNATURE
:
4676 case SD_BUS_TYPE_UNIX_FD
:
4678 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4682 r
= sd_bus_message_skip(m
, types
+ 1);
4688 case SD_BUS_TYPE_ARRAY
: {
4691 r
= signature_element_length(types
+ 1, &k
);
4697 memcpy(s
, types
+1, k
);
4700 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4705 r
= sd_bus_message_skip(m
, s
);
4712 r
= sd_bus_message_exit_container(m
);
4717 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4724 case SD_BUS_TYPE_VARIANT
: {
4725 const char *contents
;
4728 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4732 if (x
!= SD_BUS_TYPE_VARIANT
)
4735 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4739 r
= sd_bus_message_skip(m
, contents
);
4744 r
= sd_bus_message_exit_container(m
);
4748 r
= sd_bus_message_skip(m
, types
+ 1);
4755 case SD_BUS_TYPE_STRUCT_BEGIN
:
4756 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4759 r
= signature_element_length(types
, &k
);
4765 memcpy(s
, types
+1, k
-2);
4768 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4772 r
= sd_bus_message_skip(m
, s
);
4776 r
= sd_bus_message_exit_container(m
);
4781 r
= sd_bus_message_skip(m
, types
+ k
);
4793 _public_
int sd_bus_message_read_array(
4799 struct bus_container
*c
;
4805 assert_return(m
, -EINVAL
);
4806 assert_return(m
->sealed
, -EPERM
);
4807 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4808 assert_return(ptr
, -EINVAL
);
4809 assert_return(size
, -EINVAL
);
4810 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4812 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4816 c
= message_get_container(m
);
4818 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4819 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4823 sz
= c
->end
- c
->begin
;
4825 align
= bus_type_get_alignment(type
);
4829 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4833 /* Zero length array, let's return some aligned
4834 * pointer that is not NULL */
4835 p
= (uint8_t*) NULL
+ align
;
4837 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4842 r
= sd_bus_message_exit_container(m
);
4846 *ptr
= (const void*) p
;
4852 message_quit_container(m
);
4856 static int message_peek_fields(
4867 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4870 static int message_peek_field_uint32(
4882 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4885 /* identical for gvariant and dbus1 */
4887 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4892 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4897 static int message_peek_field_uint64(
4909 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4912 /* identical for gvariant and dbus1 */
4914 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4919 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4924 static int message_peek_field_string(
4926 bool (*validate
)(const char *p
),
4938 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4943 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4949 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4953 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4959 if (!validate_nul(q
, l
))
4965 if (!validate_string(q
, l
))
4975 static int message_peek_field_signature(
4988 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4993 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4999 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
5004 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
5009 if (!validate_signature(q
, l
))
5018 static int message_skip_fields(
5021 uint32_t array_size
,
5022 const char **signature
) {
5024 size_t original_index
;
5030 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
5032 original_index
= *ri
;
5038 if (array_size
!= (uint32_t) -1 &&
5039 array_size
<= *ri
- original_index
)
5046 if (t
== SD_BUS_TYPE_STRING
) {
5048 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
5054 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
5056 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
5062 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
5064 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
5070 } else if (bus_type_is_basic(t
)) {
5073 align
= bus_type_get_alignment(t
);
5074 k
= bus_type_get_size(t
);
5075 assert(align
> 0 && k
> 0);
5077 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
5083 } else if (t
== SD_BUS_TYPE_ARRAY
) {
5085 r
= signature_element_length(*signature
+1, &l
);
5095 strncpy(sig
, *signature
+ 1, l
-1);
5098 alignment
= bus_type_get_alignment(sig
[0]);
5102 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5105 if (nas
> BUS_ARRAY_MAX_SIZE
)
5108 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5112 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5117 (*signature
) += 1 + l
;
5119 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5122 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5126 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5132 } else if (t
== SD_BUS_TYPE_STRUCT
||
5133 t
== SD_BUS_TYPE_DICT_ENTRY
) {
5135 r
= signature_element_length(*signature
, &l
);
5142 strncpy(sig
, *signature
+ 1, l
-1);
5145 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5156 int bus_message_parse_fields(sd_bus_message
*m
) {
5159 uint32_t unix_fds
= 0;
5160 bool unix_fds_set
= false;
5161 void *offsets
= NULL
;
5162 unsigned n_offsets
= 0;
5168 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5171 /* Read the signature from the end of the body variant first */
5172 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5173 if (m
->footer_accessible
< 1 + sz
)
5176 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5178 if (p
< (char*) m
->footer
)
5185 /* We found the beginning of the signature
5186 * string, yay! We require the body to be a
5187 * structure, so verify it and then strip the
5188 * opening/closing brackets. */
5190 l
= ((char*) m
->footer
+ m
->footer_accessible
) - p
- (1 + sz
);
5192 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5193 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5196 c
= strndup(p
+ 1 + 1, l
- 2);
5200 free(m
->root_container
.signature
);
5201 m
->root_container
.signature
= c
;
5208 /* Calculate the actual user body size, by removing
5209 * the trailing variant signature and struct offset
5211 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5213 /* Pull out the offset table for the fields array */
5214 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5219 ri
= m
->fields_size
- sz
;
5220 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5224 framing
= bus_gvariant_read_word_le(q
, sz
);
5225 if (framing
>= m
->fields_size
- sz
)
5227 if ((m
->fields_size
- framing
) % sz
!= 0)
5231 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5235 n_offsets
= (m
->fields_size
- framing
) / sz
;
5238 m
->user_body_size
= m
->body_size
;
5241 while (ri
< m
->fields_size
) {
5242 _cleanup_free_
char *sig
= NULL
;
5243 const char *signature
;
5244 uint64_t field_type
;
5245 size_t item_size
= (size_t) -1;
5247 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5256 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5258 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5262 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5266 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5273 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5278 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5283 where
= ri
= ALIGN_TO(ri
, 8);
5284 item_size
= end
- ri
;
5285 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5289 b
= memrchr(q
, 0, item_size
);
5293 sig
= strndup(b
+1, item_size
- (b
+1-(char*) q
));
5298 item_size
= b
- (char*) q
;
5300 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5305 switch (field_type
) {
5307 case _BUS_MESSAGE_HEADER_INVALID
:
5310 case BUS_MESSAGE_HEADER_PATH
:
5315 if (!streq(signature
, "o"))
5318 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5321 case BUS_MESSAGE_HEADER_INTERFACE
:
5326 if (!streq(signature
, "s"))
5329 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5332 case BUS_MESSAGE_HEADER_MEMBER
:
5337 if (!streq(signature
, "s"))
5340 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5343 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5348 if (!streq(signature
, "s"))
5351 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5353 m
->error
._need_free
= -1;
5357 case BUS_MESSAGE_HEADER_DESTINATION
:
5362 if (!streq(signature
, "s"))
5365 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5368 case BUS_MESSAGE_HEADER_SENDER
:
5373 if (!streq(signature
, "s"))
5376 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5378 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
&& !m
->bus
->is_kernel
) {
5379 m
->creds
.unique_name
= (char*) m
->sender
;
5380 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5386 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5390 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5393 if (m
->root_container
.signature
)
5396 if (!streq(signature
, "g"))
5399 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5407 free(m
->root_container
.signature
);
5408 m
->root_container
.signature
= c
;
5412 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5414 if (m
->reply_cookie
!= 0)
5417 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5418 /* 64bit on dbus2 */
5420 if (!streq(signature
, "t"))
5423 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5427 /* 32bit on dbus1 */
5430 if (!streq(signature
, "u"))
5433 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5437 m
->reply_cookie
= serial
;
5440 if (m
->reply_cookie
== 0)
5445 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5449 if (!streq(signature
, "u"))
5452 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5456 unix_fds_set
= true;
5460 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5461 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5470 if (m
->n_fds
!= unix_fds
)
5473 switch (m
->header
->type
) {
5475 case SD_BUS_MESSAGE_SIGNAL
:
5476 if (!m
->path
|| !m
->interface
|| !m
->member
)
5479 if (m
->reply_cookie
!= 0)
5484 case SD_BUS_MESSAGE_METHOD_CALL
:
5486 if (!m
->path
|| !m
->member
)
5489 if (m
->reply_cookie
!= 0)
5494 case SD_BUS_MESSAGE_METHOD_RETURN
:
5496 if (m
->reply_cookie
== 0)
5500 case SD_BUS_MESSAGE_METHOD_ERROR
:
5502 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5507 /* Refuse non-local messages that claim they are local */
5508 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5510 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5512 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5515 m
->root_container
.end
= m
->user_body_size
;
5517 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5518 r
= build_struct_offsets(
5520 m
->root_container
.signature
,
5522 &m
->root_container
.item_size
,
5523 &m
->root_container
.offsets
,
5524 &m
->root_container
.n_offsets
);
5529 /* Try to read the error message, but if we can't it's a non-issue */
5530 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5531 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5536 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5537 assert_return(m
, -EINVAL
);
5538 assert_return(destination
, -EINVAL
);
5539 assert_return(!m
->sealed
, -EPERM
);
5540 assert_return(!m
->destination
, -EEXIST
);
5542 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5545 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5549 struct bus_body_part
*part
;
5555 total
= BUS_MESSAGE_SIZE(m
);
5561 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5562 MESSAGE_FOREACH_PART(part
, i
, m
)
5563 e
= mempcpy(e
, part
->data
, part
->size
);
5565 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5573 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5580 r
= sd_bus_message_enter_container(m
, 'a', "s");
5584 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5585 r
= strv_extend(l
, s
);
5592 r
= sd_bus_message_exit_container(m
);
5599 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5603 assert_return(m
, -EINVAL
);
5604 assert_return(m
->sealed
, -EPERM
);
5605 assert_return(l
, -EINVAL
);
5607 r
= bus_message_read_strv_extend(m
, &strv
);
5617 static int bus_message_get_arg_skip(
5621 const char **_contents
) {
5626 r
= sd_bus_message_rewind(m
, true);
5631 const char *contents
;
5634 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5640 /* Don't match against arguments after the first one we don't understand */
5641 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5642 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5647 *_contents
= contents
;
5653 r
= sd_bus_message_skip(m
, NULL
);
5660 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5667 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5671 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5674 return sd_bus_message_read_basic(m
, type
, str
);
5677 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5678 const char *contents
;
5685 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5689 if (type
!= SD_BUS_TYPE_ARRAY
)
5691 if (!STR_IN_SET(contents
, "s", "o", "g"))
5694 return sd_bus_message_read_strv(m
, strv
);
5697 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5698 assert_return(m
, EINVAL
);
5700 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5703 return sd_bus_error_get_errno(&m
->error
);
5706 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5707 struct bus_container
*c
;
5709 assert_return(m
, NULL
);
5711 c
= complete
? &m
->root_container
: message_get_container(m
);
5712 return strempty(c
->signature
);
5715 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5716 assert_return(m
, -EINVAL
);
5718 return isempty(m
->root_container
.signature
);
5721 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5722 assert_return(m
, -EINVAL
);
5724 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5727 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5728 bool done_something
= false;
5731 assert_return(m
, -EINVAL
);
5732 assert_return(source
, -EINVAL
);
5733 assert_return(!m
->sealed
, -EPERM
);
5734 assert_return(source
->sealed
, -EPERM
);
5737 const char *contents
;
5752 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5758 done_something
= true;
5760 if (bus_type_is_container(type
) > 0) {
5762 r
= sd_bus_message_enter_container(source
, type
, contents
);
5766 r
= sd_bus_message_open_container(m
, type
, contents
);
5770 r
= sd_bus_message_copy(m
, source
, true);
5774 r
= sd_bus_message_close_container(m
);
5778 r
= sd_bus_message_exit_container(source
);
5785 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5791 if (type
== SD_BUS_TYPE_OBJECT_PATH
||
5792 type
== SD_BUS_TYPE_SIGNATURE
||
5793 type
== SD_BUS_TYPE_STRING
)
5794 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5796 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5803 return done_something
;
5806 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5811 assert_return(m
, -EINVAL
);
5812 assert_return(m
->sealed
, -EPERM
);
5813 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5814 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5815 assert_return(type
|| contents
, -EINVAL
);
5816 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5818 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5822 if (type
!= 0 && type
!= t
)
5825 if (contents
&& !streq_ptr(contents
, c
))
5831 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5832 assert_return(m
, NULL
);
5837 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5838 _cleanup_bus_message_unref_ sd_bus_message
*n
= NULL
;
5846 switch ((*m
)->header
->type
) {
5848 case SD_BUS_MESSAGE_SIGNAL
:
5849 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5855 case SD_BUS_MESSAGE_METHOD_CALL
:
5856 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5862 case SD_BUS_MESSAGE_METHOD_RETURN
:
5863 case SD_BUS_MESSAGE_METHOD_ERROR
:
5865 n
= message_new(bus
, (*m
)->header
->type
);
5869 n
->reply_cookie
= (*m
)->reply_cookie
;
5871 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5875 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5876 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5880 n
->error
._need_free
= -1;
5889 if ((*m
)->destination
&& !n
->destination
) {
5890 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5895 if ((*m
)->sender
&& !n
->sender
) {
5896 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5901 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5903 r
= sd_bus_message_copy(n
, *m
, true);
5907 timeout
= (*m
)->timeout
;
5908 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
))
5909 timeout
= BUS_DEFAULT_TIMEOUT
;
5911 r
= bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5915 sd_bus_message_unref(*m
);
5922 int bus_message_append_sender(sd_bus_message
*m
, const char *sender
) {
5926 assert_return(!m
->sealed
, -EPERM
);
5927 assert_return(!m
->sender
, -EPERM
);
5929 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5932 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5933 assert_return(m
, -EINVAL
);
5934 assert_return(priority
, -EINVAL
);
5936 *priority
= m
->priority
;
5940 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5941 assert_return(m
, -EINVAL
);
5942 assert_return(!m
->sealed
, -EPERM
);
5944 m
->priority
= priority
;