1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "alloc-util.h"
28 #include "bus-gvariant.h"
29 #include "bus-internal.h"
30 #include "bus-message.h"
31 #include "bus-signature.h"
36 #include "memfd-util.h"
37 #include "string-util.h"
39 #include "time-util.h"
43 static int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
);
45 static void *adjust_pointer(const void *p
, void *old_base
, size_t sz
, void *new_base
) {
50 if (old_base
== new_base
)
53 if ((uint8_t*) p
< (uint8_t*) old_base
)
56 if ((uint8_t*) p
>= (uint8_t*) old_base
+ sz
)
59 return (uint8_t*) new_base
+ ((uint8_t*) p
- (uint8_t*) old_base
);
62 static void message_free_part(sd_bus_message
*m
, struct bus_body_part
*part
) {
67 close_and_munmap(part
->memfd
, part
->mmap_begin
, part
->mapped
);
68 else if (part
->munmap_this
)
69 munmap(part
->mmap_begin
, part
->mapped
);
70 else if (part
->free_this
)
77 static void message_reset_parts(sd_bus_message
*m
) {
78 struct bus_body_part
*part
;
83 while (m
->n_body_parts
> 0) {
84 struct bus_body_part
*next
= part
->next
;
85 message_free_part(m
, part
);
92 m
->cached_rindex_part
= NULL
;
93 m
->cached_rindex_part_begin
= 0;
96 static void message_reset_containers(sd_bus_message
*m
) {
101 for (i
= 0; i
< m
->n_containers
; i
++) {
102 free(m
->containers
[i
].signature
);
103 free(m
->containers
[i
].offsets
);
106 m
->containers
= mfree(m
->containers
);
108 m
->n_containers
= m
->containers_allocated
= 0;
109 m
->root_container
.index
= 0;
112 static void message_free(sd_bus_message
*m
) {
118 message_reset_parts(m
);
120 sd_bus_unref(m
->bus
);
123 close_many(m
->fds
, m
->n_fds
);
127 if (m
->iovec
!= m
->iovec_fixed
)
130 message_reset_containers(m
);
131 free(m
->root_container
.signature
);
132 free(m
->root_container
.offsets
);
134 free(m
->root_container
.peeked_signature
);
136 bus_creds_done(&m
->creds
);
140 static void *message_extend_fields(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
142 size_t old_size
, new_size
, start
;
149 old_size
= sizeof(struct bus_header
) + m
->fields_size
;
150 start
= ALIGN_TO(old_size
, align
);
151 new_size
= start
+ sz
;
153 if (new_size
< start
||
154 new_size
> (size_t) ((uint32_t) -1))
157 if (old_size
== new_size
)
158 return (uint8_t*) m
->header
+ old_size
;
160 if (m
->free_header
) {
161 np
= realloc(m
->header
, ALIGN8(new_size
));
165 /* Initially, the header is allocated as part of
166 * the sd_bus_message itself, let's replace it by
169 np
= malloc(ALIGN8(new_size
));
173 memcpy(np
, m
->header
, sizeof(struct bus_header
));
176 /* Zero out padding */
177 if (start
> old_size
)
178 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
182 m
->fields_size
= new_size
- sizeof(struct bus_header
);
184 /* Adjust quick access pointers */
185 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
186 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
187 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
188 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
189 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
190 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
192 m
->free_header
= true;
195 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
198 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
201 return (uint8_t*) np
+ start
;
208 static int message_append_field_string(
220 /* dbus1 only allows 8bit header field ids */
224 /* dbus1 doesn't allow strings over 32bit, let's enforce this
225 * globally, to not risk convertability */
227 if (l
> (size_t) (uint32_t) -1)
230 /* Signature "(yv)" where the variant contains "s" */
232 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
234 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
235 p
= message_extend_fields(m
, 8, 8 + l
+ 1 + 1 + 1, true);
239 *((uint64_t*) p
) = h
;
246 *ret
= (char*) p
+ 8;
249 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
250 p
= message_extend_fields(m
, 8, 4 + 4 + l
+ 1, false);
259 ((uint32_t*) p
)[1] = l
;
260 memcpy(p
+ 8, s
, l
+ 1);
263 *ret
= (char*) p
+ 8;
269 static int message_append_field_signature(
280 /* dbus1 only allows 8bit header field ids */
284 /* dbus1 doesn't allow signatures over 8bit, let's enforce
285 * this globally, to not risk convertability */
290 /* Signature "(yv)" where the variant contains "g" */
292 if (BUS_MESSAGE_IS_GVARIANT(m
))
293 /* For gvariant the serialization is the same as for normal strings */
294 return message_append_field_string(m
, h
, 'g', s
, ret
);
296 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
297 p
= message_extend_fields(m
, 8, 4 + 1 + l
+ 1, false);
303 p
[2] = SD_BUS_TYPE_SIGNATURE
;
306 memcpy(p
+ 5, s
, l
+ 1);
309 *ret
= (const char*) p
+ 5;
315 static int message_append_field_uint32(sd_bus_message
*m
, uint64_t h
, uint32_t x
) {
320 /* dbus1 only allows 8bit header field ids */
324 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
325 /* (field id 64bit + ((value + NUL + signature string 'u') */
327 p
= message_extend_fields(m
, 8, 8 + 4 + 1 + 1, true);
331 *((uint64_t*) p
) = h
;
332 *((uint32_t*) (p
+ 8)) = x
;
336 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
337 p
= message_extend_fields(m
, 8, 4 + 4, false);
346 ((uint32_t*) p
)[1] = x
;
352 static int message_append_field_uint64(sd_bus_message
*m
, uint64_t h
, uint64_t x
) {
357 /* dbus1 only allows 8bit header field ids */
361 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
362 /* (field id 64bit + ((value + NUL + signature string 't') */
364 p
= message_extend_fields(m
, 8, 8 + 8 + 1 + 1, true);
368 *((uint64_t*) p
) = h
;
369 *((uint64_t*) (p
+ 8)) = x
;
373 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
374 p
= message_extend_fields(m
, 8, 4 + 4 + 8, false);
387 ((uint64_t*) p
)[1] = x
;
393 static int message_append_reply_cookie(sd_bus_message
*m
, uint64_t cookie
) {
396 if (BUS_MESSAGE_IS_GVARIANT(m
))
397 return message_append_field_uint64(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, cookie
);
399 /* 64bit cookies are not supported on dbus1 */
400 if (cookie
> 0xffffffffUL
)
403 return message_append_field_uint32(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) cookie
);
407 int bus_message_from_header(
410 size_t header_accessible
,
412 size_t footer_accessible
,
418 sd_bus_message
**ret
) {
420 _cleanup_free_ sd_bus_message
*m
= NULL
;
421 struct bus_header
*h
;
425 assert(header
|| header_accessible
<= 0);
426 assert(footer
|| footer_accessible
<= 0);
427 assert(fds
|| n_fds
<= 0);
430 if (header_accessible
< sizeof(struct bus_header
))
433 if (header_accessible
> message_size
)
435 if (footer_accessible
> message_size
)
439 if (!IN_SET(h
->version
, 1, 2))
442 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
445 if (!IN_SET(h
->endian
, BUS_LITTLE_ENDIAN
, BUS_BIG_ENDIAN
))
448 /* Note that we are happy with unknown flags in the flags header! */
450 a
= ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
453 label_sz
= strlen(label
);
464 m
->header_accessible
= header_accessible
;
466 m
->footer_accessible
= footer_accessible
;
468 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
471 if (h
->dbus2
.cookie
== 0)
474 /* dbus2 derives the sizes from the message size and
475 the offset table at the end, since it is formatted as
476 gvariant "yyyyuta{tv}v". Since the message itself is a
477 structure with precisely to variable sized entries,
478 there's only one offset in the table, which marks the
479 end of the fields array. */
481 ws
= bus_gvariant_determine_word_size(message_size
, 0);
482 if (footer_accessible
< ws
)
485 m
->fields_size
= bus_gvariant_read_word_le((uint8_t*) footer
+ footer_accessible
- ws
, ws
);
486 if (ALIGN8(m
->fields_size
) > message_size
- ws
)
488 if (m
->fields_size
< sizeof(struct bus_header
))
491 m
->fields_size
-= sizeof(struct bus_header
);
492 m
->body_size
= message_size
- (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
));
494 if (h
->dbus1
.serial
== 0)
497 /* dbus1 has the sizes in the header */
498 m
->fields_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.fields_size
);
499 m
->body_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.body_size
);
501 if (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
!= message_size
)
509 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
510 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
512 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
515 m
->bus
= sd_bus_ref(bus
);
521 int bus_message_from_malloc(
528 sd_bus_message
**ret
) {
534 r
= bus_message_from_header(
536 buffer
, length
, /* in this case the initial bytes and the final bytes are the same */
545 sz
= length
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
);
548 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(m
->fields_size
);
550 m
->body
.sealed
= true;
555 m
->iovec
= m
->iovec_fixed
;
556 m
->iovec
[0].iov_base
= buffer
;
557 m
->iovec
[0].iov_len
= length
;
559 r
= bus_message_parse_fields(m
);
563 /* We take possession of the memory and fds now */
564 m
->free_header
= true;
575 _public_
int sd_bus_message_new(
582 assert_return(bus
, -ENOTCONN
);
583 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
584 assert_return(m
, -EINVAL
);
585 assert_return(type
< _SD_BUS_MESSAGE_TYPE_MAX
, -EINVAL
);
587 t
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
592 t
->header
= (struct bus_header
*) ((uint8_t*) t
+ ALIGN(sizeof(struct sd_bus_message
)));
593 t
->header
->endian
= BUS_NATIVE_ENDIAN
;
594 t
->header
->type
= type
;
595 t
->header
->version
= bus
->message_version
;
596 t
->allow_fds
= bus
->can_fds
|| !IN_SET(bus
->state
, BUS_HELLO
, BUS_RUNNING
);
597 t
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(t
);
598 t
->bus
= sd_bus_ref(bus
);
600 if (bus
->allow_interactive_authorization
)
601 t
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
607 _public_
int sd_bus_message_new_signal(
611 const char *interface
,
612 const char *member
) {
617 assert_return(bus
, -ENOTCONN
);
618 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
619 assert_return(object_path_is_valid(path
), -EINVAL
);
620 assert_return(interface_name_is_valid(interface
), -EINVAL
);
621 assert_return(member_name_is_valid(member
), -EINVAL
);
622 assert_return(m
, -EINVAL
);
624 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_SIGNAL
);
630 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
632 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
635 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
638 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
646 sd_bus_message_unref(t
);
650 _public_
int sd_bus_message_new_method_call(
653 const char *destination
,
655 const char *interface
,
656 const char *member
) {
661 assert_return(bus
, -ENOTCONN
);
662 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
663 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
664 assert_return(object_path_is_valid(path
), -EINVAL
);
665 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
666 assert_return(member_name_is_valid(member
), -EINVAL
);
667 assert_return(m
, -EINVAL
);
669 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_CALL
);
675 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
678 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
683 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
689 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
702 static int message_new_reply(
703 sd_bus_message
*call
,
705 sd_bus_message
**m
) {
711 assert_return(call
, -EINVAL
);
712 assert_return(call
->sealed
, -EPERM
);
713 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
714 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
715 assert_return(m
, -EINVAL
);
717 cookie
= BUS_MESSAGE_COOKIE(call
);
721 r
= sd_bus_message_new(call
->bus
, &t
, type
);
727 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
728 t
->reply_cookie
= cookie
;
729 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
734 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
739 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
740 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
750 _public_
int sd_bus_message_new_method_return(
751 sd_bus_message
*call
,
752 sd_bus_message
**m
) {
754 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
757 _public_
int sd_bus_message_new_method_error(
758 sd_bus_message
*call
,
760 const sd_bus_error
*e
) {
765 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
766 assert_return(m
, -EINVAL
);
768 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
772 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
777 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
782 t
->error
._need_free
= -1;
792 _public_
int sd_bus_message_new_method_errorf(
793 sd_bus_message
*call
,
799 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
802 assert_return(name
, -EINVAL
);
803 assert_return(m
, -EINVAL
);
805 va_start(ap
, format
);
806 bus_error_setfv(&error
, name
, format
, ap
);
809 return sd_bus_message_new_method_error(call
, m
, &error
);
812 _public_
int sd_bus_message_new_method_errno(
813 sd_bus_message
*call
,
816 const sd_bus_error
*p
) {
818 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
820 if (sd_bus_error_is_set(p
))
821 return sd_bus_message_new_method_error(call
, m
, p
);
823 sd_bus_error_set_errno(&berror
, error
);
825 return sd_bus_message_new_method_error(call
, m
, &berror
);
828 _public_
int sd_bus_message_new_method_errnof(
829 sd_bus_message
*call
,
835 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
838 va_start(ap
, format
);
839 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
842 return sd_bus_message_new_method_error(call
, m
, &berror
);
845 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
849 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
850 m
->creds
.well_known_names_local
= true;
851 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
854 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
858 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
859 m
->creds
.well_known_names_driver
= true;
860 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
863 int bus_message_new_synthetic_error(
866 const sd_bus_error
*e
,
867 sd_bus_message
**m
) {
873 assert(sd_bus_error_is_set(e
));
876 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_ERROR
);
882 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
883 t
->reply_cookie
= cookie
;
885 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
889 if (bus
&& bus
->unique_name
) {
890 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
895 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
900 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
905 t
->error
._need_free
= -1;
907 bus_message_set_sender_driver(bus
, t
);
917 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
922 assert(m
->n_ref
> 0);
928 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
933 assert(m
->n_ref
> 0);
943 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
944 assert_return(m
, -EINVAL
);
945 assert_return(type
, -EINVAL
);
947 *type
= m
->header
->type
;
951 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
954 assert_return(m
, -EINVAL
);
955 assert_return(cookie
, -EINVAL
);
957 c
= BUS_MESSAGE_COOKIE(m
);
961 *cookie
= BUS_MESSAGE_COOKIE(m
);
965 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
966 assert_return(m
, -EINVAL
);
967 assert_return(cookie
, -EINVAL
);
969 if (m
->reply_cookie
== 0)
972 *cookie
= m
->reply_cookie
;
976 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
977 assert_return(m
, -EINVAL
);
979 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
980 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
983 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
984 assert_return(m
, -EINVAL
);
986 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
989 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
990 assert_return(m
, -EINVAL
);
992 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
993 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
996 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
997 assert_return(m
, NULL
);
1002 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
1003 assert_return(m
, NULL
);
1005 return m
->interface
;
1008 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
1009 assert_return(m
, NULL
);
1014 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
1015 assert_return(m
, NULL
);
1017 return m
->destination
;
1020 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
1021 assert_return(m
, NULL
);
1026 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
1027 assert_return(m
, NULL
);
1029 if (!sd_bus_error_is_set(&m
->error
))
1035 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
1036 assert_return(m
, -EINVAL
);
1037 assert_return(usec
, -EINVAL
);
1039 if (m
->monotonic
<= 0)
1042 *usec
= m
->monotonic
;
1046 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1047 assert_return(m
, -EINVAL
);
1048 assert_return(usec
, -EINVAL
);
1050 if (m
->realtime
<= 0)
1053 *usec
= m
->realtime
;
1057 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1058 assert_return(m
, -EINVAL
);
1059 assert_return(seqnum
, -EINVAL
);
1064 *seqnum
= m
->seqnum
;
1068 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1069 assert_return(m
, NULL
);
1071 if (m
->creds
.mask
== 0)
1077 _public_
int sd_bus_message_is_signal(
1079 const char *interface
,
1080 const char *member
) {
1082 assert_return(m
, -EINVAL
);
1084 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1087 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1090 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1096 _public_
int sd_bus_message_is_method_call(
1098 const char *interface
,
1099 const char *member
) {
1101 assert_return(m
, -EINVAL
);
1103 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1106 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1109 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1115 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1116 assert_return(m
, -EINVAL
);
1118 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1121 if (name
&& (!m
->error
.name
|| !streq(m
->error
.name
, name
)))
1127 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1128 assert_return(m
, -EINVAL
);
1129 assert_return(!m
->sealed
, -EPERM
);
1130 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1132 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_REPLY_EXPECTED
, !b
);
1137 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1138 assert_return(m
, -EINVAL
);
1139 assert_return(!m
->sealed
, -EPERM
);
1141 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_AUTO_START
, !b
);
1146 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1147 assert_return(m
, -EINVAL
);
1148 assert_return(!m
->sealed
, -EPERM
);
1150 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
, b
);
1155 static struct bus_container
*message_get_container(sd_bus_message
*m
) {
1158 if (m
->n_containers
== 0)
1159 return &m
->root_container
;
1161 assert(m
->containers
);
1162 return m
->containers
+ m
->n_containers
- 1;
1165 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1166 struct bus_body_part
*part
;
1173 if (m
->n_body_parts
<= 0) {
1177 assert(m
->body_end
);
1179 part
= new0(struct bus_body_part
, 1);
1185 m
->body_end
->next
= part
;
1195 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1200 /* All other fields can be left in their defaults */
1201 assert(!part
->data
);
1202 assert(part
->memfd
< 0);
1205 part
->is_zero
= true;
1206 part
->sealed
= true;
1209 static int part_make_space(
1210 struct sd_bus_message
*m
,
1211 struct bus_body_part
*part
,
1219 assert(!part
->sealed
);
1224 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1225 size_t new_allocated
;
1227 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1228 n
= realloc(part
->data
, new_allocated
);
1235 part
->allocated
= new_allocated
;
1236 part
->free_this
= true;
1240 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1246 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1247 struct bus_container
*c
;
1250 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1252 /* Add offset to current container, unless this is the first
1253 * item in it, which will have the 0 offset, which we can
1255 c
= message_get_container(m
);
1257 if (!c
->need_offsets
)
1260 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1263 c
->offsets
[c
->n_offsets
++] = offset
;
1267 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1268 struct bus_container
*c
;
1275 /* Update counters */
1276 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++) {
1279 *c
->array_size
+= expand
;
1283 static void *message_extend_body(
1288 bool force_inline
) {
1290 size_t start_body
, end_body
, padding
, added
;
1301 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1302 end_body
= start_body
+ sz
;
1304 padding
= start_body
- m
->body_size
;
1305 added
= padding
+ sz
;
1307 /* Check for 32bit overflows */
1308 if (end_body
> (size_t) ((uint32_t) -1) ||
1309 end_body
< start_body
) {
1315 struct bus_body_part
*part
= NULL
;
1319 m
->n_body_parts
<= 0 ||
1320 m
->body_end
->sealed
||
1321 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1322 (force_inline
&& m
->body_end
->size
> MEMFD_MIN_SIZE
);
1323 /* If this must be an inlined extension, let's create a new part if
1324 * the previous part is large enough to be inlined. */
1328 part
= message_append_part(m
);
1332 part_zero(part
, padding
);
1335 part
= message_append_part(m
);
1339 r
= part_make_space(m
, part
, sz
, &p
);
1343 struct bus_container
*c
;
1345 size_t os
, start_part
, end_part
;
1351 start_part
= ALIGN_TO(part
->size
, align
);
1352 end_part
= start_part
+ sz
;
1354 r
= part_make_space(m
, part
, end_part
, &p
);
1359 memzero(p
, padding
);
1360 p
= (uint8_t*) p
+ padding
;
1363 /* Readjust pointers */
1364 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1365 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1367 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1370 /* Return something that is not NULL and is aligned */
1371 p
= (uint8_t*) align
;
1373 m
->body_size
= end_body
;
1374 message_extend_containers(m
, added
);
1377 r
= message_add_offset(m
, end_body
);
1387 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1398 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1402 f
= reallocarray(m
->fds
, sizeof(int), m
->n_fds
+ 1);
1410 m
->fds
[m
->n_fds
] = copy
;
1416 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1417 _cleanup_close_
int fd
= -1;
1418 struct bus_container
*c
;
1422 assert_return(m
, -EINVAL
);
1423 assert_return(!m
->sealed
, -EPERM
);
1424 assert_return(bus_type_is_basic(type
), -EINVAL
);
1425 assert_return(!m
->poisoned
, -ESTALE
);
1427 c
= message_get_container(m
);
1429 if (c
->signature
&& c
->signature
[c
->index
]) {
1430 /* Container signature is already set */
1432 if (c
->signature
[c
->index
] != type
)
1437 /* Maybe we can append to the signature? But only if this is the top-level container */
1438 if (c
->enclosing
!= 0)
1441 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1448 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1454 case SD_BUS_TYPE_SIGNATURE
:
1455 case SD_BUS_TYPE_STRING
:
1459 case SD_BUS_TYPE_OBJECT_PATH
:
1467 case SD_BUS_TYPE_BOOLEAN
:
1469 u8
= p
&& *(int*) p
;
1475 case SD_BUS_TYPE_UNIX_FD
:
1480 fd
= message_push_fd(m
, *(int*) p
);
1491 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1492 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1499 a
= message_extend_body(m
, align
, sz
, true, false);
1506 *stored
= (const uint8_t*) a
;
1513 case SD_BUS_TYPE_STRING
:
1514 /* To make things easy we'll serialize a NULL string
1515 * into the empty string */
1519 case SD_BUS_TYPE_OBJECT_PATH
:
1525 sz
= 4 + strlen(p
) + 1;
1528 case SD_BUS_TYPE_SIGNATURE
:
1533 sz
= 1 + strlen(p
) + 1;
1536 case SD_BUS_TYPE_BOOLEAN
:
1538 u32
= p
&& *(int*) p
;
1544 case SD_BUS_TYPE_UNIX_FD
:
1549 fd
= message_push_fd(m
, *(int*) p
);
1560 align
= bus_type_get_alignment(type
);
1561 sz
= bus_type_get_size(type
);
1568 a
= message_extend_body(m
, align
, sz
, false, false);
1572 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
1573 *(uint32_t*) a
= sz
- 5;
1574 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1577 *stored
= (const uint8_t*) a
+ 4;
1579 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1580 *(uint8_t*) a
= sz
- 2;
1581 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1584 *stored
= (const uint8_t*) a
+ 1;
1593 if (type
== SD_BUS_TYPE_UNIX_FD
)
1596 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1603 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1604 return message_append_basic(m
, type
, p
, NULL
);
1607 _public_
int sd_bus_message_append_string_space(
1612 struct bus_container
*c
;
1615 assert_return(m
, -EINVAL
);
1616 assert_return(s
, -EINVAL
);
1617 assert_return(!m
->sealed
, -EPERM
);
1618 assert_return(!m
->poisoned
, -ESTALE
);
1620 c
= message_get_container(m
);
1622 if (c
->signature
&& c
->signature
[c
->index
]) {
1623 /* Container signature is already set */
1625 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1630 /* Maybe we can append to the signature? But only if this is the top-level container */
1631 if (c
->enclosing
!= 0)
1634 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1641 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1642 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1648 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1652 *(uint32_t*) a
= size
;
1658 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1664 _public_
int sd_bus_message_append_string_iovec(
1666 const struct iovec
*iov
,
1674 assert_return(m
, -EINVAL
);
1675 assert_return(!m
->sealed
, -EPERM
);
1676 assert_return(iov
|| n
== 0, -EINVAL
);
1677 assert_return(!m
->poisoned
, -ESTALE
);
1679 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1681 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1685 for (i
= 0; i
< n
; i
++) {
1687 if (iov
[i
].iov_base
)
1688 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1690 memset(p
, ' ', iov
[i
].iov_len
);
1692 p
+= iov
[i
].iov_len
;
1698 static int bus_message_open_array(
1700 struct bus_container
*c
,
1701 const char *contents
,
1702 uint32_t **array_size
,
1704 bool *need_offsets
) {
1714 assert(need_offsets
);
1716 if (!signature_is_single(contents
, true))
1719 if (c
->signature
&& c
->signature
[c
->index
]) {
1721 /* Verify the existing signature */
1723 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1726 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1729 nindex
= c
->index
+ 1 + strlen(contents
);
1733 if (c
->enclosing
!= 0)
1736 /* Extend the existing signature */
1738 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1744 nindex
= e
- c
->signature
;
1747 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1748 alignment
= bus_gvariant_get_alignment(contents
);
1752 /* Add alignment padding and add to offset list */
1753 if (!message_extend_body(m
, alignment
, 0, false, false))
1756 r
= bus_gvariant_is_fixed_size(contents
);
1760 *begin
= m
->body_size
;
1761 *need_offsets
= r
== 0;
1765 struct bus_body_part
*o
;
1767 alignment
= bus_type_get_alignment(contents
[0]);
1771 a
= message_extend_body(m
, 4, 4, false, false);
1776 op
= m
->body_end
->data
;
1777 os
= m
->body_end
->size
;
1779 /* Add alignment between size and first element */
1780 if (!message_extend_body(m
, alignment
, 0, false, false))
1783 /* location of array size might have changed so let's readjust a */
1784 if (o
== m
->body_end
)
1785 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1791 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1797 static int bus_message_open_variant(
1799 struct bus_container
*c
,
1800 const char *contents
) {
1806 if (!signature_is_single(contents
, false))
1809 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1812 if (c
->signature
&& c
->signature
[c
->index
]) {
1814 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1820 if (c
->enclosing
!= 0)
1823 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1830 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1831 /* Variants are always aligned to 8 */
1833 if (!message_extend_body(m
, 8, 0, false, false))
1840 l
= strlen(contents
);
1841 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1846 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1849 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1855 static int bus_message_open_struct(
1857 struct bus_container
*c
,
1858 const char *contents
,
1860 bool *need_offsets
) {
1869 assert(need_offsets
);
1871 if (!signature_is_valid(contents
, false))
1874 if (c
->signature
&& c
->signature
[c
->index
]) {
1877 l
= strlen(contents
);
1879 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1880 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1881 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1884 nindex
= c
->index
+ 1 + l
+ 1;
1888 if (c
->enclosing
!= 0)
1891 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1897 nindex
= e
- c
->signature
;
1900 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1903 alignment
= bus_gvariant_get_alignment(contents
);
1907 if (!message_extend_body(m
, alignment
, 0, false, false))
1910 r
= bus_gvariant_is_fixed_size(contents
);
1914 *begin
= m
->body_size
;
1915 *need_offsets
= r
== 0;
1917 /* Align contents to 8 byte boundary */
1918 if (!message_extend_body(m
, 8, 0, false, false))
1922 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1928 static int bus_message_open_dict_entry(
1930 struct bus_container
*c
,
1931 const char *contents
,
1933 bool *need_offsets
) {
1941 assert(need_offsets
);
1943 if (!signature_is_pair(contents
))
1946 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1949 if (c
->signature
&& c
->signature
[c
->index
]) {
1952 l
= strlen(contents
);
1954 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
1955 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1956 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
1961 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1964 alignment
= bus_gvariant_get_alignment(contents
);
1968 if (!message_extend_body(m
, alignment
, 0, false, false))
1971 r
= bus_gvariant_is_fixed_size(contents
);
1975 *begin
= m
->body_size
;
1976 *need_offsets
= r
== 0;
1978 /* Align contents to 8 byte boundary */
1979 if (!message_extend_body(m
, 8, 0, false, false))
1986 _public_
int sd_bus_message_open_container(
1989 const char *contents
) {
1991 struct bus_container
*c
, *w
;
1992 uint32_t *array_size
= NULL
;
1994 size_t before
, begin
= 0;
1995 bool need_offsets
= false;
1998 assert_return(m
, -EINVAL
);
1999 assert_return(!m
->sealed
, -EPERM
);
2000 assert_return(contents
, -EINVAL
);
2001 assert_return(!m
->poisoned
, -ESTALE
);
2003 /* Make sure we have space for one more container */
2004 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
2009 c
= message_get_container(m
);
2011 signature
= strdup(contents
);
2017 /* Save old index in the parent container, in case we have to
2018 * abort this container */
2019 c
->saved_index
= c
->index
;
2020 before
= m
->body_size
;
2022 if (type
== SD_BUS_TYPE_ARRAY
)
2023 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
2024 else if (type
== SD_BUS_TYPE_VARIANT
)
2025 r
= bus_message_open_variant(m
, c
, contents
);
2026 else if (type
== SD_BUS_TYPE_STRUCT
)
2027 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
2028 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
2029 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
2038 /* OK, let's fill it in */
2039 w
= m
->containers
+ m
->n_containers
++;
2040 w
->enclosing
= type
;
2041 w
->signature
= signature
;
2043 w
->array_size
= array_size
;
2046 w
->n_offsets
= w
->offsets_allocated
= 0;
2048 w
->need_offsets
= need_offsets
;
2053 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2058 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2061 if (c
->need_offsets
) {
2062 size_t payload
, sz
, i
;
2065 /* Variable-width arrays */
2067 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2068 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2070 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2074 for (i
= 0; i
< c
->n_offsets
; i
++)
2075 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2079 /* Fixed-width or empty arrays */
2081 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2089 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2095 assert(c
->signature
);
2097 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2100 l
= strlen(c
->signature
);
2102 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2107 memcpy(a
+1, c
->signature
, l
);
2112 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2113 bool fixed_size
= true;
2114 size_t n_variable
= 0;
2123 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2126 p
= strempty(c
->signature
);
2130 r
= signature_element_length(p
, &n
);
2139 r
= bus_gvariant_is_fixed_size(t
);
2144 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2146 /* We need to add an offset for each item that has a
2147 * variable size and that is not the last one in the
2151 if (r
== 0 && p
[n
] != 0)
2158 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2159 assert(c
->need_offsets
|| n_variable
== 0);
2161 if (isempty(c
->signature
)) {
2162 /* The unary type is encoded as fixed 1 byte padding */
2163 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2168 } else if (n_variable
<= 0) {
2171 /* Structures with fixed-size members only have to be
2172 * fixed-size themselves. But gvariant requires all fixed-size
2173 * elements to be sized a multiple of their alignment. Hence,
2174 * we must *always* add final padding after the last member so
2175 * the overall size of the structure is properly aligned. */
2177 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2179 assert(alignment
> 0);
2181 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2188 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2190 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2192 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2196 p
= strempty(c
->signature
);
2197 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2201 r
= signature_element_length(p
, &n
);
2212 r
= bus_gvariant_is_fixed_size(t
);
2215 if (r
> 0 || p
[0] == 0)
2219 k
= n_variable
- 1 - j
;
2221 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2230 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2231 struct bus_container
*c
;
2234 assert_return(m
, -EINVAL
);
2235 assert_return(!m
->sealed
, -EPERM
);
2236 assert_return(m
->n_containers
> 0, -EINVAL
);
2237 assert_return(!m
->poisoned
, -ESTALE
);
2239 c
= message_get_container(m
);
2241 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2242 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2247 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2248 r
= bus_message_close_array(m
, c
);
2249 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2250 r
= bus_message_close_variant(m
, c
);
2251 else if (IN_SET(c
->enclosing
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
))
2252 r
= bus_message_close_struct(m
, c
, true);
2254 assert_not_reached("Unknown container type");
2268 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2275 stack
[*i
].types
= types
;
2276 stack
[*i
].n_struct
= n_struct
;
2277 stack
[*i
].n_array
= n_array
;
2283 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2294 *types
= stack
[*i
].types
;
2295 *n_struct
= stack
[*i
].n_struct
;
2296 *n_array
= stack
[*i
].n_array
;
2301 _public_
int sd_bus_message_appendv(
2306 unsigned n_array
, n_struct
;
2307 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2308 unsigned stack_ptr
= 0;
2311 assert_return(m
, -EINVAL
);
2312 assert_return(types
, -EINVAL
);
2313 assert_return(!m
->sealed
, -EPERM
);
2314 assert_return(!m
->poisoned
, -ESTALE
);
2316 n_array
= (unsigned) -1;
2317 n_struct
= strlen(types
);
2322 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2323 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2329 r
= sd_bus_message_close_container(m
);
2337 if (n_array
!= (unsigned) -1)
2346 case SD_BUS_TYPE_BYTE
: {
2349 x
= (uint8_t) va_arg(ap
, int);
2350 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2354 case SD_BUS_TYPE_BOOLEAN
:
2355 case SD_BUS_TYPE_INT32
:
2356 case SD_BUS_TYPE_UINT32
:
2357 case SD_BUS_TYPE_UNIX_FD
: {
2360 /* We assume a boolean is the same as int32_t */
2361 assert_cc(sizeof(int32_t) == sizeof(int));
2363 x
= va_arg(ap
, uint32_t);
2364 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2368 case SD_BUS_TYPE_INT16
:
2369 case SD_BUS_TYPE_UINT16
: {
2372 x
= (uint16_t) va_arg(ap
, int);
2373 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2377 case SD_BUS_TYPE_INT64
:
2378 case SD_BUS_TYPE_UINT64
: {
2381 x
= va_arg(ap
, uint64_t);
2382 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2386 case SD_BUS_TYPE_DOUBLE
: {
2389 x
= va_arg(ap
, double);
2390 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2394 case SD_BUS_TYPE_STRING
:
2395 case SD_BUS_TYPE_OBJECT_PATH
:
2396 case SD_BUS_TYPE_SIGNATURE
: {
2399 x
= va_arg(ap
, const char*);
2400 r
= sd_bus_message_append_basic(m
, *t
, x
);
2404 case SD_BUS_TYPE_ARRAY
: {
2407 r
= signature_element_length(t
+ 1, &k
);
2413 memcpy(s
, t
+ 1, k
);
2416 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2421 if (n_array
== (unsigned) -1) {
2426 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2432 n_array
= va_arg(ap
, unsigned);
2437 case SD_BUS_TYPE_VARIANT
: {
2440 s
= va_arg(ap
, const char*);
2444 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2448 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2453 n_struct
= strlen(s
);
2454 n_array
= (unsigned) -1;
2459 case SD_BUS_TYPE_STRUCT_BEGIN
:
2460 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2463 r
= signature_element_length(t
, &k
);
2470 memcpy(s
, t
+ 1, k
- 2);
2473 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2478 if (n_array
== (unsigned) -1) {
2483 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2489 n_array
= (unsigned) -1;
2505 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2509 assert_return(m
, -EINVAL
);
2510 assert_return(types
, -EINVAL
);
2511 assert_return(!m
->sealed
, -EPERM
);
2512 assert_return(!m
->poisoned
, -ESTALE
);
2514 va_start(ap
, types
);
2515 r
= sd_bus_message_appendv(m
, types
, ap
);
2521 _public_
int sd_bus_message_append_array_space(
2531 assert_return(m
, -EINVAL
);
2532 assert_return(!m
->sealed
, -EPERM
);
2533 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2534 assert_return(ptr
|| size
== 0, -EINVAL
);
2535 assert_return(!m
->poisoned
, -ESTALE
);
2537 /* alignment and size of the trivial types (except bool) is
2538 * identical for gvariant and dbus1 marshalling */
2539 align
= bus_type_get_alignment(type
);
2540 sz
= bus_type_get_size(type
);
2542 assert_se(align
> 0);
2548 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2552 a
= message_extend_body(m
, align
, size
, false, false);
2556 r
= sd_bus_message_close_container(m
);
2564 _public_
int sd_bus_message_append_array(
2572 assert_return(m
, -EINVAL
);
2573 assert_return(!m
->sealed
, -EPERM
);
2574 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2575 assert_return(ptr
|| size
== 0, -EINVAL
);
2576 assert_return(!m
->poisoned
, -ESTALE
);
2578 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2582 memcpy_safe(p
, ptr
, size
);
2587 _public_
int sd_bus_message_append_array_iovec(
2590 const struct iovec
*iov
,
2598 assert_return(m
, -EINVAL
);
2599 assert_return(!m
->sealed
, -EPERM
);
2600 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2601 assert_return(iov
|| n
== 0, -EINVAL
);
2602 assert_return(!m
->poisoned
, -ESTALE
);
2604 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2606 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2610 for (i
= 0; i
< n
; i
++) {
2612 if (iov
[i
].iov_base
)
2613 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2615 memzero(p
, iov
[i
].iov_len
);
2617 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2623 _public_
int sd_bus_message_append_array_memfd(
2630 _cleanup_close_
int copy_fd
= -1;
2631 struct bus_body_part
*part
;
2637 assert_return(m
, -EINVAL
);
2638 assert_return(memfd
>= 0, -EBADF
);
2639 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2640 assert_return(size
> 0, -EINVAL
);
2641 assert_return(!m
->sealed
, -EPERM
);
2642 assert_return(!m
->poisoned
, -ESTALE
);
2644 r
= memfd_set_sealed(memfd
);
2648 copy_fd
= fcntl(memfd
, F_DUPFD_CLOEXEC
, 3);
2652 r
= memfd_get_size(memfd
, &real_size
);
2656 if (offset
== 0 && size
== (uint64_t) -1)
2658 else if (offset
+ size
> real_size
)
2661 align
= bus_type_get_alignment(type
);
2662 sz
= bus_type_get_size(type
);
2664 assert_se(align
> 0);
2667 if (offset
% align
!= 0)
2673 if (size
> (uint64_t) (uint32_t) -1)
2676 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2680 a
= message_extend_body(m
, align
, 0, false, false);
2684 part
= message_append_part(m
);
2688 part
->memfd
= copy_fd
;
2689 part
->memfd_offset
= offset
;
2690 part
->sealed
= true;
2694 m
->body_size
+= size
;
2695 message_extend_containers(m
, size
);
2697 return sd_bus_message_close_container(m
);
2700 _public_
int sd_bus_message_append_string_memfd(
2706 _cleanup_close_
int copy_fd
= -1;
2707 struct bus_body_part
*part
;
2708 struct bus_container
*c
;
2713 assert_return(m
, -EINVAL
);
2714 assert_return(memfd
>= 0, -EBADF
);
2715 assert_return(size
> 0, -EINVAL
);
2716 assert_return(!m
->sealed
, -EPERM
);
2717 assert_return(!m
->poisoned
, -ESTALE
);
2719 r
= memfd_set_sealed(memfd
);
2723 copy_fd
= fcntl(memfd
, FD_CLOEXEC
, 3);
2727 r
= memfd_get_size(memfd
, &real_size
);
2731 if (offset
== 0 && size
== (uint64_t) -1)
2733 else if (offset
+ size
> real_size
)
2736 /* We require this to be NUL terminated */
2740 if (size
> (uint64_t) (uint32_t) -1)
2743 c
= message_get_container(m
);
2744 if (c
->signature
&& c
->signature
[c
->index
]) {
2745 /* Container signature is already set */
2747 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2752 /* Maybe we can append to the signature? But only if this is the top-level container */
2753 if (c
->enclosing
!= 0)
2756 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2763 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2764 a
= message_extend_body(m
, 4, 4, false, false);
2768 *(uint32_t*) a
= size
- 1;
2771 part
= message_append_part(m
);
2775 part
->memfd
= copy_fd
;
2776 part
->memfd_offset
= offset
;
2777 part
->sealed
= true;
2781 m
->body_size
+= size
;
2782 message_extend_containers(m
, size
);
2784 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2785 r
= message_add_offset(m
, m
->body_size
);
2792 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2798 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2802 assert_return(m
, -EINVAL
);
2803 assert_return(!m
->sealed
, -EPERM
);
2804 assert_return(!m
->poisoned
, -ESTALE
);
2806 r
= sd_bus_message_open_container(m
, 'a', "s");
2810 STRV_FOREACH(i
, l
) {
2811 r
= sd_bus_message_append_basic(m
, 's', *i
);
2816 return sd_bus_message_close_container(m
);
2819 static int bus_message_close_header(sd_bus_message
*m
) {
2823 /* The actual user data is finished now, we just complete the
2824 variant and struct now (at least on gvariant). Remember
2825 this position, so that during parsing we know where to
2826 put the outer container end. */
2827 m
->user_body_size
= m
->body_size
;
2829 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2830 const char *signature
;
2834 /* Add offset table to end of fields array */
2835 if (m
->n_header_offsets
>= 1) {
2839 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2841 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2842 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2846 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2847 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2850 /* Add gvariant NUL byte plus signature to the end of
2851 * the body, followed by the final offset pointing to
2852 * the end of the fields array */
2854 signature
= strempty(m
->root_container
.signature
);
2855 l
= strlen(signature
);
2857 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2858 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2863 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2864 memcpy((uint8_t*) d
+ 2, signature
, l
);
2865 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2867 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2870 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2872 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2873 m
->header
->dbus1
.body_size
= m
->body_size
;
2879 _public_
int sd_bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, uint64_t timeout_usec
) {
2880 struct bus_body_part
*part
;
2885 assert_return(m
, -EINVAL
);
2890 if (m
->n_containers
> 0)
2896 if (cookie
> 0xffffffffULL
&&
2897 !BUS_MESSAGE_IS_GVARIANT(m
))
2900 /* In vtables the return signature of method calls is listed,
2901 * let's check if they match if this is a response */
2902 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2903 m
->enforced_reply_signature
&&
2904 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2907 /* If gvariant marshalling is used we need to close the body structure */
2908 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2912 /* If there's a non-trivial signature set, then add it in
2913 * here, but only on dbus1 */
2914 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2915 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2921 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2926 r
= bus_message_close_header(m
);
2930 if (BUS_MESSAGE_IS_GVARIANT(m
))
2931 m
->header
->dbus2
.cookie
= cookie
;
2933 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2935 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout_usec
;
2937 /* Add padding at the end of the fields part, since we know
2938 * the body needs to start at an 8 byte alignment. We made
2939 * sure we allocated enough space for this, so all we need to
2940 * do here is to zero it out. */
2941 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2943 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2945 /* If this is something we can send as memfd, then let's seal
2946 the memfd now. Note that we can send memfds as payload only
2947 for directed messages, and not for broadcasts. */
2948 if (m
->destination
&& m
->bus
->use_memfd
) {
2949 MESSAGE_FOREACH_PART(part
, i
, m
)
2950 if (part
->memfd
>= 0 &&
2952 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
2953 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
2956 /* Try to seal it if that makes
2957 * sense. First, unmap our own map to
2958 * make sure we don't keep it busy. */
2959 bus_body_part_unmap(part
);
2961 /* Then, sync up real memfd size */
2963 r
= memfd_set_size(part
->memfd
, sz
);
2967 /* Finally, try to seal */
2968 if (memfd_set_sealed(part
->memfd
) >= 0)
2969 part
->sealed
= true;
2973 m
->root_container
.end
= m
->user_body_size
;
2974 m
->root_container
.index
= 0;
2975 m
->root_container
.offset_index
= 0;
2976 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
2983 int bus_body_part_map(struct bus_body_part
*part
) {
2992 if (part
->size
<= 0)
2995 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2996 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
2997 static const uint8_t zeroes
[7] = { };
2998 part
->data
= (void*) zeroes
;
3002 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
3003 psz
= PAGE_ALIGN(part
->size
+ shift
);
3005 if (part
->memfd
>= 0)
3006 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
3007 else if (part
->is_zero
)
3008 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
3012 if (p
== MAP_FAILED
)
3016 part
->mmap_begin
= p
;
3017 part
->data
= (uint8_t*) p
+ shift
;
3018 part
->munmap_this
= true;
3023 void bus_body_part_unmap(struct bus_body_part
*part
) {
3027 if (part
->memfd
< 0)
3030 if (!part
->mmap_begin
)
3033 if (!part
->munmap_this
)
3036 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
3038 part
->mmap_begin
= NULL
;
3041 part
->munmap_this
= false;
3046 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3047 size_t k
, start
, end
;
3052 start
= ALIGN_TO((size_t) *rindex
, align
);
3053 end
= start
+ nbytes
;
3058 /* Verify that padding is 0 */
3059 for (k
= *rindex
; k
< start
; k
++)
3060 if (((const uint8_t*) p
)[k
] != 0)
3064 *r
= (uint8_t*) p
+ start
;
3071 static bool message_end_of_signature(sd_bus_message
*m
) {
3072 struct bus_container
*c
;
3076 c
= message_get_container(m
);
3077 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3080 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3081 struct bus_container
*c
;
3085 c
= message_get_container(m
);
3086 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3089 if (BUS_MESSAGE_IS_GVARIANT(m
))
3090 return index
>= c
->end
;
3092 assert(c
->array_size
);
3093 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3097 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3098 assert_return(m
, -EINVAL
);
3099 assert_return(m
->sealed
, -EPERM
);
3101 if (complete
&& m
->n_containers
> 0)
3104 if (message_end_of_signature(m
))
3107 if (message_end_of_array(m
, m
->rindex
))
3113 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3114 struct bus_body_part
*part
;
3120 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3121 part
= m
->cached_rindex_part
;
3122 begin
= m
->cached_rindex_part_begin
;
3132 if (index
+ sz
<= begin
+ part
->size
) {
3134 r
= bus_body_part_map(part
);
3139 *p
= (uint8_t*) part
->data
+ index
- begin
;
3141 m
->cached_rindex_part
= part
;
3142 m
->cached_rindex_part_begin
= begin
;
3147 begin
+= part
->size
;
3154 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3161 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3164 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3167 sz
= bus_gvariant_get_size(c
->signature
);
3171 if (c
->offset_index
+1 >= c
->n_offsets
)
3174 /* Variable-size array */
3176 alignment
= bus_gvariant_get_alignment(c
->signature
);
3177 assert(alignment
> 0);
3179 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3180 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3183 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3186 /* Fixed-size array */
3187 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3193 } else if (IN_SET(c
->enclosing
, 0, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
3198 if (c
->offset_index
+1 >= c
->n_offsets
)
3201 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3205 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3210 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3213 alignment
= bus_gvariant_get_alignment(t
);
3216 assert(alignment
> 0);
3218 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3219 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3223 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3226 assert_not_reached("Unknown container type");
3231 /* Reached the end */
3238 static int message_peek_body(
3245 size_t k
, start
, end
, padding
;
3246 struct bus_body_part
*part
;
3253 start
= ALIGN_TO((size_t) *rindex
, align
);
3254 padding
= start
- *rindex
;
3255 end
= start
+ nbytes
;
3257 if (end
> m
->user_body_size
)
3260 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3265 /* Verify padding */
3266 for (k
= 0; k
< padding
; k
++)
3271 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3272 if (!part
|| (nbytes
> 0 && !q
))
3283 static bool validate_nul(const char *s
, size_t l
) {
3285 /* Check for NUL chars in the string */
3286 if (memchr(s
, 0, l
))
3289 /* Check for NUL termination */
3296 static bool validate_string(const char *s
, size_t l
) {
3298 if (!validate_nul(s
, l
))
3301 /* Check if valid UTF8 */
3302 if (!utf8_is_valid(s
))
3308 static bool validate_signature(const char *s
, size_t l
) {
3310 if (!validate_nul(s
, l
))
3313 /* Check if valid signature */
3314 if (!signature_is_valid(s
, true))
3320 static bool validate_object_path(const char *s
, size_t l
) {
3322 if (!validate_nul(s
, l
))
3325 if (!object_path_is_valid(s
))
3331 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3332 struct bus_container
*c
;
3337 assert_return(m
, -EINVAL
);
3338 assert_return(m
->sealed
, -EPERM
);
3339 assert_return(bus_type_is_basic(type
), -EINVAL
);
3341 if (message_end_of_signature(m
))
3344 if (message_end_of_array(m
, m
->rindex
))
3347 c
= message_get_container(m
);
3348 if (c
->signature
[c
->index
] != type
)
3353 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3355 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3358 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3362 if (type
== SD_BUS_TYPE_STRING
)
3363 ok
= validate_string(q
, c
->item_size
-1);
3364 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3365 ok
= validate_object_path(q
, c
->item_size
-1);
3367 ok
= validate_signature(q
, c
->item_size
-1);
3373 *(const char**) p
= q
;
3377 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3379 if ((size_t) sz
!= c
->item_size
)
3382 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3385 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3391 case SD_BUS_TYPE_BYTE
:
3393 *(uint8_t*) p
= *(uint8_t*) q
;
3396 case SD_BUS_TYPE_BOOLEAN
:
3398 *(int*) p
= !!*(uint8_t*) q
;
3401 case SD_BUS_TYPE_INT16
:
3402 case SD_BUS_TYPE_UINT16
:
3404 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3407 case SD_BUS_TYPE_INT32
:
3408 case SD_BUS_TYPE_UINT32
:
3410 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3413 case SD_BUS_TYPE_INT64
:
3414 case SD_BUS_TYPE_UINT64
:
3415 case SD_BUS_TYPE_DOUBLE
:
3417 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3420 case SD_BUS_TYPE_UNIX_FD
: {
3423 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3428 *(int*) p
= m
->fds
[j
];
3434 assert_not_reached("unexpected type");
3438 r
= container_next_item(m
, c
, &rindex
);
3443 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3447 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3451 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3452 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3456 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3457 ok
= validate_object_path(q
, l
);
3459 ok
= validate_string(q
, l
);
3464 *(const char**) p
= q
;
3466 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3469 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3474 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3478 if (!validate_signature(q
, l
))
3482 *(const char**) p
= q
;
3487 align
= bus_type_get_alignment(type
);
3490 sz
= bus_type_get_size(type
);
3493 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3499 case SD_BUS_TYPE_BYTE
:
3501 *(uint8_t*) p
= *(uint8_t*) q
;
3504 case SD_BUS_TYPE_BOOLEAN
:
3506 *(int*) p
= !!*(uint32_t*) q
;
3509 case SD_BUS_TYPE_INT16
:
3510 case SD_BUS_TYPE_UINT16
:
3512 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3515 case SD_BUS_TYPE_INT32
:
3516 case SD_BUS_TYPE_UINT32
:
3518 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3521 case SD_BUS_TYPE_INT64
:
3522 case SD_BUS_TYPE_UINT64
:
3523 case SD_BUS_TYPE_DOUBLE
:
3525 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3528 case SD_BUS_TYPE_UNIX_FD
: {
3531 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3536 *(int*) p
= m
->fds
[j
];
3541 assert_not_reached("Unknown basic type...");
3548 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3554 static int bus_message_enter_array(
3556 struct bus_container
*c
,
3557 const char *contents
,
3558 uint32_t **array_size
,
3561 size_t *n_offsets
) {
3575 if (!signature_is_single(contents
, true))
3578 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3581 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3584 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3589 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3592 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3596 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3599 alignment
= bus_type_get_alignment(contents
[0]);
3603 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3607 *array_size
= (uint32_t*) q
;
3609 } else if (c
->item_size
<= 0) {
3611 /* gvariant: empty array */
3616 } else if (bus_gvariant_is_fixed_size(contents
)) {
3618 /* gvariant: fixed length array */
3619 *item_size
= bus_gvariant_get_size(contents
);
3624 size_t where
, p
= 0, framing
, sz
;
3627 /* gvariant: variable length array */
3628 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3630 where
= rindex
+ c
->item_size
- sz
;
3631 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3635 framing
= bus_gvariant_read_word_le(q
, sz
);
3636 if (framing
> c
->item_size
- sz
)
3638 if ((c
->item_size
- framing
) % sz
!= 0)
3641 *n_offsets
= (c
->item_size
- framing
) / sz
;
3643 where
= rindex
+ framing
;
3644 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3648 *offsets
= new(size_t, *n_offsets
);
3652 for (i
= 0; i
< *n_offsets
; i
++) {
3655 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3656 if (x
> c
->item_size
- sz
)
3661 (*offsets
)[i
] = rindex
+ x
;
3665 *item_size
= (*offsets
)[0] - rindex
;
3670 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3671 c
->index
+= 1 + strlen(contents
);
3676 static int bus_message_enter_variant(
3678 struct bus_container
*c
,
3679 const char *contents
,
3680 size_t *item_size
) {
3692 if (!signature_is_single(contents
, false))
3695 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3698 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3701 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3706 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3709 k
= strlen(contents
);
3710 if (1+k
> c
->item_size
)
3713 where
= rindex
+ c
->item_size
- (1+k
);
3714 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3718 if (*(char*) q
!= 0)
3721 if (memcmp((uint8_t*) q
+1, contents
, k
))
3724 *item_size
= c
->item_size
- (1+k
);
3727 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3732 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3736 if (!validate_signature(q
, l
))
3739 if (!streq(q
, contents
))
3745 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3751 static int build_struct_offsets(
3753 const char *signature
,
3757 size_t *n_offsets
) {
3759 unsigned n_variable
= 0, n_total
= 0, v
;
3760 size_t previous
= 0, where
;
3771 if (isempty(signature
)) {
3772 /* Unary type is encoded as *fixed* 1 byte padding */
3773 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3777 if (*(uint8_t *) q
!= 0)
3786 sz
= bus_gvariant_determine_word_size(size
, 0);
3790 /* First, loop over signature and count variable elements and
3791 * elements in general. We use this to know how large the
3792 * offset array is at the end of the structure. Note that
3793 * GVariant only stores offsets for all variable size elements
3794 * that are not the last item. */
3800 r
= signature_element_length(p
, &n
);
3809 r
= bus_gvariant_is_fixed_size(t
);
3814 if (r
== 0 && p
[n
] != 0) /* except the last item */
3821 if (size
< n_variable
* sz
)
3824 where
= m
->rindex
+ size
- (n_variable
* sz
);
3825 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3831 *offsets
= new(size_t, n_total
);
3837 /* Second, loop again and build an offset table */
3843 r
= signature_element_length(p
, &n
);
3852 k
= bus_gvariant_get_size(t
);
3860 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3863 if (m
->rindex
+ x
< previous
)
3866 /* The last item's end
3867 * is determined from
3870 x
= size
- (n_variable
* sz
);
3872 offset
= m
->rindex
+ x
;
3878 align
= bus_gvariant_get_alignment(t
);
3881 offset
= (*n_offsets
== 0 ? m
->rindex
: ALIGN_TO((*offsets
)[*n_offsets
-1], align
)) + k
;
3885 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3890 assert(*n_offsets
== n_total
);
3892 *item_size
= (*offsets
)[0] - m
->rindex
;
3896 static int enter_struct_or_dict_entry(
3898 struct bus_container
*c
,
3899 const char *contents
,
3902 size_t *n_offsets
) {
3913 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3916 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3921 /* gvariant with contents */
3922 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3927 static int bus_message_enter_struct(
3929 struct bus_container
*c
,
3930 const char *contents
,
3933 size_t *n_offsets
) {
3945 if (!signature_is_valid(contents
, false))
3948 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3951 l
= strlen(contents
);
3953 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
3954 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3955 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
3958 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3962 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3963 c
->index
+= 1 + l
+ 1;
3968 static int bus_message_enter_dict_entry(
3970 struct bus_container
*c
,
3971 const char *contents
,
3974 size_t *n_offsets
) {
3983 if (!signature_is_pair(contents
))
3986 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3989 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3992 l
= strlen(contents
);
3994 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
3995 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3996 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
3999 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4003 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4004 c
->index
+= 1 + l
+ 1;
4009 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
4011 const char *contents
) {
4012 struct bus_container
*c
, *w
;
4013 uint32_t *array_size
= NULL
;
4016 size_t *offsets
= NULL
;
4017 size_t n_offsets
= 0, item_size
= 0;
4020 assert_return(m
, -EINVAL
);
4021 assert_return(m
->sealed
, -EPERM
);
4022 assert_return(type
!= 0 || !contents
, -EINVAL
);
4024 if (type
== 0 || !contents
) {
4028 /* Allow entering into anonymous containers */
4029 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
4033 if (type
!= 0 && type
!= tt
)
4036 if (contents
&& !streq(contents
, cc
))
4044 * We enforce a global limit on container depth, that is much
4045 * higher than the 32 structs and 32 arrays the specification
4046 * mandates. This is simpler to implement for us, and we need
4047 * this only to ensure our container array doesn't grow
4048 * without bounds. We are happy to return any data from a
4049 * message as long as the data itself is valid, even if the
4050 * overall message might be not.
4052 * Note that the message signature is validated when
4053 * parsing the headers, and that validation does check the
4056 * Note that the specification defines no limits on the depth
4057 * of stacked variants, but we do.
4059 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4062 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4065 if (message_end_of_signature(m
))
4068 if (message_end_of_array(m
, m
->rindex
))
4071 c
= message_get_container(m
);
4073 signature
= strdup(contents
);
4077 c
->saved_index
= c
->index
;
4080 if (type
== SD_BUS_TYPE_ARRAY
)
4081 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4082 else if (type
== SD_BUS_TYPE_VARIANT
)
4083 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4084 else if (type
== SD_BUS_TYPE_STRUCT
)
4085 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4086 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4087 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4097 /* OK, let's fill it in */
4098 w
= m
->containers
+ m
->n_containers
++;
4099 w
->enclosing
= type
;
4100 w
->signature
= signature
;
4101 w
->peeked_signature
= NULL
;
4105 w
->begin
= m
->rindex
;
4107 /* Unary type has fixed size of 1, but virtual size of 0 */
4108 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4109 type
== SD_BUS_TYPE_STRUCT
&&
4111 w
->end
= m
->rindex
+ 0;
4113 w
->end
= m
->rindex
+ c
->item_size
;
4115 w
->array_size
= array_size
;
4116 w
->item_size
= item_size
;
4117 w
->offsets
= offsets
;
4118 w
->n_offsets
= n_offsets
;
4119 w
->offset_index
= 0;
4124 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4125 struct bus_container
*c
;
4129 assert_return(m
, -EINVAL
);
4130 assert_return(m
->sealed
, -EPERM
);
4131 assert_return(m
->n_containers
> 0, -ENXIO
);
4133 c
= message_get_container(m
);
4135 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4136 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4140 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4141 if (m
->rindex
< c
->end
)
4144 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4147 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4148 if (c
->begin
+ l
!= m
->rindex
)
4153 free(c
->peeked_signature
);
4157 c
= message_get_container(m
);
4160 c
->index
= c
->saved_index
;
4161 r
= container_next_item(m
, c
, &m
->rindex
);
4169 static void message_quit_container(sd_bus_message
*m
) {
4170 struct bus_container
*c
;
4174 assert(m
->n_containers
> 0);
4176 c
= message_get_container(m
);
4179 assert(m
->rindex
>= c
->before
);
4180 m
->rindex
= c
->before
;
4182 /* Free container */
4187 /* Correct index of new top-level container */
4188 c
= message_get_container(m
);
4189 c
->index
= c
->saved_index
;
4192 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4193 struct bus_container
*c
;
4196 assert_return(m
, -EINVAL
);
4197 assert_return(m
->sealed
, -EPERM
);
4199 if (message_end_of_signature(m
))
4202 if (message_end_of_array(m
, m
->rindex
))
4205 c
= message_get_container(m
);
4207 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4211 *type
= c
->signature
[c
->index
];
4215 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4221 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4227 sig
= strndup(c
->signature
+ c
->index
+ 1, l
);
4231 free(c
->peeked_signature
);
4232 *contents
= c
->peeked_signature
= sig
;
4236 *type
= SD_BUS_TYPE_ARRAY
;
4241 if (IN_SET(c
->signature
[c
->index
], SD_BUS_TYPE_STRUCT_BEGIN
, SD_BUS_TYPE_DICT_ENTRY_BEGIN
)) {
4247 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4252 sig
= strndup(c
->signature
+ c
->index
+ 1, l
- 2);
4256 free(c
->peeked_signature
);
4257 *contents
= c
->peeked_signature
= sig
;
4261 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4266 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4270 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4273 if (c
->item_size
< 2)
4276 /* Look for the NUL delimiter that
4277 separates the payload from the
4278 signature. Since the body might be
4279 in a different part that then the
4280 signature we map byte by byte. */
4282 for (k
= 2; k
<= c
->item_size
; k
++) {
4285 where
= m
->rindex
+ c
->item_size
- k
;
4286 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4290 if (*(char*) q
== 0)
4294 if (k
> c
->item_size
)
4297 free(c
->peeked_signature
);
4298 c
->peeked_signature
= strndup((char*) q
+ 1, k
- 1);
4299 if (!c
->peeked_signature
)
4302 if (!signature_is_valid(c
->peeked_signature
, true))
4305 *contents
= c
->peeked_signature
;
4310 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4315 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4319 if (!validate_signature(q
, l
))
4327 *type
= SD_BUS_TYPE_VARIANT
;
4342 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4343 struct bus_container
*c
;
4345 assert_return(m
, -EINVAL
);
4346 assert_return(m
->sealed
, -EPERM
);
4349 message_reset_containers(m
);
4352 c
= message_get_container(m
);
4354 c
= message_get_container(m
);
4356 c
->offset_index
= 0;
4358 m
->rindex
= c
->begin
;
4361 c
->offset_index
= 0;
4362 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4364 return !isempty(c
->signature
);
4367 static int message_read_ap(
4372 unsigned n_array
, n_struct
;
4373 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4374 unsigned stack_ptr
= 0;
4375 unsigned n_loop
= 0;
4383 /* Ideally, we'd just call ourselves recursively on every
4384 * complex type. However, the state of a va_list that is
4385 * passed to a function is undefined after that function
4386 * returns. This means we need to docode the va_list linearly
4387 * in a single stackframe. We hence implement our own
4388 * home-grown stack in an array. */
4390 n_array
= (unsigned) -1; /* length of current array entries */
4391 n_struct
= strlen(types
); /* length of current struct contents signature */
4398 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4399 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4405 r
= sd_bus_message_exit_container(m
);
4413 if (n_array
!= (unsigned) -1)
4422 case SD_BUS_TYPE_BYTE
:
4423 case SD_BUS_TYPE_BOOLEAN
:
4424 case SD_BUS_TYPE_INT16
:
4425 case SD_BUS_TYPE_UINT16
:
4426 case SD_BUS_TYPE_INT32
:
4427 case SD_BUS_TYPE_UINT32
:
4428 case SD_BUS_TYPE_INT64
:
4429 case SD_BUS_TYPE_UINT64
:
4430 case SD_BUS_TYPE_DOUBLE
:
4431 case SD_BUS_TYPE_STRING
:
4432 case SD_BUS_TYPE_OBJECT_PATH
:
4433 case SD_BUS_TYPE_SIGNATURE
:
4434 case SD_BUS_TYPE_UNIX_FD
: {
4437 p
= va_arg(ap
, void*);
4438 r
= sd_bus_message_read_basic(m
, *t
, p
);
4451 case SD_BUS_TYPE_ARRAY
: {
4454 r
= signature_element_length(t
+ 1, &k
);
4460 memcpy(s
, t
+ 1, k
);
4463 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4474 if (n_array
== (unsigned) -1) {
4479 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4485 n_array
= va_arg(ap
, unsigned);
4490 case SD_BUS_TYPE_VARIANT
: {
4493 s
= va_arg(ap
, const char *);
4497 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4507 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4512 n_struct
= strlen(s
);
4513 n_array
= (unsigned) -1;
4518 case SD_BUS_TYPE_STRUCT_BEGIN
:
4519 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4522 r
= signature_element_length(t
, &k
);
4528 memcpy(s
, t
+ 1, k
- 2);
4531 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4541 if (n_array
== (unsigned) -1) {
4546 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4552 n_array
= (unsigned) -1;
4565 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4569 assert_return(m
, -EINVAL
);
4570 assert_return(m
->sealed
, -EPERM
);
4571 assert_return(types
, -EINVAL
);
4573 va_start(ap
, types
);
4574 r
= message_read_ap(m
, types
, ap
);
4580 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4583 assert_return(m
, -EINVAL
);
4584 assert_return(m
->sealed
, -EPERM
);
4586 /* If types is NULL, read exactly one element */
4588 struct bus_container
*c
;
4591 if (message_end_of_signature(m
))
4594 if (message_end_of_array(m
, m
->rindex
))
4597 c
= message_get_container(m
);
4599 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4603 types
= strndupa(c
->signature
+ c
->index
, l
);
4608 case 0: /* Nothing to drop */
4611 case SD_BUS_TYPE_BYTE
:
4612 case SD_BUS_TYPE_BOOLEAN
:
4613 case SD_BUS_TYPE_INT16
:
4614 case SD_BUS_TYPE_UINT16
:
4615 case SD_BUS_TYPE_INT32
:
4616 case SD_BUS_TYPE_UINT32
:
4617 case SD_BUS_TYPE_INT64
:
4618 case SD_BUS_TYPE_UINT64
:
4619 case SD_BUS_TYPE_DOUBLE
:
4620 case SD_BUS_TYPE_STRING
:
4621 case SD_BUS_TYPE_OBJECT_PATH
:
4622 case SD_BUS_TYPE_SIGNATURE
:
4623 case SD_BUS_TYPE_UNIX_FD
:
4625 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4629 r
= sd_bus_message_skip(m
, types
+ 1);
4635 case SD_BUS_TYPE_ARRAY
: {
4638 r
= signature_element_length(types
+ 1, &k
);
4644 memcpy(s
, types
+1, k
);
4647 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4652 r
= sd_bus_message_skip(m
, s
);
4659 r
= sd_bus_message_exit_container(m
);
4664 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4671 case SD_BUS_TYPE_VARIANT
: {
4672 const char *contents
;
4675 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4679 if (x
!= SD_BUS_TYPE_VARIANT
)
4682 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4686 r
= sd_bus_message_skip(m
, contents
);
4691 r
= sd_bus_message_exit_container(m
);
4695 r
= sd_bus_message_skip(m
, types
+ 1);
4702 case SD_BUS_TYPE_STRUCT_BEGIN
:
4703 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4706 r
= signature_element_length(types
, &k
);
4712 memcpy(s
, types
+1, k
-2);
4715 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4719 r
= sd_bus_message_skip(m
, s
);
4723 r
= sd_bus_message_exit_container(m
);
4728 r
= sd_bus_message_skip(m
, types
+ k
);
4740 _public_
int sd_bus_message_read_array(
4746 struct bus_container
*c
;
4752 assert_return(m
, -EINVAL
);
4753 assert_return(m
->sealed
, -EPERM
);
4754 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4755 assert_return(ptr
, -EINVAL
);
4756 assert_return(size
, -EINVAL
);
4757 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4759 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4763 c
= message_get_container(m
);
4765 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4766 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4770 sz
= c
->end
- c
->begin
;
4772 align
= bus_type_get_alignment(type
);
4776 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4780 /* Zero length array, let's return some aligned
4781 * pointer that is not NULL */
4782 p
= (uint8_t*) align
;
4784 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4789 r
= sd_bus_message_exit_container(m
);
4793 *ptr
= (const void*) p
;
4799 message_quit_container(m
);
4803 static int message_peek_fields(
4814 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4817 static int message_peek_field_uint32(
4829 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4832 /* identical for gvariant and dbus1 */
4834 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4839 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4844 static int message_peek_field_uint64(
4856 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4859 /* identical for gvariant and dbus1 */
4861 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4866 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4871 static int message_peek_field_string(
4873 bool (*validate
)(const char *p
),
4885 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4890 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4896 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4900 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4906 if (!validate_nul(q
, l
))
4912 if (!validate_string(q
, l
))
4922 static int message_peek_field_signature(
4935 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4940 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4946 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
4951 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4956 if (!validate_signature(q
, l
))
4965 static int message_skip_fields(
4968 uint32_t array_size
,
4969 const char **signature
) {
4971 size_t original_index
;
4977 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
4979 original_index
= *ri
;
4985 if (array_size
!= (uint32_t) -1 &&
4986 array_size
<= *ri
- original_index
)
4993 if (t
== SD_BUS_TYPE_STRING
) {
4995 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
5001 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
5003 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
5009 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
5011 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
5017 } else if (bus_type_is_basic(t
)) {
5020 align
= bus_type_get_alignment(t
);
5021 k
= bus_type_get_size(t
);
5022 assert(align
> 0 && k
> 0);
5024 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
5030 } else if (t
== SD_BUS_TYPE_ARRAY
) {
5032 r
= signature_element_length(*signature
+1, &l
);
5042 strncpy(sig
, *signature
+ 1, l
-1);
5045 alignment
= bus_type_get_alignment(sig
[0]);
5049 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5052 if (nas
> BUS_ARRAY_MAX_SIZE
)
5055 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5059 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5064 (*signature
) += 1 + l
;
5066 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5069 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5073 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5079 } else if (IN_SET(t
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
5081 r
= signature_element_length(*signature
, &l
);
5088 strncpy(sig
, *signature
+ 1, l
-1);
5091 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5102 int bus_message_parse_fields(sd_bus_message
*m
) {
5105 uint32_t unix_fds
= 0;
5106 bool unix_fds_set
= false;
5107 void *offsets
= NULL
;
5108 unsigned n_offsets
= 0;
5114 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5117 /* Read the signature from the end of the body variant first */
5118 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5119 if (m
->footer_accessible
< 1 + sz
)
5122 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5124 if (p
< (char*) m
->footer
)
5131 /* We found the beginning of the signature
5132 * string, yay! We require the body to be a
5133 * structure, so verify it and then strip the
5134 * opening/closing brackets. */
5136 l
= ((char*) m
->footer
+ m
->footer_accessible
) - p
- (1 + sz
);
5138 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5139 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5142 c
= strndup(p
+ 1 + 1, l
- 2);
5146 free(m
->root_container
.signature
);
5147 m
->root_container
.signature
= c
;
5154 /* Calculate the actual user body size, by removing
5155 * the trailing variant signature and struct offset
5157 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5159 /* Pull out the offset table for the fields array */
5160 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5165 ri
= m
->fields_size
- sz
;
5166 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5170 framing
= bus_gvariant_read_word_le(q
, sz
);
5171 if (framing
>= m
->fields_size
- sz
)
5173 if ((m
->fields_size
- framing
) % sz
!= 0)
5177 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5181 n_offsets
= (m
->fields_size
- framing
) / sz
;
5184 m
->user_body_size
= m
->body_size
;
5187 while (ri
< m
->fields_size
) {
5188 _cleanup_free_
char *sig
= NULL
;
5189 const char *signature
;
5190 uint64_t field_type
;
5191 size_t item_size
= (size_t) -1;
5193 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5202 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5204 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5208 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5212 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5219 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5224 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5229 where
= ri
= ALIGN_TO(ri
, 8);
5230 item_size
= end
- ri
;
5231 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5235 b
= memrchr(q
, 0, item_size
);
5239 sig
= strndup(b
+1, item_size
- (b
+1-(char*) q
));
5244 item_size
= b
- (char*) q
;
5246 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5251 switch (field_type
) {
5253 case _BUS_MESSAGE_HEADER_INVALID
:
5256 case BUS_MESSAGE_HEADER_PATH
:
5261 if (!streq(signature
, "o"))
5264 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5267 case BUS_MESSAGE_HEADER_INTERFACE
:
5272 if (!streq(signature
, "s"))
5275 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5278 case BUS_MESSAGE_HEADER_MEMBER
:
5283 if (!streq(signature
, "s"))
5286 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5289 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5294 if (!streq(signature
, "s"))
5297 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5299 m
->error
._need_free
= -1;
5303 case BUS_MESSAGE_HEADER_DESTINATION
:
5308 if (!streq(signature
, "s"))
5311 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5314 case BUS_MESSAGE_HEADER_SENDER
:
5319 if (!streq(signature
, "s"))
5322 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5324 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
) {
5325 m
->creds
.unique_name
= (char*) m
->sender
;
5326 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5332 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5336 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5339 if (m
->root_container
.signature
)
5342 if (!streq(signature
, "g"))
5345 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5353 free(m
->root_container
.signature
);
5354 m
->root_container
.signature
= c
;
5358 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5360 if (m
->reply_cookie
!= 0)
5363 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5364 /* 64bit on dbus2 */
5366 if (!streq(signature
, "t"))
5369 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5373 /* 32bit on dbus1 */
5376 if (!streq(signature
, "u"))
5379 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5383 m
->reply_cookie
= serial
;
5386 if (m
->reply_cookie
== 0)
5391 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5395 if (!streq(signature
, "u"))
5398 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5402 unix_fds_set
= true;
5406 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5407 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5416 if (m
->n_fds
!= unix_fds
)
5419 switch (m
->header
->type
) {
5421 case SD_BUS_MESSAGE_SIGNAL
:
5422 if (!m
->path
|| !m
->interface
|| !m
->member
)
5425 if (m
->reply_cookie
!= 0)
5430 case SD_BUS_MESSAGE_METHOD_CALL
:
5432 if (!m
->path
|| !m
->member
)
5435 if (m
->reply_cookie
!= 0)
5440 case SD_BUS_MESSAGE_METHOD_RETURN
:
5442 if (m
->reply_cookie
== 0)
5446 case SD_BUS_MESSAGE_METHOD_ERROR
:
5448 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5453 /* Refuse non-local messages that claim they are local */
5454 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5456 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5458 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5461 m
->root_container
.end
= m
->user_body_size
;
5463 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5464 r
= build_struct_offsets(
5466 m
->root_container
.signature
,
5468 &m
->root_container
.item_size
,
5469 &m
->root_container
.offsets
,
5470 &m
->root_container
.n_offsets
);
5475 /* Try to read the error message, but if we can't it's a non-issue */
5476 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5477 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5482 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5483 assert_return(m
, -EINVAL
);
5484 assert_return(destination
, -EINVAL
);
5485 assert_return(!m
->sealed
, -EPERM
);
5486 assert_return(!m
->destination
, -EEXIST
);
5488 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5491 _public_
int sd_bus_message_set_sender(sd_bus_message
*m
, const char *sender
) {
5492 assert_return(m
, -EINVAL
);
5493 assert_return(sender
, -EINVAL
);
5494 assert_return(!m
->sealed
, -EPERM
);
5495 assert_return(!m
->sender
, -EEXIST
);
5497 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5500 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5504 struct bus_body_part
*part
;
5510 total
= BUS_MESSAGE_SIZE(m
);
5516 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5517 MESSAGE_FOREACH_PART(part
, i
, m
)
5518 e
= mempcpy(e
, part
->data
, part
->size
);
5520 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5528 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5535 r
= sd_bus_message_enter_container(m
, 'a', "s");
5539 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5540 r
= strv_extend(l
, s
);
5547 r
= sd_bus_message_exit_container(m
);
5554 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5558 assert_return(m
, -EINVAL
);
5559 assert_return(m
->sealed
, -EPERM
);
5560 assert_return(l
, -EINVAL
);
5562 r
= bus_message_read_strv_extend(m
, &strv
);
5572 static int bus_message_get_arg_skip(
5576 const char **_contents
) {
5581 r
= sd_bus_message_rewind(m
, true);
5586 const char *contents
;
5589 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5595 /* Don't match against arguments after the first one we don't understand */
5596 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5597 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5602 *_contents
= contents
;
5608 r
= sd_bus_message_skip(m
, NULL
);
5615 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5622 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5626 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5629 return sd_bus_message_read_basic(m
, type
, str
);
5632 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5633 const char *contents
;
5640 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5644 if (type
!= SD_BUS_TYPE_ARRAY
)
5646 if (!STR_IN_SET(contents
, "s", "o", "g"))
5649 return sd_bus_message_read_strv(m
, strv
);
5652 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5653 assert_return(m
, EINVAL
);
5655 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5658 return sd_bus_error_get_errno(&m
->error
);
5661 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5662 struct bus_container
*c
;
5664 assert_return(m
, NULL
);
5666 c
= complete
? &m
->root_container
: message_get_container(m
);
5667 return strempty(c
->signature
);
5670 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5671 assert_return(m
, -EINVAL
);
5673 return isempty(m
->root_container
.signature
);
5676 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5677 assert_return(m
, -EINVAL
);
5679 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5682 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5683 bool done_something
= false;
5686 assert_return(m
, -EINVAL
);
5687 assert_return(source
, -EINVAL
);
5688 assert_return(!m
->sealed
, -EPERM
);
5689 assert_return(source
->sealed
, -EPERM
);
5692 const char *contents
;
5707 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5713 done_something
= true;
5715 if (bus_type_is_container(type
) > 0) {
5717 r
= sd_bus_message_enter_container(source
, type
, contents
);
5721 r
= sd_bus_message_open_container(m
, type
, contents
);
5725 r
= sd_bus_message_copy(m
, source
, true);
5729 r
= sd_bus_message_close_container(m
);
5733 r
= sd_bus_message_exit_container(source
);
5740 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5746 if (IN_SET(type
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
, SD_BUS_TYPE_STRING
))
5747 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5749 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5756 return done_something
;
5759 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5764 assert_return(m
, -EINVAL
);
5765 assert_return(m
->sealed
, -EPERM
);
5766 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5767 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5768 assert_return(type
|| contents
, -EINVAL
);
5769 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5771 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5775 if (type
!= 0 && type
!= t
)
5778 if (contents
&& !streq_ptr(contents
, c
))
5784 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5785 assert_return(m
, NULL
);
5790 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5791 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
5799 switch ((*m
)->header
->type
) {
5801 case SD_BUS_MESSAGE_SIGNAL
:
5802 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5808 case SD_BUS_MESSAGE_METHOD_CALL
:
5809 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5815 case SD_BUS_MESSAGE_METHOD_RETURN
:
5816 case SD_BUS_MESSAGE_METHOD_ERROR
:
5818 r
= sd_bus_message_new(bus
, &n
, (*m
)->header
->type
);
5824 n
->reply_cookie
= (*m
)->reply_cookie
;
5826 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5830 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5831 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5835 n
->error
._need_free
= -1;
5844 if ((*m
)->destination
&& !n
->destination
) {
5845 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5850 if ((*m
)->sender
&& !n
->sender
) {
5851 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5856 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5858 r
= sd_bus_message_copy(n
, *m
, true);
5862 timeout
= (*m
)->timeout
;
5863 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
))
5864 timeout
= BUS_DEFAULT_TIMEOUT
;
5866 r
= sd_bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5870 sd_bus_message_unref(*m
);
5876 int bus_message_append_sender(sd_bus_message
*m
, const char *sender
) {
5880 assert_return(!m
->sealed
, -EPERM
);
5881 assert_return(!m
->sender
, -EPERM
);
5883 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5886 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5887 assert_return(m
, -EINVAL
);
5888 assert_return(priority
, -EINVAL
);
5890 *priority
= m
->priority
;
5894 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5895 assert_return(m
, -EINVAL
);
5896 assert_return(!m
->sealed
, -EPERM
);
5898 m
->priority
= priority
;