2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "alloc-util.h"
27 #include "bus-gvariant.h"
28 #include "bus-internal.h"
29 #include "bus-message.h"
30 #include "bus-signature.h"
35 #include "memfd-util.h"
36 #include "string-util.h"
38 #include "time-util.h"
42 static int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
);
44 static void *adjust_pointer(const void *p
, void *old_base
, size_t sz
, void *new_base
) {
49 if (old_base
== new_base
)
52 if ((uint8_t*) p
< (uint8_t*) old_base
)
55 if ((uint8_t*) p
>= (uint8_t*) old_base
+ sz
)
58 return (uint8_t*) new_base
+ ((uint8_t*) p
- (uint8_t*) old_base
);
61 static void message_free_part(sd_bus_message
*m
, struct bus_body_part
*part
) {
65 if (part
->memfd
>= 0) {
66 /* If we can reuse the memfd, try that. For that it
67 * can't be sealed yet. */
70 assert(part
->memfd_offset
== 0);
71 assert(part
->data
== part
->mmap_begin
);
72 bus_kernel_push_memfd(m
->bus
, part
->memfd
, part
->data
, part
->mapped
, part
->allocated
);
75 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
77 safe_close(part
->memfd
);
80 } else if (part
->munmap_this
)
81 munmap(part
->mmap_begin
, part
->mapped
);
82 else if (part
->free_this
)
89 static void message_reset_parts(sd_bus_message
*m
) {
90 struct bus_body_part
*part
;
95 while (m
->n_body_parts
> 0) {
96 struct bus_body_part
*next
= part
->next
;
97 message_free_part(m
, part
);
104 m
->cached_rindex_part
= NULL
;
105 m
->cached_rindex_part_begin
= 0;
108 static void message_reset_containers(sd_bus_message
*m
) {
113 for (i
= 0; i
< m
->n_containers
; i
++) {
114 free(m
->containers
[i
].signature
);
115 free(m
->containers
[i
].offsets
);
118 m
->containers
= mfree(m
->containers
);
120 m
->n_containers
= m
->containers_allocated
= 0;
121 m
->root_container
.index
= 0;
124 static void message_free(sd_bus_message
*m
) {
130 message_reset_parts(m
);
132 if (m
->release_kdbus
)
133 bus_kernel_cmd_free(m
->bus
, (uint8_t *) m
->kdbus
- (uint8_t *) m
->bus
->kdbus_buffer
);
138 sd_bus_unref(m
->bus
);
141 close_many(m
->fds
, m
->n_fds
);
145 if (m
->iovec
!= m
->iovec_fixed
)
148 m
->destination_ptr
= mfree(m
->destination_ptr
);
149 message_reset_containers(m
);
150 free(m
->root_container
.signature
);
151 free(m
->root_container
.offsets
);
153 free(m
->root_container
.peeked_signature
);
155 bus_creds_done(&m
->creds
);
159 static void *message_extend_fields(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
161 size_t old_size
, new_size
, start
;
168 old_size
= sizeof(struct bus_header
) + m
->fields_size
;
169 start
= ALIGN_TO(old_size
, align
);
170 new_size
= start
+ sz
;
172 if (new_size
< start
||
173 new_size
> (size_t) ((uint32_t) -1))
176 if (old_size
== new_size
)
177 return (uint8_t*) m
->header
+ old_size
;
179 if (m
->free_header
) {
180 np
= realloc(m
->header
, ALIGN8(new_size
));
184 /* Initially, the header is allocated as part of of
185 * the sd_bus_message itself, let's replace it by
188 np
= malloc(ALIGN8(new_size
));
192 memcpy(np
, m
->header
, sizeof(struct bus_header
));
195 /* Zero out padding */
196 if (start
> old_size
)
197 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
201 m
->fields_size
= new_size
- sizeof(struct bus_header
);
203 /* Adjust quick access pointers */
204 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
205 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
206 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
207 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
208 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
209 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
211 m
->free_header
= true;
214 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
217 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
220 return (uint8_t*) np
+ start
;
227 static int message_append_field_string(
239 /* dbus1 only allows 8bit header field ids */
243 /* dbus1 doesn't allow strings over 32bit, let's enforce this
244 * globally, to not risk convertability */
246 if (l
> (size_t) (uint32_t) -1)
249 /* Signature "(yv)" where the variant contains "s" */
251 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
253 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
254 p
= message_extend_fields(m
, 8, 8 + l
+ 1 + 1 + 1, true);
258 *((uint64_t*) p
) = h
;
265 *ret
= (char*) p
+ 8;
268 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
269 p
= message_extend_fields(m
, 8, 4 + 4 + l
+ 1, false);
278 ((uint32_t*) p
)[1] = l
;
279 memcpy(p
+ 8, s
, l
+ 1);
282 *ret
= (char*) p
+ 8;
288 static int message_append_field_signature(
299 /* dbus1 only allows 8bit header field ids */
303 /* dbus1 doesn't allow signatures over 8bit, let's enforce
304 * this globally, to not risk convertability */
309 /* Signature "(yv)" where the variant contains "g" */
311 if (BUS_MESSAGE_IS_GVARIANT(m
))
312 /* For gvariant the serialization is the same as for normal strings */
313 return message_append_field_string(m
, h
, 'g', s
, ret
);
315 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
316 p
= message_extend_fields(m
, 8, 4 + 1 + l
+ 1, false);
322 p
[2] = SD_BUS_TYPE_SIGNATURE
;
325 memcpy(p
+ 5, s
, l
+ 1);
328 *ret
= (const char*) p
+ 5;
334 static int message_append_field_uint32(sd_bus_message
*m
, uint64_t h
, uint32_t x
) {
339 /* dbus1 only allows 8bit header field ids */
343 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
344 /* (field id 64bit + ((value + NUL + signature string 'u') */
346 p
= message_extend_fields(m
, 8, 8 + 4 + 1 + 1, true);
350 *((uint64_t*) p
) = h
;
351 *((uint32_t*) (p
+ 8)) = x
;
355 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
356 p
= message_extend_fields(m
, 8, 4 + 4, false);
365 ((uint32_t*) p
)[1] = x
;
371 static int message_append_field_uint64(sd_bus_message
*m
, uint64_t h
, uint64_t x
) {
376 /* dbus1 only allows 8bit header field ids */
380 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
381 /* (field id 64bit + ((value + NUL + signature string 't') */
383 p
= message_extend_fields(m
, 8, 8 + 8 + 1 + 1, true);
387 *((uint64_t*) p
) = h
;
388 *((uint64_t*) (p
+ 8)) = x
;
392 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
393 p
= message_extend_fields(m
, 8, 4 + 4 + 8, false);
406 ((uint64_t*) p
)[1] = x
;
412 static int message_append_reply_cookie(sd_bus_message
*m
, uint64_t cookie
) {
415 if (BUS_MESSAGE_IS_GVARIANT(m
))
416 return message_append_field_uint64(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, cookie
);
418 /* 64bit cookies are not supported on dbus1 */
419 if (cookie
> 0xffffffffUL
)
422 return message_append_field_uint32(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) cookie
);
426 int bus_message_from_header(
429 size_t header_accessible
,
431 size_t footer_accessible
,
437 sd_bus_message
**ret
) {
439 _cleanup_free_ sd_bus_message
*m
= NULL
;
440 struct bus_header
*h
;
444 assert(header
|| header_accessible
<= 0);
445 assert(footer
|| footer_accessible
<= 0);
446 assert(fds
|| n_fds
<= 0);
449 if (header_accessible
< sizeof(struct bus_header
))
452 if (header_accessible
> message_size
)
454 if (footer_accessible
> message_size
)
458 if (!IN_SET(h
->version
, 1, 2))
461 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
464 if (!IN_SET(h
->endian
, BUS_LITTLE_ENDIAN
, BUS_BIG_ENDIAN
))
467 /* Note that we are happy with unknown flags in the flags header! */
469 a
= ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
472 label_sz
= strlen(label
);
483 m
->header_accessible
= header_accessible
;
485 m
->footer_accessible
= footer_accessible
;
487 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
490 if (h
->dbus2
.cookie
== 0)
493 /* dbus2 derives the sizes from the message size and
494 the offset table at the end, since it is formatted as
495 gvariant "yyyyuta{tv}v". Since the message itself is a
496 structure with precisely to variable sized entries,
497 there's only one offset in the table, which marks the
498 end of the fields array. */
500 ws
= bus_gvariant_determine_word_size(message_size
, 0);
501 if (footer_accessible
< ws
)
504 m
->fields_size
= bus_gvariant_read_word_le((uint8_t*) footer
+ footer_accessible
- ws
, ws
);
505 if (ALIGN8(m
->fields_size
) > message_size
- ws
)
507 if (m
->fields_size
< sizeof(struct bus_header
))
510 m
->fields_size
-= sizeof(struct bus_header
);
511 m
->body_size
= message_size
- (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
));
513 if (h
->dbus1
.serial
== 0)
516 /* dbus1 has the sizes in the header */
517 m
->fields_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.fields_size
);
518 m
->body_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.body_size
);
520 if (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
!= message_size
)
528 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
529 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
531 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
534 m
->bus
= sd_bus_ref(bus
);
541 int bus_message_from_malloc(
548 sd_bus_message
**ret
) {
554 r
= bus_message_from_header(
556 buffer
, length
, /* in this case the initial bytes and the final bytes are the same */
565 sz
= length
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
);
568 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(m
->fields_size
);
570 m
->body
.sealed
= true;
575 m
->iovec
= m
->iovec_fixed
;
576 m
->iovec
[0].iov_base
= buffer
;
577 m
->iovec
[0].iov_len
= length
;
579 r
= bus_message_parse_fields(m
);
583 /* We take possession of the memory and fds now */
584 m
->free_header
= true;
595 static sd_bus_message
*message_new(sd_bus
*bus
, uint8_t type
) {
600 m
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
605 m
->header
= (struct bus_header
*) ((uint8_t*) m
+ ALIGN(sizeof(struct sd_bus_message
)));
606 m
->header
->endian
= BUS_NATIVE_ENDIAN
;
607 m
->header
->type
= type
;
608 m
->header
->version
= bus
->message_version
;
609 m
->allow_fds
= bus
->can_fds
|| (bus
->state
!= BUS_HELLO
&& bus
->state
!= BUS_RUNNING
);
610 m
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(m
);
611 m
->bus
= sd_bus_ref(bus
);
613 if (bus
->allow_interactive_authorization
)
614 m
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
619 _public_
int sd_bus_message_new_signal(
623 const char *interface
,
624 const char *member
) {
629 assert_return(bus
, -ENOTCONN
);
630 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
631 assert_return(object_path_is_valid(path
), -EINVAL
);
632 assert_return(interface_name_is_valid(interface
), -EINVAL
);
633 assert_return(member_name_is_valid(member
), -EINVAL
);
634 assert_return(m
, -EINVAL
);
636 t
= message_new(bus
, SD_BUS_MESSAGE_SIGNAL
);
640 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
642 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
645 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
648 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
656 sd_bus_message_unref(t
);
660 _public_
int sd_bus_message_new_method_call(
663 const char *destination
,
665 const char *interface
,
666 const char *member
) {
671 assert_return(bus
, -ENOTCONN
);
672 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
673 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
674 assert_return(object_path_is_valid(path
), -EINVAL
);
675 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
676 assert_return(member_name_is_valid(member
), -EINVAL
);
677 assert_return(m
, -EINVAL
);
679 t
= message_new(bus
, SD_BUS_MESSAGE_METHOD_CALL
);
683 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
686 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
691 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
697 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
710 static int message_new_reply(
711 sd_bus_message
*call
,
713 sd_bus_message
**m
) {
718 assert_return(call
, -EINVAL
);
719 assert_return(call
->sealed
, -EPERM
);
720 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
721 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
722 assert_return(m
, -EINVAL
);
724 t
= message_new(call
->bus
, type
);
728 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
729 t
->reply_cookie
= BUS_MESSAGE_COOKIE(call
);
730 if (t
->reply_cookie
== 0)
733 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
738 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
743 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
744 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
754 _public_
int sd_bus_message_new_method_return(
755 sd_bus_message
*call
,
756 sd_bus_message
**m
) {
758 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
761 _public_
int sd_bus_message_new_method_error(
762 sd_bus_message
*call
,
764 const sd_bus_error
*e
) {
769 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
770 assert_return(m
, -EINVAL
);
772 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
776 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
781 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
786 t
->error
._need_free
= -1;
796 _public_
int sd_bus_message_new_method_errorf(
797 sd_bus_message
*call
,
803 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
806 assert_return(name
, -EINVAL
);
807 assert_return(m
, -EINVAL
);
809 va_start(ap
, format
);
810 bus_error_setfv(&error
, name
, format
, ap
);
813 return sd_bus_message_new_method_error(call
, m
, &error
);
816 _public_
int sd_bus_message_new_method_errno(
817 sd_bus_message
*call
,
820 const sd_bus_error
*p
) {
822 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
824 if (sd_bus_error_is_set(p
))
825 return sd_bus_message_new_method_error(call
, m
, p
);
827 sd_bus_error_set_errno(&berror
, error
);
829 return sd_bus_message_new_method_error(call
, m
, &berror
);
832 _public_
int sd_bus_message_new_method_errnof(
833 sd_bus_message
*call
,
839 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
842 va_start(ap
, format
);
843 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
846 return sd_bus_message_new_method_error(call
, m
, &berror
);
849 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
853 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
854 m
->creds
.well_known_names_local
= true;
855 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
858 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
862 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
863 m
->creds
.well_known_names_driver
= true;
864 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
867 int bus_message_new_synthetic_error(
870 const sd_bus_error
*e
,
871 sd_bus_message
**m
) {
877 assert(sd_bus_error_is_set(e
));
880 t
= message_new(bus
, SD_BUS_MESSAGE_METHOD_ERROR
);
884 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
885 t
->reply_cookie
= cookie
;
887 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
891 if (bus
&& bus
->unique_name
) {
892 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
897 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
902 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
907 t
->error
._need_free
= -1;
909 bus_message_set_sender_driver(bus
, t
);
919 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
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
);
2634 memcpy_safe(p
, ptr
, size
);
2639 _public_
int sd_bus_message_append_array_iovec(
2642 const struct iovec
*iov
,
2650 assert_return(m
, -EINVAL
);
2651 assert_return(!m
->sealed
, -EPERM
);
2652 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2653 assert_return(iov
|| n
== 0, -EINVAL
);
2654 assert_return(!m
->poisoned
, -ESTALE
);
2656 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2658 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2662 for (i
= 0; i
< n
; i
++) {
2664 if (iov
[i
].iov_base
)
2665 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2667 memzero(p
, iov
[i
].iov_len
);
2669 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2675 _public_
int sd_bus_message_append_array_memfd(
2682 _cleanup_close_
int copy_fd
= -1;
2683 struct bus_body_part
*part
;
2689 assert_return(m
, -EINVAL
);
2690 assert_return(memfd
>= 0, -EBADF
);
2691 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2692 assert_return(size
> 0, -EINVAL
);
2693 assert_return(!m
->sealed
, -EPERM
);
2694 assert_return(!m
->poisoned
, -ESTALE
);
2696 r
= memfd_set_sealed(memfd
);
2700 copy_fd
= dup(memfd
);
2704 r
= memfd_get_size(memfd
, &real_size
);
2708 if (offset
== 0 && size
== (uint64_t) -1)
2710 else if (offset
+ size
> real_size
)
2713 align
= bus_type_get_alignment(type
);
2714 sz
= bus_type_get_size(type
);
2716 assert_se(align
> 0);
2719 if (offset
% align
!= 0)
2725 if (size
> (uint64_t) (uint32_t) -1)
2728 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2732 a
= message_extend_body(m
, align
, 0, false, false);
2736 part
= message_append_part(m
);
2740 part
->memfd
= copy_fd
;
2741 part
->memfd_offset
= offset
;
2742 part
->sealed
= true;
2746 m
->body_size
+= size
;
2747 message_extend_containers(m
, size
);
2749 return sd_bus_message_close_container(m
);
2752 _public_
int sd_bus_message_append_string_memfd(
2758 _cleanup_close_
int copy_fd
= -1;
2759 struct bus_body_part
*part
;
2760 struct bus_container
*c
;
2765 assert_return(m
, -EINVAL
);
2766 assert_return(memfd
>= 0, -EBADF
);
2767 assert_return(size
> 0, -EINVAL
);
2768 assert_return(!m
->sealed
, -EPERM
);
2769 assert_return(!m
->poisoned
, -ESTALE
);
2771 r
= memfd_set_sealed(memfd
);
2775 copy_fd
= dup(memfd
);
2779 r
= memfd_get_size(memfd
, &real_size
);
2783 if (offset
== 0 && size
== (uint64_t) -1)
2785 else if (offset
+ size
> real_size
)
2788 /* We require this to be NUL terminated */
2792 if (size
> (uint64_t) (uint32_t) -1)
2795 c
= message_get_container(m
);
2796 if (c
->signature
&& c
->signature
[c
->index
]) {
2797 /* Container signature is already set */
2799 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2804 /* Maybe we can append to the signature? But only if this is the top-level container */
2805 if (c
->enclosing
!= 0)
2808 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2815 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2816 a
= message_extend_body(m
, 4, 4, false, false);
2820 *(uint32_t*) a
= size
- 1;
2823 part
= message_append_part(m
);
2827 part
->memfd
= copy_fd
;
2828 part
->memfd_offset
= offset
;
2829 part
->sealed
= true;
2833 m
->body_size
+= size
;
2834 message_extend_containers(m
, size
);
2836 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2837 r
= message_add_offset(m
, m
->body_size
);
2844 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2850 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2854 assert_return(m
, -EINVAL
);
2855 assert_return(!m
->sealed
, -EPERM
);
2856 assert_return(!m
->poisoned
, -ESTALE
);
2858 r
= sd_bus_message_open_container(m
, 'a', "s");
2862 STRV_FOREACH(i
, l
) {
2863 r
= sd_bus_message_append_basic(m
, 's', *i
);
2868 return sd_bus_message_close_container(m
);
2871 static int bus_message_close_header(sd_bus_message
*m
) {
2875 /* The actual user data is finished now, we just complete the
2876 variant and struct now (at least on gvariant). Remember
2877 this position, so that during parsing we know where to to
2878 put the outer container end. */
2879 m
->user_body_size
= m
->body_size
;
2881 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2882 const char *signature
;
2886 /* Add offset table to end of fields array */
2887 if (m
->n_header_offsets
>= 1) {
2891 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2893 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2894 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2898 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2899 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2902 /* Add gvariant NUL byte plus signature to the end of
2903 * the body, followed by the final offset pointing to
2904 * the end of the fields array */
2906 signature
= strempty(m
->root_container
.signature
);
2907 l
= strlen(signature
);
2909 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2910 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2915 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2916 memcpy((uint8_t*) d
+ 2, signature
, l
);
2917 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2919 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2922 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2924 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2925 m
->header
->dbus1
.body_size
= m
->body_size
;
2931 int bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, usec_t timeout
) {
2932 struct bus_body_part
*part
;
2942 if (m
->n_containers
> 0)
2948 if (cookie
> 0xffffffffULL
&&
2949 !BUS_MESSAGE_IS_GVARIANT(m
))
2952 /* In vtables the return signature of method calls is listed,
2953 * let's check if they match if this is a response */
2954 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2955 m
->enforced_reply_signature
&&
2956 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2959 /* If gvariant marshalling is used we need to close the body structure */
2960 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2964 /* If there's a non-trivial signature set, then add it in
2965 * here, but only on dbus1 */
2966 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2967 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2973 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2978 r
= bus_message_close_header(m
);
2982 if (BUS_MESSAGE_IS_GVARIANT(m
))
2983 m
->header
->dbus2
.cookie
= cookie
;
2985 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2987 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout
;
2989 /* Add padding at the end of the fields part, since we know
2990 * the body needs to start at an 8 byte alignment. We made
2991 * sure we allocated enough space for this, so all we need to
2992 * do here is to zero it out. */
2993 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2995 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2997 /* If this is something we can send as memfd, then let's seal
2998 the memfd now. Note that we can send memfds as payload only
2999 for directed messages, and not for broadcasts. */
3000 if (m
->destination
&& m
->bus
->use_memfd
) {
3001 MESSAGE_FOREACH_PART(part
, i
, m
)
3002 if (part
->memfd
>= 0 &&
3004 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
3005 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
3008 /* Try to seal it if that makes
3009 * sense. First, unmap our own map to
3010 * make sure we don't keep it busy. */
3011 bus_body_part_unmap(part
);
3013 /* Then, sync up real memfd size */
3015 r
= memfd_set_size(part
->memfd
, sz
);
3019 /* Finally, try to seal */
3020 if (memfd_set_sealed(part
->memfd
) >= 0)
3021 part
->sealed
= true;
3025 m
->root_container
.end
= m
->user_body_size
;
3026 m
->root_container
.index
= 0;
3027 m
->root_container
.offset_index
= 0;
3028 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
3035 int bus_body_part_map(struct bus_body_part
*part
) {
3044 if (part
->size
<= 0)
3047 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3048 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
3049 static const uint8_t zeroes
[7] = { };
3050 part
->data
= (void*) zeroes
;
3054 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
3055 psz
= PAGE_ALIGN(part
->size
+ shift
);
3057 if (part
->memfd
>= 0)
3058 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
3059 else if (part
->is_zero
)
3060 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
3064 if (p
== MAP_FAILED
)
3068 part
->mmap_begin
= p
;
3069 part
->data
= (uint8_t*) p
+ shift
;
3070 part
->munmap_this
= true;
3075 void bus_body_part_unmap(struct bus_body_part
*part
) {
3079 if (part
->memfd
< 0)
3082 if (!part
->mmap_begin
)
3085 if (!part
->munmap_this
)
3088 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
3090 part
->mmap_begin
= NULL
;
3093 part
->munmap_this
= false;
3098 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3099 size_t k
, start
, end
;
3104 start
= ALIGN_TO((size_t) *rindex
, align
);
3105 end
= start
+ nbytes
;
3110 /* Verify that padding is 0 */
3111 for (k
= *rindex
; k
< start
; k
++)
3112 if (((const uint8_t*) p
)[k
] != 0)
3116 *r
= (uint8_t*) p
+ start
;
3123 static bool message_end_of_signature(sd_bus_message
*m
) {
3124 struct bus_container
*c
;
3128 c
= message_get_container(m
);
3129 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3132 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3133 struct bus_container
*c
;
3137 c
= message_get_container(m
);
3138 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3141 if (BUS_MESSAGE_IS_GVARIANT(m
))
3142 return index
>= c
->end
;
3144 assert(c
->array_size
);
3145 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3149 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3150 assert_return(m
, -EINVAL
);
3151 assert_return(m
->sealed
, -EPERM
);
3153 if (complete
&& m
->n_containers
> 0)
3156 if (message_end_of_signature(m
))
3159 if (message_end_of_array(m
, m
->rindex
))
3165 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3166 struct bus_body_part
*part
;
3172 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3173 part
= m
->cached_rindex_part
;
3174 begin
= m
->cached_rindex_part_begin
;
3184 if (index
+ sz
<= begin
+ part
->size
) {
3186 r
= bus_body_part_map(part
);
3191 *p
= (uint8_t*) part
->data
+ index
- begin
;
3193 m
->cached_rindex_part
= part
;
3194 m
->cached_rindex_part_begin
= begin
;
3199 begin
+= part
->size
;
3206 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3213 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3216 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3219 sz
= bus_gvariant_get_size(c
->signature
);
3223 if (c
->offset_index
+1 >= c
->n_offsets
)
3226 /* Variable-size array */
3228 alignment
= bus_gvariant_get_alignment(c
->signature
);
3229 assert(alignment
> 0);
3231 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3232 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3235 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3238 /* Fixed-size array */
3239 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3245 } else if (c
->enclosing
== 0 ||
3246 c
->enclosing
== SD_BUS_TYPE_STRUCT
||
3247 c
->enclosing
== SD_BUS_TYPE_DICT_ENTRY
) {
3252 if (c
->offset_index
+1 >= c
->n_offsets
)
3255 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3259 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3264 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3267 alignment
= bus_gvariant_get_alignment(t
);
3270 assert(alignment
> 0);
3272 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3273 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3277 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3280 assert_not_reached("Unknown container type");
3285 /* Reached the end */
3292 static int message_peek_body(
3299 size_t k
, start
, end
, padding
;
3300 struct bus_body_part
*part
;
3307 start
= ALIGN_TO((size_t) *rindex
, align
);
3308 padding
= start
- *rindex
;
3309 end
= start
+ nbytes
;
3311 if (end
> m
->user_body_size
)
3314 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3319 /* Verify padding */
3320 for (k
= 0; k
< padding
; k
++)
3325 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3326 if (!part
|| (nbytes
> 0 && !q
))
3337 static bool validate_nul(const char *s
, size_t l
) {
3339 /* Check for NUL chars in the string */
3340 if (memchr(s
, 0, l
))
3343 /* Check for NUL termination */
3350 static bool validate_string(const char *s
, size_t l
) {
3352 if (!validate_nul(s
, l
))
3355 /* Check if valid UTF8 */
3356 if (!utf8_is_valid(s
))
3362 static bool validate_signature(const char *s
, size_t l
) {
3364 if (!validate_nul(s
, l
))
3367 /* Check if valid signature */
3368 if (!signature_is_valid(s
, true))
3374 static bool validate_object_path(const char *s
, size_t l
) {
3376 if (!validate_nul(s
, l
))
3379 if (!object_path_is_valid(s
))
3385 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3386 struct bus_container
*c
;
3391 assert_return(m
, -EINVAL
);
3392 assert_return(m
->sealed
, -EPERM
);
3393 assert_return(bus_type_is_basic(type
), -EINVAL
);
3395 if (message_end_of_signature(m
))
3398 if (message_end_of_array(m
, m
->rindex
))
3401 c
= message_get_container(m
);
3402 if (c
->signature
[c
->index
] != type
)
3407 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3409 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3412 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3416 if (type
== SD_BUS_TYPE_STRING
)
3417 ok
= validate_string(q
, c
->item_size
-1);
3418 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3419 ok
= validate_object_path(q
, c
->item_size
-1);
3421 ok
= validate_signature(q
, c
->item_size
-1);
3427 *(const char**) p
= q
;
3431 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3433 if ((size_t) sz
!= c
->item_size
)
3436 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3439 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3445 case SD_BUS_TYPE_BYTE
:
3447 *(uint8_t*) p
= *(uint8_t*) q
;
3450 case SD_BUS_TYPE_BOOLEAN
:
3452 *(int*) p
= !!*(uint8_t*) q
;
3455 case SD_BUS_TYPE_INT16
:
3456 case SD_BUS_TYPE_UINT16
:
3458 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3461 case SD_BUS_TYPE_INT32
:
3462 case SD_BUS_TYPE_UINT32
:
3464 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3467 case SD_BUS_TYPE_INT64
:
3468 case SD_BUS_TYPE_UINT64
:
3469 case SD_BUS_TYPE_DOUBLE
:
3471 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3474 case SD_BUS_TYPE_UNIX_FD
: {
3477 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3482 *(int*) p
= m
->fds
[j
];
3488 assert_not_reached("unexpected type");
3492 r
= container_next_item(m
, c
, &rindex
);
3497 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3501 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3505 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3506 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3510 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3511 ok
= validate_object_path(q
, l
);
3513 ok
= validate_string(q
, l
);
3518 *(const char**) p
= q
;
3520 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3523 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3528 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3532 if (!validate_signature(q
, l
))
3536 *(const char**) p
= q
;
3541 align
= bus_type_get_alignment(type
);
3544 sz
= bus_type_get_size(type
);
3547 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3553 case SD_BUS_TYPE_BYTE
:
3555 *(uint8_t*) p
= *(uint8_t*) q
;
3558 case SD_BUS_TYPE_BOOLEAN
:
3560 *(int*) p
= !!*(uint32_t*) q
;
3563 case SD_BUS_TYPE_INT16
:
3564 case SD_BUS_TYPE_UINT16
:
3566 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3569 case SD_BUS_TYPE_INT32
:
3570 case SD_BUS_TYPE_UINT32
:
3572 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3575 case SD_BUS_TYPE_INT64
:
3576 case SD_BUS_TYPE_UINT64
:
3577 case SD_BUS_TYPE_DOUBLE
:
3579 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3582 case SD_BUS_TYPE_UNIX_FD
: {
3585 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3590 *(int*) p
= m
->fds
[j
];
3595 assert_not_reached("Unknown basic type...");
3602 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3608 static int bus_message_enter_array(
3610 struct bus_container
*c
,
3611 const char *contents
,
3612 uint32_t **array_size
,
3615 size_t *n_offsets
) {
3629 if (!signature_is_single(contents
, true))
3632 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3635 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3638 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3643 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3646 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3650 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3653 alignment
= bus_type_get_alignment(contents
[0]);
3657 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3661 *array_size
= (uint32_t*) q
;
3663 } else if (c
->item_size
<= 0) {
3665 /* gvariant: empty array */
3670 } else if (bus_gvariant_is_fixed_size(contents
)) {
3672 /* gvariant: fixed length array */
3673 *item_size
= bus_gvariant_get_size(contents
);
3678 size_t where
, p
= 0, framing
, sz
;
3681 /* gvariant: variable length array */
3682 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3684 where
= rindex
+ c
->item_size
- sz
;
3685 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3689 framing
= bus_gvariant_read_word_le(q
, sz
);
3690 if (framing
> c
->item_size
- sz
)
3692 if ((c
->item_size
- framing
) % sz
!= 0)
3695 *n_offsets
= (c
->item_size
- framing
) / sz
;
3697 where
= rindex
+ framing
;
3698 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3702 *offsets
= new(size_t, *n_offsets
);
3706 for (i
= 0; i
< *n_offsets
; i
++) {
3709 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3710 if (x
> c
->item_size
- sz
)
3715 (*offsets
)[i
] = rindex
+ x
;
3719 *item_size
= (*offsets
)[0] - rindex
;
3724 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3725 c
->index
+= 1 + strlen(contents
);
3730 static int bus_message_enter_variant(
3732 struct bus_container
*c
,
3733 const char *contents
,
3734 size_t *item_size
) {
3746 if (!signature_is_single(contents
, false))
3749 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3752 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3755 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3760 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3763 k
= strlen(contents
);
3764 if (1+k
> c
->item_size
)
3767 where
= rindex
+ c
->item_size
- (1+k
);
3768 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3772 if (*(char*) q
!= 0)
3775 if (memcmp((uint8_t*) q
+1, contents
, k
))
3778 *item_size
= c
->item_size
- (1+k
);
3781 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3786 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3790 if (!validate_signature(q
, l
))
3793 if (!streq(q
, contents
))
3799 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3805 static int build_struct_offsets(
3807 const char *signature
,
3811 size_t *n_offsets
) {
3813 unsigned n_variable
= 0, n_total
= 0, v
;
3814 size_t previous
= 0, where
;
3825 if (isempty(signature
)) {
3826 /* Unary type is encoded as *fixed* 1 byte padding */
3827 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3831 if (*(uint8_t *) q
!= 0)
3840 sz
= bus_gvariant_determine_word_size(size
, 0);
3844 /* First, loop over signature and count variable elements and
3845 * elements in general. We use this to know how large the
3846 * offset array is at the end of the structure. Note that
3847 * GVariant only stores offsets for all variable size elements
3848 * that are not the last item. */
3854 r
= signature_element_length(p
, &n
);
3863 r
= bus_gvariant_is_fixed_size(t
);
3868 if (r
== 0 && p
[n
] != 0) /* except the last item */
3875 if (size
< n_variable
* sz
)
3878 where
= m
->rindex
+ size
- (n_variable
* sz
);
3879 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3885 *offsets
= new(size_t, n_total
);
3891 /* Second, loop again and build an offset table */
3897 r
= signature_element_length(p
, &n
);
3906 k
= bus_gvariant_get_size(t
);
3914 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3917 if (m
->rindex
+ x
< previous
)
3920 /* The last item's end
3921 * is determined from
3924 x
= size
- (n_variable
* sz
);
3926 offset
= m
->rindex
+ x
;
3932 align
= bus_gvariant_get_alignment(t
);
3935 offset
= (*n_offsets
== 0 ? m
->rindex
: ALIGN_TO((*offsets
)[*n_offsets
-1], align
)) + k
;
3939 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3944 assert(*n_offsets
== n_total
);
3946 *item_size
= (*offsets
)[0] - m
->rindex
;
3950 static int enter_struct_or_dict_entry(
3952 struct bus_container
*c
,
3953 const char *contents
,
3956 size_t *n_offsets
) {
3967 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3970 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3975 /* gvariant with contents */
3976 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3981 static int bus_message_enter_struct(
3983 struct bus_container
*c
,
3984 const char *contents
,
3987 size_t *n_offsets
) {
3999 if (!signature_is_valid(contents
, false))
4002 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4005 l
= strlen(contents
);
4007 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
4008 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4009 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
4012 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4016 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4017 c
->index
+= 1 + l
+ 1;
4022 static int bus_message_enter_dict_entry(
4024 struct bus_container
*c
,
4025 const char *contents
,
4028 size_t *n_offsets
) {
4037 if (!signature_is_pair(contents
))
4040 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4043 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4046 l
= strlen(contents
);
4048 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
4049 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4050 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
4053 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4057 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4058 c
->index
+= 1 + l
+ 1;
4063 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
4065 const char *contents
) {
4066 struct bus_container
*c
, *w
;
4067 uint32_t *array_size
= NULL
;
4070 size_t *offsets
= NULL
;
4071 size_t n_offsets
= 0, item_size
= 0;
4074 assert_return(m
, -EINVAL
);
4075 assert_return(m
->sealed
, -EPERM
);
4076 assert_return(type
!= 0 || !contents
, -EINVAL
);
4078 if (type
== 0 || !contents
) {
4082 /* Allow entering into anonymous containers */
4083 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
4087 if (type
!= 0 && type
!= tt
)
4090 if (contents
&& !streq(contents
, cc
))
4098 * We enforce a global limit on container depth, that is much
4099 * higher than the 32 structs and 32 arrays the specification
4100 * mandates. This is simpler to implement for us, and we need
4101 * this only to ensure our container array doesn't grow
4102 * without bounds. We are happy to return any data from a
4103 * message as long as the data itself is valid, even if the
4104 * overall message might be not.
4106 * Note that the message signature is validated when
4107 * parsing the headers, and that validation does check the
4110 * Note that the specification defines no limits on the depth
4111 * of stacked variants, but we do.
4113 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4116 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4119 if (message_end_of_signature(m
))
4122 if (message_end_of_array(m
, m
->rindex
))
4125 c
= message_get_container(m
);
4127 signature
= strdup(contents
);
4131 c
->saved_index
= c
->index
;
4134 if (type
== SD_BUS_TYPE_ARRAY
)
4135 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4136 else if (type
== SD_BUS_TYPE_VARIANT
)
4137 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4138 else if (type
== SD_BUS_TYPE_STRUCT
)
4139 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4140 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4141 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4151 /* OK, let's fill it in */
4152 w
= m
->containers
+ m
->n_containers
++;
4153 w
->enclosing
= type
;
4154 w
->signature
= signature
;
4155 w
->peeked_signature
= NULL
;
4159 w
->begin
= m
->rindex
;
4161 /* Unary type has fixed size of 1, but virtual size of 0 */
4162 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4163 type
== SD_BUS_TYPE_STRUCT
&&
4165 w
->end
= m
->rindex
+ 0;
4167 w
->end
= m
->rindex
+ c
->item_size
;
4169 w
->array_size
= array_size
;
4170 w
->item_size
= item_size
;
4171 w
->offsets
= offsets
;
4172 w
->n_offsets
= n_offsets
;
4173 w
->offset_index
= 0;
4178 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4179 struct bus_container
*c
;
4183 assert_return(m
, -EINVAL
);
4184 assert_return(m
->sealed
, -EPERM
);
4185 assert_return(m
->n_containers
> 0, -ENXIO
);
4187 c
= message_get_container(m
);
4189 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4190 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4194 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4195 if (m
->rindex
< c
->end
)
4198 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4201 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4202 if (c
->begin
+ l
!= m
->rindex
)
4207 free(c
->peeked_signature
);
4211 c
= message_get_container(m
);
4214 c
->index
= c
->saved_index
;
4215 r
= container_next_item(m
, c
, &m
->rindex
);
4223 static void message_quit_container(sd_bus_message
*m
) {
4224 struct bus_container
*c
;
4228 assert(m
->n_containers
> 0);
4230 c
= message_get_container(m
);
4233 assert(m
->rindex
>= c
->before
);
4234 m
->rindex
= c
->before
;
4236 /* Free container */
4241 /* Correct index of new top-level container */
4242 c
= message_get_container(m
);
4243 c
->index
= c
->saved_index
;
4246 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4247 struct bus_container
*c
;
4250 assert_return(m
, -EINVAL
);
4251 assert_return(m
->sealed
, -EPERM
);
4253 if (message_end_of_signature(m
))
4256 if (message_end_of_array(m
, m
->rindex
))
4259 c
= message_get_container(m
);
4261 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4265 *type
= c
->signature
[c
->index
];
4269 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4275 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4281 sig
= strndup(c
->signature
+ c
->index
+ 1, l
);
4285 free(c
->peeked_signature
);
4286 *contents
= c
->peeked_signature
= sig
;
4290 *type
= SD_BUS_TYPE_ARRAY
;
4295 if (c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
||
4296 c
->signature
[c
->index
] == SD_BUS_TYPE_DICT_ENTRY_BEGIN
) {
4302 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4307 sig
= strndup(c
->signature
+ c
->index
+ 1, l
- 2);
4311 free(c
->peeked_signature
);
4312 *contents
= c
->peeked_signature
= sig
;
4316 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4321 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4325 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4328 if (c
->item_size
< 2)
4331 /* Look for the NUL delimiter that
4332 separates the payload from the
4333 signature. Since the body might be
4334 in a different part that then the
4335 signature we map byte by byte. */
4337 for (k
= 2; k
<= c
->item_size
; k
++) {
4340 where
= m
->rindex
+ c
->item_size
- k
;
4341 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4345 if (*(char*) q
== 0)
4349 if (k
> c
->item_size
)
4352 free(c
->peeked_signature
);
4353 c
->peeked_signature
= strndup((char*) q
+ 1, k
- 1);
4354 if (!c
->peeked_signature
)
4357 if (!signature_is_valid(c
->peeked_signature
, true))
4360 *contents
= c
->peeked_signature
;
4365 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4370 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4374 if (!validate_signature(q
, l
))
4382 *type
= SD_BUS_TYPE_VARIANT
;
4397 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4398 struct bus_container
*c
;
4400 assert_return(m
, -EINVAL
);
4401 assert_return(m
->sealed
, -EPERM
);
4404 message_reset_containers(m
);
4407 c
= message_get_container(m
);
4409 c
= message_get_container(m
);
4411 c
->offset_index
= 0;
4413 m
->rindex
= c
->begin
;
4416 c
->offset_index
= 0;
4417 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4419 return !isempty(c
->signature
);
4422 static int message_read_ap(
4427 unsigned n_array
, n_struct
;
4428 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4429 unsigned stack_ptr
= 0;
4430 unsigned n_loop
= 0;
4438 /* Ideally, we'd just call ourselves recursively on every
4439 * complex type. However, the state of a va_list that is
4440 * passed to a function is undefined after that function
4441 * returns. This means we need to docode the va_list linearly
4442 * in a single stackframe. We hence implement our own
4443 * home-grown stack in an array. */
4445 n_array
= (unsigned) -1; /* length of current array entries */
4446 n_struct
= strlen(types
); /* length of current struct contents signature */
4453 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4454 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4460 r
= sd_bus_message_exit_container(m
);
4468 if (n_array
!= (unsigned) -1)
4477 case SD_BUS_TYPE_BYTE
:
4478 case SD_BUS_TYPE_BOOLEAN
:
4479 case SD_BUS_TYPE_INT16
:
4480 case SD_BUS_TYPE_UINT16
:
4481 case SD_BUS_TYPE_INT32
:
4482 case SD_BUS_TYPE_UINT32
:
4483 case SD_BUS_TYPE_INT64
:
4484 case SD_BUS_TYPE_UINT64
:
4485 case SD_BUS_TYPE_DOUBLE
:
4486 case SD_BUS_TYPE_STRING
:
4487 case SD_BUS_TYPE_OBJECT_PATH
:
4488 case SD_BUS_TYPE_SIGNATURE
:
4489 case SD_BUS_TYPE_UNIX_FD
: {
4492 p
= va_arg(ap
, void*);
4493 r
= sd_bus_message_read_basic(m
, *t
, p
);
4506 case SD_BUS_TYPE_ARRAY
: {
4509 r
= signature_element_length(t
+ 1, &k
);
4515 memcpy(s
, t
+ 1, k
);
4518 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4529 if (n_array
== (unsigned) -1) {
4534 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4540 n_array
= va_arg(ap
, unsigned);
4545 case SD_BUS_TYPE_VARIANT
: {
4548 s
= va_arg(ap
, const char *);
4552 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4562 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4567 n_struct
= strlen(s
);
4568 n_array
= (unsigned) -1;
4573 case SD_BUS_TYPE_STRUCT_BEGIN
:
4574 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4577 r
= signature_element_length(t
, &k
);
4583 memcpy(s
, t
+ 1, k
- 2);
4586 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4596 if (n_array
== (unsigned) -1) {
4601 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4607 n_array
= (unsigned) -1;
4620 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4624 assert_return(m
, -EINVAL
);
4625 assert_return(m
->sealed
, -EPERM
);
4626 assert_return(types
, -EINVAL
);
4628 va_start(ap
, types
);
4629 r
= message_read_ap(m
, types
, ap
);
4635 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4638 assert_return(m
, -EINVAL
);
4639 assert_return(m
->sealed
, -EPERM
);
4641 /* If types is NULL, read exactly one element */
4643 struct bus_container
*c
;
4646 if (message_end_of_signature(m
))
4649 if (message_end_of_array(m
, m
->rindex
))
4652 c
= message_get_container(m
);
4654 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4658 types
= strndupa(c
->signature
+ c
->index
, l
);
4663 case 0: /* Nothing to drop */
4666 case SD_BUS_TYPE_BYTE
:
4667 case SD_BUS_TYPE_BOOLEAN
:
4668 case SD_BUS_TYPE_INT16
:
4669 case SD_BUS_TYPE_UINT16
:
4670 case SD_BUS_TYPE_INT32
:
4671 case SD_BUS_TYPE_UINT32
:
4672 case SD_BUS_TYPE_INT64
:
4673 case SD_BUS_TYPE_UINT64
:
4674 case SD_BUS_TYPE_DOUBLE
:
4675 case SD_BUS_TYPE_STRING
:
4676 case SD_BUS_TYPE_OBJECT_PATH
:
4677 case SD_BUS_TYPE_SIGNATURE
:
4678 case SD_BUS_TYPE_UNIX_FD
:
4680 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4684 r
= sd_bus_message_skip(m
, types
+ 1);
4690 case SD_BUS_TYPE_ARRAY
: {
4693 r
= signature_element_length(types
+ 1, &k
);
4699 memcpy(s
, types
+1, k
);
4702 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4707 r
= sd_bus_message_skip(m
, s
);
4714 r
= sd_bus_message_exit_container(m
);
4719 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4726 case SD_BUS_TYPE_VARIANT
: {
4727 const char *contents
;
4730 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4734 if (x
!= SD_BUS_TYPE_VARIANT
)
4737 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4741 r
= sd_bus_message_skip(m
, contents
);
4746 r
= sd_bus_message_exit_container(m
);
4750 r
= sd_bus_message_skip(m
, types
+ 1);
4757 case SD_BUS_TYPE_STRUCT_BEGIN
:
4758 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4761 r
= signature_element_length(types
, &k
);
4767 memcpy(s
, types
+1, k
-2);
4770 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4774 r
= sd_bus_message_skip(m
, s
);
4778 r
= sd_bus_message_exit_container(m
);
4783 r
= sd_bus_message_skip(m
, types
+ k
);
4795 _public_
int sd_bus_message_read_array(
4801 struct bus_container
*c
;
4807 assert_return(m
, -EINVAL
);
4808 assert_return(m
->sealed
, -EPERM
);
4809 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4810 assert_return(ptr
, -EINVAL
);
4811 assert_return(size
, -EINVAL
);
4812 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4814 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4818 c
= message_get_container(m
);
4820 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4821 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4825 sz
= c
->end
- c
->begin
;
4827 align
= bus_type_get_alignment(type
);
4831 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4835 /* Zero length array, let's return some aligned
4836 * pointer that is not NULL */
4837 p
= (uint8_t*) NULL
+ align
;
4839 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4844 r
= sd_bus_message_exit_container(m
);
4848 *ptr
= (const void*) p
;
4854 message_quit_container(m
);
4858 static int message_peek_fields(
4869 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4872 static int message_peek_field_uint32(
4884 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4887 /* identical for gvariant and dbus1 */
4889 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4894 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4899 static int message_peek_field_uint64(
4911 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4914 /* identical for gvariant and dbus1 */
4916 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4921 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4926 static int message_peek_field_string(
4928 bool (*validate
)(const char *p
),
4940 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4945 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4951 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4955 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4961 if (!validate_nul(q
, l
))
4967 if (!validate_string(q
, l
))
4977 static int message_peek_field_signature(
4990 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4995 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
5001 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
5006 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
5011 if (!validate_signature(q
, l
))
5020 static int message_skip_fields(
5023 uint32_t array_size
,
5024 const char **signature
) {
5026 size_t original_index
;
5032 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
5034 original_index
= *ri
;
5040 if (array_size
!= (uint32_t) -1 &&
5041 array_size
<= *ri
- original_index
)
5048 if (t
== SD_BUS_TYPE_STRING
) {
5050 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
5056 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
5058 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
5064 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
5066 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
5072 } else if (bus_type_is_basic(t
)) {
5075 align
= bus_type_get_alignment(t
);
5076 k
= bus_type_get_size(t
);
5077 assert(align
> 0 && k
> 0);
5079 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
5085 } else if (t
== SD_BUS_TYPE_ARRAY
) {
5087 r
= signature_element_length(*signature
+1, &l
);
5097 strncpy(sig
, *signature
+ 1, l
-1);
5100 alignment
= bus_type_get_alignment(sig
[0]);
5104 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5107 if (nas
> BUS_ARRAY_MAX_SIZE
)
5110 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5114 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5119 (*signature
) += 1 + l
;
5121 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5124 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5128 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5134 } else if (t
== SD_BUS_TYPE_STRUCT
||
5135 t
== SD_BUS_TYPE_DICT_ENTRY
) {
5137 r
= signature_element_length(*signature
, &l
);
5144 strncpy(sig
, *signature
+ 1, l
-1);
5147 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5158 int bus_message_parse_fields(sd_bus_message
*m
) {
5161 uint32_t unix_fds
= 0;
5162 bool unix_fds_set
= false;
5163 void *offsets
= NULL
;
5164 unsigned n_offsets
= 0;
5170 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5173 /* Read the signature from the end of the body variant first */
5174 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5175 if (m
->footer_accessible
< 1 + sz
)
5178 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5180 if (p
< (char*) m
->footer
)
5187 /* We found the beginning of the signature
5188 * string, yay! We require the body to be a
5189 * structure, so verify it and then strip the
5190 * opening/closing brackets. */
5192 l
= ((char*) m
->footer
+ m
->footer_accessible
) - p
- (1 + sz
);
5194 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5195 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5198 c
= strndup(p
+ 1 + 1, l
- 2);
5202 free(m
->root_container
.signature
);
5203 m
->root_container
.signature
= c
;
5210 /* Calculate the actual user body size, by removing
5211 * the trailing variant signature and struct offset
5213 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5215 /* Pull out the offset table for the fields array */
5216 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5221 ri
= m
->fields_size
- sz
;
5222 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5226 framing
= bus_gvariant_read_word_le(q
, sz
);
5227 if (framing
>= m
->fields_size
- sz
)
5229 if ((m
->fields_size
- framing
) % sz
!= 0)
5233 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5237 n_offsets
= (m
->fields_size
- framing
) / sz
;
5240 m
->user_body_size
= m
->body_size
;
5243 while (ri
< m
->fields_size
) {
5244 _cleanup_free_
char *sig
= NULL
;
5245 const char *signature
;
5246 uint64_t field_type
;
5247 size_t item_size
= (size_t) -1;
5249 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5258 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5260 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5264 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5268 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5275 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5280 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5285 where
= ri
= ALIGN_TO(ri
, 8);
5286 item_size
= end
- ri
;
5287 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5291 b
= memrchr(q
, 0, item_size
);
5295 sig
= strndup(b
+1, item_size
- (b
+1-(char*) q
));
5300 item_size
= b
- (char*) q
;
5302 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5307 switch (field_type
) {
5309 case _BUS_MESSAGE_HEADER_INVALID
:
5312 case BUS_MESSAGE_HEADER_PATH
:
5317 if (!streq(signature
, "o"))
5320 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5323 case BUS_MESSAGE_HEADER_INTERFACE
:
5328 if (!streq(signature
, "s"))
5331 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5334 case BUS_MESSAGE_HEADER_MEMBER
:
5339 if (!streq(signature
, "s"))
5342 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5345 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5350 if (!streq(signature
, "s"))
5353 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5355 m
->error
._need_free
= -1;
5359 case BUS_MESSAGE_HEADER_DESTINATION
:
5364 if (!streq(signature
, "s"))
5367 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5370 case BUS_MESSAGE_HEADER_SENDER
:
5375 if (!streq(signature
, "s"))
5378 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5380 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
&& !m
->bus
->is_kernel
) {
5381 m
->creds
.unique_name
= (char*) m
->sender
;
5382 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5388 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5392 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5395 if (m
->root_container
.signature
)
5398 if (!streq(signature
, "g"))
5401 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5409 free(m
->root_container
.signature
);
5410 m
->root_container
.signature
= c
;
5414 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5416 if (m
->reply_cookie
!= 0)
5419 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5420 /* 64bit on dbus2 */
5422 if (!streq(signature
, "t"))
5425 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5429 /* 32bit on dbus1 */
5432 if (!streq(signature
, "u"))
5435 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5439 m
->reply_cookie
= serial
;
5442 if (m
->reply_cookie
== 0)
5447 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5451 if (!streq(signature
, "u"))
5454 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5458 unix_fds_set
= true;
5462 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5463 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5472 if (m
->n_fds
!= unix_fds
)
5475 switch (m
->header
->type
) {
5477 case SD_BUS_MESSAGE_SIGNAL
:
5478 if (!m
->path
|| !m
->interface
|| !m
->member
)
5481 if (m
->reply_cookie
!= 0)
5486 case SD_BUS_MESSAGE_METHOD_CALL
:
5488 if (!m
->path
|| !m
->member
)
5491 if (m
->reply_cookie
!= 0)
5496 case SD_BUS_MESSAGE_METHOD_RETURN
:
5498 if (m
->reply_cookie
== 0)
5502 case SD_BUS_MESSAGE_METHOD_ERROR
:
5504 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5509 /* Refuse non-local messages that claim they are local */
5510 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5512 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5514 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5517 m
->root_container
.end
= m
->user_body_size
;
5519 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5520 r
= build_struct_offsets(
5522 m
->root_container
.signature
,
5524 &m
->root_container
.item_size
,
5525 &m
->root_container
.offsets
,
5526 &m
->root_container
.n_offsets
);
5531 /* Try to read the error message, but if we can't it's a non-issue */
5532 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5533 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5538 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5539 assert_return(m
, -EINVAL
);
5540 assert_return(destination
, -EINVAL
);
5541 assert_return(!m
->sealed
, -EPERM
);
5542 assert_return(!m
->destination
, -EEXIST
);
5544 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5547 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5551 struct bus_body_part
*part
;
5557 total
= BUS_MESSAGE_SIZE(m
);
5563 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5564 MESSAGE_FOREACH_PART(part
, i
, m
)
5565 e
= mempcpy(e
, part
->data
, part
->size
);
5567 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5575 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5582 r
= sd_bus_message_enter_container(m
, 'a', "s");
5586 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5587 r
= strv_extend(l
, s
);
5594 r
= sd_bus_message_exit_container(m
);
5601 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5605 assert_return(m
, -EINVAL
);
5606 assert_return(m
->sealed
, -EPERM
);
5607 assert_return(l
, -EINVAL
);
5609 r
= bus_message_read_strv_extend(m
, &strv
);
5619 static int bus_message_get_arg_skip(
5623 const char **_contents
) {
5628 r
= sd_bus_message_rewind(m
, true);
5633 const char *contents
;
5636 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5642 /* Don't match against arguments after the first one we don't understand */
5643 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5644 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5649 *_contents
= contents
;
5655 r
= sd_bus_message_skip(m
, NULL
);
5662 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5669 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5673 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5676 return sd_bus_message_read_basic(m
, type
, str
);
5679 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5680 const char *contents
;
5687 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5691 if (type
!= SD_BUS_TYPE_ARRAY
)
5693 if (!STR_IN_SET(contents
, "s", "o", "g"))
5696 return sd_bus_message_read_strv(m
, strv
);
5699 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5700 assert_return(m
, EINVAL
);
5702 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5705 return sd_bus_error_get_errno(&m
->error
);
5708 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5709 struct bus_container
*c
;
5711 assert_return(m
, NULL
);
5713 c
= complete
? &m
->root_container
: message_get_container(m
);
5714 return strempty(c
->signature
);
5717 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5718 assert_return(m
, -EINVAL
);
5720 return isempty(m
->root_container
.signature
);
5723 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5724 assert_return(m
, -EINVAL
);
5726 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5729 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5730 bool done_something
= false;
5733 assert_return(m
, -EINVAL
);
5734 assert_return(source
, -EINVAL
);
5735 assert_return(!m
->sealed
, -EPERM
);
5736 assert_return(source
->sealed
, -EPERM
);
5739 const char *contents
;
5754 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5760 done_something
= true;
5762 if (bus_type_is_container(type
) > 0) {
5764 r
= sd_bus_message_enter_container(source
, type
, contents
);
5768 r
= sd_bus_message_open_container(m
, type
, contents
);
5772 r
= sd_bus_message_copy(m
, source
, true);
5776 r
= sd_bus_message_close_container(m
);
5780 r
= sd_bus_message_exit_container(source
);
5787 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5793 if (type
== SD_BUS_TYPE_OBJECT_PATH
||
5794 type
== SD_BUS_TYPE_SIGNATURE
||
5795 type
== SD_BUS_TYPE_STRING
)
5796 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5798 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5805 return done_something
;
5808 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5813 assert_return(m
, -EINVAL
);
5814 assert_return(m
->sealed
, -EPERM
);
5815 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5816 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5817 assert_return(type
|| contents
, -EINVAL
);
5818 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5820 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5824 if (type
!= 0 && type
!= t
)
5827 if (contents
&& !streq_ptr(contents
, c
))
5833 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5834 assert_return(m
, NULL
);
5839 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5840 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
5848 switch ((*m
)->header
->type
) {
5850 case SD_BUS_MESSAGE_SIGNAL
:
5851 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5857 case SD_BUS_MESSAGE_METHOD_CALL
:
5858 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5864 case SD_BUS_MESSAGE_METHOD_RETURN
:
5865 case SD_BUS_MESSAGE_METHOD_ERROR
:
5867 n
= message_new(bus
, (*m
)->header
->type
);
5871 n
->reply_cookie
= (*m
)->reply_cookie
;
5873 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5877 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5878 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5882 n
->error
._need_free
= -1;
5891 if ((*m
)->destination
&& !n
->destination
) {
5892 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5897 if ((*m
)->sender
&& !n
->sender
) {
5898 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5903 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5905 r
= sd_bus_message_copy(n
, *m
, true);
5909 timeout
= (*m
)->timeout
;
5910 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
))
5911 timeout
= BUS_DEFAULT_TIMEOUT
;
5913 r
= bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5917 sd_bus_message_unref(*m
);
5924 int bus_message_append_sender(sd_bus_message
*m
, const char *sender
) {
5928 assert_return(!m
->sealed
, -EPERM
);
5929 assert_return(!m
->sender
, -EPERM
);
5931 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5934 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5935 assert_return(m
, -EINVAL
);
5936 assert_return(priority
, -EINVAL
);
5938 *priority
= m
->priority
;
5942 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5943 assert_return(m
, -EINVAL
);
5944 assert_return(!m
->sealed
, -EPERM
);
5946 m
->priority
= priority
;