1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "bus-gvariant.h"
29 #include "bus-internal.h"
30 #include "bus-message.h"
31 #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_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_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_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
) {
920 assert_return(m
, NULL
);
922 assert(m
->n_ref
> 0);
928 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
933 assert(m
->n_ref
> 0);
943 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
944 assert_return(m
, -EINVAL
);
945 assert_return(type
, -EINVAL
);
947 *type
= m
->header
->type
;
951 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
954 assert_return(m
, -EINVAL
);
955 assert_return(cookie
, -EINVAL
);
957 c
= BUS_MESSAGE_COOKIE(m
);
961 *cookie
= BUS_MESSAGE_COOKIE(m
);
965 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
966 assert_return(m
, -EINVAL
);
967 assert_return(cookie
, -EINVAL
);
969 if (m
->reply_cookie
== 0)
972 *cookie
= m
->reply_cookie
;
976 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
977 assert_return(m
, -EINVAL
);
979 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
980 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
983 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
984 assert_return(m
, -EINVAL
);
986 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
989 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
990 assert_return(m
, -EINVAL
);
992 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
993 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
996 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
997 assert_return(m
, NULL
);
1002 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
1003 assert_return(m
, NULL
);
1005 return m
->interface
;
1008 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
1009 assert_return(m
, NULL
);
1014 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
1015 assert_return(m
, NULL
);
1017 return m
->destination
;
1020 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
1021 assert_return(m
, NULL
);
1026 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
1027 assert_return(m
, NULL
);
1029 if (!sd_bus_error_is_set(&m
->error
))
1035 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
1036 assert_return(m
, -EINVAL
);
1037 assert_return(usec
, -EINVAL
);
1039 if (m
->monotonic
<= 0)
1042 *usec
= m
->monotonic
;
1046 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1047 assert_return(m
, -EINVAL
);
1048 assert_return(usec
, -EINVAL
);
1050 if (m
->realtime
<= 0)
1053 *usec
= m
->realtime
;
1057 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1058 assert_return(m
, -EINVAL
);
1059 assert_return(seqnum
, -EINVAL
);
1064 *seqnum
= m
->seqnum
;
1068 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1069 assert_return(m
, NULL
);
1071 if (m
->creds
.mask
== 0)
1077 _public_
int sd_bus_message_is_signal(
1079 const char *interface
,
1080 const char *member
) {
1082 assert_return(m
, -EINVAL
);
1084 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1087 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1090 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1096 _public_
int sd_bus_message_is_method_call(
1098 const char *interface
,
1099 const char *member
) {
1101 assert_return(m
, -EINVAL
);
1103 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1106 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1109 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1115 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1116 assert_return(m
, -EINVAL
);
1118 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1121 if (name
&& (!m
->error
.name
|| !streq(m
->error
.name
, name
)))
1127 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1128 assert_return(m
, -EINVAL
);
1129 assert_return(!m
->sealed
, -EPERM
);
1130 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1133 m
->header
->flags
&= ~BUS_MESSAGE_NO_REPLY_EXPECTED
;
1135 m
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
1140 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1141 assert_return(m
, -EINVAL
);
1142 assert_return(!m
->sealed
, -EPERM
);
1145 m
->header
->flags
&= ~BUS_MESSAGE_NO_AUTO_START
;
1147 m
->header
->flags
|= BUS_MESSAGE_NO_AUTO_START
;
1152 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1153 assert_return(m
, -EINVAL
);
1154 assert_return(!m
->sealed
, -EPERM
);
1157 m
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
1159 m
->header
->flags
&= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
1164 static struct bus_container
*message_get_container(sd_bus_message
*m
) {
1167 if (m
->n_containers
== 0)
1168 return &m
->root_container
;
1170 assert(m
->containers
);
1171 return m
->containers
+ m
->n_containers
- 1;
1174 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1175 struct bus_body_part
*part
;
1182 if (m
->n_body_parts
<= 0) {
1186 assert(m
->body_end
);
1188 part
= new0(struct bus_body_part
, 1);
1194 m
->body_end
->next
= part
;
1204 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1209 /* All other fields can be left in their defaults */
1210 assert(!part
->data
);
1211 assert(part
->memfd
< 0);
1214 part
->is_zero
= true;
1215 part
->sealed
= true;
1218 static int part_make_space(
1219 struct sd_bus_message
*m
,
1220 struct bus_body_part
*part
,
1229 assert(!part
->sealed
);
1234 if (!part
->data
&& part
->memfd
< 0) {
1235 part
->memfd
= bus_kernel_pop_memfd(m
->bus
, &part
->data
, &part
->mapped
, &part
->allocated
);
1236 part
->mmap_begin
= part
->data
;
1239 if (part
->memfd
>= 0) {
1241 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1242 uint64_t new_allocated
;
1244 new_allocated
= PAGE_ALIGN(sz
> 0 ? 2 * sz
: 1);
1245 r
= memfd_set_size(part
->memfd
, new_allocated
);
1251 part
->allocated
= new_allocated
;
1254 if (!part
->data
|| sz
> part
->mapped
) {
1257 psz
= PAGE_ALIGN(sz
> 0 ? sz
: 1);
1258 if (part
->mapped
<= 0)
1259 n
= mmap(NULL
, psz
, PROT_READ
|PROT_WRITE
, MAP_SHARED
, part
->memfd
, 0);
1261 n
= mremap(part
->mmap_begin
, part
->mapped
, psz
, MREMAP_MAYMOVE
);
1263 if (n
== MAP_FAILED
) {
1268 part
->mmap_begin
= part
->data
= n
;
1270 part
->memfd_offset
= 0;
1273 part
->munmap_this
= true;
1275 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1276 size_t new_allocated
;
1278 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1279 n
= realloc(part
->data
, new_allocated
);
1286 part
->allocated
= new_allocated
;
1287 part
->free_this
= true;
1292 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1298 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1299 struct bus_container
*c
;
1302 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1304 /* Add offset to current container, unless this is the first
1305 * item in it, which will have the 0 offset, which we can
1307 c
= message_get_container(m
);
1309 if (!c
->need_offsets
)
1312 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1315 c
->offsets
[c
->n_offsets
++] = offset
;
1319 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1320 struct bus_container
*c
;
1327 /* Update counters */
1328 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++) {
1331 *c
->array_size
+= expand
;
1335 static void *message_extend_body(
1340 bool force_inline
) {
1342 size_t start_body
, end_body
, padding
, added
;
1353 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1354 end_body
= start_body
+ sz
;
1356 padding
= start_body
- m
->body_size
;
1357 added
= padding
+ sz
;
1359 /* Check for 32bit overflows */
1360 if (end_body
> (size_t) ((uint32_t) -1) ||
1361 end_body
< start_body
) {
1367 struct bus_body_part
*part
= NULL
;
1371 m
->n_body_parts
<= 0 ||
1372 m
->body_end
->sealed
||
1373 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1374 (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 */
1378 part
= message_append_part(m
);
1382 part_zero(part
, padding
);
1385 part
= message_append_part(m
);
1389 r
= part_make_space(m
, part
, sz
, &p
);
1393 struct bus_container
*c
;
1395 size_t os
, start_part
, end_part
;
1401 start_part
= ALIGN_TO(part
->size
, align
);
1402 end_part
= start_part
+ sz
;
1404 r
= part_make_space(m
, part
, end_part
, &p
);
1409 memzero(p
, padding
);
1410 p
= (uint8_t*) p
+ padding
;
1413 /* Readjust pointers */
1414 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1415 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1417 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1420 /* Return something that is not NULL and is aligned */
1421 p
= (uint8_t *) NULL
+ align
;
1423 m
->body_size
= end_body
;
1424 message_extend_containers(m
, added
);
1427 r
= message_add_offset(m
, end_body
);
1437 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1448 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1452 f
= realloc(m
->fds
, sizeof(int) * (m
->n_fds
+ 1));
1460 m
->fds
[m
->n_fds
] = copy
;
1466 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1467 _cleanup_close_
int fd
= -1;
1468 struct bus_container
*c
;
1472 assert_return(m
, -EINVAL
);
1473 assert_return(!m
->sealed
, -EPERM
);
1474 assert_return(bus_type_is_basic(type
), -EINVAL
);
1475 assert_return(!m
->poisoned
, -ESTALE
);
1477 c
= message_get_container(m
);
1479 if (c
->signature
&& c
->signature
[c
->index
]) {
1480 /* Container signature is already set */
1482 if (c
->signature
[c
->index
] != type
)
1487 /* Maybe we can append to the signature? But only if this is the top-level container */
1488 if (c
->enclosing
!= 0)
1491 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1498 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1504 case SD_BUS_TYPE_SIGNATURE
:
1505 case SD_BUS_TYPE_STRING
:
1508 /* Fall through... */
1509 case SD_BUS_TYPE_OBJECT_PATH
:
1517 case SD_BUS_TYPE_BOOLEAN
:
1519 u8
= p
&& *(int*) p
;
1525 case SD_BUS_TYPE_UNIX_FD
:
1530 fd
= message_push_fd(m
, *(int*) p
);
1541 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1542 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1549 a
= message_extend_body(m
, align
, sz
, true, false);
1556 *stored
= (const uint8_t*) a
;
1563 case SD_BUS_TYPE_STRING
:
1564 /* To make things easy we'll serialize a NULL string
1565 * into the empty string */
1568 /* Fall through... */
1569 case SD_BUS_TYPE_OBJECT_PATH
:
1575 sz
= 4 + strlen(p
) + 1;
1578 case SD_BUS_TYPE_SIGNATURE
:
1583 sz
= 1 + strlen(p
) + 1;
1586 case SD_BUS_TYPE_BOOLEAN
:
1588 u32
= p
&& *(int*) p
;
1594 case SD_BUS_TYPE_UNIX_FD
:
1599 fd
= message_push_fd(m
, *(int*) p
);
1610 align
= bus_type_get_alignment(type
);
1611 sz
= bus_type_get_size(type
);
1618 a
= message_extend_body(m
, align
, sz
, false, false);
1622 if (type
== SD_BUS_TYPE_STRING
|| type
== SD_BUS_TYPE_OBJECT_PATH
) {
1623 *(uint32_t*) a
= sz
- 5;
1624 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1627 *stored
= (const uint8_t*) a
+ 4;
1629 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1630 *(uint8_t*) a
= sz
- 2;
1631 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1634 *stored
= (const uint8_t*) a
+ 1;
1643 if (type
== SD_BUS_TYPE_UNIX_FD
)
1646 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1653 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1654 return message_append_basic(m
, type
, p
, NULL
);
1657 _public_
int sd_bus_message_append_string_space(
1662 struct bus_container
*c
;
1665 assert_return(m
, -EINVAL
);
1666 assert_return(s
, -EINVAL
);
1667 assert_return(!m
->sealed
, -EPERM
);
1668 assert_return(!m
->poisoned
, -ESTALE
);
1670 c
= message_get_container(m
);
1672 if (c
->signature
&& c
->signature
[c
->index
]) {
1673 /* Container signature is already set */
1675 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1680 /* Maybe we can append to the signature? But only if this is the top-level container */
1681 if (c
->enclosing
!= 0)
1684 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1691 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1692 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1698 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1702 *(uint32_t*) a
= size
;
1708 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1714 _public_
int sd_bus_message_append_string_iovec(
1716 const struct iovec
*iov
,
1724 assert_return(m
, -EINVAL
);
1725 assert_return(!m
->sealed
, -EPERM
);
1726 assert_return(iov
|| n
== 0, -EINVAL
);
1727 assert_return(!m
->poisoned
, -ESTALE
);
1729 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1731 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1735 for (i
= 0; i
< n
; i
++) {
1737 if (iov
[i
].iov_base
)
1738 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1740 memset(p
, ' ', iov
[i
].iov_len
);
1742 p
+= iov
[i
].iov_len
;
1748 static int bus_message_open_array(
1750 struct bus_container
*c
,
1751 const char *contents
,
1752 uint32_t **array_size
,
1754 bool *need_offsets
) {
1764 assert(need_offsets
);
1766 if (!signature_is_single(contents
, true))
1769 if (c
->signature
&& c
->signature
[c
->index
]) {
1771 /* Verify the existing signature */
1773 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1776 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1779 nindex
= c
->index
+ 1 + strlen(contents
);
1783 if (c
->enclosing
!= 0)
1786 /* Extend the existing signature */
1788 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1794 nindex
= e
- c
->signature
;
1797 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1798 alignment
= bus_gvariant_get_alignment(contents
);
1802 /* Add alignment padding and add to offset list */
1803 if (!message_extend_body(m
, alignment
, 0, false, false))
1806 r
= bus_gvariant_is_fixed_size(contents
);
1810 *begin
= m
->body_size
;
1811 *need_offsets
= r
== 0;
1815 struct bus_body_part
*o
;
1817 alignment
= bus_type_get_alignment(contents
[0]);
1821 a
= message_extend_body(m
, 4, 4, false, false);
1826 op
= m
->body_end
->data
;
1827 os
= m
->body_end
->size
;
1829 /* Add alignment between size and first element */
1830 if (!message_extend_body(m
, alignment
, 0, false, false))
1833 /* location of array size might have changed so let's readjust a */
1834 if (o
== m
->body_end
)
1835 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1841 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1847 static int bus_message_open_variant(
1849 struct bus_container
*c
,
1850 const char *contents
) {
1856 if (!signature_is_single(contents
, false))
1859 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1862 if (c
->signature
&& c
->signature
[c
->index
]) {
1864 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1870 if (c
->enclosing
!= 0)
1873 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1880 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1881 /* Variants are always aligned to 8 */
1883 if (!message_extend_body(m
, 8, 0, false, false))
1890 l
= strlen(contents
);
1891 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1896 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1899 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1905 static int bus_message_open_struct(
1907 struct bus_container
*c
,
1908 const char *contents
,
1910 bool *need_offsets
) {
1919 assert(need_offsets
);
1921 if (!signature_is_valid(contents
, false))
1924 if (c
->signature
&& c
->signature
[c
->index
]) {
1927 l
= strlen(contents
);
1929 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1930 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1931 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1934 nindex
= c
->index
+ 1 + l
+ 1;
1938 if (c
->enclosing
!= 0)
1941 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1947 nindex
= e
- c
->signature
;
1950 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1953 alignment
= bus_gvariant_get_alignment(contents
);
1957 if (!message_extend_body(m
, alignment
, 0, false, false))
1960 r
= bus_gvariant_is_fixed_size(contents
);
1964 *begin
= m
->body_size
;
1965 *need_offsets
= r
== 0;
1967 /* Align contents to 8 byte boundary */
1968 if (!message_extend_body(m
, 8, 0, false, false))
1972 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1978 static int bus_message_open_dict_entry(
1980 struct bus_container
*c
,
1981 const char *contents
,
1983 bool *need_offsets
) {
1991 assert(need_offsets
);
1993 if (!signature_is_pair(contents
))
1996 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1999 if (c
->signature
&& c
->signature
[c
->index
]) {
2002 l
= strlen(contents
);
2004 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
2005 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
2006 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
2011 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2014 alignment
= bus_gvariant_get_alignment(contents
);
2018 if (!message_extend_body(m
, alignment
, 0, false, false))
2021 r
= bus_gvariant_is_fixed_size(contents
);
2025 *begin
= m
->body_size
;
2026 *need_offsets
= r
== 0;
2028 /* Align contents to 8 byte boundary */
2029 if (!message_extend_body(m
, 8, 0, false, false))
2036 _public_
int sd_bus_message_open_container(
2039 const char *contents
) {
2041 struct bus_container
*c
, *w
;
2042 uint32_t *array_size
= NULL
;
2044 size_t before
, begin
= 0;
2045 bool need_offsets
= false;
2048 assert_return(m
, -EINVAL
);
2049 assert_return(!m
->sealed
, -EPERM
);
2050 assert_return(contents
, -EINVAL
);
2051 assert_return(!m
->poisoned
, -ESTALE
);
2053 /* Make sure we have space for one more container */
2054 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
2059 c
= message_get_container(m
);
2061 signature
= strdup(contents
);
2067 /* Save old index in the parent container, in case we have to
2068 * abort this container */
2069 c
->saved_index
= c
->index
;
2070 before
= m
->body_size
;
2072 if (type
== SD_BUS_TYPE_ARRAY
)
2073 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
2074 else if (type
== SD_BUS_TYPE_VARIANT
)
2075 r
= bus_message_open_variant(m
, c
, contents
);
2076 else if (type
== SD_BUS_TYPE_STRUCT
)
2077 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
2078 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
2079 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
2088 /* OK, let's fill it in */
2089 w
= m
->containers
+ m
->n_containers
++;
2090 w
->enclosing
= type
;
2091 w
->signature
= signature
;
2093 w
->array_size
= array_size
;
2096 w
->n_offsets
= w
->offsets_allocated
= 0;
2098 w
->need_offsets
= need_offsets
;
2103 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2108 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2111 if (c
->need_offsets
) {
2112 size_t payload
, sz
, i
;
2115 /* Variable-width arrays */
2117 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2118 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2120 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2124 for (i
= 0; i
< c
->n_offsets
; i
++)
2125 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2129 /* Fixed-width or empty arrays */
2131 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2139 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2145 assert(c
->signature
);
2147 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2150 l
= strlen(c
->signature
);
2152 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2157 memcpy(a
+1, c
->signature
, l
);
2162 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2163 bool fixed_size
= true;
2164 size_t n_variable
= 0;
2173 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2176 p
= strempty(c
->signature
);
2180 r
= signature_element_length(p
, &n
);
2189 r
= bus_gvariant_is_fixed_size(t
);
2194 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2196 /* We need to add an offset for each item that has a
2197 * variable size and that is not the last one in the
2201 if (r
== 0 && p
[n
] != 0)
2208 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2209 assert(c
->need_offsets
|| n_variable
== 0);
2211 if (isempty(c
->signature
)) {
2212 /* The unary type is encoded as fixed 1 byte padding */
2213 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2218 } else if (n_variable
<= 0) {
2221 /* Structures with fixed-size members only have to be
2222 * fixed-size themselves. But gvariant requires all fixed-size
2223 * elements to be sized a multiple of their alignment. Hence,
2224 * we must *always* add final padding after the last member so
2225 * the overall size of the structure is properly aligned. */
2227 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2229 assert(alignment
> 0);
2231 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2238 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2240 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2242 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2246 p
= strempty(c
->signature
);
2247 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2251 r
= signature_element_length(p
, &n
);
2262 r
= bus_gvariant_is_fixed_size(t
);
2265 if (r
> 0 || p
[0] == 0)
2269 k
= n_variable
- 1 - j
;
2271 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2280 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2281 struct bus_container
*c
;
2284 assert_return(m
, -EINVAL
);
2285 assert_return(!m
->sealed
, -EPERM
);
2286 assert_return(m
->n_containers
> 0, -EINVAL
);
2287 assert_return(!m
->poisoned
, -ESTALE
);
2289 c
= message_get_container(m
);
2291 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2292 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2297 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2298 r
= bus_message_close_array(m
, c
);
2299 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2300 r
= bus_message_close_variant(m
, c
);
2301 else if (c
->enclosing
== SD_BUS_TYPE_STRUCT
|| c
->enclosing
== SD_BUS_TYPE_DICT_ENTRY
)
2302 r
= bus_message_close_struct(m
, c
, true);
2304 assert_not_reached("Unknown container type");
2318 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2325 stack
[*i
].types
= types
;
2326 stack
[*i
].n_struct
= n_struct
;
2327 stack
[*i
].n_array
= n_array
;
2333 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2344 *types
= stack
[*i
].types
;
2345 *n_struct
= stack
[*i
].n_struct
;
2346 *n_array
= stack
[*i
].n_array
;
2351 int bus_message_append_ap(
2356 unsigned n_array
, n_struct
;
2357 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2358 unsigned stack_ptr
= 0;
2366 n_array
= (unsigned) -1;
2367 n_struct
= strlen(types
);
2372 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2373 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2379 r
= sd_bus_message_close_container(m
);
2387 if (n_array
!= (unsigned) -1)
2396 case SD_BUS_TYPE_BYTE
: {
2399 x
= (uint8_t) va_arg(ap
, int);
2400 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2404 case SD_BUS_TYPE_BOOLEAN
:
2405 case SD_BUS_TYPE_INT32
:
2406 case SD_BUS_TYPE_UINT32
:
2407 case SD_BUS_TYPE_UNIX_FD
: {
2410 /* We assume a boolean is the same as int32_t */
2411 assert_cc(sizeof(int32_t) == sizeof(int));
2413 x
= va_arg(ap
, uint32_t);
2414 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2418 case SD_BUS_TYPE_INT16
:
2419 case SD_BUS_TYPE_UINT16
: {
2422 x
= (uint16_t) va_arg(ap
, int);
2423 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2427 case SD_BUS_TYPE_INT64
:
2428 case SD_BUS_TYPE_UINT64
: {
2431 x
= va_arg(ap
, uint64_t);
2432 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2436 case SD_BUS_TYPE_DOUBLE
: {
2439 x
= va_arg(ap
, double);
2440 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2444 case SD_BUS_TYPE_STRING
:
2445 case SD_BUS_TYPE_OBJECT_PATH
:
2446 case SD_BUS_TYPE_SIGNATURE
: {
2449 x
= va_arg(ap
, const char*);
2450 r
= sd_bus_message_append_basic(m
, *t
, x
);
2454 case SD_BUS_TYPE_ARRAY
: {
2457 r
= signature_element_length(t
+ 1, &k
);
2463 memcpy(s
, t
+ 1, k
);
2466 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2471 if (n_array
== (unsigned) -1) {
2476 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2482 n_array
= va_arg(ap
, unsigned);
2487 case SD_BUS_TYPE_VARIANT
: {
2490 s
= va_arg(ap
, const char*);
2494 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2498 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2503 n_struct
= strlen(s
);
2504 n_array
= (unsigned) -1;
2509 case SD_BUS_TYPE_STRUCT_BEGIN
:
2510 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2513 r
= signature_element_length(t
, &k
);
2520 memcpy(s
, t
+ 1, k
- 2);
2523 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2528 if (n_array
== (unsigned) -1) {
2533 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2539 n_array
= (unsigned) -1;
2555 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2559 assert_return(m
, -EINVAL
);
2560 assert_return(types
, -EINVAL
);
2561 assert_return(!m
->sealed
, -EPERM
);
2562 assert_return(!m
->poisoned
, -ESTALE
);
2564 va_start(ap
, types
);
2565 r
= bus_message_append_ap(m
, types
, ap
);
2571 _public_
int sd_bus_message_append_array_space(
2581 assert_return(m
, -EINVAL
);
2582 assert_return(!m
->sealed
, -EPERM
);
2583 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2584 assert_return(ptr
|| size
== 0, -EINVAL
);
2585 assert_return(!m
->poisoned
, -ESTALE
);
2587 /* alignment and size of the trivial types (except bool) is
2588 * identical for gvariant and dbus1 marshalling */
2589 align
= bus_type_get_alignment(type
);
2590 sz
= bus_type_get_size(type
);
2592 assert_se(align
> 0);
2598 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2602 a
= message_extend_body(m
, align
, size
, false, false);
2606 r
= sd_bus_message_close_container(m
);
2614 _public_
int sd_bus_message_append_array(
2622 assert_return(m
, -EINVAL
);
2623 assert_return(!m
->sealed
, -EPERM
);
2624 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2625 assert_return(ptr
|| size
== 0, -EINVAL
);
2626 assert_return(!m
->poisoned
, -ESTALE
);
2628 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2633 memcpy(p
, ptr
, size
);
2638 _public_
int sd_bus_message_append_array_iovec(
2641 const struct iovec
*iov
,
2649 assert_return(m
, -EINVAL
);
2650 assert_return(!m
->sealed
, -EPERM
);
2651 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2652 assert_return(iov
|| n
== 0, -EINVAL
);
2653 assert_return(!m
->poisoned
, -ESTALE
);
2655 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2657 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2661 for (i
= 0; i
< n
; i
++) {
2663 if (iov
[i
].iov_base
)
2664 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2666 memzero(p
, iov
[i
].iov_len
);
2668 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2674 _public_
int sd_bus_message_append_array_memfd(
2681 _cleanup_close_
int copy_fd
= -1;
2682 struct bus_body_part
*part
;
2688 assert_return(m
, -EINVAL
);
2689 assert_return(memfd
>= 0, -EBADF
);
2690 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2691 assert_return(size
> 0, -EINVAL
);
2692 assert_return(!m
->sealed
, -EPERM
);
2693 assert_return(!m
->poisoned
, -ESTALE
);
2695 r
= memfd_set_sealed(memfd
);
2699 copy_fd
= dup(memfd
);
2703 r
= memfd_get_size(memfd
, &real_size
);
2707 if (offset
== 0 && size
== (uint64_t) -1)
2709 else if (offset
+ size
> real_size
)
2712 align
= bus_type_get_alignment(type
);
2713 sz
= bus_type_get_size(type
);
2715 assert_se(align
> 0);
2718 if (offset
% align
!= 0)
2724 if (size
> (uint64_t) (uint32_t) -1)
2727 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2731 a
= message_extend_body(m
, align
, 0, false, false);
2735 part
= message_append_part(m
);
2739 part
->memfd
= copy_fd
;
2740 part
->memfd_offset
= offset
;
2741 part
->sealed
= true;
2745 m
->body_size
+= size
;
2746 message_extend_containers(m
, size
);
2748 return sd_bus_message_close_container(m
);
2751 _public_
int sd_bus_message_append_string_memfd(
2757 _cleanup_close_
int copy_fd
= -1;
2758 struct bus_body_part
*part
;
2759 struct bus_container
*c
;
2764 assert_return(m
, -EINVAL
);
2765 assert_return(memfd
>= 0, -EBADF
);
2766 assert_return(size
> 0, -EINVAL
);
2767 assert_return(!m
->sealed
, -EPERM
);
2768 assert_return(!m
->poisoned
, -ESTALE
);
2770 r
= memfd_set_sealed(memfd
);
2774 copy_fd
= dup(memfd
);
2778 r
= memfd_get_size(memfd
, &real_size
);
2782 if (offset
== 0 && size
== (uint64_t) -1)
2784 else if (offset
+ size
> real_size
)
2787 /* We require this to be NUL terminated */
2791 if (size
> (uint64_t) (uint32_t) -1)
2794 c
= message_get_container(m
);
2795 if (c
->signature
&& c
->signature
[c
->index
]) {
2796 /* Container signature is already set */
2798 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2803 /* Maybe we can append to the signature? But only if this is the top-level container */
2804 if (c
->enclosing
!= 0)
2807 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2814 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2815 a
= message_extend_body(m
, 4, 4, false, false);
2819 *(uint32_t*) a
= size
- 1;
2822 part
= message_append_part(m
);
2826 part
->memfd
= copy_fd
;
2827 part
->memfd_offset
= offset
;
2828 part
->sealed
= true;
2832 m
->body_size
+= size
;
2833 message_extend_containers(m
, size
);
2835 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2836 r
= message_add_offset(m
, m
->body_size
);
2843 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2849 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2853 assert_return(m
, -EINVAL
);
2854 assert_return(!m
->sealed
, -EPERM
);
2855 assert_return(!m
->poisoned
, -ESTALE
);
2857 r
= sd_bus_message_open_container(m
, 'a', "s");
2861 STRV_FOREACH(i
, l
) {
2862 r
= sd_bus_message_append_basic(m
, 's', *i
);
2867 return sd_bus_message_close_container(m
);
2870 static int bus_message_close_header(sd_bus_message
*m
) {
2874 /* The actual user data is finished now, we just complete the
2875 variant and struct now (at least on gvariant). Remember
2876 this position, so that during parsing we know where to to
2877 put the outer container end. */
2878 m
->user_body_size
= m
->body_size
;
2880 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2881 const char *signature
;
2885 /* Add offset table to end of fields array */
2886 if (m
->n_header_offsets
>= 1) {
2890 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2892 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2893 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2897 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2898 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2901 /* Add gvariant NUL byte plus signature to the end of
2902 * the body, followed by the final offset pointing to
2903 * the end of the fields array */
2905 signature
= strempty(m
->root_container
.signature
);
2906 l
= strlen(signature
);
2908 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2909 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2914 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2915 memcpy((uint8_t*) d
+ 2, signature
, l
);
2916 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2918 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2921 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2923 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2924 m
->header
->dbus1
.body_size
= m
->body_size
;
2930 int bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, usec_t timeout
) {
2931 struct bus_body_part
*part
;
2941 if (m
->n_containers
> 0)
2947 if (cookie
> 0xffffffffULL
&&
2948 !BUS_MESSAGE_IS_GVARIANT(m
))
2951 /* In vtables the return signature of method calls is listed,
2952 * let's check if they match if this is a response */
2953 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2954 m
->enforced_reply_signature
&&
2955 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2958 /* If gvariant marshalling is used we need to close the body structure */
2959 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2963 /* If there's a non-trivial signature set, then add it in
2964 * here, but only on dbus1 */
2965 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2966 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2972 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2977 r
= bus_message_close_header(m
);
2981 if (BUS_MESSAGE_IS_GVARIANT(m
))
2982 m
->header
->dbus2
.cookie
= cookie
;
2984 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2986 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout
;
2988 /* Add padding at the end of the fields part, since we know
2989 * the body needs to start at an 8 byte alignment. We made
2990 * sure we allocated enough space for this, so all we need to
2991 * do here is to zero it out. */
2992 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2994 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2996 /* If this is something we can send as memfd, then let's seal
2997 the memfd now. Note that we can send memfds as payload only
2998 for directed messages, and not for broadcasts. */
2999 if (m
->destination
&& m
->bus
->use_memfd
) {
3000 MESSAGE_FOREACH_PART(part
, i
, m
)
3001 if (part
->memfd
>= 0 &&
3003 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
3004 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
3007 /* Try to seal it if that makes
3008 * sense. First, unmap our own map to
3009 * make sure we don't keep it busy. */
3010 bus_body_part_unmap(part
);
3012 /* Then, sync up real memfd size */
3014 r
= memfd_set_size(part
->memfd
, sz
);
3018 /* Finally, try to seal */
3019 if (memfd_set_sealed(part
->memfd
) >= 0)
3020 part
->sealed
= true;
3024 m
->root_container
.end
= m
->user_body_size
;
3025 m
->root_container
.index
= 0;
3026 m
->root_container
.offset_index
= 0;
3027 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
3034 int bus_body_part_map(struct bus_body_part
*part
) {
3043 if (part
->size
<= 0)
3046 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3047 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
3048 static const uint8_t zeroes
[7] = { };
3049 part
->data
= (void*) zeroes
;
3053 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
3054 psz
= PAGE_ALIGN(part
->size
+ shift
);
3056 if (part
->memfd
>= 0)
3057 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
3058 else if (part
->is_zero
)
3059 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
3063 if (p
== MAP_FAILED
)
3067 part
->mmap_begin
= p
;
3068 part
->data
= (uint8_t*) p
+ shift
;
3069 part
->munmap_this
= true;
3074 void bus_body_part_unmap(struct bus_body_part
*part
) {
3078 if (part
->memfd
< 0)
3081 if (!part
->mmap_begin
)
3084 if (!part
->munmap_this
)
3087 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
3089 part
->mmap_begin
= NULL
;
3092 part
->munmap_this
= false;
3097 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3098 size_t k
, start
, end
;
3103 start
= ALIGN_TO((size_t) *rindex
, align
);
3104 end
= start
+ nbytes
;
3109 /* Verify that padding is 0 */
3110 for (k
= *rindex
; k
< start
; k
++)
3111 if (((const uint8_t*) p
)[k
] != 0)
3115 *r
= (uint8_t*) p
+ start
;
3122 static bool message_end_of_signature(sd_bus_message
*m
) {
3123 struct bus_container
*c
;
3127 c
= message_get_container(m
);
3128 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3131 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3132 struct bus_container
*c
;
3136 c
= message_get_container(m
);
3137 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3140 if (BUS_MESSAGE_IS_GVARIANT(m
))
3141 return index
>= c
->end
;
3143 assert(c
->array_size
);
3144 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3148 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3149 assert_return(m
, -EINVAL
);
3150 assert_return(m
->sealed
, -EPERM
);
3152 if (complete
&& m
->n_containers
> 0)
3155 if (message_end_of_signature(m
))
3158 if (message_end_of_array(m
, m
->rindex
))
3164 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3165 struct bus_body_part
*part
;
3171 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3172 part
= m
->cached_rindex_part
;
3173 begin
= m
->cached_rindex_part_begin
;
3183 if (index
+ sz
<= begin
+ part
->size
) {
3185 r
= bus_body_part_map(part
);
3190 *p
= (uint8_t*) part
->data
+ index
- begin
;
3192 m
->cached_rindex_part
= part
;
3193 m
->cached_rindex_part_begin
= begin
;
3198 begin
+= part
->size
;
3205 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3212 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3215 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3218 sz
= bus_gvariant_get_size(c
->signature
);
3222 if (c
->offset_index
+1 >= c
->n_offsets
)
3225 /* Variable-size array */
3227 alignment
= bus_gvariant_get_alignment(c
->signature
);
3228 assert(alignment
> 0);
3230 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3231 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3234 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3237 /* Fixed-size array */
3238 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3244 } else if (c
->enclosing
== 0 ||
3245 c
->enclosing
== SD_BUS_TYPE_STRUCT
||
3246 c
->enclosing
== SD_BUS_TYPE_DICT_ENTRY
) {
3251 if (c
->offset_index
+1 >= c
->n_offsets
)
3254 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3258 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3263 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3266 alignment
= bus_gvariant_get_alignment(t
);
3269 assert(alignment
> 0);
3271 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3272 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3276 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3279 assert_not_reached("Unknown container type");
3284 /* Reached the end */
3291 static int message_peek_body(
3298 size_t k
, start
, end
, padding
;
3299 struct bus_body_part
*part
;
3306 start
= ALIGN_TO((size_t) *rindex
, align
);
3307 padding
= start
- *rindex
;
3308 end
= start
+ nbytes
;
3310 if (end
> m
->user_body_size
)
3313 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3318 /* Verify padding */
3319 for (k
= 0; k
< padding
; k
++)
3324 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3325 if (!part
|| (nbytes
> 0 && !q
))
3336 static bool validate_nul(const char *s
, size_t l
) {
3338 /* Check for NUL chars in the string */
3339 if (memchr(s
, 0, l
))
3342 /* Check for NUL termination */
3349 static bool validate_string(const char *s
, size_t l
) {
3351 if (!validate_nul(s
, l
))
3354 /* Check if valid UTF8 */
3355 if (!utf8_is_valid(s
))
3361 static bool validate_signature(const char *s
, size_t l
) {
3363 if (!validate_nul(s
, l
))
3366 /* Check if valid signature */
3367 if (!signature_is_valid(s
, true))
3373 static bool validate_object_path(const char *s
, size_t l
) {
3375 if (!validate_nul(s
, l
))
3378 if (!object_path_is_valid(s
))
3384 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3385 struct bus_container
*c
;
3390 assert_return(m
, -EINVAL
);
3391 assert_return(m
->sealed
, -EPERM
);
3392 assert_return(bus_type_is_basic(type
), -EINVAL
);
3394 if (message_end_of_signature(m
))
3397 if (message_end_of_array(m
, m
->rindex
))
3400 c
= message_get_container(m
);
3401 if (c
->signature
[c
->index
] != type
)
3406 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3408 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3411 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3415 if (type
== SD_BUS_TYPE_STRING
)
3416 ok
= validate_string(q
, c
->item_size
-1);
3417 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3418 ok
= validate_object_path(q
, c
->item_size
-1);
3420 ok
= validate_signature(q
, c
->item_size
-1);
3426 *(const char**) p
= q
;
3430 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3432 if ((size_t) sz
!= c
->item_size
)
3435 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3438 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3444 case SD_BUS_TYPE_BYTE
:
3446 *(uint8_t*) p
= *(uint8_t*) q
;
3449 case SD_BUS_TYPE_BOOLEAN
:
3451 *(int*) p
= !!*(uint8_t*) q
;
3454 case SD_BUS_TYPE_INT16
:
3455 case SD_BUS_TYPE_UINT16
:
3457 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3460 case SD_BUS_TYPE_INT32
:
3461 case SD_BUS_TYPE_UINT32
:
3463 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3466 case SD_BUS_TYPE_INT64
:
3467 case SD_BUS_TYPE_UINT64
:
3468 case SD_BUS_TYPE_DOUBLE
:
3470 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3473 case SD_BUS_TYPE_UNIX_FD
: {
3476 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3481 *(int*) p
= m
->fds
[j
];
3487 assert_not_reached("unexpected type");
3491 r
= container_next_item(m
, c
, &rindex
);
3496 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3500 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3504 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3505 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3509 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3510 ok
= validate_object_path(q
, l
);
3512 ok
= validate_string(q
, l
);
3517 *(const char**) p
= q
;
3519 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3522 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3527 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3531 if (!validate_signature(q
, l
))
3535 *(const char**) p
= q
;
3540 align
= bus_type_get_alignment(type
);
3543 sz
= bus_type_get_size(type
);
3546 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3552 case SD_BUS_TYPE_BYTE
:
3554 *(uint8_t*) p
= *(uint8_t*) q
;
3557 case SD_BUS_TYPE_BOOLEAN
:
3559 *(int*) p
= !!*(uint32_t*) q
;
3562 case SD_BUS_TYPE_INT16
:
3563 case SD_BUS_TYPE_UINT16
:
3565 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3568 case SD_BUS_TYPE_INT32
:
3569 case SD_BUS_TYPE_UINT32
:
3571 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3574 case SD_BUS_TYPE_INT64
:
3575 case SD_BUS_TYPE_UINT64
:
3576 case SD_BUS_TYPE_DOUBLE
:
3578 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3581 case SD_BUS_TYPE_UNIX_FD
: {
3584 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3589 *(int*) p
= m
->fds
[j
];
3594 assert_not_reached("Unknown basic type...");
3601 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3607 static int bus_message_enter_array(
3609 struct bus_container
*c
,
3610 const char *contents
,
3611 uint32_t **array_size
,
3614 size_t *n_offsets
) {
3628 if (!signature_is_single(contents
, true))
3631 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3634 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3637 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3642 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3645 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3649 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3652 alignment
= bus_type_get_alignment(contents
[0]);
3656 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3660 *array_size
= (uint32_t*) q
;
3662 } else if (c
->item_size
<= 0) {
3664 /* gvariant: empty array */
3669 } else if (bus_gvariant_is_fixed_size(contents
)) {
3671 /* gvariant: fixed length array */
3672 *item_size
= bus_gvariant_get_size(contents
);
3677 size_t where
, p
= 0, framing
, sz
;
3680 /* gvariant: variable length array */
3681 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3683 where
= rindex
+ c
->item_size
- sz
;
3684 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3688 framing
= bus_gvariant_read_word_le(q
, sz
);
3689 if (framing
> c
->item_size
- sz
)
3691 if ((c
->item_size
- framing
) % sz
!= 0)
3694 *n_offsets
= (c
->item_size
- framing
) / sz
;
3696 where
= rindex
+ framing
;
3697 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3701 *offsets
= new(size_t, *n_offsets
);
3705 for (i
= 0; i
< *n_offsets
; i
++) {
3708 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3709 if (x
> c
->item_size
- sz
)
3714 (*offsets
)[i
] = rindex
+ x
;
3718 *item_size
= (*offsets
)[0] - rindex
;
3723 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3724 c
->index
+= 1 + strlen(contents
);
3729 static int bus_message_enter_variant(
3731 struct bus_container
*c
,
3732 const char *contents
,
3733 size_t *item_size
) {
3745 if (!signature_is_single(contents
, false))
3748 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3751 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3754 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3759 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3762 k
= strlen(contents
);
3763 if (1+k
> c
->item_size
)
3766 where
= rindex
+ c
->item_size
- (1+k
);
3767 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3771 if (*(char*) q
!= 0)
3774 if (memcmp((uint8_t*) q
+1, contents
, k
))
3777 *item_size
= c
->item_size
- (1+k
);
3780 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3785 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3789 if (!validate_signature(q
, l
))
3792 if (!streq(q
, contents
))
3798 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3804 static int build_struct_offsets(
3806 const char *signature
,
3810 size_t *n_offsets
) {
3812 unsigned n_variable
= 0, n_total
= 0, v
;
3813 size_t previous
= 0, where
;
3824 if (isempty(signature
)) {
3825 /* Unary type is encoded as *fixed* 1 byte padding */
3826 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3830 if (*(uint8_t *) q
!= 0)
3839 sz
= bus_gvariant_determine_word_size(size
, 0);
3843 /* First, loop over signature and count variable elements and
3844 * elements in general. We use this to know how large the
3845 * offset array is at the end of the structure. Note that
3846 * GVariant only stores offsets for all variable size elements
3847 * that are not the last item. */
3853 r
= signature_element_length(p
, &n
);
3862 r
= bus_gvariant_is_fixed_size(t
);
3867 if (r
== 0 && p
[n
] != 0) /* except the last item */
3874 if (size
< n_variable
* sz
)
3877 where
= m
->rindex
+ size
- (n_variable
* sz
);
3878 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3884 *offsets
= new(size_t, n_total
);
3890 /* Second, loop again and build an offset table */
3896 r
= signature_element_length(p
, &n
);
3905 k
= bus_gvariant_get_size(t
);
3913 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3916 if (m
->rindex
+ x
< previous
)
3919 /* The last item's end
3920 * is determined from
3923 x
= size
- (n_variable
* sz
);
3925 offset
= m
->rindex
+ x
;
3931 align
= bus_gvariant_get_alignment(t
);
3934 offset
= (*n_offsets
== 0 ? m
->rindex
: ALIGN_TO((*offsets
)[*n_offsets
-1], align
)) + k
;
3938 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3943 assert(*n_offsets
== n_total
);
3945 *item_size
= (*offsets
)[0] - m
->rindex
;
3949 static int enter_struct_or_dict_entry(
3951 struct bus_container
*c
,
3952 const char *contents
,
3955 size_t *n_offsets
) {
3966 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3969 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3974 /* gvariant with contents */
3975 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3980 static int bus_message_enter_struct(
3982 struct bus_container
*c
,
3983 const char *contents
,
3986 size_t *n_offsets
) {
3998 if (!signature_is_valid(contents
, false))
4001 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4004 l
= strlen(contents
);
4006 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
4007 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4008 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
4011 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4015 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4016 c
->index
+= 1 + l
+ 1;
4021 static int bus_message_enter_dict_entry(
4023 struct bus_container
*c
,
4024 const char *contents
,
4027 size_t *n_offsets
) {
4036 if (!signature_is_pair(contents
))
4039 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4042 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4045 l
= strlen(contents
);
4047 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
4048 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4049 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
4052 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4056 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4057 c
->index
+= 1 + l
+ 1;
4062 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
4064 const char *contents
) {
4065 struct bus_container
*c
, *w
;
4066 uint32_t *array_size
= NULL
;
4069 size_t *offsets
= NULL
;
4070 size_t n_offsets
= 0, item_size
= 0;
4073 assert_return(m
, -EINVAL
);
4074 assert_return(m
->sealed
, -EPERM
);
4075 assert_return(type
!= 0 || !contents
, -EINVAL
);
4077 if (type
== 0 || !contents
) {
4081 /* Allow entering into anonymous containers */
4082 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
4086 if (type
!= 0 && type
!= tt
)
4089 if (contents
&& !streq(contents
, cc
))
4097 * We enforce a global limit on container depth, that is much
4098 * higher than the 32 structs and 32 arrays the specification
4099 * mandates. This is simpler to implement for us, and we need
4100 * this only to ensure our container array doesn't grow
4101 * without bounds. We are happy to return any data from a
4102 * message as long as the data itself is valid, even if the
4103 * overall message might be not.
4105 * Note that the message signature is validated when
4106 * parsing the headers, and that validation does check the
4109 * Note that the specification defines no limits on the depth
4110 * of stacked variants, but we do.
4112 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4115 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4118 if (message_end_of_signature(m
))
4121 if (message_end_of_array(m
, m
->rindex
))
4124 c
= message_get_container(m
);
4126 signature
= strdup(contents
);
4130 c
->saved_index
= c
->index
;
4133 if (type
== SD_BUS_TYPE_ARRAY
)
4134 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4135 else if (type
== SD_BUS_TYPE_VARIANT
)
4136 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4137 else if (type
== SD_BUS_TYPE_STRUCT
)
4138 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4139 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4140 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4150 /* OK, let's fill it in */
4151 w
= m
->containers
+ m
->n_containers
++;
4152 w
->enclosing
= type
;
4153 w
->signature
= signature
;
4154 w
->peeked_signature
= NULL
;
4158 w
->begin
= m
->rindex
;
4160 /* Unary type has fixed size of 1, but virtual size of 0 */
4161 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4162 type
== SD_BUS_TYPE_STRUCT
&&
4164 w
->end
= m
->rindex
+ 0;
4166 w
->end
= m
->rindex
+ c
->item_size
;
4168 w
->array_size
= array_size
;
4169 w
->item_size
= item_size
;
4170 w
->offsets
= offsets
;
4171 w
->n_offsets
= n_offsets
;
4172 w
->offset_index
= 0;
4177 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4178 struct bus_container
*c
;
4182 assert_return(m
, -EINVAL
);
4183 assert_return(m
->sealed
, -EPERM
);
4184 assert_return(m
->n_containers
> 0, -ENXIO
);
4186 c
= message_get_container(m
);
4188 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4189 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4193 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4194 if (m
->rindex
< c
->end
)
4197 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4200 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4201 if (c
->begin
+ l
!= m
->rindex
)
4206 free(c
->peeked_signature
);
4210 c
= message_get_container(m
);
4213 c
->index
= c
->saved_index
;
4214 r
= container_next_item(m
, c
, &m
->rindex
);
4222 static void message_quit_container(sd_bus_message
*m
) {
4223 struct bus_container
*c
;
4227 assert(m
->n_containers
> 0);
4229 c
= message_get_container(m
);
4232 assert(m
->rindex
>= c
->before
);
4233 m
->rindex
= c
->before
;
4235 /* Free container */
4240 /* Correct index of new top-level container */
4241 c
= message_get_container(m
);
4242 c
->index
= c
->saved_index
;
4245 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4246 struct bus_container
*c
;
4249 assert_return(m
, -EINVAL
);
4250 assert_return(m
->sealed
, -EPERM
);
4252 if (message_end_of_signature(m
))
4255 if (message_end_of_array(m
, m
->rindex
))
4258 c
= message_get_container(m
);
4260 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4264 *type
= c
->signature
[c
->index
];
4268 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4274 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4280 sig
= strndup(c
->signature
+ c
->index
+ 1, l
);
4284 free(c
->peeked_signature
);
4285 *contents
= c
->peeked_signature
= sig
;
4289 *type
= SD_BUS_TYPE_ARRAY
;
4294 if (c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
||
4295 c
->signature
[c
->index
] == SD_BUS_TYPE_DICT_ENTRY_BEGIN
) {
4301 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4306 sig
= strndup(c
->signature
+ c
->index
+ 1, l
- 2);
4310 free(c
->peeked_signature
);
4311 *contents
= c
->peeked_signature
= sig
;
4315 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4320 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4324 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4327 if (c
->item_size
< 2)
4330 /* Look for the NUL delimiter that
4331 separates the payload from the
4332 signature. Since the body might be
4333 in a different part that then the
4334 signature we map byte by byte. */
4336 for (k
= 2; k
<= c
->item_size
; k
++) {
4339 where
= m
->rindex
+ c
->item_size
- k
;
4340 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4344 if (*(char*) q
== 0)
4348 if (k
> c
->item_size
)
4351 free(c
->peeked_signature
);
4352 c
->peeked_signature
= strndup((char*) q
+ 1, k
- 1);
4353 if (!c
->peeked_signature
)
4356 if (!signature_is_valid(c
->peeked_signature
, true))
4359 *contents
= c
->peeked_signature
;
4364 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4369 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4373 if (!validate_signature(q
, l
))
4381 *type
= SD_BUS_TYPE_VARIANT
;
4396 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4397 struct bus_container
*c
;
4399 assert_return(m
, -EINVAL
);
4400 assert_return(m
->sealed
, -EPERM
);
4403 message_reset_containers(m
);
4406 c
= message_get_container(m
);
4408 c
= message_get_container(m
);
4410 c
->offset_index
= 0;
4412 m
->rindex
= c
->begin
;
4415 c
->offset_index
= 0;
4416 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4418 return !isempty(c
->signature
);
4421 static int message_read_ap(
4426 unsigned n_array
, n_struct
;
4427 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4428 unsigned stack_ptr
= 0;
4429 unsigned n_loop
= 0;
4437 /* Ideally, we'd just call ourselves recursively on every
4438 * complex type. However, the state of a va_list that is
4439 * passed to a function is undefined after that function
4440 * returns. This means we need to docode the va_list linearly
4441 * in a single stackframe. We hence implement our own
4442 * home-grown stack in an array. */
4444 n_array
= (unsigned) -1; /* length of current array entries */
4445 n_struct
= strlen(types
); /* length of current struct contents signature */
4452 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4453 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4459 r
= sd_bus_message_exit_container(m
);
4467 if (n_array
!= (unsigned) -1)
4476 case SD_BUS_TYPE_BYTE
:
4477 case SD_BUS_TYPE_BOOLEAN
:
4478 case SD_BUS_TYPE_INT16
:
4479 case SD_BUS_TYPE_UINT16
:
4480 case SD_BUS_TYPE_INT32
:
4481 case SD_BUS_TYPE_UINT32
:
4482 case SD_BUS_TYPE_INT64
:
4483 case SD_BUS_TYPE_UINT64
:
4484 case SD_BUS_TYPE_DOUBLE
:
4485 case SD_BUS_TYPE_STRING
:
4486 case SD_BUS_TYPE_OBJECT_PATH
:
4487 case SD_BUS_TYPE_SIGNATURE
:
4488 case SD_BUS_TYPE_UNIX_FD
: {
4491 p
= va_arg(ap
, void*);
4492 r
= sd_bus_message_read_basic(m
, *t
, p
);
4505 case SD_BUS_TYPE_ARRAY
: {
4508 r
= signature_element_length(t
+ 1, &k
);
4514 memcpy(s
, t
+ 1, k
);
4517 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4528 if (n_array
== (unsigned) -1) {
4533 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4539 n_array
= va_arg(ap
, unsigned);
4544 case SD_BUS_TYPE_VARIANT
: {
4547 s
= va_arg(ap
, const char *);
4551 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4561 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4566 n_struct
= strlen(s
);
4567 n_array
= (unsigned) -1;
4572 case SD_BUS_TYPE_STRUCT_BEGIN
:
4573 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4576 r
= signature_element_length(t
, &k
);
4582 memcpy(s
, t
+ 1, k
- 2);
4585 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4595 if (n_array
== (unsigned) -1) {
4600 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4606 n_array
= (unsigned) -1;
4619 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4623 assert_return(m
, -EINVAL
);
4624 assert_return(m
->sealed
, -EPERM
);
4625 assert_return(types
, -EINVAL
);
4627 va_start(ap
, types
);
4628 r
= message_read_ap(m
, types
, ap
);
4634 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4637 assert_return(m
, -EINVAL
);
4638 assert_return(m
->sealed
, -EPERM
);
4640 /* If types is NULL, read exactly one element */
4642 struct bus_container
*c
;
4645 if (message_end_of_signature(m
))
4648 if (message_end_of_array(m
, m
->rindex
))
4651 c
= message_get_container(m
);
4653 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4657 types
= strndupa(c
->signature
+ c
->index
, l
);
4662 case 0: /* Nothing to drop */
4665 case SD_BUS_TYPE_BYTE
:
4666 case SD_BUS_TYPE_BOOLEAN
:
4667 case SD_BUS_TYPE_INT16
:
4668 case SD_BUS_TYPE_UINT16
:
4669 case SD_BUS_TYPE_INT32
:
4670 case SD_BUS_TYPE_UINT32
:
4671 case SD_BUS_TYPE_INT64
:
4672 case SD_BUS_TYPE_UINT64
:
4673 case SD_BUS_TYPE_DOUBLE
:
4674 case SD_BUS_TYPE_STRING
:
4675 case SD_BUS_TYPE_OBJECT_PATH
:
4676 case SD_BUS_TYPE_SIGNATURE
:
4677 case SD_BUS_TYPE_UNIX_FD
:
4679 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4683 r
= sd_bus_message_skip(m
, types
+ 1);
4689 case SD_BUS_TYPE_ARRAY
: {
4692 r
= signature_element_length(types
+ 1, &k
);
4698 memcpy(s
, types
+1, k
);
4701 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4706 r
= sd_bus_message_skip(m
, s
);
4713 r
= sd_bus_message_exit_container(m
);
4718 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4725 case SD_BUS_TYPE_VARIANT
: {
4726 const char *contents
;
4729 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4733 if (x
!= SD_BUS_TYPE_VARIANT
)
4736 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4740 r
= sd_bus_message_skip(m
, contents
);
4745 r
= sd_bus_message_exit_container(m
);
4749 r
= sd_bus_message_skip(m
, types
+ 1);
4756 case SD_BUS_TYPE_STRUCT_BEGIN
:
4757 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4760 r
= signature_element_length(types
, &k
);
4766 memcpy(s
, types
+1, k
-2);
4769 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4773 r
= sd_bus_message_skip(m
, s
);
4777 r
= sd_bus_message_exit_container(m
);
4782 r
= sd_bus_message_skip(m
, types
+ k
);
4794 _public_
int sd_bus_message_read_array(
4800 struct bus_container
*c
;
4806 assert_return(m
, -EINVAL
);
4807 assert_return(m
->sealed
, -EPERM
);
4808 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4809 assert_return(ptr
, -EINVAL
);
4810 assert_return(size
, -EINVAL
);
4811 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4813 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4817 c
= message_get_container(m
);
4819 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4820 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4824 sz
= c
->end
- c
->begin
;
4826 align
= bus_type_get_alignment(type
);
4830 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4834 /* Zero length array, let's return some aligned
4835 * pointer that is not NULL */
4836 p
= (uint8_t*) NULL
+ align
;
4838 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4843 r
= sd_bus_message_exit_container(m
);
4847 *ptr
= (const void*) p
;
4853 message_quit_container(m
);
4857 static int message_peek_fields(
4868 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4871 static int message_peek_field_uint32(
4883 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4886 /* identical for gvariant and dbus1 */
4888 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4893 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4898 static int message_peek_field_uint64(
4910 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4913 /* identical for gvariant and dbus1 */
4915 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4920 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4925 static int message_peek_field_string(
4927 bool (*validate
)(const char *p
),
4939 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4944 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4950 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4954 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4960 if (!validate_nul(q
, l
))
4966 if (!validate_string(q
, l
))
4976 static int message_peek_field_signature(
4989 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4994 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
5000 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
5005 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
5010 if (!validate_signature(q
, l
))
5019 static int message_skip_fields(
5022 uint32_t array_size
,
5023 const char **signature
) {
5025 size_t original_index
;
5031 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
5033 original_index
= *ri
;
5039 if (array_size
!= (uint32_t) -1 &&
5040 array_size
<= *ri
- original_index
)
5047 if (t
== SD_BUS_TYPE_STRING
) {
5049 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
5055 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
5057 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
5063 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
5065 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
5071 } else if (bus_type_is_basic(t
)) {
5074 align
= bus_type_get_alignment(t
);
5075 k
= bus_type_get_size(t
);
5076 assert(align
> 0 && k
> 0);
5078 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
5084 } else if (t
== SD_BUS_TYPE_ARRAY
) {
5086 r
= signature_element_length(*signature
+1, &l
);
5096 strncpy(sig
, *signature
+ 1, l
-1);
5099 alignment
= bus_type_get_alignment(sig
[0]);
5103 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5106 if (nas
> BUS_ARRAY_MAX_SIZE
)
5109 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5113 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5118 (*signature
) += 1 + l
;
5120 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5123 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5127 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5133 } else if (t
== SD_BUS_TYPE_STRUCT
||
5134 t
== SD_BUS_TYPE_DICT_ENTRY
) {
5136 r
= signature_element_length(*signature
, &l
);
5143 strncpy(sig
, *signature
+ 1, l
-1);
5146 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5157 int bus_message_parse_fields(sd_bus_message
*m
) {
5160 uint32_t unix_fds
= 0;
5161 bool unix_fds_set
= false;
5162 void *offsets
= NULL
;
5163 unsigned n_offsets
= 0;
5169 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5172 /* Read the signature from the end of the body variant first */
5173 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5174 if (m
->footer_accessible
< 1 + sz
)
5177 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5179 if (p
< (char*) m
->footer
)
5186 /* We found the beginning of the signature
5187 * string, yay! We require the body to be a
5188 * structure, so verify it and then strip the
5189 * opening/closing brackets. */
5191 l
= ((char*) m
->footer
+ m
->footer_accessible
) - p
- (1 + sz
);
5193 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5194 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5197 c
= strndup(p
+ 1 + 1, l
- 2);
5201 free(m
->root_container
.signature
);
5202 m
->root_container
.signature
= c
;
5209 /* Calculate the actual user body size, by removing
5210 * the trailing variant signature and struct offset
5212 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5214 /* Pull out the offset table for the fields array */
5215 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5220 ri
= m
->fields_size
- sz
;
5221 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5225 framing
= bus_gvariant_read_word_le(q
, sz
);
5226 if (framing
>= m
->fields_size
- sz
)
5228 if ((m
->fields_size
- framing
) % sz
!= 0)
5232 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5236 n_offsets
= (m
->fields_size
- framing
) / sz
;
5239 m
->user_body_size
= m
->body_size
;
5242 while (ri
< m
->fields_size
) {
5243 _cleanup_free_
char *sig
= NULL
;
5244 const char *signature
;
5245 uint64_t field_type
;
5246 size_t item_size
= (size_t) -1;
5248 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5257 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5259 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5263 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5267 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5274 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5279 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5284 where
= ri
= ALIGN_TO(ri
, 8);
5285 item_size
= end
- ri
;
5286 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5290 b
= memrchr(q
, 0, item_size
);
5294 sig
= strndup(b
+1, item_size
- (b
+1-(char*) q
));
5299 item_size
= b
- (char*) q
;
5301 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5306 switch (field_type
) {
5308 case _BUS_MESSAGE_HEADER_INVALID
:
5311 case BUS_MESSAGE_HEADER_PATH
:
5316 if (!streq(signature
, "o"))
5319 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5322 case BUS_MESSAGE_HEADER_INTERFACE
:
5327 if (!streq(signature
, "s"))
5330 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5333 case BUS_MESSAGE_HEADER_MEMBER
:
5338 if (!streq(signature
, "s"))
5341 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5344 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5349 if (!streq(signature
, "s"))
5352 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5354 m
->error
._need_free
= -1;
5358 case BUS_MESSAGE_HEADER_DESTINATION
:
5363 if (!streq(signature
, "s"))
5366 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5369 case BUS_MESSAGE_HEADER_SENDER
:
5374 if (!streq(signature
, "s"))
5377 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5379 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
&& !m
->bus
->is_kernel
) {
5380 m
->creds
.unique_name
= (char*) m
->sender
;
5381 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5387 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5391 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5394 if (m
->root_container
.signature
)
5397 if (!streq(signature
, "g"))
5400 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5408 free(m
->root_container
.signature
);
5409 m
->root_container
.signature
= c
;
5413 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5415 if (m
->reply_cookie
!= 0)
5418 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5419 /* 64bit on dbus2 */
5421 if (!streq(signature
, "t"))
5424 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5428 /* 32bit on dbus1 */
5431 if (!streq(signature
, "u"))
5434 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5438 m
->reply_cookie
= serial
;
5441 if (m
->reply_cookie
== 0)
5446 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5450 if (!streq(signature
, "u"))
5453 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5457 unix_fds_set
= true;
5461 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5462 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5471 if (m
->n_fds
!= unix_fds
)
5474 switch (m
->header
->type
) {
5476 case SD_BUS_MESSAGE_SIGNAL
:
5477 if (!m
->path
|| !m
->interface
|| !m
->member
)
5480 if (m
->reply_cookie
!= 0)
5485 case SD_BUS_MESSAGE_METHOD_CALL
:
5487 if (!m
->path
|| !m
->member
)
5490 if (m
->reply_cookie
!= 0)
5495 case SD_BUS_MESSAGE_METHOD_RETURN
:
5497 if (m
->reply_cookie
== 0)
5501 case SD_BUS_MESSAGE_METHOD_ERROR
:
5503 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5508 /* Refuse non-local messages that claim they are local */
5509 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5511 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5513 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5516 m
->root_container
.end
= m
->user_body_size
;
5518 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5519 r
= build_struct_offsets(
5521 m
->root_container
.signature
,
5523 &m
->root_container
.item_size
,
5524 &m
->root_container
.offsets
,
5525 &m
->root_container
.n_offsets
);
5530 /* Try to read the error message, but if we can't it's a non-issue */
5531 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5532 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5537 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5538 assert_return(m
, -EINVAL
);
5539 assert_return(destination
, -EINVAL
);
5540 assert_return(!m
->sealed
, -EPERM
);
5541 assert_return(!m
->destination
, -EEXIST
);
5543 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5546 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5550 struct bus_body_part
*part
;
5556 total
= BUS_MESSAGE_SIZE(m
);
5562 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5563 MESSAGE_FOREACH_PART(part
, i
, m
)
5564 e
= mempcpy(e
, part
->data
, part
->size
);
5566 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5574 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5581 r
= sd_bus_message_enter_container(m
, 'a', "s");
5585 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5586 r
= strv_extend(l
, s
);
5593 r
= sd_bus_message_exit_container(m
);
5600 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5604 assert_return(m
, -EINVAL
);
5605 assert_return(m
->sealed
, -EPERM
);
5606 assert_return(l
, -EINVAL
);
5608 r
= bus_message_read_strv_extend(m
, &strv
);
5618 static int bus_message_get_arg_skip(
5622 const char **_contents
) {
5627 r
= sd_bus_message_rewind(m
, true);
5632 const char *contents
;
5635 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5641 /* Don't match against arguments after the first one we don't understand */
5642 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5643 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5648 *_contents
= contents
;
5654 r
= sd_bus_message_skip(m
, NULL
);
5661 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5668 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5672 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5675 return sd_bus_message_read_basic(m
, type
, str
);
5678 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5679 const char *contents
;
5686 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5690 if (type
!= SD_BUS_TYPE_ARRAY
)
5692 if (!STR_IN_SET(contents
, "s", "o", "g"))
5695 return sd_bus_message_read_strv(m
, strv
);
5698 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5699 assert_return(m
, EINVAL
);
5701 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5704 return sd_bus_error_get_errno(&m
->error
);
5707 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5708 struct bus_container
*c
;
5710 assert_return(m
, NULL
);
5712 c
= complete
? &m
->root_container
: message_get_container(m
);
5713 return strempty(c
->signature
);
5716 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5717 assert_return(m
, -EINVAL
);
5719 return isempty(m
->root_container
.signature
);
5722 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5723 assert_return(m
, -EINVAL
);
5725 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5728 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5729 bool done_something
= false;
5732 assert_return(m
, -EINVAL
);
5733 assert_return(source
, -EINVAL
);
5734 assert_return(!m
->sealed
, -EPERM
);
5735 assert_return(source
->sealed
, -EPERM
);
5738 const char *contents
;
5753 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5759 done_something
= true;
5761 if (bus_type_is_container(type
) > 0) {
5763 r
= sd_bus_message_enter_container(source
, type
, contents
);
5767 r
= sd_bus_message_open_container(m
, type
, contents
);
5771 r
= sd_bus_message_copy(m
, source
, true);
5775 r
= sd_bus_message_close_container(m
);
5779 r
= sd_bus_message_exit_container(source
);
5786 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5792 if (type
== SD_BUS_TYPE_OBJECT_PATH
||
5793 type
== SD_BUS_TYPE_SIGNATURE
||
5794 type
== SD_BUS_TYPE_STRING
)
5795 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5797 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5804 return done_something
;
5807 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5812 assert_return(m
, -EINVAL
);
5813 assert_return(m
->sealed
, -EPERM
);
5814 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5815 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5816 assert_return(type
|| contents
, -EINVAL
);
5817 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5819 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5823 if (type
!= 0 && type
!= t
)
5826 if (contents
&& !streq_ptr(contents
, c
))
5832 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5833 assert_return(m
, NULL
);
5838 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5839 _cleanup_bus_message_unref_ sd_bus_message
*n
= NULL
;
5847 switch ((*m
)->header
->type
) {
5849 case SD_BUS_MESSAGE_SIGNAL
:
5850 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5856 case SD_BUS_MESSAGE_METHOD_CALL
:
5857 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5863 case SD_BUS_MESSAGE_METHOD_RETURN
:
5864 case SD_BUS_MESSAGE_METHOD_ERROR
:
5866 n
= message_new(bus
, (*m
)->header
->type
);
5870 n
->reply_cookie
= (*m
)->reply_cookie
;
5872 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5876 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5877 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5881 n
->error
._need_free
= -1;
5890 if ((*m
)->destination
&& !n
->destination
) {
5891 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5896 if ((*m
)->sender
&& !n
->sender
) {
5897 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5902 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5904 r
= sd_bus_message_copy(n
, *m
, true);
5908 timeout
= (*m
)->timeout
;
5909 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
))
5910 timeout
= BUS_DEFAULT_TIMEOUT
;
5912 r
= bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5916 sd_bus_message_unref(*m
);
5923 int bus_message_append_sender(sd_bus_message
*m
, const char *sender
) {
5927 assert_return(!m
->sealed
, -EPERM
);
5928 assert_return(!m
->sender
, -EPERM
);
5930 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5933 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5934 assert_return(m
, -EINVAL
);
5935 assert_return(priority
, -EINVAL
);
5937 *priority
= m
->priority
;
5941 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5942 assert_return(m
, -EINVAL
);
5943 assert_return(!m
->sealed
, -EPERM
);
5945 m
->priority
= priority
;