1 /* SPDX-License-Identifier: LGPL-2.1+ */
9 #include "alloc-util.h"
10 #include "bus-gvariant.h"
11 #include "bus-internal.h"
12 #include "bus-message.h"
13 #include "bus-signature.h"
18 #include "memfd-util.h"
19 #include "string-util.h"
21 #include "time-util.h"
25 static int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
);
27 static void *adjust_pointer(const void *p
, void *old_base
, size_t sz
, void *new_base
) {
32 if (old_base
== new_base
)
35 if ((uint8_t*) p
< (uint8_t*) old_base
)
38 if ((uint8_t*) p
>= (uint8_t*) old_base
+ sz
)
41 return (uint8_t*) new_base
+ ((uint8_t*) p
- (uint8_t*) old_base
);
44 static void message_free_part(sd_bus_message
*m
, struct bus_body_part
*part
) {
49 close_and_munmap(part
->memfd
, part
->mmap_begin
, part
->mapped
);
50 else if (part
->munmap_this
)
51 munmap(part
->mmap_begin
, part
->mapped
);
52 else if (part
->free_this
)
59 static void message_reset_parts(sd_bus_message
*m
) {
60 struct bus_body_part
*part
;
65 while (m
->n_body_parts
> 0) {
66 struct bus_body_part
*next
= part
->next
;
67 message_free_part(m
, part
);
74 m
->cached_rindex_part
= NULL
;
75 m
->cached_rindex_part_begin
= 0;
78 static void message_reset_containers(sd_bus_message
*m
) {
83 for (i
= 0; i
< m
->n_containers
; i
++) {
84 free(m
->containers
[i
].signature
);
85 free(m
->containers
[i
].offsets
);
88 m
->containers
= mfree(m
->containers
);
90 m
->n_containers
= m
->containers_allocated
= 0;
91 m
->root_container
.index
= 0;
94 static sd_bus_message
* message_free(sd_bus_message
*m
) {
100 message_reset_parts(m
);
102 sd_bus_unref(m
->bus
);
105 close_many(m
->fds
, m
->n_fds
);
109 if (m
->iovec
!= m
->iovec_fixed
)
112 message_reset_containers(m
);
113 free(m
->root_container
.signature
);
114 free(m
->root_container
.offsets
);
116 free(m
->root_container
.peeked_signature
);
118 bus_creds_done(&m
->creds
);
122 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message
*, message_free
);
124 static void *message_extend_fields(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
126 size_t old_size
, new_size
, start
;
133 old_size
= sizeof(struct bus_header
) + m
->fields_size
;
134 start
= ALIGN_TO(old_size
, align
);
135 new_size
= start
+ sz
;
137 if (new_size
< start
||
138 new_size
> (size_t) ((uint32_t) -1))
141 if (old_size
== new_size
)
142 return (uint8_t*) m
->header
+ old_size
;
144 if (m
->free_header
) {
145 np
= realloc(m
->header
, ALIGN8(new_size
));
149 /* Initially, the header is allocated as part of
150 * the sd_bus_message itself, let's replace it by
153 np
= malloc(ALIGN8(new_size
));
157 memcpy(np
, m
->header
, sizeof(struct bus_header
));
160 /* Zero out padding */
161 if (start
> old_size
)
162 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
166 m
->fields_size
= new_size
- sizeof(struct bus_header
);
168 /* Adjust quick access pointers */
169 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
170 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
171 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
172 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
173 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
174 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
176 m
->free_header
= true;
179 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
182 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
185 return (uint8_t*) np
+ start
;
192 static int message_append_field_string(
204 /* dbus1 only allows 8bit header field ids */
208 /* dbus1 doesn't allow strings over 32bit, let's enforce this
209 * globally, to not risk convertability */
211 if (l
> (size_t) (uint32_t) -1)
214 /* Signature "(yv)" where the variant contains "s" */
216 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
218 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
219 p
= message_extend_fields(m
, 8, 8 + l
+ 1 + 1 + 1, true);
223 *((uint64_t*) p
) = h
;
230 *ret
= (char*) p
+ 8;
233 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
234 p
= message_extend_fields(m
, 8, 4 + 4 + l
+ 1, false);
243 ((uint32_t*) p
)[1] = l
;
244 memcpy(p
+ 8, s
, l
+ 1);
247 *ret
= (char*) p
+ 8;
253 static int message_append_field_signature(
264 /* dbus1 only allows 8bit header field ids */
268 /* dbus1 doesn't allow signatures over 8bit, let's enforce
269 * this globally, to not risk convertability */
274 /* Signature "(yv)" where the variant contains "g" */
276 if (BUS_MESSAGE_IS_GVARIANT(m
))
277 /* For gvariant the serialization is the same as for normal strings */
278 return message_append_field_string(m
, h
, 'g', s
, ret
);
280 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
281 p
= message_extend_fields(m
, 8, 4 + 1 + l
+ 1, false);
287 p
[2] = SD_BUS_TYPE_SIGNATURE
;
290 memcpy(p
+ 5, s
, l
+ 1);
293 *ret
= (const char*) p
+ 5;
299 static int message_append_field_uint32(sd_bus_message
*m
, uint64_t h
, uint32_t x
) {
304 /* dbus1 only allows 8bit header field ids */
308 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
309 /* (field id 64bit + ((value + NUL + signature string 'u') */
311 p
= message_extend_fields(m
, 8, 8 + 4 + 1 + 1, true);
315 *((uint64_t*) p
) = h
;
316 *((uint32_t*) (p
+ 8)) = x
;
320 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
321 p
= message_extend_fields(m
, 8, 4 + 4, false);
330 ((uint32_t*) p
)[1] = x
;
336 static int message_append_field_uint64(sd_bus_message
*m
, uint64_t h
, uint64_t x
) {
341 /* dbus1 only allows 8bit header field ids */
345 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
346 /* (field id 64bit + ((value + NUL + signature string 't') */
348 p
= message_extend_fields(m
, 8, 8 + 8 + 1 + 1, true);
352 *((uint64_t*) p
) = h
;
353 *((uint64_t*) (p
+ 8)) = x
;
357 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
358 p
= message_extend_fields(m
, 8, 4 + 4 + 8, false);
371 ((uint64_t*) p
)[1] = x
;
377 static int message_append_reply_cookie(sd_bus_message
*m
, uint64_t cookie
) {
380 if (BUS_MESSAGE_IS_GVARIANT(m
))
381 return message_append_field_uint64(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, cookie
);
383 /* 64bit cookies are not supported on dbus1 */
384 if (cookie
> 0xffffffffUL
)
387 return message_append_field_uint32(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) cookie
);
391 int bus_message_from_header(
394 size_t header_accessible
,
396 size_t footer_accessible
,
402 sd_bus_message
**ret
) {
404 _cleanup_free_ sd_bus_message
*m
= NULL
;
405 struct bus_header
*h
;
409 assert(header
|| header_accessible
<= 0);
410 assert(footer
|| footer_accessible
<= 0);
411 assert(fds
|| n_fds
<= 0);
414 if (header_accessible
< sizeof(struct bus_header
))
417 if (header_accessible
> message_size
)
419 if (footer_accessible
> message_size
)
423 if (!IN_SET(h
->version
, 1, 2))
426 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
429 if (!IN_SET(h
->endian
, BUS_LITTLE_ENDIAN
, BUS_BIG_ENDIAN
))
432 /* Note that we are happy with unknown flags in the flags header! */
434 a
= ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
437 label_sz
= strlen(label
);
448 m
->header_accessible
= header_accessible
;
450 m
->footer_accessible
= footer_accessible
;
452 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
455 if (h
->dbus2
.cookie
== 0)
458 /* dbus2 derives the sizes from the message size and
459 the offset table at the end, since it is formatted as
460 gvariant "yyyyuta{tv}v". Since the message itself is a
461 structure with precisely to variable sized entries,
462 there's only one offset in the table, which marks the
463 end of the fields array. */
465 ws
= bus_gvariant_determine_word_size(message_size
, 0);
466 if (footer_accessible
< ws
)
469 m
->fields_size
= bus_gvariant_read_word_le((uint8_t*) footer
+ footer_accessible
- ws
, ws
);
470 if (ALIGN8(m
->fields_size
) > message_size
- ws
)
472 if (m
->fields_size
< sizeof(struct bus_header
))
475 m
->fields_size
-= sizeof(struct bus_header
);
476 m
->body_size
= message_size
- (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
));
478 if (h
->dbus1
.serial
== 0)
481 /* dbus1 has the sizes in the header */
482 m
->fields_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.fields_size
);
483 m
->body_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.body_size
);
485 if (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
!= message_size
)
493 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
494 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
496 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
499 m
->bus
= sd_bus_ref(bus
);
505 int bus_message_from_malloc(
512 sd_bus_message
**ret
) {
514 _cleanup_(message_freep
) sd_bus_message
*m
= NULL
;
518 r
= bus_message_from_header(
520 buffer
, length
, /* in this case the initial bytes and the final bytes are the same */
529 sz
= length
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
);
532 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(m
->fields_size
);
534 m
->body
.sealed
= true;
539 m
->iovec
= m
->iovec_fixed
;
540 m
->iovec
[0].iov_base
= buffer
;
541 m
->iovec
[0].iov_len
= length
;
543 r
= bus_message_parse_fields(m
);
547 /* We take possession of the memory and fds now */
548 m
->free_header
= true;
555 _public_
int sd_bus_message_new(
562 assert_return(bus
, -ENOTCONN
);
563 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
564 assert_return(m
, -EINVAL
);
565 assert_return(type
< _SD_BUS_MESSAGE_TYPE_MAX
, -EINVAL
);
567 t
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
572 t
->header
= (struct bus_header
*) ((uint8_t*) t
+ ALIGN(sizeof(struct sd_bus_message
)));
573 t
->header
->endian
= BUS_NATIVE_ENDIAN
;
574 t
->header
->type
= type
;
575 t
->header
->version
= bus
->message_version
;
576 t
->allow_fds
= bus
->can_fds
|| !IN_SET(bus
->state
, BUS_HELLO
, BUS_RUNNING
);
577 t
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(t
);
578 t
->bus
= sd_bus_ref(bus
);
580 if (bus
->allow_interactive_authorization
)
581 t
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
587 _public_
int sd_bus_message_new_signal(
591 const char *interface
,
592 const char *member
) {
594 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
597 assert_return(bus
, -ENOTCONN
);
598 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
599 assert_return(object_path_is_valid(path
), -EINVAL
);
600 assert_return(interface_name_is_valid(interface
), -EINVAL
);
601 assert_return(member_name_is_valid(member
), -EINVAL
);
602 assert_return(m
, -EINVAL
);
604 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_SIGNAL
);
610 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
612 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
615 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
618 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
626 _public_
int sd_bus_message_new_method_call(
629 const char *destination
,
631 const char *interface
,
632 const char *member
) {
634 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
637 assert_return(bus
, -ENOTCONN
);
638 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
639 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
640 assert_return(object_path_is_valid(path
), -EINVAL
);
641 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
642 assert_return(member_name_is_valid(member
), -EINVAL
);
643 assert_return(m
, -EINVAL
);
645 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_CALL
);
651 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
654 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
659 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
665 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
674 static int message_new_reply(
675 sd_bus_message
*call
,
677 sd_bus_message
**m
) {
679 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
683 assert_return(call
, -EINVAL
);
684 assert_return(call
->sealed
, -EPERM
);
685 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
686 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
687 assert_return(m
, -EINVAL
);
689 cookie
= BUS_MESSAGE_COOKIE(call
);
693 r
= sd_bus_message_new(call
->bus
, &t
, type
);
699 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
700 t
->reply_cookie
= cookie
;
701 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
706 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
711 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
712 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
718 _public_
int sd_bus_message_new_method_return(
719 sd_bus_message
*call
,
720 sd_bus_message
**m
) {
722 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
725 _public_
int sd_bus_message_new_method_error(
726 sd_bus_message
*call
,
728 const sd_bus_error
*e
) {
730 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
733 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
734 assert_return(m
, -EINVAL
);
736 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
740 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
745 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
750 t
->error
._need_free
= -1;
756 _public_
int sd_bus_message_new_method_errorf(
757 sd_bus_message
*call
,
763 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
766 assert_return(name
, -EINVAL
);
767 assert_return(m
, -EINVAL
);
769 va_start(ap
, format
);
770 bus_error_setfv(&error
, name
, format
, ap
);
773 return sd_bus_message_new_method_error(call
, m
, &error
);
776 _public_
int sd_bus_message_new_method_errno(
777 sd_bus_message
*call
,
780 const sd_bus_error
*p
) {
782 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
784 if (sd_bus_error_is_set(p
))
785 return sd_bus_message_new_method_error(call
, m
, p
);
787 sd_bus_error_set_errno(&berror
, error
);
789 return sd_bus_message_new_method_error(call
, m
, &berror
);
792 _public_
int sd_bus_message_new_method_errnof(
793 sd_bus_message
*call
,
799 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
802 va_start(ap
, format
);
803 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
806 return sd_bus_message_new_method_error(call
, m
, &berror
);
809 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
813 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
814 m
->creds
.well_known_names_local
= true;
815 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
818 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
822 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
823 m
->creds
.well_known_names_driver
= true;
824 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
827 int bus_message_new_synthetic_error(
830 const sd_bus_error
*e
,
831 sd_bus_message
**m
) {
833 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
837 assert(sd_bus_error_is_set(e
));
840 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_ERROR
);
846 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
847 t
->reply_cookie
= cookie
;
849 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
853 if (bus
&& bus
->unique_name
) {
854 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
859 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
864 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
869 t
->error
._need_free
= -1;
871 bus_message_set_sender_driver(bus
, t
);
877 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
882 assert(m
->n_ref
> 0);
888 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
893 assert(m
->n_ref
> 0);
899 return message_free(m
);
902 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
903 assert_return(m
, -EINVAL
);
904 assert_return(type
, -EINVAL
);
906 *type
= m
->header
->type
;
910 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
913 assert_return(m
, -EINVAL
);
914 assert_return(cookie
, -EINVAL
);
916 c
= BUS_MESSAGE_COOKIE(m
);
920 *cookie
= BUS_MESSAGE_COOKIE(m
);
924 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
925 assert_return(m
, -EINVAL
);
926 assert_return(cookie
, -EINVAL
);
928 if (m
->reply_cookie
== 0)
931 *cookie
= m
->reply_cookie
;
935 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
936 assert_return(m
, -EINVAL
);
938 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
939 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
942 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
943 assert_return(m
, -EINVAL
);
945 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
948 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
949 assert_return(m
, -EINVAL
);
951 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
952 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
955 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
956 assert_return(m
, NULL
);
961 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
962 assert_return(m
, NULL
);
967 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
968 assert_return(m
, NULL
);
973 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
974 assert_return(m
, NULL
);
976 return m
->destination
;
979 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
980 assert_return(m
, NULL
);
985 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
986 assert_return(m
, NULL
);
988 if (!sd_bus_error_is_set(&m
->error
))
994 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
995 assert_return(m
, -EINVAL
);
996 assert_return(usec
, -EINVAL
);
998 if (m
->monotonic
<= 0)
1001 *usec
= m
->monotonic
;
1005 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1006 assert_return(m
, -EINVAL
);
1007 assert_return(usec
, -EINVAL
);
1009 if (m
->realtime
<= 0)
1012 *usec
= m
->realtime
;
1016 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1017 assert_return(m
, -EINVAL
);
1018 assert_return(seqnum
, -EINVAL
);
1023 *seqnum
= m
->seqnum
;
1027 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1028 assert_return(m
, NULL
);
1030 if (m
->creds
.mask
== 0)
1036 _public_
int sd_bus_message_is_signal(
1038 const char *interface
,
1039 const char *member
) {
1041 assert_return(m
, -EINVAL
);
1043 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1046 if (interface
&& !streq_ptr(m
->interface
, interface
))
1049 if (member
&& !streq_ptr(m
->member
, member
))
1055 _public_
int sd_bus_message_is_method_call(
1057 const char *interface
,
1058 const char *member
) {
1060 assert_return(m
, -EINVAL
);
1062 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1065 if (interface
&& !streq_ptr(m
->interface
, interface
))
1068 if (member
&& !streq_ptr(m
->member
, member
))
1074 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1075 assert_return(m
, -EINVAL
);
1077 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1080 if (name
&& !streq_ptr(m
->error
.name
, name
))
1086 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1087 assert_return(m
, -EINVAL
);
1088 assert_return(!m
->sealed
, -EPERM
);
1089 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1091 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_REPLY_EXPECTED
, !b
);
1096 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1097 assert_return(m
, -EINVAL
);
1098 assert_return(!m
->sealed
, -EPERM
);
1100 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_AUTO_START
, !b
);
1105 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1106 assert_return(m
, -EINVAL
);
1107 assert_return(!m
->sealed
, -EPERM
);
1109 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
, b
);
1114 static struct bus_container
*message_get_container(sd_bus_message
*m
) {
1117 if (m
->n_containers
== 0)
1118 return &m
->root_container
;
1120 assert(m
->containers
);
1121 return m
->containers
+ m
->n_containers
- 1;
1124 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1125 struct bus_body_part
*part
;
1132 if (m
->n_body_parts
<= 0) {
1136 assert(m
->body_end
);
1138 part
= new0(struct bus_body_part
, 1);
1144 m
->body_end
->next
= part
;
1154 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1159 /* All other fields can be left in their defaults */
1160 assert(!part
->data
);
1161 assert(part
->memfd
< 0);
1164 part
->is_zero
= true;
1165 part
->sealed
= true;
1168 static int part_make_space(
1169 struct sd_bus_message
*m
,
1170 struct bus_body_part
*part
,
1178 assert(!part
->sealed
);
1183 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1184 size_t new_allocated
;
1186 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1187 n
= realloc(part
->data
, new_allocated
);
1194 part
->allocated
= new_allocated
;
1195 part
->free_this
= true;
1199 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1205 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1206 struct bus_container
*c
;
1209 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1211 /* Add offset to current container, unless this is the first
1212 * item in it, which will have the 0 offset, which we can
1214 c
= message_get_container(m
);
1216 if (!c
->need_offsets
)
1219 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1222 c
->offsets
[c
->n_offsets
++] = offset
;
1226 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1227 struct bus_container
*c
;
1234 /* Update counters */
1235 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++) {
1238 *c
->array_size
+= expand
;
1242 static void *message_extend_body(
1247 bool force_inline
) {
1249 size_t start_body
, end_body
, padding
, added
;
1260 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1261 end_body
= start_body
+ sz
;
1263 padding
= start_body
- m
->body_size
;
1264 added
= padding
+ sz
;
1266 /* Check for 32bit overflows */
1267 if (end_body
> (size_t) ((uint32_t) -1) ||
1268 end_body
< start_body
) {
1274 struct bus_body_part
*part
= NULL
;
1278 m
->n_body_parts
<= 0 ||
1279 m
->body_end
->sealed
||
1280 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1281 (force_inline
&& m
->body_end
->size
> MEMFD_MIN_SIZE
);
1282 /* If this must be an inlined extension, let's create a new part if
1283 * the previous part is large enough to be inlined. */
1287 part
= message_append_part(m
);
1291 part_zero(part
, padding
);
1294 part
= message_append_part(m
);
1298 r
= part_make_space(m
, part
, sz
, &p
);
1302 struct bus_container
*c
;
1304 size_t os
, start_part
, end_part
;
1310 start_part
= ALIGN_TO(part
->size
, align
);
1311 end_part
= start_part
+ sz
;
1313 r
= part_make_space(m
, part
, end_part
, &p
);
1318 memzero(p
, padding
);
1319 p
= (uint8_t*) p
+ padding
;
1322 /* Readjust pointers */
1323 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1324 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1326 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1329 /* Return something that is not NULL and is aligned */
1330 p
= (uint8_t*) align
;
1332 m
->body_size
= end_body
;
1333 message_extend_containers(m
, added
);
1336 r
= message_add_offset(m
, end_body
);
1346 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1357 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1361 f
= reallocarray(m
->fds
, sizeof(int), m
->n_fds
+ 1);
1369 m
->fds
[m
->n_fds
] = copy
;
1375 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1376 _cleanup_close_
int fd
= -1;
1377 struct bus_container
*c
;
1381 assert_return(m
, -EINVAL
);
1382 assert_return(!m
->sealed
, -EPERM
);
1383 assert_return(bus_type_is_basic(type
), -EINVAL
);
1384 assert_return(!m
->poisoned
, -ESTALE
);
1386 c
= message_get_container(m
);
1388 if (c
->signature
&& c
->signature
[c
->index
]) {
1389 /* Container signature is already set */
1391 if (c
->signature
[c
->index
] != type
)
1396 /* Maybe we can append to the signature? But only if this is the top-level container */
1397 if (c
->enclosing
!= 0)
1400 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1407 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1413 case SD_BUS_TYPE_SIGNATURE
:
1414 case SD_BUS_TYPE_STRING
:
1418 case SD_BUS_TYPE_OBJECT_PATH
:
1426 case SD_BUS_TYPE_BOOLEAN
:
1428 u8
= p
&& *(int*) p
;
1434 case SD_BUS_TYPE_UNIX_FD
:
1439 fd
= message_push_fd(m
, *(int*) p
);
1450 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1451 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1458 a
= message_extend_body(m
, align
, sz
, true, false);
1465 *stored
= (const uint8_t*) a
;
1472 case SD_BUS_TYPE_STRING
:
1473 /* To make things easy we'll serialize a NULL string
1474 * into the empty string */
1478 case SD_BUS_TYPE_OBJECT_PATH
:
1484 sz
= 4 + strlen(p
) + 1;
1487 case SD_BUS_TYPE_SIGNATURE
:
1492 sz
= 1 + strlen(p
) + 1;
1495 case SD_BUS_TYPE_BOOLEAN
:
1497 u32
= p
&& *(int*) p
;
1503 case SD_BUS_TYPE_UNIX_FD
:
1508 fd
= message_push_fd(m
, *(int*) p
);
1519 align
= bus_type_get_alignment(type
);
1520 sz
= bus_type_get_size(type
);
1527 a
= message_extend_body(m
, align
, sz
, false, false);
1531 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
1532 *(uint32_t*) a
= sz
- 5;
1533 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1536 *stored
= (const uint8_t*) a
+ 4;
1538 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1539 *(uint8_t*) a
= sz
- 2;
1540 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1543 *stored
= (const uint8_t*) a
+ 1;
1552 if (type
== SD_BUS_TYPE_UNIX_FD
)
1555 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1562 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1563 return message_append_basic(m
, type
, p
, NULL
);
1566 _public_
int sd_bus_message_append_string_space(
1571 struct bus_container
*c
;
1574 assert_return(m
, -EINVAL
);
1575 assert_return(s
, -EINVAL
);
1576 assert_return(!m
->sealed
, -EPERM
);
1577 assert_return(!m
->poisoned
, -ESTALE
);
1579 c
= message_get_container(m
);
1581 if (c
->signature
&& c
->signature
[c
->index
]) {
1582 /* Container signature is already set */
1584 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1589 /* Maybe we can append to the signature? But only if this is the top-level container */
1590 if (c
->enclosing
!= 0)
1593 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1600 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1601 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1607 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1611 *(uint32_t*) a
= size
;
1617 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1623 _public_
int sd_bus_message_append_string_iovec(
1625 const struct iovec
*iov
,
1626 unsigned n
/* should be size_t, but is API now… 😞 */) {
1633 assert_return(m
, -EINVAL
);
1634 assert_return(!m
->sealed
, -EPERM
);
1635 assert_return(iov
|| n
== 0, -EINVAL
);
1636 assert_return(!m
->poisoned
, -ESTALE
);
1638 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1640 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1644 for (i
= 0; i
< n
; i
++) {
1646 if (iov
[i
].iov_base
)
1647 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1649 memset(p
, ' ', iov
[i
].iov_len
);
1651 p
+= iov
[i
].iov_len
;
1657 static int bus_message_open_array(
1659 struct bus_container
*c
,
1660 const char *contents
,
1661 uint32_t **array_size
,
1663 bool *need_offsets
) {
1673 assert(need_offsets
);
1675 if (!signature_is_single(contents
, true))
1678 if (c
->signature
&& c
->signature
[c
->index
]) {
1680 /* Verify the existing signature */
1682 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1685 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1688 nindex
= c
->index
+ 1 + strlen(contents
);
1692 if (c
->enclosing
!= 0)
1695 /* Extend the existing signature */
1697 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1703 nindex
= e
- c
->signature
;
1706 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1707 alignment
= bus_gvariant_get_alignment(contents
);
1711 /* Add alignment padding and add to offset list */
1712 if (!message_extend_body(m
, alignment
, 0, false, false))
1715 r
= bus_gvariant_is_fixed_size(contents
);
1719 *begin
= m
->body_size
;
1720 *need_offsets
= r
== 0;
1724 struct bus_body_part
*o
;
1726 alignment
= bus_type_get_alignment(contents
[0]);
1730 a
= message_extend_body(m
, 4, 4, false, false);
1735 op
= m
->body_end
->data
;
1736 os
= m
->body_end
->size
;
1738 /* Add alignment between size and first element */
1739 if (!message_extend_body(m
, alignment
, 0, false, false))
1742 /* location of array size might have changed so let's readjust a */
1743 if (o
== m
->body_end
)
1744 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1750 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1756 static int bus_message_open_variant(
1758 struct bus_container
*c
,
1759 const char *contents
) {
1765 if (!signature_is_single(contents
, false))
1768 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1771 if (c
->signature
&& c
->signature
[c
->index
]) {
1773 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1779 if (c
->enclosing
!= 0)
1782 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1789 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1790 /* Variants are always aligned to 8 */
1792 if (!message_extend_body(m
, 8, 0, false, false))
1799 l
= strlen(contents
);
1800 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1805 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1808 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1814 static int bus_message_open_struct(
1816 struct bus_container
*c
,
1817 const char *contents
,
1819 bool *need_offsets
) {
1828 assert(need_offsets
);
1830 if (!signature_is_valid(contents
, false))
1833 if (c
->signature
&& c
->signature
[c
->index
]) {
1836 l
= strlen(contents
);
1838 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1839 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1840 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1843 nindex
= c
->index
+ 1 + l
+ 1;
1847 if (c
->enclosing
!= 0)
1850 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1856 nindex
= e
- c
->signature
;
1859 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1862 alignment
= bus_gvariant_get_alignment(contents
);
1866 if (!message_extend_body(m
, alignment
, 0, false, false))
1869 r
= bus_gvariant_is_fixed_size(contents
);
1873 *begin
= m
->body_size
;
1874 *need_offsets
= r
== 0;
1876 /* Align contents to 8 byte boundary */
1877 if (!message_extend_body(m
, 8, 0, false, false))
1881 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1887 static int bus_message_open_dict_entry(
1889 struct bus_container
*c
,
1890 const char *contents
,
1892 bool *need_offsets
) {
1900 assert(need_offsets
);
1902 if (!signature_is_pair(contents
))
1905 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1908 if (c
->signature
&& c
->signature
[c
->index
]) {
1911 l
= strlen(contents
);
1913 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
1914 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1915 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
1920 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1923 alignment
= bus_gvariant_get_alignment(contents
);
1927 if (!message_extend_body(m
, alignment
, 0, false, false))
1930 r
= bus_gvariant_is_fixed_size(contents
);
1934 *begin
= m
->body_size
;
1935 *need_offsets
= r
== 0;
1937 /* Align contents to 8 byte boundary */
1938 if (!message_extend_body(m
, 8, 0, false, false))
1945 _public_
int sd_bus_message_open_container(
1948 const char *contents
) {
1950 struct bus_container
*c
, *w
;
1951 uint32_t *array_size
= NULL
;
1952 _cleanup_free_
char *signature
= NULL
;
1953 size_t before
, begin
= 0;
1954 bool need_offsets
= false;
1957 assert_return(m
, -EINVAL
);
1958 assert_return(!m
->sealed
, -EPERM
);
1959 assert_return(contents
, -EINVAL
);
1960 assert_return(!m
->poisoned
, -ESTALE
);
1962 /* Make sure we have space for one more container */
1963 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
1968 c
= message_get_container(m
);
1970 signature
= strdup(contents
);
1976 /* Save old index in the parent container, in case we have to
1977 * abort this container */
1978 c
->saved_index
= c
->index
;
1979 before
= m
->body_size
;
1981 if (type
== SD_BUS_TYPE_ARRAY
)
1982 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
1983 else if (type
== SD_BUS_TYPE_VARIANT
)
1984 r
= bus_message_open_variant(m
, c
, contents
);
1985 else if (type
== SD_BUS_TYPE_STRUCT
)
1986 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
1987 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
1988 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
1994 /* OK, let's fill it in */
1995 w
= m
->containers
+ m
->n_containers
++;
1996 w
->enclosing
= type
;
1997 w
->signature
= TAKE_PTR(signature
);
1999 w
->array_size
= array_size
;
2002 w
->n_offsets
= w
->offsets_allocated
= 0;
2004 w
->need_offsets
= need_offsets
;
2009 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2014 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2017 if (c
->need_offsets
) {
2018 size_t payload
, sz
, i
;
2021 /* Variable-width arrays */
2023 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2024 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2026 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2030 for (i
= 0; i
< c
->n_offsets
; i
++)
2031 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2035 /* Fixed-width or empty arrays */
2037 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2045 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2051 assert(c
->signature
);
2053 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2056 l
= strlen(c
->signature
);
2058 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2063 memcpy(a
+1, c
->signature
, l
);
2068 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2069 bool fixed_size
= true;
2070 size_t n_variable
= 0;
2079 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2082 p
= strempty(c
->signature
);
2086 r
= signature_element_length(p
, &n
);
2095 r
= bus_gvariant_is_fixed_size(t
);
2100 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2102 /* We need to add an offset for each item that has a
2103 * variable size and that is not the last one in the
2107 if (r
== 0 && p
[n
] != 0)
2114 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2115 assert(c
->need_offsets
|| n_variable
== 0);
2117 if (isempty(c
->signature
)) {
2118 /* The unary type is encoded as fixed 1 byte padding */
2119 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2124 } else if (n_variable
<= 0) {
2127 /* Structures with fixed-size members only have to be
2128 * fixed-size themselves. But gvariant requires all fixed-size
2129 * elements to be sized a multiple of their alignment. Hence,
2130 * we must *always* add final padding after the last member so
2131 * the overall size of the structure is properly aligned. */
2133 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2135 assert(alignment
> 0);
2137 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2144 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2146 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2148 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2152 p
= strempty(c
->signature
);
2153 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2157 r
= signature_element_length(p
, &n
);
2168 r
= bus_gvariant_is_fixed_size(t
);
2171 if (r
> 0 || p
[0] == 0)
2175 k
= n_variable
- 1 - j
;
2177 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2186 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2187 struct bus_container
*c
;
2190 assert_return(m
, -EINVAL
);
2191 assert_return(!m
->sealed
, -EPERM
);
2192 assert_return(m
->n_containers
> 0, -EINVAL
);
2193 assert_return(!m
->poisoned
, -ESTALE
);
2195 c
= message_get_container(m
);
2197 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2198 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2203 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2204 r
= bus_message_close_array(m
, c
);
2205 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2206 r
= bus_message_close_variant(m
, c
);
2207 else if (IN_SET(c
->enclosing
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
))
2208 r
= bus_message_close_struct(m
, c
, true);
2210 assert_not_reached("Unknown container type");
2224 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2231 stack
[*i
].types
= types
;
2232 stack
[*i
].n_struct
= n_struct
;
2233 stack
[*i
].n_array
= n_array
;
2239 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2250 *types
= stack
[*i
].types
;
2251 *n_struct
= stack
[*i
].n_struct
;
2252 *n_array
= stack
[*i
].n_array
;
2257 _public_
int sd_bus_message_appendv(
2262 unsigned n_array
, n_struct
;
2263 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2264 unsigned stack_ptr
= 0;
2267 assert_return(m
, -EINVAL
);
2268 assert_return(types
, -EINVAL
);
2269 assert_return(!m
->sealed
, -EPERM
);
2270 assert_return(!m
->poisoned
, -ESTALE
);
2272 n_array
= (unsigned) -1;
2273 n_struct
= strlen(types
);
2278 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2279 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2285 r
= sd_bus_message_close_container(m
);
2293 if (n_array
!= (unsigned) -1)
2302 case SD_BUS_TYPE_BYTE
: {
2305 x
= (uint8_t) va_arg(ap
, int);
2306 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2310 case SD_BUS_TYPE_BOOLEAN
:
2311 case SD_BUS_TYPE_INT32
:
2312 case SD_BUS_TYPE_UINT32
:
2313 case SD_BUS_TYPE_UNIX_FD
: {
2316 /* We assume a boolean is the same as int32_t */
2317 assert_cc(sizeof(int32_t) == sizeof(int));
2319 x
= va_arg(ap
, uint32_t);
2320 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2324 case SD_BUS_TYPE_INT16
:
2325 case SD_BUS_TYPE_UINT16
: {
2328 x
= (uint16_t) va_arg(ap
, int);
2329 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2333 case SD_BUS_TYPE_INT64
:
2334 case SD_BUS_TYPE_UINT64
: {
2337 x
= va_arg(ap
, uint64_t);
2338 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2342 case SD_BUS_TYPE_DOUBLE
: {
2345 x
= va_arg(ap
, double);
2346 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2350 case SD_BUS_TYPE_STRING
:
2351 case SD_BUS_TYPE_OBJECT_PATH
:
2352 case SD_BUS_TYPE_SIGNATURE
: {
2355 x
= va_arg(ap
, const char*);
2356 r
= sd_bus_message_append_basic(m
, *t
, x
);
2360 case SD_BUS_TYPE_ARRAY
: {
2363 r
= signature_element_length(t
+ 1, &k
);
2369 memcpy(s
, t
+ 1, k
);
2372 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2377 if (n_array
== (unsigned) -1) {
2382 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2388 n_array
= va_arg(ap
, unsigned);
2393 case SD_BUS_TYPE_VARIANT
: {
2396 s
= va_arg(ap
, const char*);
2400 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2404 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2409 n_struct
= strlen(s
);
2410 n_array
= (unsigned) -1;
2415 case SD_BUS_TYPE_STRUCT_BEGIN
:
2416 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2419 r
= signature_element_length(t
, &k
);
2426 memcpy(s
, t
+ 1, k
- 2);
2429 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2434 if (n_array
== (unsigned) -1) {
2439 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2445 n_array
= (unsigned) -1;
2461 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2465 assert_return(m
, -EINVAL
);
2466 assert_return(types
, -EINVAL
);
2467 assert_return(!m
->sealed
, -EPERM
);
2468 assert_return(!m
->poisoned
, -ESTALE
);
2470 va_start(ap
, types
);
2471 r
= sd_bus_message_appendv(m
, types
, ap
);
2477 _public_
int sd_bus_message_append_array_space(
2487 assert_return(m
, -EINVAL
);
2488 assert_return(!m
->sealed
, -EPERM
);
2489 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2490 assert_return(ptr
|| size
== 0, -EINVAL
);
2491 assert_return(!m
->poisoned
, -ESTALE
);
2493 /* alignment and size of the trivial types (except bool) is
2494 * identical for gvariant and dbus1 marshalling */
2495 align
= bus_type_get_alignment(type
);
2496 sz
= bus_type_get_size(type
);
2498 assert_se(align
> 0);
2504 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2508 a
= message_extend_body(m
, align
, size
, false, false);
2512 r
= sd_bus_message_close_container(m
);
2520 _public_
int sd_bus_message_append_array(
2528 assert_return(m
, -EINVAL
);
2529 assert_return(!m
->sealed
, -EPERM
);
2530 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2531 assert_return(ptr
|| size
== 0, -EINVAL
);
2532 assert_return(!m
->poisoned
, -ESTALE
);
2534 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2538 memcpy_safe(p
, ptr
, size
);
2543 _public_
int sd_bus_message_append_array_iovec(
2546 const struct iovec
*iov
,
2547 unsigned n
/* should be size_t, but is API now… 😞 */) {
2554 assert_return(m
, -EINVAL
);
2555 assert_return(!m
->sealed
, -EPERM
);
2556 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2557 assert_return(iov
|| n
== 0, -EINVAL
);
2558 assert_return(!m
->poisoned
, -ESTALE
);
2560 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2562 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2566 for (i
= 0; i
< n
; i
++) {
2568 if (iov
[i
].iov_base
)
2569 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2571 memzero(p
, iov
[i
].iov_len
);
2573 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2579 _public_
int sd_bus_message_append_array_memfd(
2586 _cleanup_close_
int copy_fd
= -1;
2587 struct bus_body_part
*part
;
2593 assert_return(m
, -EINVAL
);
2594 assert_return(memfd
>= 0, -EBADF
);
2595 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2596 assert_return(size
> 0, -EINVAL
);
2597 assert_return(!m
->sealed
, -EPERM
);
2598 assert_return(!m
->poisoned
, -ESTALE
);
2600 r
= memfd_set_sealed(memfd
);
2604 copy_fd
= fcntl(memfd
, F_DUPFD_CLOEXEC
, 3);
2608 r
= memfd_get_size(memfd
, &real_size
);
2612 if (offset
== 0 && size
== (uint64_t) -1)
2614 else if (offset
+ size
> real_size
)
2617 align
= bus_type_get_alignment(type
);
2618 sz
= bus_type_get_size(type
);
2620 assert_se(align
> 0);
2623 if (offset
% align
!= 0)
2629 if (size
> (uint64_t) (uint32_t) -1)
2632 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2636 a
= message_extend_body(m
, align
, 0, false, false);
2640 part
= message_append_part(m
);
2644 part
->memfd
= copy_fd
;
2645 part
->memfd_offset
= offset
;
2646 part
->sealed
= true;
2650 m
->body_size
+= size
;
2651 message_extend_containers(m
, size
);
2653 return sd_bus_message_close_container(m
);
2656 _public_
int sd_bus_message_append_string_memfd(
2662 _cleanup_close_
int copy_fd
= -1;
2663 struct bus_body_part
*part
;
2664 struct bus_container
*c
;
2669 assert_return(m
, -EINVAL
);
2670 assert_return(memfd
>= 0, -EBADF
);
2671 assert_return(size
> 0, -EINVAL
);
2672 assert_return(!m
->sealed
, -EPERM
);
2673 assert_return(!m
->poisoned
, -ESTALE
);
2675 r
= memfd_set_sealed(memfd
);
2679 copy_fd
= fcntl(memfd
, FD_CLOEXEC
, 3);
2683 r
= memfd_get_size(memfd
, &real_size
);
2687 if (offset
== 0 && size
== (uint64_t) -1)
2689 else if (offset
+ size
> real_size
)
2692 /* We require this to be NUL terminated */
2696 if (size
> (uint64_t) (uint32_t) -1)
2699 c
= message_get_container(m
);
2700 if (c
->signature
&& c
->signature
[c
->index
]) {
2701 /* Container signature is already set */
2703 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2708 /* Maybe we can append to the signature? But only if this is the top-level container */
2709 if (c
->enclosing
!= 0)
2712 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2719 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2720 a
= message_extend_body(m
, 4, 4, false, false);
2724 *(uint32_t*) a
= size
- 1;
2727 part
= message_append_part(m
);
2731 part
->memfd
= copy_fd
;
2732 part
->memfd_offset
= offset
;
2733 part
->sealed
= true;
2737 m
->body_size
+= size
;
2738 message_extend_containers(m
, size
);
2740 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2741 r
= message_add_offset(m
, m
->body_size
);
2748 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2754 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2758 assert_return(m
, -EINVAL
);
2759 assert_return(!m
->sealed
, -EPERM
);
2760 assert_return(!m
->poisoned
, -ESTALE
);
2762 r
= sd_bus_message_open_container(m
, 'a', "s");
2766 STRV_FOREACH(i
, l
) {
2767 r
= sd_bus_message_append_basic(m
, 's', *i
);
2772 return sd_bus_message_close_container(m
);
2775 static int bus_message_close_header(sd_bus_message
*m
) {
2779 /* The actual user data is finished now, we just complete the
2780 variant and struct now (at least on gvariant). Remember
2781 this position, so that during parsing we know where to
2782 put the outer container end. */
2783 m
->user_body_size
= m
->body_size
;
2785 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2786 const char *signature
;
2790 /* Add offset table to end of fields array */
2791 if (m
->n_header_offsets
>= 1) {
2795 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2797 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2798 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2802 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2803 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2806 /* Add gvariant NUL byte plus signature to the end of
2807 * the body, followed by the final offset pointing to
2808 * the end of the fields array */
2810 signature
= strempty(m
->root_container
.signature
);
2811 l
= strlen(signature
);
2813 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2814 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2819 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2820 memcpy((uint8_t*) d
+ 2, signature
, l
);
2821 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2823 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2826 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2828 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2829 m
->header
->dbus1
.body_size
= m
->body_size
;
2835 _public_
int sd_bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, uint64_t timeout_usec
) {
2836 struct bus_body_part
*part
;
2841 assert_return(m
, -EINVAL
);
2846 if (m
->n_containers
> 0)
2852 if (cookie
> 0xffffffffULL
&&
2853 !BUS_MESSAGE_IS_GVARIANT(m
))
2856 /* In vtables the return signature of method calls is listed,
2857 * let's check if they match if this is a response */
2858 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2859 m
->enforced_reply_signature
&&
2860 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2863 /* If gvariant marshalling is used we need to close the body structure */
2864 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2868 /* If there's a non-trivial signature set, then add it in
2869 * here, but only on dbus1 */
2870 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2871 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2877 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2882 r
= bus_message_close_header(m
);
2886 if (BUS_MESSAGE_IS_GVARIANT(m
))
2887 m
->header
->dbus2
.cookie
= cookie
;
2889 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2891 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout_usec
;
2893 /* Add padding at the end of the fields part, since we know
2894 * the body needs to start at an 8 byte alignment. We made
2895 * sure we allocated enough space for this, so all we need to
2896 * do here is to zero it out. */
2897 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2899 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2901 /* If this is something we can send as memfd, then let's seal
2902 the memfd now. Note that we can send memfds as payload only
2903 for directed messages, and not for broadcasts. */
2904 if (m
->destination
&& m
->bus
->use_memfd
) {
2905 MESSAGE_FOREACH_PART(part
, i
, m
)
2906 if (part
->memfd
>= 0 &&
2908 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
2909 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
2912 /* Try to seal it if that makes
2913 * sense. First, unmap our own map to
2914 * make sure we don't keep it busy. */
2915 bus_body_part_unmap(part
);
2917 /* Then, sync up real memfd size */
2919 r
= memfd_set_size(part
->memfd
, sz
);
2923 /* Finally, try to seal */
2924 if (memfd_set_sealed(part
->memfd
) >= 0)
2925 part
->sealed
= true;
2929 m
->root_container
.end
= m
->user_body_size
;
2930 m
->root_container
.index
= 0;
2931 m
->root_container
.offset_index
= 0;
2932 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
2939 int bus_body_part_map(struct bus_body_part
*part
) {
2948 if (part
->size
<= 0)
2951 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2952 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
2953 static const uint8_t zeroes
[7] = { };
2954 part
->data
= (void*) zeroes
;
2958 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
2959 psz
= PAGE_ALIGN(part
->size
+ shift
);
2961 if (part
->memfd
>= 0)
2962 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
2963 else if (part
->is_zero
)
2964 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
2968 if (p
== MAP_FAILED
)
2972 part
->mmap_begin
= p
;
2973 part
->data
= (uint8_t*) p
+ shift
;
2974 part
->munmap_this
= true;
2979 void bus_body_part_unmap(struct bus_body_part
*part
) {
2983 if (part
->memfd
< 0)
2986 if (!part
->mmap_begin
)
2989 if (!part
->munmap_this
)
2992 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
2994 part
->mmap_begin
= NULL
;
2997 part
->munmap_this
= false;
3002 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3003 size_t k
, start
, end
;
3008 start
= ALIGN_TO((size_t) *rindex
, align
);
3009 end
= start
+ nbytes
;
3014 /* Verify that padding is 0 */
3015 for (k
= *rindex
; k
< start
; k
++)
3016 if (((const uint8_t*) p
)[k
] != 0)
3020 *r
= (uint8_t*) p
+ start
;
3027 static bool message_end_of_signature(sd_bus_message
*m
) {
3028 struct bus_container
*c
;
3032 c
= message_get_container(m
);
3033 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3036 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3037 struct bus_container
*c
;
3041 c
= message_get_container(m
);
3042 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3045 if (BUS_MESSAGE_IS_GVARIANT(m
))
3046 return index
>= c
->end
;
3048 assert(c
->array_size
);
3049 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3053 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3054 assert_return(m
, -EINVAL
);
3055 assert_return(m
->sealed
, -EPERM
);
3057 if (complete
&& m
->n_containers
> 0)
3060 if (message_end_of_signature(m
))
3063 if (message_end_of_array(m
, m
->rindex
))
3069 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3070 struct bus_body_part
*part
;
3076 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3077 part
= m
->cached_rindex_part
;
3078 begin
= m
->cached_rindex_part_begin
;
3088 if (index
+ sz
<= begin
+ part
->size
) {
3090 r
= bus_body_part_map(part
);
3095 *p
= (uint8_t*) part
->data
+ index
- begin
;
3097 m
->cached_rindex_part
= part
;
3098 m
->cached_rindex_part_begin
= begin
;
3103 begin
+= part
->size
;
3110 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3117 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3120 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3123 sz
= bus_gvariant_get_size(c
->signature
);
3127 if (c
->offset_index
+1 >= c
->n_offsets
)
3130 /* Variable-size array */
3132 alignment
= bus_gvariant_get_alignment(c
->signature
);
3133 assert(alignment
> 0);
3135 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3136 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3139 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3142 /* Fixed-size array */
3143 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3149 } else if (IN_SET(c
->enclosing
, 0, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
3154 if (c
->offset_index
+1 >= c
->n_offsets
)
3157 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3161 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3166 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3169 alignment
= bus_gvariant_get_alignment(t
);
3172 assert(alignment
> 0);
3174 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3175 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3179 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3182 assert_not_reached("Unknown container type");
3187 /* Reached the end */
3193 static int message_peek_body(
3200 size_t k
, start
, end
, padding
;
3201 struct bus_body_part
*part
;
3208 start
= ALIGN_TO((size_t) *rindex
, align
);
3209 padding
= start
- *rindex
;
3210 end
= start
+ nbytes
;
3212 if (end
> m
->user_body_size
)
3215 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3220 /* Verify padding */
3221 for (k
= 0; k
< padding
; k
++)
3226 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3227 if (!part
|| (nbytes
> 0 && !q
))
3238 static bool validate_nul(const char *s
, size_t l
) {
3240 /* Check for NUL chars in the string */
3241 if (memchr(s
, 0, l
))
3244 /* Check for NUL termination */
3251 static bool validate_string(const char *s
, size_t l
) {
3253 if (!validate_nul(s
, l
))
3256 /* Check if valid UTF8 */
3257 if (!utf8_is_valid(s
))
3263 static bool validate_signature(const char *s
, size_t l
) {
3265 if (!validate_nul(s
, l
))
3268 /* Check if valid signature */
3269 if (!signature_is_valid(s
, true))
3275 static bool validate_object_path(const char *s
, size_t l
) {
3277 if (!validate_nul(s
, l
))
3280 if (!object_path_is_valid(s
))
3286 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3287 struct bus_container
*c
;
3292 assert_return(m
, -EINVAL
);
3293 assert_return(m
->sealed
, -EPERM
);
3294 assert_return(bus_type_is_basic(type
), -EINVAL
);
3296 if (message_end_of_signature(m
))
3299 if (message_end_of_array(m
, m
->rindex
))
3302 c
= message_get_container(m
);
3303 if (c
->signature
[c
->index
] != type
)
3308 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3310 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3313 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3317 if (type
== SD_BUS_TYPE_STRING
)
3318 ok
= validate_string(q
, c
->item_size
-1);
3319 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3320 ok
= validate_object_path(q
, c
->item_size
-1);
3322 ok
= validate_signature(q
, c
->item_size
-1);
3328 *(const char**) p
= q
;
3332 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3334 if ((size_t) sz
!= c
->item_size
)
3337 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3340 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3346 case SD_BUS_TYPE_BYTE
:
3348 *(uint8_t*) p
= *(uint8_t*) q
;
3351 case SD_BUS_TYPE_BOOLEAN
:
3353 *(int*) p
= !!*(uint8_t*) q
;
3356 case SD_BUS_TYPE_INT16
:
3357 case SD_BUS_TYPE_UINT16
:
3359 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3362 case SD_BUS_TYPE_INT32
:
3363 case SD_BUS_TYPE_UINT32
:
3365 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3368 case SD_BUS_TYPE_INT64
:
3369 case SD_BUS_TYPE_UINT64
:
3370 case SD_BUS_TYPE_DOUBLE
:
3372 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3375 case SD_BUS_TYPE_UNIX_FD
: {
3378 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3383 *(int*) p
= m
->fds
[j
];
3389 assert_not_reached("unexpected type");
3393 r
= container_next_item(m
, c
, &rindex
);
3398 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3402 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3406 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3407 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3411 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3412 ok
= validate_object_path(q
, l
);
3414 ok
= validate_string(q
, l
);
3419 *(const char**) p
= q
;
3421 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3424 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3429 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3433 if (!validate_signature(q
, l
))
3437 *(const char**) p
= q
;
3442 align
= bus_type_get_alignment(type
);
3445 sz
= bus_type_get_size(type
);
3448 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3454 case SD_BUS_TYPE_BYTE
:
3456 *(uint8_t*) p
= *(uint8_t*) q
;
3459 case SD_BUS_TYPE_BOOLEAN
:
3461 *(int*) p
= !!*(uint32_t*) q
;
3464 case SD_BUS_TYPE_INT16
:
3465 case SD_BUS_TYPE_UINT16
:
3467 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3470 case SD_BUS_TYPE_INT32
:
3471 case SD_BUS_TYPE_UINT32
:
3473 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3476 case SD_BUS_TYPE_INT64
:
3477 case SD_BUS_TYPE_UINT64
:
3478 case SD_BUS_TYPE_DOUBLE
:
3480 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3483 case SD_BUS_TYPE_UNIX_FD
: {
3486 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3491 *(int*) p
= m
->fds
[j
];
3496 assert_not_reached("Unknown basic type...");
3503 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3509 static int bus_message_enter_array(
3511 struct bus_container
*c
,
3512 const char *contents
,
3513 uint32_t **array_size
,
3516 size_t *n_offsets
) {
3530 if (!signature_is_single(contents
, true))
3533 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3536 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3539 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3544 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3547 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3551 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3554 alignment
= bus_type_get_alignment(contents
[0]);
3558 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3562 *array_size
= (uint32_t*) q
;
3564 } else if (c
->item_size
<= 0) {
3566 /* gvariant: empty array */
3571 } else if (bus_gvariant_is_fixed_size(contents
)) {
3573 /* gvariant: fixed length array */
3574 *item_size
= bus_gvariant_get_size(contents
);
3579 size_t where
, p
= 0, framing
, sz
;
3582 /* gvariant: variable length array */
3583 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3585 where
= rindex
+ c
->item_size
- sz
;
3586 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3590 framing
= bus_gvariant_read_word_le(q
, sz
);
3591 if (framing
> c
->item_size
- sz
)
3593 if ((c
->item_size
- framing
) % sz
!= 0)
3596 *n_offsets
= (c
->item_size
- framing
) / sz
;
3598 where
= rindex
+ framing
;
3599 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3603 *offsets
= new(size_t, *n_offsets
);
3607 for (i
= 0; i
< *n_offsets
; i
++) {
3610 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3611 if (x
> c
->item_size
- sz
)
3616 (*offsets
)[i
] = rindex
+ x
;
3620 *item_size
= (*offsets
)[0] - rindex
;
3625 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3626 c
->index
+= 1 + strlen(contents
);
3631 static int bus_message_enter_variant(
3633 struct bus_container
*c
,
3634 const char *contents
,
3635 size_t *item_size
) {
3647 if (!signature_is_single(contents
, false))
3650 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3653 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3656 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3661 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3664 k
= strlen(contents
);
3665 if (1+k
> c
->item_size
)
3668 where
= rindex
+ c
->item_size
- (1+k
);
3669 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3673 if (*(char*) q
!= 0)
3676 if (memcmp((uint8_t*) q
+1, contents
, k
))
3679 *item_size
= c
->item_size
- (1+k
);
3682 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3687 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3691 if (!validate_signature(q
, l
))
3694 if (!streq(q
, contents
))
3700 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3706 static int build_struct_offsets(
3708 const char *signature
,
3712 size_t *n_offsets
) {
3714 unsigned n_variable
= 0, n_total
= 0, v
;
3715 size_t previous
= 0, where
;
3726 if (isempty(signature
)) {
3727 /* Unary type is encoded as *fixed* 1 byte padding */
3728 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3732 if (*(uint8_t *) q
!= 0)
3741 sz
= bus_gvariant_determine_word_size(size
, 0);
3745 /* First, loop over signature and count variable elements and
3746 * elements in general. We use this to know how large the
3747 * offset array is at the end of the structure. Note that
3748 * GVariant only stores offsets for all variable size elements
3749 * that are not the last item. */
3755 r
= signature_element_length(p
, &n
);
3764 r
= bus_gvariant_is_fixed_size(t
);
3769 if (r
== 0 && p
[n
] != 0) /* except the last item */
3776 if (size
< n_variable
* sz
)
3779 where
= m
->rindex
+ size
- (n_variable
* sz
);
3780 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3786 *offsets
= new(size_t, n_total
);
3792 /* Second, loop again and build an offset table */
3798 r
= signature_element_length(p
, &n
);
3807 k
= bus_gvariant_get_size(t
);
3815 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3818 if (m
->rindex
+ x
< previous
)
3821 /* The last item's end
3822 * is determined from
3825 x
= size
- (n_variable
* sz
);
3827 offset
= m
->rindex
+ x
;
3833 align
= bus_gvariant_get_alignment(t
);
3836 offset
= (*n_offsets
== 0 ? m
->rindex
: ALIGN_TO((*offsets
)[*n_offsets
-1], align
)) + k
;
3840 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3845 assert(*n_offsets
== n_total
);
3847 *item_size
= (*offsets
)[0] - m
->rindex
;
3851 static int enter_struct_or_dict_entry(
3853 struct bus_container
*c
,
3854 const char *contents
,
3857 size_t *n_offsets
) {
3868 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3871 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3876 /* gvariant with contents */
3877 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3882 static int bus_message_enter_struct(
3884 struct bus_container
*c
,
3885 const char *contents
,
3888 size_t *n_offsets
) {
3900 if (!signature_is_valid(contents
, false))
3903 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3906 l
= strlen(contents
);
3908 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
3909 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3910 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
3913 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3917 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3918 c
->index
+= 1 + l
+ 1;
3923 static int bus_message_enter_dict_entry(
3925 struct bus_container
*c
,
3926 const char *contents
,
3929 size_t *n_offsets
) {
3938 if (!signature_is_pair(contents
))
3941 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3944 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3947 l
= strlen(contents
);
3949 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
3950 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3951 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
3954 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3958 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3959 c
->index
+= 1 + l
+ 1;
3964 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
3966 const char *contents
) {
3967 struct bus_container
*c
, *w
;
3968 uint32_t *array_size
= NULL
;
3969 _cleanup_free_
char *signature
= NULL
;
3971 _cleanup_free_
size_t *offsets
= NULL
;
3972 size_t n_offsets
= 0, item_size
= 0;
3975 assert_return(m
, -EINVAL
);
3976 assert_return(m
->sealed
, -EPERM
);
3977 assert_return(type
!= 0 || !contents
, -EINVAL
);
3979 if (type
== 0 || !contents
) {
3983 /* Allow entering into anonymous containers */
3984 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
3988 if (type
!= 0 && type
!= tt
)
3991 if (contents
&& !streq(contents
, cc
))
3999 * We enforce a global limit on container depth, that is much
4000 * higher than the 32 structs and 32 arrays the specification
4001 * mandates. This is simpler to implement for us, and we need
4002 * this only to ensure our container array doesn't grow
4003 * without bounds. We are happy to return any data from a
4004 * message as long as the data itself is valid, even if the
4005 * overall message might be not.
4007 * Note that the message signature is validated when
4008 * parsing the headers, and that validation does check the
4011 * Note that the specification defines no limits on the depth
4012 * of stacked variants, but we do.
4014 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4017 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4020 if (message_end_of_signature(m
))
4023 if (message_end_of_array(m
, m
->rindex
))
4026 c
= message_get_container(m
);
4028 signature
= strdup(contents
);
4032 c
->saved_index
= c
->index
;
4035 if (type
== SD_BUS_TYPE_ARRAY
)
4036 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4037 else if (type
== SD_BUS_TYPE_VARIANT
)
4038 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4039 else if (type
== SD_BUS_TYPE_STRUCT
)
4040 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4041 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4042 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4048 /* OK, let's fill it in */
4049 w
= m
->containers
+ m
->n_containers
++;
4050 w
->enclosing
= type
;
4051 w
->signature
= TAKE_PTR(signature
);
4052 w
->peeked_signature
= NULL
;
4056 w
->begin
= m
->rindex
;
4058 /* Unary type has fixed size of 1, but virtual size of 0 */
4059 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4060 type
== SD_BUS_TYPE_STRUCT
&&
4062 w
->end
= m
->rindex
+ 0;
4064 w
->end
= m
->rindex
+ c
->item_size
;
4066 w
->array_size
= array_size
;
4067 w
->item_size
= item_size
;
4068 w
->offsets
= TAKE_PTR(offsets
);
4069 w
->n_offsets
= n_offsets
;
4070 w
->offset_index
= 0;
4075 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4076 struct bus_container
*c
;
4080 assert_return(m
, -EINVAL
);
4081 assert_return(m
->sealed
, -EPERM
);
4082 assert_return(m
->n_containers
> 0, -ENXIO
);
4084 c
= message_get_container(m
);
4086 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4087 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4091 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4092 if (m
->rindex
< c
->end
)
4095 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4098 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4099 if (c
->begin
+ l
!= m
->rindex
)
4104 free(c
->peeked_signature
);
4108 c
= message_get_container(m
);
4111 c
->index
= c
->saved_index
;
4112 r
= container_next_item(m
, c
, &m
->rindex
);
4120 static void message_quit_container(sd_bus_message
*m
) {
4121 struct bus_container
*c
;
4125 assert(m
->n_containers
> 0);
4127 c
= message_get_container(m
);
4130 assert(m
->rindex
>= c
->before
);
4131 m
->rindex
= c
->before
;
4133 /* Free container */
4138 /* Correct index of new top-level container */
4139 c
= message_get_container(m
);
4140 c
->index
= c
->saved_index
;
4143 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4144 struct bus_container
*c
;
4147 assert_return(m
, -EINVAL
);
4148 assert_return(m
->sealed
, -EPERM
);
4150 if (message_end_of_signature(m
))
4153 if (message_end_of_array(m
, m
->rindex
))
4156 c
= message_get_container(m
);
4158 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4162 *type
= c
->signature
[c
->index
];
4166 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4172 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4178 sig
= strndup(c
->signature
+ c
->index
+ 1, l
);
4182 free(c
->peeked_signature
);
4183 *contents
= c
->peeked_signature
= sig
;
4187 *type
= SD_BUS_TYPE_ARRAY
;
4192 if (IN_SET(c
->signature
[c
->index
], SD_BUS_TYPE_STRUCT_BEGIN
, SD_BUS_TYPE_DICT_ENTRY_BEGIN
)) {
4198 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4203 sig
= strndup(c
->signature
+ c
->index
+ 1, l
- 2);
4207 free(c
->peeked_signature
);
4208 *contents
= c
->peeked_signature
= sig
;
4212 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4217 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4221 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4224 if (c
->item_size
< 2)
4227 /* Look for the NUL delimiter that
4228 separates the payload from the
4229 signature. Since the body might be
4230 in a different part that then the
4231 signature we map byte by byte. */
4233 for (k
= 2; k
<= c
->item_size
; k
++) {
4236 where
= m
->rindex
+ c
->item_size
- k
;
4237 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4241 if (*(char*) q
== 0)
4245 if (k
> c
->item_size
)
4248 free(c
->peeked_signature
);
4249 c
->peeked_signature
= strndup((char*) q
+ 1, k
- 1);
4250 if (!c
->peeked_signature
)
4253 if (!signature_is_valid(c
->peeked_signature
, true))
4256 *contents
= c
->peeked_signature
;
4261 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4266 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4270 if (!validate_signature(q
, l
))
4278 *type
= SD_BUS_TYPE_VARIANT
;
4293 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4294 struct bus_container
*c
;
4296 assert_return(m
, -EINVAL
);
4297 assert_return(m
->sealed
, -EPERM
);
4300 message_reset_containers(m
);
4303 c
= message_get_container(m
);
4305 c
= message_get_container(m
);
4307 c
->offset_index
= 0;
4309 m
->rindex
= c
->begin
;
4312 c
->offset_index
= 0;
4313 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4315 return !isempty(c
->signature
);
4318 _public_
int sd_bus_message_readv(
4323 unsigned n_array
, n_struct
;
4324 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4325 unsigned stack_ptr
= 0;
4326 unsigned n_loop
= 0;
4329 assert_return(m
, -EINVAL
);
4330 assert_return(m
->sealed
, -EPERM
);
4331 assert_return(types
, -EINVAL
);
4336 /* Ideally, we'd just call ourselves recursively on every
4337 * complex type. However, the state of a va_list that is
4338 * passed to a function is undefined after that function
4339 * returns. This means we need to decode the va_list linearly
4340 * in a single stackframe. We hence implement our own
4341 * home-grown stack in an array. */
4343 n_array
= (unsigned) -1; /* length of current array entries */
4344 n_struct
= strlen(types
); /* length of current struct contents signature */
4351 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4352 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4358 r
= sd_bus_message_exit_container(m
);
4366 if (n_array
!= (unsigned) -1)
4375 case SD_BUS_TYPE_BYTE
:
4376 case SD_BUS_TYPE_BOOLEAN
:
4377 case SD_BUS_TYPE_INT16
:
4378 case SD_BUS_TYPE_UINT16
:
4379 case SD_BUS_TYPE_INT32
:
4380 case SD_BUS_TYPE_UINT32
:
4381 case SD_BUS_TYPE_INT64
:
4382 case SD_BUS_TYPE_UINT64
:
4383 case SD_BUS_TYPE_DOUBLE
:
4384 case SD_BUS_TYPE_STRING
:
4385 case SD_BUS_TYPE_OBJECT_PATH
:
4386 case SD_BUS_TYPE_SIGNATURE
:
4387 case SD_BUS_TYPE_UNIX_FD
: {
4390 p
= va_arg(ap
, void*);
4391 r
= sd_bus_message_read_basic(m
, *t
, p
);
4404 case SD_BUS_TYPE_ARRAY
: {
4407 r
= signature_element_length(t
+ 1, &k
);
4413 memcpy(s
, t
+ 1, k
);
4416 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4427 if (n_array
== (unsigned) -1) {
4432 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4438 n_array
= va_arg(ap
, unsigned);
4443 case SD_BUS_TYPE_VARIANT
: {
4446 s
= va_arg(ap
, const char *);
4450 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4460 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4465 n_struct
= strlen(s
);
4466 n_array
= (unsigned) -1;
4471 case SD_BUS_TYPE_STRUCT_BEGIN
:
4472 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4475 r
= signature_element_length(t
, &k
);
4481 memcpy(s
, t
+ 1, k
- 2);
4484 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4494 if (n_array
== (unsigned) -1) {
4499 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4505 n_array
= (unsigned) -1;
4518 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4522 assert_return(m
, -EINVAL
);
4523 assert_return(m
->sealed
, -EPERM
);
4524 assert_return(types
, -EINVAL
);
4526 va_start(ap
, types
);
4527 r
= sd_bus_message_readv(m
, types
, ap
);
4533 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4536 assert_return(m
, -EINVAL
);
4537 assert_return(m
->sealed
, -EPERM
);
4539 /* If types is NULL, read exactly one element */
4541 struct bus_container
*c
;
4544 if (message_end_of_signature(m
))
4547 if (message_end_of_array(m
, m
->rindex
))
4550 c
= message_get_container(m
);
4552 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4556 types
= strndupa(c
->signature
+ c
->index
, l
);
4561 case 0: /* Nothing to drop */
4564 case SD_BUS_TYPE_BYTE
:
4565 case SD_BUS_TYPE_BOOLEAN
:
4566 case SD_BUS_TYPE_INT16
:
4567 case SD_BUS_TYPE_UINT16
:
4568 case SD_BUS_TYPE_INT32
:
4569 case SD_BUS_TYPE_UINT32
:
4570 case SD_BUS_TYPE_INT64
:
4571 case SD_BUS_TYPE_UINT64
:
4572 case SD_BUS_TYPE_DOUBLE
:
4573 case SD_BUS_TYPE_STRING
:
4574 case SD_BUS_TYPE_OBJECT_PATH
:
4575 case SD_BUS_TYPE_SIGNATURE
:
4576 case SD_BUS_TYPE_UNIX_FD
:
4578 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4582 r
= sd_bus_message_skip(m
, types
+ 1);
4588 case SD_BUS_TYPE_ARRAY
: {
4591 r
= signature_element_length(types
+ 1, &k
);
4597 memcpy(s
, types
+1, k
);
4600 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4605 r
= sd_bus_message_skip(m
, s
);
4612 r
= sd_bus_message_exit_container(m
);
4617 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4624 case SD_BUS_TYPE_VARIANT
: {
4625 const char *contents
;
4628 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4632 if (x
!= SD_BUS_TYPE_VARIANT
)
4635 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4639 r
= sd_bus_message_skip(m
, contents
);
4644 r
= sd_bus_message_exit_container(m
);
4648 r
= sd_bus_message_skip(m
, types
+ 1);
4655 case SD_BUS_TYPE_STRUCT_BEGIN
:
4656 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4659 r
= signature_element_length(types
, &k
);
4665 memcpy(s
, types
+1, k
-2);
4668 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4672 r
= sd_bus_message_skip(m
, s
);
4676 r
= sd_bus_message_exit_container(m
);
4681 r
= sd_bus_message_skip(m
, types
+ k
);
4693 _public_
int sd_bus_message_read_array(
4699 struct bus_container
*c
;
4705 assert_return(m
, -EINVAL
);
4706 assert_return(m
->sealed
, -EPERM
);
4707 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4708 assert_return(ptr
, -EINVAL
);
4709 assert_return(size
, -EINVAL
);
4710 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4712 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4716 c
= message_get_container(m
);
4718 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4719 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4723 sz
= c
->end
- c
->begin
;
4725 align
= bus_type_get_alignment(type
);
4729 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4733 /* Zero length array, let's return some aligned
4734 * pointer that is not NULL */
4735 p
= (uint8_t*) align
;
4737 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4742 r
= sd_bus_message_exit_container(m
);
4746 *ptr
= (const void*) p
;
4752 message_quit_container(m
);
4756 static int message_peek_fields(
4767 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4770 static int message_peek_field_uint32(
4782 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4785 /* identical for gvariant and dbus1 */
4787 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4792 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4797 static int message_peek_field_uint64(
4809 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4812 /* identical for gvariant and dbus1 */
4814 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4819 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4824 static int message_peek_field_string(
4826 bool (*validate
)(const char *p
),
4838 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4843 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4849 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4853 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4859 if (!validate_nul(q
, l
))
4865 if (!validate_string(q
, l
))
4875 static int message_peek_field_signature(
4888 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4893 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4899 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
4904 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4909 if (!validate_signature(q
, l
))
4918 static int message_skip_fields(
4921 uint32_t array_size
,
4922 const char **signature
) {
4924 size_t original_index
;
4930 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
4932 original_index
= *ri
;
4938 if (array_size
!= (uint32_t) -1 &&
4939 array_size
<= *ri
- original_index
)
4946 if (t
== SD_BUS_TYPE_STRING
) {
4948 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
4954 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
4956 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
4962 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
4964 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
4970 } else if (bus_type_is_basic(t
)) {
4973 align
= bus_type_get_alignment(t
);
4974 k
= bus_type_get_size(t
);
4975 assert(align
> 0 && k
> 0);
4977 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
4983 } else if (t
== SD_BUS_TYPE_ARRAY
) {
4985 r
= signature_element_length(*signature
+1, &l
);
4995 strncpy(sig
, *signature
+ 1, l
-1);
4998 alignment
= bus_type_get_alignment(sig
[0]);
5002 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5005 if (nas
> BUS_ARRAY_MAX_SIZE
)
5008 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5012 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5017 (*signature
) += 1 + l
;
5019 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5022 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5026 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5032 } else if (IN_SET(t
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
5034 r
= signature_element_length(*signature
, &l
);
5041 strncpy(sig
, *signature
+ 1, l
-1);
5044 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5055 int bus_message_parse_fields(sd_bus_message
*m
) {
5058 uint32_t unix_fds
= 0;
5059 bool unix_fds_set
= false;
5060 void *offsets
= NULL
;
5061 unsigned n_offsets
= 0;
5067 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5070 /* Read the signature from the end of the body variant first */
5071 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5072 if (m
->footer_accessible
< 1 + sz
)
5075 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5077 if (p
< (char*) m
->footer
)
5084 /* We found the beginning of the signature
5085 * string, yay! We require the body to be a
5086 * structure, so verify it and then strip the
5087 * opening/closing brackets. */
5089 l
= ((char*) m
->footer
+ m
->footer_accessible
) - p
- (1 + sz
);
5091 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5092 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5095 c
= strndup(p
+ 1 + 1, l
- 2);
5099 free(m
->root_container
.signature
);
5100 m
->root_container
.signature
= c
;
5107 /* Calculate the actual user body size, by removing
5108 * the trailing variant signature and struct offset
5110 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5112 /* Pull out the offset table for the fields array */
5113 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5118 ri
= m
->fields_size
- sz
;
5119 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5123 framing
= bus_gvariant_read_word_le(q
, sz
);
5124 if (framing
>= m
->fields_size
- sz
)
5126 if ((m
->fields_size
- framing
) % sz
!= 0)
5130 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5134 n_offsets
= (m
->fields_size
- framing
) / sz
;
5137 m
->user_body_size
= m
->body_size
;
5140 while (ri
< m
->fields_size
) {
5141 _cleanup_free_
char *sig
= NULL
;
5142 const char *signature
;
5143 uint64_t field_type
;
5144 size_t item_size
= (size_t) -1;
5146 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5155 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5157 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5161 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5165 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5172 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5177 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5182 where
= ri
= ALIGN_TO(ri
, 8);
5183 item_size
= end
- ri
;
5184 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5188 b
= memrchr(q
, 0, item_size
);
5192 sig
= strndup(b
+1, item_size
- (b
+1-(char*) q
));
5197 item_size
= b
- (char*) q
;
5199 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5204 switch (field_type
) {
5206 case _BUS_MESSAGE_HEADER_INVALID
:
5209 case BUS_MESSAGE_HEADER_PATH
:
5214 if (!streq(signature
, "o"))
5217 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5220 case BUS_MESSAGE_HEADER_INTERFACE
:
5225 if (!streq(signature
, "s"))
5228 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5231 case BUS_MESSAGE_HEADER_MEMBER
:
5236 if (!streq(signature
, "s"))
5239 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5242 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5247 if (!streq(signature
, "s"))
5250 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5252 m
->error
._need_free
= -1;
5256 case BUS_MESSAGE_HEADER_DESTINATION
:
5261 if (!streq(signature
, "s"))
5264 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5267 case BUS_MESSAGE_HEADER_SENDER
:
5272 if (!streq(signature
, "s"))
5275 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5277 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
) {
5278 m
->creds
.unique_name
= (char*) m
->sender
;
5279 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5284 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5288 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5291 if (m
->root_container
.signature
)
5294 if (!streq(signature
, "g"))
5297 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5305 free_and_replace(m
->root_container
.signature
, c
);
5309 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5311 if (m
->reply_cookie
!= 0)
5314 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5315 /* 64bit on dbus2 */
5317 if (!streq(signature
, "t"))
5320 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5324 /* 32bit on dbus1 */
5327 if (!streq(signature
, "u"))
5330 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5334 m
->reply_cookie
= serial
;
5337 if (m
->reply_cookie
== 0)
5342 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5346 if (!streq(signature
, "u"))
5349 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5353 unix_fds_set
= true;
5357 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5358 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5367 if (m
->n_fds
!= unix_fds
)
5370 switch (m
->header
->type
) {
5372 case SD_BUS_MESSAGE_SIGNAL
:
5373 if (!m
->path
|| !m
->interface
|| !m
->member
)
5376 if (m
->reply_cookie
!= 0)
5381 case SD_BUS_MESSAGE_METHOD_CALL
:
5383 if (!m
->path
|| !m
->member
)
5386 if (m
->reply_cookie
!= 0)
5391 case SD_BUS_MESSAGE_METHOD_RETURN
:
5393 if (m
->reply_cookie
== 0)
5397 case SD_BUS_MESSAGE_METHOD_ERROR
:
5399 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5404 /* Refuse non-local messages that claim they are local */
5405 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5407 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5409 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5412 m
->root_container
.end
= m
->user_body_size
;
5414 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5415 r
= build_struct_offsets(
5417 m
->root_container
.signature
,
5419 &m
->root_container
.item_size
,
5420 &m
->root_container
.offsets
,
5421 &m
->root_container
.n_offsets
);
5426 /* Try to read the error message, but if we can't it's a non-issue */
5427 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5428 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5433 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5434 assert_return(m
, -EINVAL
);
5435 assert_return(destination
, -EINVAL
);
5436 assert_return(service_name_is_valid(destination
), -EINVAL
);
5437 assert_return(!m
->sealed
, -EPERM
);
5438 assert_return(!m
->destination
, -EEXIST
);
5440 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5443 _public_
int sd_bus_message_set_sender(sd_bus_message
*m
, const char *sender
) {
5444 assert_return(m
, -EINVAL
);
5445 assert_return(sender
, -EINVAL
);
5446 assert_return(service_name_is_valid(sender
), -EINVAL
);
5447 assert_return(!m
->sealed
, -EPERM
);
5448 assert_return(!m
->sender
, -EEXIST
);
5450 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5453 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5457 struct bus_body_part
*part
;
5463 total
= BUS_MESSAGE_SIZE(m
);
5469 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5470 MESSAGE_FOREACH_PART(part
, i
, m
)
5471 e
= mempcpy(e
, part
->data
, part
->size
);
5473 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5481 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5488 r
= sd_bus_message_enter_container(m
, 'a', "s");
5492 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5493 r
= strv_extend(l
, s
);
5500 r
= sd_bus_message_exit_container(m
);
5507 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5508 _cleanup_strv_free_
char **strv
= NULL
;
5511 assert_return(m
, -EINVAL
);
5512 assert_return(m
->sealed
, -EPERM
);
5513 assert_return(l
, -EINVAL
);
5515 r
= bus_message_read_strv_extend(m
, &strv
);
5519 *l
= TAKE_PTR(strv
);
5523 static int bus_message_get_arg_skip(
5527 const char **_contents
) {
5532 r
= sd_bus_message_rewind(m
, true);
5537 const char *contents
;
5540 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5546 /* Don't match against arguments after the first one we don't understand */
5547 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5548 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5553 *_contents
= contents
;
5559 r
= sd_bus_message_skip(m
, NULL
);
5566 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5573 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5577 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5580 return sd_bus_message_read_basic(m
, type
, str
);
5583 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5584 const char *contents
;
5591 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5595 if (type
!= SD_BUS_TYPE_ARRAY
)
5597 if (!STR_IN_SET(contents
, "s", "o", "g"))
5600 return sd_bus_message_read_strv(m
, strv
);
5603 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5604 assert_return(m
, EINVAL
);
5606 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5609 return sd_bus_error_get_errno(&m
->error
);
5612 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5613 struct bus_container
*c
;
5615 assert_return(m
, NULL
);
5617 c
= complete
? &m
->root_container
: message_get_container(m
);
5618 return strempty(c
->signature
);
5621 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5622 assert_return(m
, -EINVAL
);
5624 return isempty(m
->root_container
.signature
);
5627 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5628 assert_return(m
, -EINVAL
);
5630 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5633 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5634 bool done_something
= false;
5637 assert_return(m
, -EINVAL
);
5638 assert_return(source
, -EINVAL
);
5639 assert_return(!m
->sealed
, -EPERM
);
5640 assert_return(source
->sealed
, -EPERM
);
5643 const char *contents
;
5658 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5664 done_something
= true;
5666 if (bus_type_is_container(type
) > 0) {
5668 r
= sd_bus_message_enter_container(source
, type
, contents
);
5672 r
= sd_bus_message_open_container(m
, type
, contents
);
5676 r
= sd_bus_message_copy(m
, source
, true);
5680 r
= sd_bus_message_close_container(m
);
5684 r
= sd_bus_message_exit_container(source
);
5691 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5697 if (IN_SET(type
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
, SD_BUS_TYPE_STRING
))
5698 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5700 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5707 return done_something
;
5710 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5715 assert_return(m
, -EINVAL
);
5716 assert_return(m
->sealed
, -EPERM
);
5717 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5718 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5719 assert_return(type
|| contents
, -EINVAL
);
5720 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5722 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5726 if (type
!= 0 && type
!= t
)
5729 if (contents
&& !streq_ptr(contents
, c
))
5735 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5736 assert_return(m
, NULL
);
5741 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5742 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
5750 switch ((*m
)->header
->type
) {
5752 case SD_BUS_MESSAGE_SIGNAL
:
5753 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5759 case SD_BUS_MESSAGE_METHOD_CALL
:
5760 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5766 case SD_BUS_MESSAGE_METHOD_RETURN
:
5767 case SD_BUS_MESSAGE_METHOD_ERROR
:
5769 r
= sd_bus_message_new(bus
, &n
, (*m
)->header
->type
);
5775 n
->reply_cookie
= (*m
)->reply_cookie
;
5777 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5781 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5782 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5786 n
->error
._need_free
= -1;
5795 if ((*m
)->destination
&& !n
->destination
) {
5796 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5801 if ((*m
)->sender
&& !n
->sender
) {
5802 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5807 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5809 r
= sd_bus_message_copy(n
, *m
, true);
5813 timeout
= (*m
)->timeout
;
5814 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
)) {
5815 r
= sd_bus_get_method_call_timeout(bus
, &timeout
);
5820 r
= sd_bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5824 sd_bus_message_unref(*m
);
5830 int bus_message_append_sender(sd_bus_message
*m
, const char *sender
) {
5834 assert_return(!m
->sealed
, -EPERM
);
5835 assert_return(!m
->sender
, -EPERM
);
5837 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5840 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5841 assert_return(m
, -EINVAL
);
5842 assert_return(priority
, -EINVAL
);
5844 *priority
= m
->priority
;
5848 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5849 assert_return(m
, -EINVAL
);
5850 assert_return(!m
->sealed
, -EPERM
);
5852 m
->priority
= priority
;