1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "alloc-util.h"
29 #include "bus-gvariant.h"
30 #include "bus-internal.h"
31 #include "bus-message.h"
32 #include "bus-signature.h"
37 #include "memfd-util.h"
38 #include "string-util.h"
40 #include "time-util.h"
44 static int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
);
46 static void *adjust_pointer(const void *p
, void *old_base
, size_t sz
, void *new_base
) {
51 if (old_base
== new_base
)
54 if ((uint8_t*) p
< (uint8_t*) old_base
)
57 if ((uint8_t*) p
>= (uint8_t*) old_base
+ sz
)
60 return (uint8_t*) new_base
+ ((uint8_t*) p
- (uint8_t*) old_base
);
63 static void message_free_part(sd_bus_message
*m
, struct bus_body_part
*part
) {
67 if (part
->memfd
>= 0) {
68 /* If we can reuse the memfd, try that. For that it
69 * can't be sealed yet. */
72 assert(part
->memfd_offset
== 0);
73 assert(part
->data
== part
->mmap_begin
);
74 bus_kernel_push_memfd(m
->bus
, part
->memfd
, part
->data
, part
->mapped
, part
->allocated
);
77 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
79 safe_close(part
->memfd
);
82 } else if (part
->munmap_this
)
83 munmap(part
->mmap_begin
, part
->mapped
);
84 else if (part
->free_this
)
91 static void message_reset_parts(sd_bus_message
*m
) {
92 struct bus_body_part
*part
;
97 while (m
->n_body_parts
> 0) {
98 struct bus_body_part
*next
= part
->next
;
99 message_free_part(m
, part
);
106 m
->cached_rindex_part
= NULL
;
107 m
->cached_rindex_part_begin
= 0;
110 static void message_reset_containers(sd_bus_message
*m
) {
115 for (i
= 0; i
< m
->n_containers
; i
++) {
116 free(m
->containers
[i
].signature
);
117 free(m
->containers
[i
].offsets
);
120 m
->containers
= mfree(m
->containers
);
122 m
->n_containers
= m
->containers_allocated
= 0;
123 m
->root_container
.index
= 0;
126 static void message_free(sd_bus_message
*m
) {
132 message_reset_parts(m
);
134 if (m
->release_kdbus
)
135 bus_kernel_cmd_free(m
->bus
, (uint8_t *) m
->kdbus
- (uint8_t *) m
->bus
->kdbus_buffer
);
140 sd_bus_unref(m
->bus
);
143 close_many(m
->fds
, m
->n_fds
);
147 if (m
->iovec
!= m
->iovec_fixed
)
150 m
->destination_ptr
= mfree(m
->destination_ptr
);
151 message_reset_containers(m
);
152 free(m
->root_container
.signature
);
153 free(m
->root_container
.offsets
);
155 free(m
->root_container
.peeked_signature
);
157 bus_creds_done(&m
->creds
);
161 static void *message_extend_fields(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
163 size_t old_size
, new_size
, start
;
170 old_size
= sizeof(struct bus_header
) + m
->fields_size
;
171 start
= ALIGN_TO(old_size
, align
);
172 new_size
= start
+ sz
;
174 if (new_size
< start
||
175 new_size
> (size_t) ((uint32_t) -1))
178 if (old_size
== new_size
)
179 return (uint8_t*) m
->header
+ old_size
;
181 if (m
->free_header
) {
182 np
= realloc(m
->header
, ALIGN8(new_size
));
186 /* Initially, the header is allocated as part of of
187 * the sd_bus_message itself, let's replace it by
190 np
= malloc(ALIGN8(new_size
));
194 memcpy(np
, m
->header
, sizeof(struct bus_header
));
197 /* Zero out padding */
198 if (start
> old_size
)
199 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
203 m
->fields_size
= new_size
- sizeof(struct bus_header
);
205 /* Adjust quick access pointers */
206 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
207 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
208 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
209 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
210 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
211 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
213 m
->free_header
= true;
216 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
219 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
222 return (uint8_t*) np
+ start
;
229 static int message_append_field_string(
241 /* dbus1 only allows 8bit header field ids */
245 /* dbus1 doesn't allow strings over 32bit, let's enforce this
246 * globally, to not risk convertability */
248 if (l
> (size_t) (uint32_t) -1)
251 /* Signature "(yv)" where the variant contains "s" */
253 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
255 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
256 p
= message_extend_fields(m
, 8, 8 + l
+ 1 + 1 + 1, true);
260 *((uint64_t*) p
) = h
;
267 *ret
= (char*) p
+ 8;
270 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
271 p
= message_extend_fields(m
, 8, 4 + 4 + l
+ 1, false);
280 ((uint32_t*) p
)[1] = l
;
281 memcpy(p
+ 8, s
, l
+ 1);
284 *ret
= (char*) p
+ 8;
290 static int message_append_field_signature(
301 /* dbus1 only allows 8bit header field ids */
305 /* dbus1 doesn't allow signatures over 8bit, let's enforce
306 * this globally, to not risk convertability */
311 /* Signature "(yv)" where the variant contains "g" */
313 if (BUS_MESSAGE_IS_GVARIANT(m
))
314 /* For gvariant the serialization is the same as for normal strings */
315 return message_append_field_string(m
, h
, 'g', s
, ret
);
317 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
318 p
= message_extend_fields(m
, 8, 4 + 1 + l
+ 1, false);
324 p
[2] = SD_BUS_TYPE_SIGNATURE
;
327 memcpy(p
+ 5, s
, l
+ 1);
330 *ret
= (const char*) p
+ 5;
336 static int message_append_field_uint32(sd_bus_message
*m
, uint64_t h
, uint32_t x
) {
341 /* dbus1 only allows 8bit header field ids */
345 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
346 /* (field id 64bit + ((value + NUL + signature string 'u') */
348 p
= message_extend_fields(m
, 8, 8 + 4 + 1 + 1, true);
352 *((uint64_t*) p
) = h
;
353 *((uint32_t*) (p
+ 8)) = x
;
357 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
358 p
= message_extend_fields(m
, 8, 4 + 4, false);
367 ((uint32_t*) p
)[1] = x
;
373 static int message_append_field_uint64(sd_bus_message
*m
, uint64_t h
, uint64_t x
) {
378 /* dbus1 only allows 8bit header field ids */
382 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
383 /* (field id 64bit + ((value + NUL + signature string 't') */
385 p
= message_extend_fields(m
, 8, 8 + 8 + 1 + 1, true);
389 *((uint64_t*) p
) = h
;
390 *((uint64_t*) (p
+ 8)) = x
;
394 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
395 p
= message_extend_fields(m
, 8, 4 + 4 + 8, false);
408 ((uint64_t*) p
)[1] = x
;
414 static int message_append_reply_cookie(sd_bus_message
*m
, uint64_t cookie
) {
417 if (BUS_MESSAGE_IS_GVARIANT(m
))
418 return message_append_field_uint64(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, cookie
);
420 /* 64bit cookies are not supported on dbus1 */
421 if (cookie
> 0xffffffffUL
)
424 return message_append_field_uint32(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) cookie
);
428 int bus_message_from_header(
431 size_t header_accessible
,
433 size_t footer_accessible
,
439 sd_bus_message
**ret
) {
441 _cleanup_free_ sd_bus_message
*m
= NULL
;
442 struct bus_header
*h
;
446 assert(header
|| header_accessible
<= 0);
447 assert(footer
|| footer_accessible
<= 0);
448 assert(fds
|| n_fds
<= 0);
451 if (header_accessible
< sizeof(struct bus_header
))
454 if (header_accessible
> message_size
)
456 if (footer_accessible
> message_size
)
460 if (!IN_SET(h
->version
, 1, 2))
463 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
466 if (!IN_SET(h
->endian
, BUS_LITTLE_ENDIAN
, BUS_BIG_ENDIAN
))
469 /* Note that we are happy with unknown flags in the flags header! */
471 a
= ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
474 label_sz
= strlen(label
);
485 m
->header_accessible
= header_accessible
;
487 m
->footer_accessible
= footer_accessible
;
489 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
492 if (h
->dbus2
.cookie
== 0)
495 /* dbus2 derives the sizes from the message size and
496 the offset table at the end, since it is formatted as
497 gvariant "yyyyuta{tv}v". Since the message itself is a
498 structure with precisely to variable sized entries,
499 there's only one offset in the table, which marks the
500 end of the fields array. */
502 ws
= bus_gvariant_determine_word_size(message_size
, 0);
503 if (footer_accessible
< ws
)
506 m
->fields_size
= bus_gvariant_read_word_le((uint8_t*) footer
+ footer_accessible
- ws
, ws
);
507 if (ALIGN8(m
->fields_size
) > message_size
- ws
)
509 if (m
->fields_size
< sizeof(struct bus_header
))
512 m
->fields_size
-= sizeof(struct bus_header
);
513 m
->body_size
= message_size
- (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
));
515 if (h
->dbus1
.serial
== 0)
518 /* dbus1 has the sizes in the header */
519 m
->fields_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.fields_size
);
520 m
->body_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.body_size
);
522 if (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
!= message_size
)
530 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
531 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
533 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
536 m
->bus
= sd_bus_ref(bus
);
543 int bus_message_from_malloc(
550 sd_bus_message
**ret
) {
556 r
= bus_message_from_header(
558 buffer
, length
, /* in this case the initial bytes and the final bytes are the same */
567 sz
= length
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
);
570 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(m
->fields_size
);
572 m
->body
.sealed
= true;
577 m
->iovec
= m
->iovec_fixed
;
578 m
->iovec
[0].iov_base
= buffer
;
579 m
->iovec
[0].iov_len
= length
;
581 r
= bus_message_parse_fields(m
);
585 /* We take possession of the memory and fds now */
586 m
->free_header
= true;
597 static sd_bus_message
*message_new(sd_bus
*bus
, uint8_t type
) {
602 m
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
607 m
->header
= (struct bus_header
*) ((uint8_t*) m
+ ALIGN(sizeof(struct sd_bus_message
)));
608 m
->header
->endian
= BUS_NATIVE_ENDIAN
;
609 m
->header
->type
= type
;
610 m
->header
->version
= bus
->message_version
;
611 m
->allow_fds
= bus
->can_fds
|| (bus
->state
!= BUS_HELLO
&& bus
->state
!= BUS_RUNNING
);
612 m
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(m
);
613 m
->bus
= sd_bus_ref(bus
);
615 if (bus
->allow_interactive_authorization
)
616 m
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
621 _public_
int sd_bus_message_new_signal(
625 const char *interface
,
626 const char *member
) {
631 assert_return(bus
, -ENOTCONN
);
632 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
633 assert_return(object_path_is_valid(path
), -EINVAL
);
634 assert_return(interface_name_is_valid(interface
), -EINVAL
);
635 assert_return(member_name_is_valid(member
), -EINVAL
);
636 assert_return(m
, -EINVAL
);
638 t
= message_new(bus
, SD_BUS_MESSAGE_SIGNAL
);
642 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
644 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
647 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
650 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
658 sd_bus_message_unref(t
);
662 _public_
int sd_bus_message_new_method_call(
665 const char *destination
,
667 const char *interface
,
668 const char *member
) {
673 assert_return(bus
, -ENOTCONN
);
674 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
675 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
676 assert_return(object_path_is_valid(path
), -EINVAL
);
677 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
678 assert_return(member_name_is_valid(member
), -EINVAL
);
679 assert_return(m
, -EINVAL
);
681 t
= message_new(bus
, SD_BUS_MESSAGE_METHOD_CALL
);
685 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
688 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
693 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
699 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
712 static int message_new_reply(
713 sd_bus_message
*call
,
715 sd_bus_message
**m
) {
720 assert_return(call
, -EINVAL
);
721 assert_return(call
->sealed
, -EPERM
);
722 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
723 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
724 assert_return(m
, -EINVAL
);
726 t
= message_new(call
->bus
, type
);
730 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
731 t
->reply_cookie
= BUS_MESSAGE_COOKIE(call
);
732 if (t
->reply_cookie
== 0)
735 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
740 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
745 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
746 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
756 _public_
int sd_bus_message_new_method_return(
757 sd_bus_message
*call
,
758 sd_bus_message
**m
) {
760 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
763 _public_
int sd_bus_message_new_method_error(
764 sd_bus_message
*call
,
766 const sd_bus_error
*e
) {
771 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
772 assert_return(m
, -EINVAL
);
774 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
778 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
783 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
788 t
->error
._need_free
= -1;
798 _public_
int sd_bus_message_new_method_errorf(
799 sd_bus_message
*call
,
805 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
808 assert_return(name
, -EINVAL
);
809 assert_return(m
, -EINVAL
);
811 va_start(ap
, format
);
812 bus_error_setfv(&error
, name
, format
, ap
);
815 return sd_bus_message_new_method_error(call
, m
, &error
);
818 _public_
int sd_bus_message_new_method_errno(
819 sd_bus_message
*call
,
822 const sd_bus_error
*p
) {
824 _cleanup_bus_error_free_ sd_bus_error berror
= SD_BUS_ERROR_NULL
;
826 if (sd_bus_error_is_set(p
))
827 return sd_bus_message_new_method_error(call
, m
, p
);
829 sd_bus_error_set_errno(&berror
, error
);
831 return sd_bus_message_new_method_error(call
, m
, &berror
);
834 _public_
int sd_bus_message_new_method_errnof(
835 sd_bus_message
*call
,
841 _cleanup_bus_error_free_ sd_bus_error berror
= SD_BUS_ERROR_NULL
;
844 va_start(ap
, format
);
845 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
848 return sd_bus_message_new_method_error(call
, m
, &berror
);
851 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
855 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
856 m
->creds
.well_known_names_local
= true;
857 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
860 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
864 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
865 m
->creds
.well_known_names_driver
= true;
866 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
869 int bus_message_new_synthetic_error(
872 const sd_bus_error
*e
,
873 sd_bus_message
**m
) {
879 assert(sd_bus_error_is_set(e
));
882 t
= message_new(bus
, SD_BUS_MESSAGE_METHOD_ERROR
);
886 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
887 t
->reply_cookie
= cookie
;
889 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
893 if (bus
&& bus
->unique_name
) {
894 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
899 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
904 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
909 t
->error
._need_free
= -1;
911 bus_message_set_sender_driver(bus
, t
);
921 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
922 assert_return(m
, NULL
);
924 assert(m
->n_ref
> 0);
930 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
935 assert(m
->n_ref
> 0);
945 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
946 assert_return(m
, -EINVAL
);
947 assert_return(type
, -EINVAL
);
949 *type
= m
->header
->type
;
953 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
956 assert_return(m
, -EINVAL
);
957 assert_return(cookie
, -EINVAL
);
959 c
= BUS_MESSAGE_COOKIE(m
);
963 *cookie
= BUS_MESSAGE_COOKIE(m
);
967 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
968 assert_return(m
, -EINVAL
);
969 assert_return(cookie
, -EINVAL
);
971 if (m
->reply_cookie
== 0)
974 *cookie
= m
->reply_cookie
;
978 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
979 assert_return(m
, -EINVAL
);
981 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
982 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
985 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
986 assert_return(m
, -EINVAL
);
988 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
991 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
992 assert_return(m
, -EINVAL
);
994 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
995 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
998 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
999 assert_return(m
, NULL
);
1004 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
1005 assert_return(m
, NULL
);
1007 return m
->interface
;
1010 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
1011 assert_return(m
, NULL
);
1016 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
1017 assert_return(m
, NULL
);
1019 return m
->destination
;
1022 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
1023 assert_return(m
, NULL
);
1028 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
1029 assert_return(m
, NULL
);
1031 if (!sd_bus_error_is_set(&m
->error
))
1037 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
1038 assert_return(m
, -EINVAL
);
1039 assert_return(usec
, -EINVAL
);
1041 if (m
->monotonic
<= 0)
1044 *usec
= m
->monotonic
;
1048 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1049 assert_return(m
, -EINVAL
);
1050 assert_return(usec
, -EINVAL
);
1052 if (m
->realtime
<= 0)
1055 *usec
= m
->realtime
;
1059 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1060 assert_return(m
, -EINVAL
);
1061 assert_return(seqnum
, -EINVAL
);
1066 *seqnum
= m
->seqnum
;
1070 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1071 assert_return(m
, NULL
);
1073 if (m
->creds
.mask
== 0)
1079 _public_
int sd_bus_message_is_signal(
1081 const char *interface
,
1082 const char *member
) {
1084 assert_return(m
, -EINVAL
);
1086 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1089 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1092 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1098 _public_
int sd_bus_message_is_method_call(
1100 const char *interface
,
1101 const char *member
) {
1103 assert_return(m
, -EINVAL
);
1105 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1108 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1111 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1117 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1118 assert_return(m
, -EINVAL
);
1120 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1123 if (name
&& (!m
->error
.name
|| !streq(m
->error
.name
, name
)))
1129 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1130 assert_return(m
, -EINVAL
);
1131 assert_return(!m
->sealed
, -EPERM
);
1132 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1135 m
->header
->flags
&= ~BUS_MESSAGE_NO_REPLY_EXPECTED
;
1137 m
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
1142 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1143 assert_return(m
, -EINVAL
);
1144 assert_return(!m
->sealed
, -EPERM
);
1147 m
->header
->flags
&= ~BUS_MESSAGE_NO_AUTO_START
;
1149 m
->header
->flags
|= BUS_MESSAGE_NO_AUTO_START
;
1154 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1155 assert_return(m
, -EINVAL
);
1156 assert_return(!m
->sealed
, -EPERM
);
1159 m
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
1161 m
->header
->flags
&= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
1166 static struct bus_container
*message_get_container(sd_bus_message
*m
) {
1169 if (m
->n_containers
== 0)
1170 return &m
->root_container
;
1172 assert(m
->containers
);
1173 return m
->containers
+ m
->n_containers
- 1;
1176 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1177 struct bus_body_part
*part
;
1184 if (m
->n_body_parts
<= 0) {
1188 assert(m
->body_end
);
1190 part
= new0(struct bus_body_part
, 1);
1196 m
->body_end
->next
= part
;
1206 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1211 /* All other fields can be left in their defaults */
1212 assert(!part
->data
);
1213 assert(part
->memfd
< 0);
1216 part
->is_zero
= true;
1217 part
->sealed
= true;
1220 static int part_make_space(
1221 struct sd_bus_message
*m
,
1222 struct bus_body_part
*part
,
1231 assert(!part
->sealed
);
1236 if (!part
->data
&& part
->memfd
< 0) {
1237 part
->memfd
= bus_kernel_pop_memfd(m
->bus
, &part
->data
, &part
->mapped
, &part
->allocated
);
1238 part
->mmap_begin
= part
->data
;
1241 if (part
->memfd
>= 0) {
1243 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1244 uint64_t new_allocated
;
1246 new_allocated
= PAGE_ALIGN(sz
> 0 ? 2 * sz
: 1);
1247 r
= memfd_set_size(part
->memfd
, new_allocated
);
1253 part
->allocated
= new_allocated
;
1256 if (!part
->data
|| sz
> part
->mapped
) {
1259 psz
= PAGE_ALIGN(sz
> 0 ? sz
: 1);
1260 if (part
->mapped
<= 0)
1261 n
= mmap(NULL
, psz
, PROT_READ
|PROT_WRITE
, MAP_SHARED
, part
->memfd
, 0);
1263 n
= mremap(part
->mmap_begin
, part
->mapped
, psz
, MREMAP_MAYMOVE
);
1265 if (n
== MAP_FAILED
) {
1270 part
->mmap_begin
= part
->data
= n
;
1272 part
->memfd_offset
= 0;
1275 part
->munmap_this
= true;
1277 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1278 size_t new_allocated
;
1280 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1281 n
= realloc(part
->data
, new_allocated
);
1288 part
->allocated
= new_allocated
;
1289 part
->free_this
= true;
1294 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1300 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1301 struct bus_container
*c
;
1304 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1306 /* Add offset to current container, unless this is the first
1307 * item in it, which will have the 0 offset, which we can
1309 c
= message_get_container(m
);
1311 if (!c
->need_offsets
)
1314 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1317 c
->offsets
[c
->n_offsets
++] = offset
;
1321 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1322 struct bus_container
*c
;
1329 /* Update counters */
1330 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++) {
1333 *c
->array_size
+= expand
;
1337 static void *message_extend_body(
1342 bool force_inline
) {
1344 size_t start_body
, end_body
, padding
, added
;
1355 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1356 end_body
= start_body
+ sz
;
1358 padding
= start_body
- m
->body_size
;
1359 added
= padding
+ sz
;
1361 /* Check for 32bit overflows */
1362 if (end_body
> (size_t) ((uint32_t) -1) ||
1363 end_body
< start_body
) {
1369 struct bus_body_part
*part
= NULL
;
1373 m
->n_body_parts
<= 0 ||
1374 m
->body_end
->sealed
||
1375 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1376 (force_inline
&& m
->body_end
->size
> MEMFD_MIN_SIZE
); /* if this must be an inlined extension, let's create a new part if the previous part is large enough to be inlined */
1380 part
= message_append_part(m
);
1384 part_zero(part
, padding
);
1387 part
= message_append_part(m
);
1391 r
= part_make_space(m
, part
, sz
, &p
);
1395 struct bus_container
*c
;
1397 size_t os
, start_part
, end_part
;
1403 start_part
= ALIGN_TO(part
->size
, align
);
1404 end_part
= start_part
+ sz
;
1406 r
= part_make_space(m
, part
, end_part
, &p
);
1411 memzero(p
, padding
);
1412 p
= (uint8_t*) p
+ padding
;
1415 /* Readjust pointers */
1416 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1417 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1419 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1422 /* Return something that is not NULL and is aligned */
1423 p
= (uint8_t *) NULL
+ align
;
1425 m
->body_size
= end_body
;
1426 message_extend_containers(m
, added
);
1429 r
= message_add_offset(m
, end_body
);
1439 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1450 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1454 f
= realloc(m
->fds
, sizeof(int) * (m
->n_fds
+ 1));
1462 m
->fds
[m
->n_fds
] = copy
;
1468 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1469 _cleanup_close_
int fd
= -1;
1470 struct bus_container
*c
;
1474 assert_return(m
, -EINVAL
);
1475 assert_return(!m
->sealed
, -EPERM
);
1476 assert_return(bus_type_is_basic(type
), -EINVAL
);
1477 assert_return(!m
->poisoned
, -ESTALE
);
1479 c
= message_get_container(m
);
1481 if (c
->signature
&& c
->signature
[c
->index
]) {
1482 /* Container signature is already set */
1484 if (c
->signature
[c
->index
] != type
)
1489 /* Maybe we can append to the signature? But only if this is the top-level container */
1490 if (c
->enclosing
!= 0)
1493 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1500 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1506 case SD_BUS_TYPE_SIGNATURE
:
1507 case SD_BUS_TYPE_STRING
:
1510 /* Fall through... */
1511 case SD_BUS_TYPE_OBJECT_PATH
:
1519 case SD_BUS_TYPE_BOOLEAN
:
1521 u8
= p
&& *(int*) p
;
1527 case SD_BUS_TYPE_UNIX_FD
:
1532 fd
= message_push_fd(m
, *(int*) p
);
1543 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1544 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1551 a
= message_extend_body(m
, align
, sz
, true, false);
1558 *stored
= (const uint8_t*) a
;
1565 case SD_BUS_TYPE_STRING
:
1566 /* To make things easy we'll serialize a NULL string
1567 * into the empty string */
1570 /* Fall through... */
1571 case SD_BUS_TYPE_OBJECT_PATH
:
1577 sz
= 4 + strlen(p
) + 1;
1580 case SD_BUS_TYPE_SIGNATURE
:
1585 sz
= 1 + strlen(p
) + 1;
1588 case SD_BUS_TYPE_BOOLEAN
:
1590 u32
= p
&& *(int*) p
;
1596 case SD_BUS_TYPE_UNIX_FD
:
1601 fd
= message_push_fd(m
, *(int*) p
);
1612 align
= bus_type_get_alignment(type
);
1613 sz
= bus_type_get_size(type
);
1620 a
= message_extend_body(m
, align
, sz
, false, false);
1624 if (type
== SD_BUS_TYPE_STRING
|| type
== SD_BUS_TYPE_OBJECT_PATH
) {
1625 *(uint32_t*) a
= sz
- 5;
1626 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1629 *stored
= (const uint8_t*) a
+ 4;
1631 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1632 *(uint8_t*) a
= sz
- 2;
1633 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1636 *stored
= (const uint8_t*) a
+ 1;
1645 if (type
== SD_BUS_TYPE_UNIX_FD
)
1648 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1655 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1656 return message_append_basic(m
, type
, p
, NULL
);
1659 _public_
int sd_bus_message_append_string_space(
1664 struct bus_container
*c
;
1667 assert_return(m
, -EINVAL
);
1668 assert_return(s
, -EINVAL
);
1669 assert_return(!m
->sealed
, -EPERM
);
1670 assert_return(!m
->poisoned
, -ESTALE
);
1672 c
= message_get_container(m
);
1674 if (c
->signature
&& c
->signature
[c
->index
]) {
1675 /* Container signature is already set */
1677 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1682 /* Maybe we can append to the signature? But only if this is the top-level container */
1683 if (c
->enclosing
!= 0)
1686 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1693 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1694 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1700 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1704 *(uint32_t*) a
= size
;
1710 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1716 _public_
int sd_bus_message_append_string_iovec(
1718 const struct iovec
*iov
,
1726 assert_return(m
, -EINVAL
);
1727 assert_return(!m
->sealed
, -EPERM
);
1728 assert_return(iov
|| n
== 0, -EINVAL
);
1729 assert_return(!m
->poisoned
, -ESTALE
);
1731 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1733 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1737 for (i
= 0; i
< n
; i
++) {
1739 if (iov
[i
].iov_base
)
1740 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1742 memset(p
, ' ', iov
[i
].iov_len
);
1744 p
+= iov
[i
].iov_len
;
1750 static int bus_message_open_array(
1752 struct bus_container
*c
,
1753 const char *contents
,
1754 uint32_t **array_size
,
1756 bool *need_offsets
) {
1766 assert(need_offsets
);
1768 if (!signature_is_single(contents
, true))
1771 if (c
->signature
&& c
->signature
[c
->index
]) {
1773 /* Verify the existing signature */
1775 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1778 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1781 nindex
= c
->index
+ 1 + strlen(contents
);
1785 if (c
->enclosing
!= 0)
1788 /* Extend the existing signature */
1790 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1796 nindex
= e
- c
->signature
;
1799 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1800 alignment
= bus_gvariant_get_alignment(contents
);
1804 /* Add alignment padding and add to offset list */
1805 if (!message_extend_body(m
, alignment
, 0, false, false))
1808 r
= bus_gvariant_is_fixed_size(contents
);
1812 *begin
= m
->body_size
;
1813 *need_offsets
= r
== 0;
1817 struct bus_body_part
*o
;
1819 alignment
= bus_type_get_alignment(contents
[0]);
1823 a
= message_extend_body(m
, 4, 4, false, false);
1828 op
= m
->body_end
->data
;
1829 os
= m
->body_end
->size
;
1831 /* Add alignment between size and first element */
1832 if (!message_extend_body(m
, alignment
, 0, false, false))
1835 /* location of array size might have changed so let's readjust a */
1836 if (o
== m
->body_end
)
1837 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1843 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1849 static int bus_message_open_variant(
1851 struct bus_container
*c
,
1852 const char *contents
) {
1858 if (!signature_is_single(contents
, false))
1861 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1864 if (c
->signature
&& c
->signature
[c
->index
]) {
1866 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1872 if (c
->enclosing
!= 0)
1875 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1882 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1883 /* Variants are always aligned to 8 */
1885 if (!message_extend_body(m
, 8, 0, false, false))
1892 l
= strlen(contents
);
1893 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1898 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1901 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1907 static int bus_message_open_struct(
1909 struct bus_container
*c
,
1910 const char *contents
,
1912 bool *need_offsets
) {
1921 assert(need_offsets
);
1923 if (!signature_is_valid(contents
, false))
1926 if (c
->signature
&& c
->signature
[c
->index
]) {
1929 l
= strlen(contents
);
1931 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1932 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1933 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1936 nindex
= c
->index
+ 1 + l
+ 1;
1940 if (c
->enclosing
!= 0)
1943 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1949 nindex
= e
- c
->signature
;
1952 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1955 alignment
= bus_gvariant_get_alignment(contents
);
1959 if (!message_extend_body(m
, alignment
, 0, false, false))
1962 r
= bus_gvariant_is_fixed_size(contents
);
1966 *begin
= m
->body_size
;
1967 *need_offsets
= r
== 0;
1969 /* Align contents to 8 byte boundary */
1970 if (!message_extend_body(m
, 8, 0, false, false))
1974 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1980 static int bus_message_open_dict_entry(
1982 struct bus_container
*c
,
1983 const char *contents
,
1985 bool *need_offsets
) {
1993 assert(need_offsets
);
1995 if (!signature_is_pair(contents
))
1998 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2001 if (c
->signature
&& c
->signature
[c
->index
]) {
2004 l
= strlen(contents
);
2006 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
2007 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
2008 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
2013 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2016 alignment
= bus_gvariant_get_alignment(contents
);
2020 if (!message_extend_body(m
, alignment
, 0, false, false))
2023 r
= bus_gvariant_is_fixed_size(contents
);
2027 *begin
= m
->body_size
;
2028 *need_offsets
= r
== 0;
2030 /* Align contents to 8 byte boundary */
2031 if (!message_extend_body(m
, 8, 0, false, false))
2038 _public_
int sd_bus_message_open_container(
2041 const char *contents
) {
2043 struct bus_container
*c
, *w
;
2044 uint32_t *array_size
= NULL
;
2046 size_t before
, begin
= 0;
2047 bool need_offsets
= false;
2050 assert_return(m
, -EINVAL
);
2051 assert_return(!m
->sealed
, -EPERM
);
2052 assert_return(contents
, -EINVAL
);
2053 assert_return(!m
->poisoned
, -ESTALE
);
2055 /* Make sure we have space for one more container */
2056 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
2061 c
= message_get_container(m
);
2063 signature
= strdup(contents
);
2069 /* Save old index in the parent container, in case we have to
2070 * abort this container */
2071 c
->saved_index
= c
->index
;
2072 before
= m
->body_size
;
2074 if (type
== SD_BUS_TYPE_ARRAY
)
2075 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
2076 else if (type
== SD_BUS_TYPE_VARIANT
)
2077 r
= bus_message_open_variant(m
, c
, contents
);
2078 else if (type
== SD_BUS_TYPE_STRUCT
)
2079 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
2080 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
2081 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
2090 /* OK, let's fill it in */
2091 w
= m
->containers
+ m
->n_containers
++;
2092 w
->enclosing
= type
;
2093 w
->signature
= signature
;
2095 w
->array_size
= array_size
;
2098 w
->n_offsets
= w
->offsets_allocated
= 0;
2100 w
->need_offsets
= need_offsets
;
2105 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2110 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2113 if (c
->need_offsets
) {
2114 size_t payload
, sz
, i
;
2117 /* Variable-width arrays */
2119 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2120 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2122 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2126 for (i
= 0; i
< c
->n_offsets
; i
++)
2127 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2131 /* Fixed-width or empty arrays */
2133 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2141 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2147 assert(c
->signature
);
2149 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2152 l
= strlen(c
->signature
);
2154 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2159 memcpy(a
+1, c
->signature
, l
);
2164 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2165 bool fixed_size
= true;
2166 size_t n_variable
= 0;
2175 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2178 p
= strempty(c
->signature
);
2182 r
= signature_element_length(p
, &n
);
2191 r
= bus_gvariant_is_fixed_size(t
);
2196 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2198 /* We need to add an offset for each item that has a
2199 * variable size and that is not the last one in the
2203 if (r
== 0 && p
[n
] != 0)
2210 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2211 assert(c
->need_offsets
|| n_variable
== 0);
2213 if (isempty(c
->signature
)) {
2214 /* The unary type is encoded as fixed 1 byte padding */
2215 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2220 } else if (n_variable
<= 0) {
2223 /* Structures with fixed-size members only have to be
2224 * fixed-size themselves. But gvariant requires all fixed-size
2225 * elements to be sized a multiple of their alignment. Hence,
2226 * we must *always* add final padding after the last member so
2227 * the overall size of the structure is properly aligned. */
2229 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2231 assert(alignment
> 0);
2233 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2240 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2242 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2244 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2248 p
= strempty(c
->signature
);
2249 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2253 r
= signature_element_length(p
, &n
);
2264 r
= bus_gvariant_is_fixed_size(t
);
2267 if (r
> 0 || p
[0] == 0)
2271 k
= n_variable
- 1 - j
;
2273 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2282 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2283 struct bus_container
*c
;
2286 assert_return(m
, -EINVAL
);
2287 assert_return(!m
->sealed
, -EPERM
);
2288 assert_return(m
->n_containers
> 0, -EINVAL
);
2289 assert_return(!m
->poisoned
, -ESTALE
);
2291 c
= message_get_container(m
);
2293 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2294 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2299 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2300 r
= bus_message_close_array(m
, c
);
2301 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2302 r
= bus_message_close_variant(m
, c
);
2303 else if (c
->enclosing
== SD_BUS_TYPE_STRUCT
|| c
->enclosing
== SD_BUS_TYPE_DICT_ENTRY
)
2304 r
= bus_message_close_struct(m
, c
, true);
2306 assert_not_reached("Unknown container type");
2320 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2327 stack
[*i
].types
= types
;
2328 stack
[*i
].n_struct
= n_struct
;
2329 stack
[*i
].n_array
= n_array
;
2335 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2346 *types
= stack
[*i
].types
;
2347 *n_struct
= stack
[*i
].n_struct
;
2348 *n_array
= stack
[*i
].n_array
;
2353 int bus_message_append_ap(
2358 unsigned n_array
, n_struct
;
2359 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2360 unsigned stack_ptr
= 0;
2368 n_array
= (unsigned) -1;
2369 n_struct
= strlen(types
);
2374 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2375 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2381 r
= sd_bus_message_close_container(m
);
2389 if (n_array
!= (unsigned) -1)
2398 case SD_BUS_TYPE_BYTE
: {
2401 x
= (uint8_t) va_arg(ap
, int);
2402 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2406 case SD_BUS_TYPE_BOOLEAN
:
2407 case SD_BUS_TYPE_INT32
:
2408 case SD_BUS_TYPE_UINT32
:
2409 case SD_BUS_TYPE_UNIX_FD
: {
2412 /* We assume a boolean is the same as int32_t */
2413 assert_cc(sizeof(int32_t) == sizeof(int));
2415 x
= va_arg(ap
, uint32_t);
2416 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2420 case SD_BUS_TYPE_INT16
:
2421 case SD_BUS_TYPE_UINT16
: {
2424 x
= (uint16_t) va_arg(ap
, int);
2425 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2429 case SD_BUS_TYPE_INT64
:
2430 case SD_BUS_TYPE_UINT64
: {
2433 x
= va_arg(ap
, uint64_t);
2434 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2438 case SD_BUS_TYPE_DOUBLE
: {
2441 x
= va_arg(ap
, double);
2442 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2446 case SD_BUS_TYPE_STRING
:
2447 case SD_BUS_TYPE_OBJECT_PATH
:
2448 case SD_BUS_TYPE_SIGNATURE
: {
2451 x
= va_arg(ap
, const char*);
2452 r
= sd_bus_message_append_basic(m
, *t
, x
);
2456 case SD_BUS_TYPE_ARRAY
: {
2459 r
= signature_element_length(t
+ 1, &k
);
2465 memcpy(s
, t
+ 1, k
);
2468 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2473 if (n_array
== (unsigned) -1) {
2478 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2484 n_array
= va_arg(ap
, unsigned);
2489 case SD_BUS_TYPE_VARIANT
: {
2492 s
= va_arg(ap
, const char*);
2496 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2500 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2505 n_struct
= strlen(s
);
2506 n_array
= (unsigned) -1;
2511 case SD_BUS_TYPE_STRUCT_BEGIN
:
2512 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2515 r
= signature_element_length(t
, &k
);
2522 memcpy(s
, t
+ 1, k
- 2);
2525 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2530 if (n_array
== (unsigned) -1) {
2535 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2541 n_array
= (unsigned) -1;
2557 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2561 assert_return(m
, -EINVAL
);
2562 assert_return(types
, -EINVAL
);
2563 assert_return(!m
->sealed
, -EPERM
);
2564 assert_return(!m
->poisoned
, -ESTALE
);
2566 va_start(ap
, types
);
2567 r
= bus_message_append_ap(m
, types
, ap
);
2573 _public_
int sd_bus_message_append_array_space(
2583 assert_return(m
, -EINVAL
);
2584 assert_return(!m
->sealed
, -EPERM
);
2585 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2586 assert_return(ptr
|| size
== 0, -EINVAL
);
2587 assert_return(!m
->poisoned
, -ESTALE
);
2589 /* alignment and size of the trivial types (except bool) is
2590 * identical for gvariant and dbus1 marshalling */
2591 align
= bus_type_get_alignment(type
);
2592 sz
= bus_type_get_size(type
);
2594 assert_se(align
> 0);
2600 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2604 a
= message_extend_body(m
, align
, size
, false, false);
2608 r
= sd_bus_message_close_container(m
);
2616 _public_
int sd_bus_message_append_array(
2624 assert_return(m
, -EINVAL
);
2625 assert_return(!m
->sealed
, -EPERM
);
2626 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2627 assert_return(ptr
|| size
== 0, -EINVAL
);
2628 assert_return(!m
->poisoned
, -ESTALE
);
2630 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2635 memcpy(p
, ptr
, size
);
2640 _public_
int sd_bus_message_append_array_iovec(
2643 const struct iovec
*iov
,
2651 assert_return(m
, -EINVAL
);
2652 assert_return(!m
->sealed
, -EPERM
);
2653 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2654 assert_return(iov
|| n
== 0, -EINVAL
);
2655 assert_return(!m
->poisoned
, -ESTALE
);
2657 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2659 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2663 for (i
= 0; i
< n
; i
++) {
2665 if (iov
[i
].iov_base
)
2666 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2668 memzero(p
, iov
[i
].iov_len
);
2670 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2676 _public_
int sd_bus_message_append_array_memfd(
2683 _cleanup_close_
int copy_fd
= -1;
2684 struct bus_body_part
*part
;
2690 assert_return(m
, -EINVAL
);
2691 assert_return(memfd
>= 0, -EBADF
);
2692 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2693 assert_return(size
> 0, -EINVAL
);
2694 assert_return(!m
->sealed
, -EPERM
);
2695 assert_return(!m
->poisoned
, -ESTALE
);
2697 r
= memfd_set_sealed(memfd
);
2701 copy_fd
= dup(memfd
);
2705 r
= memfd_get_size(memfd
, &real_size
);
2709 if (offset
== 0 && size
== (uint64_t) -1)
2711 else if (offset
+ size
> real_size
)
2714 align
= bus_type_get_alignment(type
);
2715 sz
= bus_type_get_size(type
);
2717 assert_se(align
> 0);
2720 if (offset
% align
!= 0)
2726 if (size
> (uint64_t) (uint32_t) -1)
2729 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2733 a
= message_extend_body(m
, align
, 0, false, false);
2737 part
= message_append_part(m
);
2741 part
->memfd
= copy_fd
;
2742 part
->memfd_offset
= offset
;
2743 part
->sealed
= true;
2747 m
->body_size
+= size
;
2748 message_extend_containers(m
, size
);
2750 return sd_bus_message_close_container(m
);
2753 _public_
int sd_bus_message_append_string_memfd(
2759 _cleanup_close_
int copy_fd
= -1;
2760 struct bus_body_part
*part
;
2761 struct bus_container
*c
;
2766 assert_return(m
, -EINVAL
);
2767 assert_return(memfd
>= 0, -EBADF
);
2768 assert_return(size
> 0, -EINVAL
);
2769 assert_return(!m
->sealed
, -EPERM
);
2770 assert_return(!m
->poisoned
, -ESTALE
);
2772 r
= memfd_set_sealed(memfd
);
2776 copy_fd
= dup(memfd
);
2780 r
= memfd_get_size(memfd
, &real_size
);
2784 if (offset
== 0 && size
== (uint64_t) -1)
2786 else if (offset
+ size
> real_size
)
2789 /* We require this to be NUL terminated */
2793 if (size
> (uint64_t) (uint32_t) -1)
2796 c
= message_get_container(m
);
2797 if (c
->signature
&& c
->signature
[c
->index
]) {
2798 /* Container signature is already set */
2800 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2805 /* Maybe we can append to the signature? But only if this is the top-level container */
2806 if (c
->enclosing
!= 0)
2809 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2816 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2817 a
= message_extend_body(m
, 4, 4, false, false);
2821 *(uint32_t*) a
= size
- 1;
2824 part
= message_append_part(m
);
2828 part
->memfd
= copy_fd
;
2829 part
->memfd_offset
= offset
;
2830 part
->sealed
= true;
2834 m
->body_size
+= size
;
2835 message_extend_containers(m
, size
);
2837 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2838 r
= message_add_offset(m
, m
->body_size
);
2845 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2851 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2855 assert_return(m
, -EINVAL
);
2856 assert_return(!m
->sealed
, -EPERM
);
2857 assert_return(!m
->poisoned
, -ESTALE
);
2859 r
= sd_bus_message_open_container(m
, 'a', "s");
2863 STRV_FOREACH(i
, l
) {
2864 r
= sd_bus_message_append_basic(m
, 's', *i
);
2869 return sd_bus_message_close_container(m
);
2872 static int bus_message_close_header(sd_bus_message
*m
) {
2876 /* The actual user data is finished now, we just complete the
2877 variant and struct now (at least on gvariant). Remember
2878 this position, so that during parsing we know where to to
2879 put the outer container end. */
2880 m
->user_body_size
= m
->body_size
;
2882 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2883 const char *signature
;
2887 /* Add offset table to end of fields array */
2888 if (m
->n_header_offsets
>= 1) {
2892 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2894 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2895 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2899 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2900 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2903 /* Add gvariant NUL byte plus signature to the end of
2904 * the body, followed by the final offset pointing to
2905 * the end of the fields array */
2907 signature
= strempty(m
->root_container
.signature
);
2908 l
= strlen(signature
);
2910 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2911 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2916 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2917 memcpy((uint8_t*) d
+ 2, signature
, l
);
2918 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2920 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2923 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2925 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2926 m
->header
->dbus1
.body_size
= m
->body_size
;
2932 int bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, usec_t timeout
) {
2933 struct bus_body_part
*part
;
2943 if (m
->n_containers
> 0)
2949 if (cookie
> 0xffffffffULL
&&
2950 !BUS_MESSAGE_IS_GVARIANT(m
))
2953 /* In vtables the return signature of method calls is listed,
2954 * let's check if they match if this is a response */
2955 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2956 m
->enforced_reply_signature
&&
2957 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2960 /* If gvariant marshalling is used we need to close the body structure */
2961 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2965 /* If there's a non-trivial signature set, then add it in
2966 * here, but only on dbus1 */
2967 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2968 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2974 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2979 r
= bus_message_close_header(m
);
2983 if (BUS_MESSAGE_IS_GVARIANT(m
))
2984 m
->header
->dbus2
.cookie
= cookie
;
2986 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2988 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout
;
2990 /* Add padding at the end of the fields part, since we know
2991 * the body needs to start at an 8 byte alignment. We made
2992 * sure we allocated enough space for this, so all we need to
2993 * do here is to zero it out. */
2994 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2996 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2998 /* If this is something we can send as memfd, then let's seal
2999 the memfd now. Note that we can send memfds as payload only
3000 for directed messages, and not for broadcasts. */
3001 if (m
->destination
&& m
->bus
->use_memfd
) {
3002 MESSAGE_FOREACH_PART(part
, i
, m
)
3003 if (part
->memfd
>= 0 &&
3005 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
3006 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
3009 /* Try to seal it if that makes
3010 * sense. First, unmap our own map to
3011 * make sure we don't keep it busy. */
3012 bus_body_part_unmap(part
);
3014 /* Then, sync up real memfd size */
3016 r
= memfd_set_size(part
->memfd
, sz
);
3020 /* Finally, try to seal */
3021 if (memfd_set_sealed(part
->memfd
) >= 0)
3022 part
->sealed
= true;
3026 m
->root_container
.end
= m
->user_body_size
;
3027 m
->root_container
.index
= 0;
3028 m
->root_container
.offset_index
= 0;
3029 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
3036 int bus_body_part_map(struct bus_body_part
*part
) {
3045 if (part
->size
<= 0)
3048 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3049 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
3050 static const uint8_t zeroes
[7] = { };
3051 part
->data
= (void*) zeroes
;
3055 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
3056 psz
= PAGE_ALIGN(part
->size
+ shift
);
3058 if (part
->memfd
>= 0)
3059 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
3060 else if (part
->is_zero
)
3061 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
3065 if (p
== MAP_FAILED
)
3069 part
->mmap_begin
= p
;
3070 part
->data
= (uint8_t*) p
+ shift
;
3071 part
->munmap_this
= true;
3076 void bus_body_part_unmap(struct bus_body_part
*part
) {
3080 if (part
->memfd
< 0)
3083 if (!part
->mmap_begin
)
3086 if (!part
->munmap_this
)
3089 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
3091 part
->mmap_begin
= NULL
;
3094 part
->munmap_this
= false;
3099 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3100 size_t k
, start
, end
;
3105 start
= ALIGN_TO((size_t) *rindex
, align
);
3106 end
= start
+ nbytes
;
3111 /* Verify that padding is 0 */
3112 for (k
= *rindex
; k
< start
; k
++)
3113 if (((const uint8_t*) p
)[k
] != 0)
3117 *r
= (uint8_t*) p
+ start
;
3124 static bool message_end_of_signature(sd_bus_message
*m
) {
3125 struct bus_container
*c
;
3129 c
= message_get_container(m
);
3130 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3133 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3134 struct bus_container
*c
;
3138 c
= message_get_container(m
);
3139 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3142 if (BUS_MESSAGE_IS_GVARIANT(m
))
3143 return index
>= c
->end
;
3145 assert(c
->array_size
);
3146 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3150 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3151 assert_return(m
, -EINVAL
);
3152 assert_return(m
->sealed
, -EPERM
);
3154 if (complete
&& m
->n_containers
> 0)
3157 if (message_end_of_signature(m
))
3160 if (message_end_of_array(m
, m
->rindex
))
3166 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3167 struct bus_body_part
*part
;
3173 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3174 part
= m
->cached_rindex_part
;
3175 begin
= m
->cached_rindex_part_begin
;
3185 if (index
+ sz
<= begin
+ part
->size
) {
3187 r
= bus_body_part_map(part
);
3192 *p
= (uint8_t*) part
->data
+ index
- begin
;
3194 m
->cached_rindex_part
= part
;
3195 m
->cached_rindex_part_begin
= begin
;
3200 begin
+= part
->size
;
3207 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3214 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3217 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3220 sz
= bus_gvariant_get_size(c
->signature
);
3224 if (c
->offset_index
+1 >= c
->n_offsets
)
3227 /* Variable-size array */
3229 alignment
= bus_gvariant_get_alignment(c
->signature
);
3230 assert(alignment
> 0);
3232 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3233 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3236 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3239 /* Fixed-size array */
3240 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3246 } else if (c
->enclosing
== 0 ||
3247 c
->enclosing
== SD_BUS_TYPE_STRUCT
||
3248 c
->enclosing
== SD_BUS_TYPE_DICT_ENTRY
) {
3253 if (c
->offset_index
+1 >= c
->n_offsets
)
3256 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3260 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3265 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3268 alignment
= bus_gvariant_get_alignment(t
);
3271 assert(alignment
> 0);
3273 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3274 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3278 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3281 assert_not_reached("Unknown container type");
3286 /* Reached the end */
3293 static int message_peek_body(
3300 size_t k
, start
, end
, padding
;
3301 struct bus_body_part
*part
;
3308 start
= ALIGN_TO((size_t) *rindex
, align
);
3309 padding
= start
- *rindex
;
3310 end
= start
+ nbytes
;
3312 if (end
> m
->user_body_size
)
3315 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3320 /* Verify padding */
3321 for (k
= 0; k
< padding
; k
++)
3326 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3327 if (!part
|| (nbytes
> 0 && !q
))
3338 static bool validate_nul(const char *s
, size_t l
) {
3340 /* Check for NUL chars in the string */
3341 if (memchr(s
, 0, l
))
3344 /* Check for NUL termination */
3351 static bool validate_string(const char *s
, size_t l
) {
3353 if (!validate_nul(s
, l
))
3356 /* Check if valid UTF8 */
3357 if (!utf8_is_valid(s
))
3363 static bool validate_signature(const char *s
, size_t l
) {
3365 if (!validate_nul(s
, l
))
3368 /* Check if valid signature */
3369 if (!signature_is_valid(s
, true))
3375 static bool validate_object_path(const char *s
, size_t l
) {
3377 if (!validate_nul(s
, l
))
3380 if (!object_path_is_valid(s
))
3386 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3387 struct bus_container
*c
;
3392 assert_return(m
, -EINVAL
);
3393 assert_return(m
->sealed
, -EPERM
);
3394 assert_return(bus_type_is_basic(type
), -EINVAL
);
3396 if (message_end_of_signature(m
))
3399 if (message_end_of_array(m
, m
->rindex
))
3402 c
= message_get_container(m
);
3403 if (c
->signature
[c
->index
] != type
)
3408 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3410 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3413 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3417 if (type
== SD_BUS_TYPE_STRING
)
3418 ok
= validate_string(q
, c
->item_size
-1);
3419 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3420 ok
= validate_object_path(q
, c
->item_size
-1);
3422 ok
= validate_signature(q
, c
->item_size
-1);
3428 *(const char**) p
= q
;
3432 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3434 if ((size_t) sz
!= c
->item_size
)
3437 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3440 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3446 case SD_BUS_TYPE_BYTE
:
3448 *(uint8_t*) p
= *(uint8_t*) q
;
3451 case SD_BUS_TYPE_BOOLEAN
:
3453 *(int*) p
= !!*(uint8_t*) q
;
3456 case SD_BUS_TYPE_INT16
:
3457 case SD_BUS_TYPE_UINT16
:
3459 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3462 case SD_BUS_TYPE_INT32
:
3463 case SD_BUS_TYPE_UINT32
:
3465 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3468 case SD_BUS_TYPE_INT64
:
3469 case SD_BUS_TYPE_UINT64
:
3470 case SD_BUS_TYPE_DOUBLE
:
3472 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3475 case SD_BUS_TYPE_UNIX_FD
: {
3478 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3483 *(int*) p
= m
->fds
[j
];
3489 assert_not_reached("unexpected type");
3493 r
= container_next_item(m
, c
, &rindex
);
3498 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3502 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3506 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3507 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3511 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3512 ok
= validate_object_path(q
, l
);
3514 ok
= validate_string(q
, l
);
3519 *(const char**) p
= q
;
3521 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3524 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3529 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3533 if (!validate_signature(q
, l
))
3537 *(const char**) p
= q
;
3542 align
= bus_type_get_alignment(type
);
3545 sz
= bus_type_get_size(type
);
3548 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3554 case SD_BUS_TYPE_BYTE
:
3556 *(uint8_t*) p
= *(uint8_t*) q
;
3559 case SD_BUS_TYPE_BOOLEAN
:
3561 *(int*) p
= !!*(uint32_t*) q
;
3564 case SD_BUS_TYPE_INT16
:
3565 case SD_BUS_TYPE_UINT16
:
3567 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3570 case SD_BUS_TYPE_INT32
:
3571 case SD_BUS_TYPE_UINT32
:
3573 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3576 case SD_BUS_TYPE_INT64
:
3577 case SD_BUS_TYPE_UINT64
:
3578 case SD_BUS_TYPE_DOUBLE
:
3580 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3583 case SD_BUS_TYPE_UNIX_FD
: {
3586 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3591 *(int*) p
= m
->fds
[j
];
3596 assert_not_reached("Unknown basic type...");
3603 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3609 static int bus_message_enter_array(
3611 struct bus_container
*c
,
3612 const char *contents
,
3613 uint32_t **array_size
,
3616 size_t *n_offsets
) {
3630 if (!signature_is_single(contents
, true))
3633 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3636 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3639 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3644 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3647 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3651 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3654 alignment
= bus_type_get_alignment(contents
[0]);
3658 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3662 *array_size
= (uint32_t*) q
;
3664 } else if (c
->item_size
<= 0) {
3666 /* gvariant: empty array */
3671 } else if (bus_gvariant_is_fixed_size(contents
)) {
3673 /* gvariant: fixed length array */
3674 *item_size
= bus_gvariant_get_size(contents
);
3679 size_t where
, p
= 0, framing
, sz
;
3682 /* gvariant: variable length array */
3683 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3685 where
= rindex
+ c
->item_size
- sz
;
3686 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3690 framing
= bus_gvariant_read_word_le(q
, sz
);
3691 if (framing
> c
->item_size
- sz
)
3693 if ((c
->item_size
- framing
) % sz
!= 0)
3696 *n_offsets
= (c
->item_size
- framing
) / sz
;
3698 where
= rindex
+ framing
;
3699 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3703 *offsets
= new(size_t, *n_offsets
);
3707 for (i
= 0; i
< *n_offsets
; i
++) {
3710 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3711 if (x
> c
->item_size
- sz
)
3716 (*offsets
)[i
] = rindex
+ x
;
3720 *item_size
= (*offsets
)[0] - rindex
;
3725 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3726 c
->index
+= 1 + strlen(contents
);
3731 static int bus_message_enter_variant(
3733 struct bus_container
*c
,
3734 const char *contents
,
3735 size_t *item_size
) {
3747 if (!signature_is_single(contents
, false))
3750 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3753 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3756 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3761 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3764 k
= strlen(contents
);
3765 if (1+k
> c
->item_size
)
3768 where
= rindex
+ c
->item_size
- (1+k
);
3769 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3773 if (*(char*) q
!= 0)
3776 if (memcmp((uint8_t*) q
+1, contents
, k
))
3779 *item_size
= c
->item_size
- (1+k
);
3782 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3787 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3791 if (!validate_signature(q
, l
))
3794 if (!streq(q
, contents
))
3800 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3806 static int build_struct_offsets(
3808 const char *signature
,
3812 size_t *n_offsets
) {
3814 unsigned n_variable
= 0, n_total
= 0, v
;
3815 size_t previous
= 0, where
;
3826 if (isempty(signature
)) {
3827 /* Unary type is encoded as *fixed* 1 byte padding */
3828 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3832 if (*(uint8_t *) q
!= 0)
3841 sz
= bus_gvariant_determine_word_size(size
, 0);
3845 /* First, loop over signature and count variable elements and
3846 * elements in general. We use this to know how large the
3847 * offset array is at the end of the structure. Note that
3848 * GVariant only stores offsets for all variable size elements
3849 * that are not the last item. */
3855 r
= signature_element_length(p
, &n
);
3864 r
= bus_gvariant_is_fixed_size(t
);
3869 if (r
== 0 && p
[n
] != 0) /* except the last item */
3876 if (size
< n_variable
* sz
)
3879 where
= m
->rindex
+ size
- (n_variable
* sz
);
3880 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3886 *offsets
= new(size_t, n_total
);
3892 /* Second, loop again and build an offset table */
3898 r
= signature_element_length(p
, &n
);
3907 k
= bus_gvariant_get_size(t
);
3915 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3918 if (m
->rindex
+ x
< previous
)
3921 /* The last item's end
3922 * is determined from
3925 x
= size
- (n_variable
* sz
);
3927 offset
= m
->rindex
+ x
;
3933 align
= bus_gvariant_get_alignment(t
);
3936 offset
= (*n_offsets
== 0 ? m
->rindex
: ALIGN_TO((*offsets
)[*n_offsets
-1], align
)) + k
;
3940 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3945 assert(*n_offsets
== n_total
);
3947 *item_size
= (*offsets
)[0] - m
->rindex
;
3951 static int enter_struct_or_dict_entry(
3953 struct bus_container
*c
,
3954 const char *contents
,
3957 size_t *n_offsets
) {
3968 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3971 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3976 /* gvariant with contents */
3977 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3982 static int bus_message_enter_struct(
3984 struct bus_container
*c
,
3985 const char *contents
,
3988 size_t *n_offsets
) {
4000 if (!signature_is_valid(contents
, false))
4003 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4006 l
= strlen(contents
);
4008 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
4009 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4010 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
4013 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4017 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4018 c
->index
+= 1 + l
+ 1;
4023 static int bus_message_enter_dict_entry(
4025 struct bus_container
*c
,
4026 const char *contents
,
4029 size_t *n_offsets
) {
4038 if (!signature_is_pair(contents
))
4041 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4044 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4047 l
= strlen(contents
);
4049 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
4050 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4051 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
4054 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4058 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4059 c
->index
+= 1 + l
+ 1;
4064 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
4066 const char *contents
) {
4067 struct bus_container
*c
, *w
;
4068 uint32_t *array_size
= NULL
;
4071 size_t *offsets
= NULL
;
4072 size_t n_offsets
= 0, item_size
= 0;
4075 assert_return(m
, -EINVAL
);
4076 assert_return(m
->sealed
, -EPERM
);
4077 assert_return(type
!= 0 || !contents
, -EINVAL
);
4079 if (type
== 0 || !contents
) {
4083 /* Allow entering into anonymous containers */
4084 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
4088 if (type
!= 0 && type
!= tt
)
4091 if (contents
&& !streq(contents
, cc
))
4099 * We enforce a global limit on container depth, that is much
4100 * higher than the 32 structs and 32 arrays the specification
4101 * mandates. This is simpler to implement for us, and we need
4102 * this only to ensure our container array doesn't grow
4103 * without bounds. We are happy to return any data from a
4104 * message as long as the data itself is valid, even if the
4105 * overall message might be not.
4107 * Note that the message signature is validated when
4108 * parsing the headers, and that validation does check the
4111 * Note that the specification defines no limits on the depth
4112 * of stacked variants, but we do.
4114 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4117 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4120 if (message_end_of_signature(m
))
4123 if (message_end_of_array(m
, m
->rindex
))
4126 c
= message_get_container(m
);
4128 signature
= strdup(contents
);
4132 c
->saved_index
= c
->index
;
4135 if (type
== SD_BUS_TYPE_ARRAY
)
4136 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4137 else if (type
== SD_BUS_TYPE_VARIANT
)
4138 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4139 else if (type
== SD_BUS_TYPE_STRUCT
)
4140 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4141 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4142 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4152 /* OK, let's fill it in */
4153 w
= m
->containers
+ m
->n_containers
++;
4154 w
->enclosing
= type
;
4155 w
->signature
= signature
;
4156 w
->peeked_signature
= NULL
;
4160 w
->begin
= m
->rindex
;
4162 /* Unary type has fixed size of 1, but virtual size of 0 */
4163 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4164 type
== SD_BUS_TYPE_STRUCT
&&
4166 w
->end
= m
->rindex
+ 0;
4168 w
->end
= m
->rindex
+ c
->item_size
;
4170 w
->array_size
= array_size
;
4171 w
->item_size
= item_size
;
4172 w
->offsets
= offsets
;
4173 w
->n_offsets
= n_offsets
;
4174 w
->offset_index
= 0;
4179 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4180 struct bus_container
*c
;
4184 assert_return(m
, -EINVAL
);
4185 assert_return(m
->sealed
, -EPERM
);
4186 assert_return(m
->n_containers
> 0, -ENXIO
);
4188 c
= message_get_container(m
);
4190 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4191 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4195 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4196 if (m
->rindex
< c
->end
)
4199 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4202 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4203 if (c
->begin
+ l
!= m
->rindex
)
4208 free(c
->peeked_signature
);
4212 c
= message_get_container(m
);
4215 c
->index
= c
->saved_index
;
4216 r
= container_next_item(m
, c
, &m
->rindex
);
4224 static void message_quit_container(sd_bus_message
*m
) {
4225 struct bus_container
*c
;
4229 assert(m
->n_containers
> 0);
4231 c
= message_get_container(m
);
4234 assert(m
->rindex
>= c
->before
);
4235 m
->rindex
= c
->before
;
4237 /* Free container */
4242 /* Correct index of new top-level container */
4243 c
= message_get_container(m
);
4244 c
->index
= c
->saved_index
;
4247 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4248 struct bus_container
*c
;
4251 assert_return(m
, -EINVAL
);
4252 assert_return(m
->sealed
, -EPERM
);
4254 if (message_end_of_signature(m
))
4257 if (message_end_of_array(m
, m
->rindex
))
4260 c
= message_get_container(m
);
4262 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4266 *type
= c
->signature
[c
->index
];
4270 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4276 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4282 sig
= strndup(c
->signature
+ c
->index
+ 1, l
);
4286 free(c
->peeked_signature
);
4287 *contents
= c
->peeked_signature
= sig
;
4291 *type
= SD_BUS_TYPE_ARRAY
;
4296 if (c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
||
4297 c
->signature
[c
->index
] == SD_BUS_TYPE_DICT_ENTRY_BEGIN
) {
4303 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4308 sig
= strndup(c
->signature
+ c
->index
+ 1, l
- 2);
4312 free(c
->peeked_signature
);
4313 *contents
= c
->peeked_signature
= sig
;
4317 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4322 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4326 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4329 if (c
->item_size
< 2)
4332 /* Look for the NUL delimiter that
4333 separates the payload from the
4334 signature. Since the body might be
4335 in a different part that then the
4336 signature we map byte by byte. */
4338 for (k
= 2; k
<= c
->item_size
; k
++) {
4341 where
= m
->rindex
+ c
->item_size
- k
;
4342 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4346 if (*(char*) q
== 0)
4350 if (k
> c
->item_size
)
4353 free(c
->peeked_signature
);
4354 c
->peeked_signature
= strndup((char*) q
+ 1, k
- 1);
4355 if (!c
->peeked_signature
)
4358 if (!signature_is_valid(c
->peeked_signature
, true))
4361 *contents
= c
->peeked_signature
;
4366 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4371 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4375 if (!validate_signature(q
, l
))
4383 *type
= SD_BUS_TYPE_VARIANT
;
4398 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4399 struct bus_container
*c
;
4401 assert_return(m
, -EINVAL
);
4402 assert_return(m
->sealed
, -EPERM
);
4405 message_reset_containers(m
);
4408 c
= message_get_container(m
);
4410 c
= message_get_container(m
);
4412 c
->offset_index
= 0;
4414 m
->rindex
= c
->begin
;
4417 c
->offset_index
= 0;
4418 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4420 return !isempty(c
->signature
);
4423 static int message_read_ap(
4428 unsigned n_array
, n_struct
;
4429 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4430 unsigned stack_ptr
= 0;
4431 unsigned n_loop
= 0;
4439 /* Ideally, we'd just call ourselves recursively on every
4440 * complex type. However, the state of a va_list that is
4441 * passed to a function is undefined after that function
4442 * returns. This means we need to docode the va_list linearly
4443 * in a single stackframe. We hence implement our own
4444 * home-grown stack in an array. */
4446 n_array
= (unsigned) -1; /* length of current array entries */
4447 n_struct
= strlen(types
); /* length of current struct contents signature */
4454 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4455 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4461 r
= sd_bus_message_exit_container(m
);
4469 if (n_array
!= (unsigned) -1)
4478 case SD_BUS_TYPE_BYTE
:
4479 case SD_BUS_TYPE_BOOLEAN
:
4480 case SD_BUS_TYPE_INT16
:
4481 case SD_BUS_TYPE_UINT16
:
4482 case SD_BUS_TYPE_INT32
:
4483 case SD_BUS_TYPE_UINT32
:
4484 case SD_BUS_TYPE_INT64
:
4485 case SD_BUS_TYPE_UINT64
:
4486 case SD_BUS_TYPE_DOUBLE
:
4487 case SD_BUS_TYPE_STRING
:
4488 case SD_BUS_TYPE_OBJECT_PATH
:
4489 case SD_BUS_TYPE_SIGNATURE
:
4490 case SD_BUS_TYPE_UNIX_FD
: {
4493 p
= va_arg(ap
, void*);
4494 r
= sd_bus_message_read_basic(m
, *t
, p
);
4507 case SD_BUS_TYPE_ARRAY
: {
4510 r
= signature_element_length(t
+ 1, &k
);
4516 memcpy(s
, t
+ 1, k
);
4519 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4530 if (n_array
== (unsigned) -1) {
4535 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4541 n_array
= va_arg(ap
, unsigned);
4546 case SD_BUS_TYPE_VARIANT
: {
4549 s
= va_arg(ap
, const char *);
4553 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4563 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4568 n_struct
= strlen(s
);
4569 n_array
= (unsigned) -1;
4574 case SD_BUS_TYPE_STRUCT_BEGIN
:
4575 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4578 r
= signature_element_length(t
, &k
);
4584 memcpy(s
, t
+ 1, k
- 2);
4587 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4597 if (n_array
== (unsigned) -1) {
4602 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4608 n_array
= (unsigned) -1;
4621 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4625 assert_return(m
, -EINVAL
);
4626 assert_return(m
->sealed
, -EPERM
);
4627 assert_return(types
, -EINVAL
);
4629 va_start(ap
, types
);
4630 r
= message_read_ap(m
, types
, ap
);
4636 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4639 assert_return(m
, -EINVAL
);
4640 assert_return(m
->sealed
, -EPERM
);
4642 /* If types is NULL, read exactly one element */
4644 struct bus_container
*c
;
4647 if (message_end_of_signature(m
))
4650 if (message_end_of_array(m
, m
->rindex
))
4653 c
= message_get_container(m
);
4655 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4659 types
= strndupa(c
->signature
+ c
->index
, l
);
4664 case 0: /* Nothing to drop */
4667 case SD_BUS_TYPE_BYTE
:
4668 case SD_BUS_TYPE_BOOLEAN
:
4669 case SD_BUS_TYPE_INT16
:
4670 case SD_BUS_TYPE_UINT16
:
4671 case SD_BUS_TYPE_INT32
:
4672 case SD_BUS_TYPE_UINT32
:
4673 case SD_BUS_TYPE_INT64
:
4674 case SD_BUS_TYPE_UINT64
:
4675 case SD_BUS_TYPE_DOUBLE
:
4676 case SD_BUS_TYPE_STRING
:
4677 case SD_BUS_TYPE_OBJECT_PATH
:
4678 case SD_BUS_TYPE_SIGNATURE
:
4679 case SD_BUS_TYPE_UNIX_FD
:
4681 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4685 r
= sd_bus_message_skip(m
, types
+ 1);
4691 case SD_BUS_TYPE_ARRAY
: {
4694 r
= signature_element_length(types
+ 1, &k
);
4700 memcpy(s
, types
+1, k
);
4703 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4708 r
= sd_bus_message_skip(m
, s
);
4715 r
= sd_bus_message_exit_container(m
);
4720 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4727 case SD_BUS_TYPE_VARIANT
: {
4728 const char *contents
;
4731 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4735 if (x
!= SD_BUS_TYPE_VARIANT
)
4738 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4742 r
= sd_bus_message_skip(m
, contents
);
4747 r
= sd_bus_message_exit_container(m
);
4751 r
= sd_bus_message_skip(m
, types
+ 1);
4758 case SD_BUS_TYPE_STRUCT_BEGIN
:
4759 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4762 r
= signature_element_length(types
, &k
);
4768 memcpy(s
, types
+1, k
-2);
4771 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4775 r
= sd_bus_message_skip(m
, s
);
4779 r
= sd_bus_message_exit_container(m
);
4784 r
= sd_bus_message_skip(m
, types
+ k
);
4796 _public_
int sd_bus_message_read_array(
4802 struct bus_container
*c
;
4808 assert_return(m
, -EINVAL
);
4809 assert_return(m
->sealed
, -EPERM
);
4810 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4811 assert_return(ptr
, -EINVAL
);
4812 assert_return(size
, -EINVAL
);
4813 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4815 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4819 c
= message_get_container(m
);
4821 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4822 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4826 sz
= c
->end
- c
->begin
;
4828 align
= bus_type_get_alignment(type
);
4832 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4836 /* Zero length array, let's return some aligned
4837 * pointer that is not NULL */
4838 p
= (uint8_t*) NULL
+ align
;
4840 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4845 r
= sd_bus_message_exit_container(m
);
4849 *ptr
= (const void*) p
;
4855 message_quit_container(m
);
4859 static int message_peek_fields(
4870 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4873 static int message_peek_field_uint32(
4885 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4888 /* identical for gvariant and dbus1 */
4890 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4895 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4900 static int message_peek_field_uint64(
4912 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4915 /* identical for gvariant and dbus1 */
4917 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4922 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4927 static int message_peek_field_string(
4929 bool (*validate
)(const char *p
),
4941 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4946 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4952 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4956 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4962 if (!validate_nul(q
, l
))
4968 if (!validate_string(q
, l
))
4978 static int message_peek_field_signature(
4991 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4996 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
5002 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
5007 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
5012 if (!validate_signature(q
, l
))
5021 static int message_skip_fields(
5024 uint32_t array_size
,
5025 const char **signature
) {
5027 size_t original_index
;
5033 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
5035 original_index
= *ri
;
5041 if (array_size
!= (uint32_t) -1 &&
5042 array_size
<= *ri
- original_index
)
5049 if (t
== SD_BUS_TYPE_STRING
) {
5051 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
5057 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
5059 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
5065 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
5067 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
5073 } else if (bus_type_is_basic(t
)) {
5076 align
= bus_type_get_alignment(t
);
5077 k
= bus_type_get_size(t
);
5078 assert(align
> 0 && k
> 0);
5080 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
5086 } else if (t
== SD_BUS_TYPE_ARRAY
) {
5088 r
= signature_element_length(*signature
+1, &l
);
5098 strncpy(sig
, *signature
+ 1, l
-1);
5101 alignment
= bus_type_get_alignment(sig
[0]);
5105 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5108 if (nas
> BUS_ARRAY_MAX_SIZE
)
5111 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5115 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5120 (*signature
) += 1 + l
;
5122 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5125 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5129 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5135 } else if (t
== SD_BUS_TYPE_STRUCT
||
5136 t
== SD_BUS_TYPE_DICT_ENTRY
) {
5138 r
= signature_element_length(*signature
, &l
);
5145 strncpy(sig
, *signature
+ 1, l
-1);
5148 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5159 int bus_message_parse_fields(sd_bus_message
*m
) {
5162 uint32_t unix_fds
= 0;
5163 bool unix_fds_set
= false;
5164 void *offsets
= NULL
;
5165 unsigned n_offsets
= 0;
5171 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5174 /* Read the signature from the end of the body variant first */
5175 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5176 if (m
->footer_accessible
< 1 + sz
)
5179 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5181 if (p
< (char*) m
->footer
)
5188 /* We found the beginning of the signature
5189 * string, yay! We require the body to be a
5190 * structure, so verify it and then strip the
5191 * opening/closing brackets. */
5193 l
= ((char*) m
->footer
+ m
->footer_accessible
) - p
- (1 + sz
);
5195 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5196 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5199 c
= strndup(p
+ 1 + 1, l
- 2);
5203 free(m
->root_container
.signature
);
5204 m
->root_container
.signature
= c
;
5211 /* Calculate the actual user body size, by removing
5212 * the trailing variant signature and struct offset
5214 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5216 /* Pull out the offset table for the fields array */
5217 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5222 ri
= m
->fields_size
- sz
;
5223 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5227 framing
= bus_gvariant_read_word_le(q
, sz
);
5228 if (framing
>= m
->fields_size
- sz
)
5230 if ((m
->fields_size
- framing
) % sz
!= 0)
5234 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5238 n_offsets
= (m
->fields_size
- framing
) / sz
;
5241 m
->user_body_size
= m
->body_size
;
5244 while (ri
< m
->fields_size
) {
5245 _cleanup_free_
char *sig
= NULL
;
5246 const char *signature
;
5247 uint64_t field_type
;
5248 size_t item_size
= (size_t) -1;
5250 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5259 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5261 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5265 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5269 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5276 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5281 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5286 where
= ri
= ALIGN_TO(ri
, 8);
5287 item_size
= end
- ri
;
5288 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5292 b
= memrchr(q
, 0, item_size
);
5296 sig
= strndup(b
+1, item_size
- (b
+1-(char*) q
));
5301 item_size
= b
- (char*) q
;
5303 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5308 switch (field_type
) {
5310 case _BUS_MESSAGE_HEADER_INVALID
:
5313 case BUS_MESSAGE_HEADER_PATH
:
5318 if (!streq(signature
, "o"))
5321 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5324 case BUS_MESSAGE_HEADER_INTERFACE
:
5329 if (!streq(signature
, "s"))
5332 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5335 case BUS_MESSAGE_HEADER_MEMBER
:
5340 if (!streq(signature
, "s"))
5343 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5346 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5351 if (!streq(signature
, "s"))
5354 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5356 m
->error
._need_free
= -1;
5360 case BUS_MESSAGE_HEADER_DESTINATION
:
5365 if (!streq(signature
, "s"))
5368 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5371 case BUS_MESSAGE_HEADER_SENDER
:
5376 if (!streq(signature
, "s"))
5379 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5381 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
&& !m
->bus
->is_kernel
) {
5382 m
->creds
.unique_name
= (char*) m
->sender
;
5383 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5389 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5393 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5396 if (m
->root_container
.signature
)
5399 if (!streq(signature
, "g"))
5402 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5410 free(m
->root_container
.signature
);
5411 m
->root_container
.signature
= c
;
5415 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5417 if (m
->reply_cookie
!= 0)
5420 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5421 /* 64bit on dbus2 */
5423 if (!streq(signature
, "t"))
5426 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5430 /* 32bit on dbus1 */
5433 if (!streq(signature
, "u"))
5436 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5440 m
->reply_cookie
= serial
;
5443 if (m
->reply_cookie
== 0)
5448 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5452 if (!streq(signature
, "u"))
5455 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5459 unix_fds_set
= true;
5463 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5464 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5473 if (m
->n_fds
!= unix_fds
)
5476 switch (m
->header
->type
) {
5478 case SD_BUS_MESSAGE_SIGNAL
:
5479 if (!m
->path
|| !m
->interface
|| !m
->member
)
5482 if (m
->reply_cookie
!= 0)
5487 case SD_BUS_MESSAGE_METHOD_CALL
:
5489 if (!m
->path
|| !m
->member
)
5492 if (m
->reply_cookie
!= 0)
5497 case SD_BUS_MESSAGE_METHOD_RETURN
:
5499 if (m
->reply_cookie
== 0)
5503 case SD_BUS_MESSAGE_METHOD_ERROR
:
5505 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5510 /* Refuse non-local messages that claim they are local */
5511 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5513 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5515 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5518 m
->root_container
.end
= m
->user_body_size
;
5520 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5521 r
= build_struct_offsets(
5523 m
->root_container
.signature
,
5525 &m
->root_container
.item_size
,
5526 &m
->root_container
.offsets
,
5527 &m
->root_container
.n_offsets
);
5532 /* Try to read the error message, but if we can't it's a non-issue */
5533 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5534 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5539 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5540 assert_return(m
, -EINVAL
);
5541 assert_return(destination
, -EINVAL
);
5542 assert_return(!m
->sealed
, -EPERM
);
5543 assert_return(!m
->destination
, -EEXIST
);
5545 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5548 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5552 struct bus_body_part
*part
;
5558 total
= BUS_MESSAGE_SIZE(m
);
5564 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5565 MESSAGE_FOREACH_PART(part
, i
, m
)
5566 e
= mempcpy(e
, part
->data
, part
->size
);
5568 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5576 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5583 r
= sd_bus_message_enter_container(m
, 'a', "s");
5587 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5588 r
= strv_extend(l
, s
);
5595 r
= sd_bus_message_exit_container(m
);
5602 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5606 assert_return(m
, -EINVAL
);
5607 assert_return(m
->sealed
, -EPERM
);
5608 assert_return(l
, -EINVAL
);
5610 r
= bus_message_read_strv_extend(m
, &strv
);
5620 static int bus_message_get_arg_skip(
5624 const char **_contents
) {
5629 r
= sd_bus_message_rewind(m
, true);
5634 const char *contents
;
5637 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5643 /* Don't match against arguments after the first one we don't understand */
5644 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5645 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5650 *_contents
= contents
;
5656 r
= sd_bus_message_skip(m
, NULL
);
5663 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5670 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5674 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5677 return sd_bus_message_read_basic(m
, type
, str
);
5680 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5681 const char *contents
;
5688 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5692 if (type
!= SD_BUS_TYPE_ARRAY
)
5694 if (!STR_IN_SET(contents
, "s", "o", "g"))
5697 return sd_bus_message_read_strv(m
, strv
);
5700 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5701 assert_return(m
, EINVAL
);
5703 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5706 return sd_bus_error_get_errno(&m
->error
);
5709 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5710 struct bus_container
*c
;
5712 assert_return(m
, NULL
);
5714 c
= complete
? &m
->root_container
: message_get_container(m
);
5715 return strempty(c
->signature
);
5718 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5719 assert_return(m
, -EINVAL
);
5721 return isempty(m
->root_container
.signature
);
5724 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5725 assert_return(m
, -EINVAL
);
5727 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5730 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5731 bool done_something
= false;
5734 assert_return(m
, -EINVAL
);
5735 assert_return(source
, -EINVAL
);
5736 assert_return(!m
->sealed
, -EPERM
);
5737 assert_return(source
->sealed
, -EPERM
);
5740 const char *contents
;
5755 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5761 done_something
= true;
5763 if (bus_type_is_container(type
) > 0) {
5765 r
= sd_bus_message_enter_container(source
, type
, contents
);
5769 r
= sd_bus_message_open_container(m
, type
, contents
);
5773 r
= sd_bus_message_copy(m
, source
, true);
5777 r
= sd_bus_message_close_container(m
);
5781 r
= sd_bus_message_exit_container(source
);
5788 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5794 if (type
== SD_BUS_TYPE_OBJECT_PATH
||
5795 type
== SD_BUS_TYPE_SIGNATURE
||
5796 type
== SD_BUS_TYPE_STRING
)
5797 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5799 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5806 return done_something
;
5809 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5814 assert_return(m
, -EINVAL
);
5815 assert_return(m
->sealed
, -EPERM
);
5816 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5817 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5818 assert_return(type
|| contents
, -EINVAL
);
5819 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5821 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5825 if (type
!= 0 && type
!= t
)
5828 if (contents
&& !streq_ptr(contents
, c
))
5834 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5835 assert_return(m
, NULL
);
5840 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5841 _cleanup_bus_message_unref_ sd_bus_message
*n
= NULL
;
5849 switch ((*m
)->header
->type
) {
5851 case SD_BUS_MESSAGE_SIGNAL
:
5852 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5858 case SD_BUS_MESSAGE_METHOD_CALL
:
5859 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5865 case SD_BUS_MESSAGE_METHOD_RETURN
:
5866 case SD_BUS_MESSAGE_METHOD_ERROR
:
5868 n
= message_new(bus
, (*m
)->header
->type
);
5872 n
->reply_cookie
= (*m
)->reply_cookie
;
5874 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5878 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5879 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5883 n
->error
._need_free
= -1;
5892 if ((*m
)->destination
&& !n
->destination
) {
5893 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5898 if ((*m
)->sender
&& !n
->sender
) {
5899 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5904 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5906 r
= sd_bus_message_copy(n
, *m
, true);
5910 timeout
= (*m
)->timeout
;
5911 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
))
5912 timeout
= BUS_DEFAULT_TIMEOUT
;
5914 r
= bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5918 sd_bus_message_unref(*m
);
5925 int bus_message_append_sender(sd_bus_message
*m
, const char *sender
) {
5929 assert_return(!m
->sealed
, -EPERM
);
5930 assert_return(!m
->sender
, -EPERM
);
5932 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5935 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5936 assert_return(m
, -EINVAL
);
5937 assert_return(priority
, -EINVAL
);
5939 *priority
= m
->priority
;
5943 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5944 assert_return(m
, -EINVAL
);
5945 assert_return(!m
->sealed
, -EPERM
);
5947 m
->priority
= priority
;