1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright 2013 Lennart Poettering
12 #include "alloc-util.h"
13 #include "bus-gvariant.h"
14 #include "bus-internal.h"
15 #include "bus-message.h"
16 #include "bus-signature.h"
21 #include "memfd-util.h"
22 #include "string-util.h"
24 #include "time-util.h"
28 static int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
);
30 static void *adjust_pointer(const void *p
, void *old_base
, size_t sz
, void *new_base
) {
35 if (old_base
== new_base
)
38 if ((uint8_t*) p
< (uint8_t*) old_base
)
41 if ((uint8_t*) p
>= (uint8_t*) old_base
+ sz
)
44 return (uint8_t*) new_base
+ ((uint8_t*) p
- (uint8_t*) old_base
);
47 static void message_free_part(sd_bus_message
*m
, struct bus_body_part
*part
) {
52 close_and_munmap(part
->memfd
, part
->mmap_begin
, part
->mapped
);
53 else if (part
->munmap_this
)
54 munmap(part
->mmap_begin
, part
->mapped
);
55 else if (part
->free_this
)
62 static void message_reset_parts(sd_bus_message
*m
) {
63 struct bus_body_part
*part
;
68 while (m
->n_body_parts
> 0) {
69 struct bus_body_part
*next
= part
->next
;
70 message_free_part(m
, part
);
77 m
->cached_rindex_part
= NULL
;
78 m
->cached_rindex_part_begin
= 0;
81 static void message_reset_containers(sd_bus_message
*m
) {
86 for (i
= 0; i
< m
->n_containers
; i
++) {
87 free(m
->containers
[i
].signature
);
88 free(m
->containers
[i
].offsets
);
91 m
->containers
= mfree(m
->containers
);
93 m
->n_containers
= m
->containers_allocated
= 0;
94 m
->root_container
.index
= 0;
97 static sd_bus_message
* message_free(sd_bus_message
*m
) {
103 message_reset_parts(m
);
105 sd_bus_unref(m
->bus
);
108 close_many(m
->fds
, m
->n_fds
);
112 if (m
->iovec
!= m
->iovec_fixed
)
115 message_reset_containers(m
);
116 free(m
->root_container
.signature
);
117 free(m
->root_container
.offsets
);
119 free(m
->root_container
.peeked_signature
);
121 bus_creds_done(&m
->creds
);
125 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message
*, message_free
);
127 static void *message_extend_fields(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
129 size_t old_size
, new_size
, start
;
136 old_size
= sizeof(struct bus_header
) + m
->fields_size
;
137 start
= ALIGN_TO(old_size
, align
);
138 new_size
= start
+ sz
;
140 if (new_size
< start
||
141 new_size
> (size_t) ((uint32_t) -1))
144 if (old_size
== new_size
)
145 return (uint8_t*) m
->header
+ old_size
;
147 if (m
->free_header
) {
148 np
= realloc(m
->header
, ALIGN8(new_size
));
152 /* Initially, the header is allocated as part of
153 * the sd_bus_message itself, let's replace it by
156 np
= malloc(ALIGN8(new_size
));
160 memcpy(np
, m
->header
, sizeof(struct bus_header
));
163 /* Zero out padding */
164 if (start
> old_size
)
165 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
169 m
->fields_size
= new_size
- sizeof(struct bus_header
);
171 /* Adjust quick access pointers */
172 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
173 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
174 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
175 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
176 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
177 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
179 m
->free_header
= true;
182 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
185 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
188 return (uint8_t*) np
+ start
;
195 static int message_append_field_string(
207 /* dbus1 only allows 8bit header field ids */
211 /* dbus1 doesn't allow strings over 32bit, let's enforce this
212 * globally, to not risk convertability */
214 if (l
> (size_t) (uint32_t) -1)
217 /* Signature "(yv)" where the variant contains "s" */
219 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
221 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
222 p
= message_extend_fields(m
, 8, 8 + l
+ 1 + 1 + 1, true);
226 *((uint64_t*) p
) = h
;
233 *ret
= (char*) p
+ 8;
236 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
237 p
= message_extend_fields(m
, 8, 4 + 4 + l
+ 1, false);
246 ((uint32_t*) p
)[1] = l
;
247 memcpy(p
+ 8, s
, l
+ 1);
250 *ret
= (char*) p
+ 8;
256 static int message_append_field_signature(
267 /* dbus1 only allows 8bit header field ids */
271 /* dbus1 doesn't allow signatures over 8bit, let's enforce
272 * this globally, to not risk convertability */
277 /* Signature "(yv)" where the variant contains "g" */
279 if (BUS_MESSAGE_IS_GVARIANT(m
))
280 /* For gvariant the serialization is the same as for normal strings */
281 return message_append_field_string(m
, h
, 'g', s
, ret
);
283 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
284 p
= message_extend_fields(m
, 8, 4 + 1 + l
+ 1, false);
290 p
[2] = SD_BUS_TYPE_SIGNATURE
;
293 memcpy(p
+ 5, s
, l
+ 1);
296 *ret
= (const char*) p
+ 5;
302 static int message_append_field_uint32(sd_bus_message
*m
, uint64_t h
, uint32_t x
) {
307 /* dbus1 only allows 8bit header field ids */
311 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
312 /* (field id 64bit + ((value + NUL + signature string 'u') */
314 p
= message_extend_fields(m
, 8, 8 + 4 + 1 + 1, true);
318 *((uint64_t*) p
) = h
;
319 *((uint32_t*) (p
+ 8)) = x
;
323 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
324 p
= message_extend_fields(m
, 8, 4 + 4, false);
333 ((uint32_t*) p
)[1] = x
;
339 static int message_append_field_uint64(sd_bus_message
*m
, uint64_t h
, uint64_t x
) {
344 /* dbus1 only allows 8bit header field ids */
348 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
349 /* (field id 64bit + ((value + NUL + signature string 't') */
351 p
= message_extend_fields(m
, 8, 8 + 8 + 1 + 1, true);
355 *((uint64_t*) p
) = h
;
356 *((uint64_t*) (p
+ 8)) = x
;
360 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
361 p
= message_extend_fields(m
, 8, 4 + 4 + 8, false);
374 ((uint64_t*) p
)[1] = x
;
380 static int message_append_reply_cookie(sd_bus_message
*m
, uint64_t cookie
) {
383 if (BUS_MESSAGE_IS_GVARIANT(m
))
384 return message_append_field_uint64(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, cookie
);
386 /* 64bit cookies are not supported on dbus1 */
387 if (cookie
> 0xffffffffUL
)
390 return message_append_field_uint32(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) cookie
);
394 int bus_message_from_header(
397 size_t header_accessible
,
399 size_t footer_accessible
,
405 sd_bus_message
**ret
) {
407 _cleanup_free_ sd_bus_message
*m
= NULL
;
408 struct bus_header
*h
;
412 assert(header
|| header_accessible
<= 0);
413 assert(footer
|| footer_accessible
<= 0);
414 assert(fds
|| n_fds
<= 0);
417 if (header_accessible
< sizeof(struct bus_header
))
420 if (header_accessible
> message_size
)
422 if (footer_accessible
> message_size
)
426 if (!IN_SET(h
->version
, 1, 2))
429 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
432 if (!IN_SET(h
->endian
, BUS_LITTLE_ENDIAN
, BUS_BIG_ENDIAN
))
435 /* Note that we are happy with unknown flags in the flags header! */
437 a
= ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
440 label_sz
= strlen(label
);
451 m
->header_accessible
= header_accessible
;
453 m
->footer_accessible
= footer_accessible
;
455 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
458 if (h
->dbus2
.cookie
== 0)
461 /* dbus2 derives the sizes from the message size and
462 the offset table at the end, since it is formatted as
463 gvariant "yyyyuta{tv}v". Since the message itself is a
464 structure with precisely to variable sized entries,
465 there's only one offset in the table, which marks the
466 end of the fields array. */
468 ws
= bus_gvariant_determine_word_size(message_size
, 0);
469 if (footer_accessible
< ws
)
472 m
->fields_size
= bus_gvariant_read_word_le((uint8_t*) footer
+ footer_accessible
- ws
, ws
);
473 if (ALIGN8(m
->fields_size
) > message_size
- ws
)
475 if (m
->fields_size
< sizeof(struct bus_header
))
478 m
->fields_size
-= sizeof(struct bus_header
);
479 m
->body_size
= message_size
- (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
));
481 if (h
->dbus1
.serial
== 0)
484 /* dbus1 has the sizes in the header */
485 m
->fields_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.fields_size
);
486 m
->body_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.body_size
);
488 if (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
!= message_size
)
496 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
497 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
499 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
502 m
->bus
= sd_bus_ref(bus
);
508 int bus_message_from_malloc(
515 sd_bus_message
**ret
) {
517 _cleanup_(message_freep
) sd_bus_message
*m
= NULL
;
521 r
= bus_message_from_header(
523 buffer
, length
, /* in this case the initial bytes and the final bytes are the same */
532 sz
= length
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
);
535 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(m
->fields_size
);
537 m
->body
.sealed
= true;
542 m
->iovec
= m
->iovec_fixed
;
543 m
->iovec
[0].iov_base
= buffer
;
544 m
->iovec
[0].iov_len
= length
;
546 r
= bus_message_parse_fields(m
);
550 /* We take possession of the memory and fds now */
551 m
->free_header
= true;
558 _public_
int sd_bus_message_new(
565 assert_return(bus
, -ENOTCONN
);
566 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
567 assert_return(m
, -EINVAL
);
568 assert_return(type
< _SD_BUS_MESSAGE_TYPE_MAX
, -EINVAL
);
570 t
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
575 t
->header
= (struct bus_header
*) ((uint8_t*) t
+ ALIGN(sizeof(struct sd_bus_message
)));
576 t
->header
->endian
= BUS_NATIVE_ENDIAN
;
577 t
->header
->type
= type
;
578 t
->header
->version
= bus
->message_version
;
579 t
->allow_fds
= bus
->can_fds
|| !IN_SET(bus
->state
, BUS_HELLO
, BUS_RUNNING
);
580 t
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(t
);
581 t
->bus
= sd_bus_ref(bus
);
583 if (bus
->allow_interactive_authorization
)
584 t
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
590 _public_
int sd_bus_message_new_signal(
594 const char *interface
,
595 const char *member
) {
597 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
600 assert_return(bus
, -ENOTCONN
);
601 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
602 assert_return(object_path_is_valid(path
), -EINVAL
);
603 assert_return(interface_name_is_valid(interface
), -EINVAL
);
604 assert_return(member_name_is_valid(member
), -EINVAL
);
605 assert_return(m
, -EINVAL
);
607 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_SIGNAL
);
613 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
615 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
618 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
621 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
629 _public_
int sd_bus_message_new_method_call(
632 const char *destination
,
634 const char *interface
,
635 const char *member
) {
637 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
640 assert_return(bus
, -ENOTCONN
);
641 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
642 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
643 assert_return(object_path_is_valid(path
), -EINVAL
);
644 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
645 assert_return(member_name_is_valid(member
), -EINVAL
);
646 assert_return(m
, -EINVAL
);
648 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_CALL
);
654 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
657 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
662 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
668 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
677 static int message_new_reply(
678 sd_bus_message
*call
,
680 sd_bus_message
**m
) {
682 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
686 assert_return(call
, -EINVAL
);
687 assert_return(call
->sealed
, -EPERM
);
688 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
689 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
690 assert_return(m
, -EINVAL
);
692 cookie
= BUS_MESSAGE_COOKIE(call
);
696 r
= sd_bus_message_new(call
->bus
, &t
, type
);
702 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
703 t
->reply_cookie
= cookie
;
704 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
709 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
714 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
715 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
721 _public_
int sd_bus_message_new_method_return(
722 sd_bus_message
*call
,
723 sd_bus_message
**m
) {
725 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
728 _public_
int sd_bus_message_new_method_error(
729 sd_bus_message
*call
,
731 const sd_bus_error
*e
) {
733 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
736 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
737 assert_return(m
, -EINVAL
);
739 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
743 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
748 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
753 t
->error
._need_free
= -1;
759 _public_
int sd_bus_message_new_method_errorf(
760 sd_bus_message
*call
,
766 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
769 assert_return(name
, -EINVAL
);
770 assert_return(m
, -EINVAL
);
772 va_start(ap
, format
);
773 bus_error_setfv(&error
, name
, format
, ap
);
776 return sd_bus_message_new_method_error(call
, m
, &error
);
779 _public_
int sd_bus_message_new_method_errno(
780 sd_bus_message
*call
,
783 const sd_bus_error
*p
) {
785 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
787 if (sd_bus_error_is_set(p
))
788 return sd_bus_message_new_method_error(call
, m
, p
);
790 sd_bus_error_set_errno(&berror
, error
);
792 return sd_bus_message_new_method_error(call
, m
, &berror
);
795 _public_
int sd_bus_message_new_method_errnof(
796 sd_bus_message
*call
,
802 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
805 va_start(ap
, format
);
806 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
809 return sd_bus_message_new_method_error(call
, m
, &berror
);
812 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
816 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
817 m
->creds
.well_known_names_local
= true;
818 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
821 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
825 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
826 m
->creds
.well_known_names_driver
= true;
827 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
830 int bus_message_new_synthetic_error(
833 const sd_bus_error
*e
,
834 sd_bus_message
**m
) {
836 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
840 assert(sd_bus_error_is_set(e
));
843 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_ERROR
);
849 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
850 t
->reply_cookie
= cookie
;
852 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
856 if (bus
&& bus
->unique_name
) {
857 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
862 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
867 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
872 t
->error
._need_free
= -1;
874 bus_message_set_sender_driver(bus
, t
);
880 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
885 assert(m
->n_ref
> 0);
891 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
896 assert(m
->n_ref
> 0);
902 return message_free(m
);
905 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
906 assert_return(m
, -EINVAL
);
907 assert_return(type
, -EINVAL
);
909 *type
= m
->header
->type
;
913 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
916 assert_return(m
, -EINVAL
);
917 assert_return(cookie
, -EINVAL
);
919 c
= BUS_MESSAGE_COOKIE(m
);
923 *cookie
= BUS_MESSAGE_COOKIE(m
);
927 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
928 assert_return(m
, -EINVAL
);
929 assert_return(cookie
, -EINVAL
);
931 if (m
->reply_cookie
== 0)
934 *cookie
= m
->reply_cookie
;
938 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
939 assert_return(m
, -EINVAL
);
941 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
942 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
945 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
946 assert_return(m
, -EINVAL
);
948 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
951 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
952 assert_return(m
, -EINVAL
);
954 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
955 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
958 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
959 assert_return(m
, NULL
);
964 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
965 assert_return(m
, NULL
);
970 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
971 assert_return(m
, NULL
);
976 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
977 assert_return(m
, NULL
);
979 return m
->destination
;
982 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
983 assert_return(m
, NULL
);
988 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
989 assert_return(m
, NULL
);
991 if (!sd_bus_error_is_set(&m
->error
))
997 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
998 assert_return(m
, -EINVAL
);
999 assert_return(usec
, -EINVAL
);
1001 if (m
->monotonic
<= 0)
1004 *usec
= m
->monotonic
;
1008 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1009 assert_return(m
, -EINVAL
);
1010 assert_return(usec
, -EINVAL
);
1012 if (m
->realtime
<= 0)
1015 *usec
= m
->realtime
;
1019 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1020 assert_return(m
, -EINVAL
);
1021 assert_return(seqnum
, -EINVAL
);
1026 *seqnum
= m
->seqnum
;
1030 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1031 assert_return(m
, NULL
);
1033 if (m
->creds
.mask
== 0)
1039 _public_
int sd_bus_message_is_signal(
1041 const char *interface
,
1042 const char *member
) {
1044 assert_return(m
, -EINVAL
);
1046 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1049 if (interface
&& !streq_ptr(m
->interface
, interface
))
1052 if (member
&& !streq_ptr(m
->member
, member
))
1058 _public_
int sd_bus_message_is_method_call(
1060 const char *interface
,
1061 const char *member
) {
1063 assert_return(m
, -EINVAL
);
1065 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1068 if (interface
&& !streq_ptr(m
->interface
, interface
))
1071 if (member
&& !streq_ptr(m
->member
, member
))
1077 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1078 assert_return(m
, -EINVAL
);
1080 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1083 if (name
&& !streq_ptr(m
->error
.name
, name
))
1089 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1090 assert_return(m
, -EINVAL
);
1091 assert_return(!m
->sealed
, -EPERM
);
1092 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1094 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_REPLY_EXPECTED
, !b
);
1099 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1100 assert_return(m
, -EINVAL
);
1101 assert_return(!m
->sealed
, -EPERM
);
1103 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_AUTO_START
, !b
);
1108 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1109 assert_return(m
, -EINVAL
);
1110 assert_return(!m
->sealed
, -EPERM
);
1112 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
, b
);
1117 static struct bus_container
*message_get_container(sd_bus_message
*m
) {
1120 if (m
->n_containers
== 0)
1121 return &m
->root_container
;
1123 assert(m
->containers
);
1124 return m
->containers
+ m
->n_containers
- 1;
1127 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1128 struct bus_body_part
*part
;
1135 if (m
->n_body_parts
<= 0) {
1139 assert(m
->body_end
);
1141 part
= new0(struct bus_body_part
, 1);
1147 m
->body_end
->next
= part
;
1157 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1162 /* All other fields can be left in their defaults */
1163 assert(!part
->data
);
1164 assert(part
->memfd
< 0);
1167 part
->is_zero
= true;
1168 part
->sealed
= true;
1171 static int part_make_space(
1172 struct sd_bus_message
*m
,
1173 struct bus_body_part
*part
,
1181 assert(!part
->sealed
);
1186 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1187 size_t new_allocated
;
1189 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1190 n
= realloc(part
->data
, new_allocated
);
1197 part
->allocated
= new_allocated
;
1198 part
->free_this
= true;
1202 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1208 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1209 struct bus_container
*c
;
1212 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1214 /* Add offset to current container, unless this is the first
1215 * item in it, which will have the 0 offset, which we can
1217 c
= message_get_container(m
);
1219 if (!c
->need_offsets
)
1222 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1225 c
->offsets
[c
->n_offsets
++] = offset
;
1229 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1230 struct bus_container
*c
;
1237 /* Update counters */
1238 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++) {
1241 *c
->array_size
+= expand
;
1245 static void *message_extend_body(
1250 bool force_inline
) {
1252 size_t start_body
, end_body
, padding
, added
;
1263 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1264 end_body
= start_body
+ sz
;
1266 padding
= start_body
- m
->body_size
;
1267 added
= padding
+ sz
;
1269 /* Check for 32bit overflows */
1270 if (end_body
> (size_t) ((uint32_t) -1) ||
1271 end_body
< start_body
) {
1277 struct bus_body_part
*part
= NULL
;
1281 m
->n_body_parts
<= 0 ||
1282 m
->body_end
->sealed
||
1283 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1284 (force_inline
&& m
->body_end
->size
> MEMFD_MIN_SIZE
);
1285 /* If this must be an inlined extension, let's create a new part if
1286 * the previous part is large enough to be inlined. */
1290 part
= message_append_part(m
);
1294 part_zero(part
, padding
);
1297 part
= message_append_part(m
);
1301 r
= part_make_space(m
, part
, sz
, &p
);
1305 struct bus_container
*c
;
1307 size_t os
, start_part
, end_part
;
1313 start_part
= ALIGN_TO(part
->size
, align
);
1314 end_part
= start_part
+ sz
;
1316 r
= part_make_space(m
, part
, end_part
, &p
);
1321 memzero(p
, padding
);
1322 p
= (uint8_t*) p
+ padding
;
1325 /* Readjust pointers */
1326 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1327 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1329 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1332 /* Return something that is not NULL and is aligned */
1333 p
= (uint8_t*) align
;
1335 m
->body_size
= end_body
;
1336 message_extend_containers(m
, added
);
1339 r
= message_add_offset(m
, end_body
);
1349 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1360 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1364 f
= reallocarray(m
->fds
, sizeof(int), m
->n_fds
+ 1);
1372 m
->fds
[m
->n_fds
] = copy
;
1378 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1379 _cleanup_close_
int fd
= -1;
1380 struct bus_container
*c
;
1384 assert_return(m
, -EINVAL
);
1385 assert_return(!m
->sealed
, -EPERM
);
1386 assert_return(bus_type_is_basic(type
), -EINVAL
);
1387 assert_return(!m
->poisoned
, -ESTALE
);
1389 c
= message_get_container(m
);
1391 if (c
->signature
&& c
->signature
[c
->index
]) {
1392 /* Container signature is already set */
1394 if (c
->signature
[c
->index
] != type
)
1399 /* Maybe we can append to the signature? But only if this is the top-level container */
1400 if (c
->enclosing
!= 0)
1403 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1410 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1416 case SD_BUS_TYPE_SIGNATURE
:
1417 case SD_BUS_TYPE_STRING
:
1421 case SD_BUS_TYPE_OBJECT_PATH
:
1429 case SD_BUS_TYPE_BOOLEAN
:
1431 u8
= p
&& *(int*) p
;
1437 case SD_BUS_TYPE_UNIX_FD
:
1442 fd
= message_push_fd(m
, *(int*) p
);
1453 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1454 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1461 a
= message_extend_body(m
, align
, sz
, true, false);
1468 *stored
= (const uint8_t*) a
;
1475 case SD_BUS_TYPE_STRING
:
1476 /* To make things easy we'll serialize a NULL string
1477 * into the empty string */
1481 case SD_BUS_TYPE_OBJECT_PATH
:
1487 sz
= 4 + strlen(p
) + 1;
1490 case SD_BUS_TYPE_SIGNATURE
:
1495 sz
= 1 + strlen(p
) + 1;
1498 case SD_BUS_TYPE_BOOLEAN
:
1500 u32
= p
&& *(int*) p
;
1506 case SD_BUS_TYPE_UNIX_FD
:
1511 fd
= message_push_fd(m
, *(int*) p
);
1522 align
= bus_type_get_alignment(type
);
1523 sz
= bus_type_get_size(type
);
1530 a
= message_extend_body(m
, align
, sz
, false, false);
1534 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
1535 *(uint32_t*) a
= sz
- 5;
1536 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1539 *stored
= (const uint8_t*) a
+ 4;
1541 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1542 *(uint8_t*) a
= sz
- 2;
1543 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1546 *stored
= (const uint8_t*) a
+ 1;
1555 if (type
== SD_BUS_TYPE_UNIX_FD
)
1558 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1565 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1566 return message_append_basic(m
, type
, p
, NULL
);
1569 _public_
int sd_bus_message_append_string_space(
1574 struct bus_container
*c
;
1577 assert_return(m
, -EINVAL
);
1578 assert_return(s
, -EINVAL
);
1579 assert_return(!m
->sealed
, -EPERM
);
1580 assert_return(!m
->poisoned
, -ESTALE
);
1582 c
= message_get_container(m
);
1584 if (c
->signature
&& c
->signature
[c
->index
]) {
1585 /* Container signature is already set */
1587 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1592 /* Maybe we can append to the signature? But only if this is the top-level container */
1593 if (c
->enclosing
!= 0)
1596 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1603 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1604 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1610 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1614 *(uint32_t*) a
= size
;
1620 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1626 _public_
int sd_bus_message_append_string_iovec(
1628 const struct iovec
*iov
,
1629 unsigned n
/* should be size_t, but is API now… 😞 */) {
1636 assert_return(m
, -EINVAL
);
1637 assert_return(!m
->sealed
, -EPERM
);
1638 assert_return(iov
|| n
== 0, -EINVAL
);
1639 assert_return(!m
->poisoned
, -ESTALE
);
1641 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1643 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1647 for (i
= 0; i
< n
; i
++) {
1649 if (iov
[i
].iov_base
)
1650 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1652 memset(p
, ' ', iov
[i
].iov_len
);
1654 p
+= iov
[i
].iov_len
;
1660 static int bus_message_open_array(
1662 struct bus_container
*c
,
1663 const char *contents
,
1664 uint32_t **array_size
,
1666 bool *need_offsets
) {
1676 assert(need_offsets
);
1678 if (!signature_is_single(contents
, true))
1681 if (c
->signature
&& c
->signature
[c
->index
]) {
1683 /* Verify the existing signature */
1685 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1688 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1691 nindex
= c
->index
+ 1 + strlen(contents
);
1695 if (c
->enclosing
!= 0)
1698 /* Extend the existing signature */
1700 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1706 nindex
= e
- c
->signature
;
1709 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1710 alignment
= bus_gvariant_get_alignment(contents
);
1714 /* Add alignment padding and add to offset list */
1715 if (!message_extend_body(m
, alignment
, 0, false, false))
1718 r
= bus_gvariant_is_fixed_size(contents
);
1722 *begin
= m
->body_size
;
1723 *need_offsets
= r
== 0;
1727 struct bus_body_part
*o
;
1729 alignment
= bus_type_get_alignment(contents
[0]);
1733 a
= message_extend_body(m
, 4, 4, false, false);
1738 op
= m
->body_end
->data
;
1739 os
= m
->body_end
->size
;
1741 /* Add alignment between size and first element */
1742 if (!message_extend_body(m
, alignment
, 0, false, false))
1745 /* location of array size might have changed so let's readjust a */
1746 if (o
== m
->body_end
)
1747 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1753 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1759 static int bus_message_open_variant(
1761 struct bus_container
*c
,
1762 const char *contents
) {
1768 if (!signature_is_single(contents
, false))
1771 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1774 if (c
->signature
&& c
->signature
[c
->index
]) {
1776 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1782 if (c
->enclosing
!= 0)
1785 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1792 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1793 /* Variants are always aligned to 8 */
1795 if (!message_extend_body(m
, 8, 0, false, false))
1802 l
= strlen(contents
);
1803 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1808 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1811 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1817 static int bus_message_open_struct(
1819 struct bus_container
*c
,
1820 const char *contents
,
1822 bool *need_offsets
) {
1831 assert(need_offsets
);
1833 if (!signature_is_valid(contents
, false))
1836 if (c
->signature
&& c
->signature
[c
->index
]) {
1839 l
= strlen(contents
);
1841 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1842 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1843 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1846 nindex
= c
->index
+ 1 + l
+ 1;
1850 if (c
->enclosing
!= 0)
1853 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1859 nindex
= e
- c
->signature
;
1862 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1865 alignment
= bus_gvariant_get_alignment(contents
);
1869 if (!message_extend_body(m
, alignment
, 0, false, false))
1872 r
= bus_gvariant_is_fixed_size(contents
);
1876 *begin
= m
->body_size
;
1877 *need_offsets
= r
== 0;
1879 /* Align contents to 8 byte boundary */
1880 if (!message_extend_body(m
, 8, 0, false, false))
1884 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1890 static int bus_message_open_dict_entry(
1892 struct bus_container
*c
,
1893 const char *contents
,
1895 bool *need_offsets
) {
1903 assert(need_offsets
);
1905 if (!signature_is_pair(contents
))
1908 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1911 if (c
->signature
&& c
->signature
[c
->index
]) {
1914 l
= strlen(contents
);
1916 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
1917 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1918 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
1923 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1926 alignment
= bus_gvariant_get_alignment(contents
);
1930 if (!message_extend_body(m
, alignment
, 0, false, false))
1933 r
= bus_gvariant_is_fixed_size(contents
);
1937 *begin
= m
->body_size
;
1938 *need_offsets
= r
== 0;
1940 /* Align contents to 8 byte boundary */
1941 if (!message_extend_body(m
, 8, 0, false, false))
1948 _public_
int sd_bus_message_open_container(
1951 const char *contents
) {
1953 struct bus_container
*c
, *w
;
1954 uint32_t *array_size
= NULL
;
1955 _cleanup_free_
char *signature
= NULL
;
1956 size_t before
, begin
= 0;
1957 bool need_offsets
= false;
1960 assert_return(m
, -EINVAL
);
1961 assert_return(!m
->sealed
, -EPERM
);
1962 assert_return(contents
, -EINVAL
);
1963 assert_return(!m
->poisoned
, -ESTALE
);
1965 /* Make sure we have space for one more container */
1966 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
1971 c
= message_get_container(m
);
1973 signature
= strdup(contents
);
1979 /* Save old index in the parent container, in case we have to
1980 * abort this container */
1981 c
->saved_index
= c
->index
;
1982 before
= m
->body_size
;
1984 if (type
== SD_BUS_TYPE_ARRAY
)
1985 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
1986 else if (type
== SD_BUS_TYPE_VARIANT
)
1987 r
= bus_message_open_variant(m
, c
, contents
);
1988 else if (type
== SD_BUS_TYPE_STRUCT
)
1989 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
1990 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
1991 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
1997 /* OK, let's fill it in */
1998 w
= m
->containers
+ m
->n_containers
++;
1999 w
->enclosing
= type
;
2000 w
->signature
= TAKE_PTR(signature
);
2002 w
->array_size
= array_size
;
2005 w
->n_offsets
= w
->offsets_allocated
= 0;
2007 w
->need_offsets
= need_offsets
;
2012 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2017 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2020 if (c
->need_offsets
) {
2021 size_t payload
, sz
, i
;
2024 /* Variable-width arrays */
2026 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2027 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2029 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2033 for (i
= 0; i
< c
->n_offsets
; i
++)
2034 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2038 /* Fixed-width or empty arrays */
2040 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2048 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2054 assert(c
->signature
);
2056 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2059 l
= strlen(c
->signature
);
2061 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2066 memcpy(a
+1, c
->signature
, l
);
2071 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2072 bool fixed_size
= true;
2073 size_t n_variable
= 0;
2082 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2085 p
= strempty(c
->signature
);
2089 r
= signature_element_length(p
, &n
);
2098 r
= bus_gvariant_is_fixed_size(t
);
2103 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2105 /* We need to add an offset for each item that has a
2106 * variable size and that is not the last one in the
2110 if (r
== 0 && p
[n
] != 0)
2117 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2118 assert(c
->need_offsets
|| n_variable
== 0);
2120 if (isempty(c
->signature
)) {
2121 /* The unary type is encoded as fixed 1 byte padding */
2122 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2127 } else if (n_variable
<= 0) {
2130 /* Structures with fixed-size members only have to be
2131 * fixed-size themselves. But gvariant requires all fixed-size
2132 * elements to be sized a multiple of their alignment. Hence,
2133 * we must *always* add final padding after the last member so
2134 * the overall size of the structure is properly aligned. */
2136 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2138 assert(alignment
> 0);
2140 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2147 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2149 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2151 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2155 p
= strempty(c
->signature
);
2156 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2160 r
= signature_element_length(p
, &n
);
2171 r
= bus_gvariant_is_fixed_size(t
);
2174 if (r
> 0 || p
[0] == 0)
2178 k
= n_variable
- 1 - j
;
2180 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2189 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2190 struct bus_container
*c
;
2193 assert_return(m
, -EINVAL
);
2194 assert_return(!m
->sealed
, -EPERM
);
2195 assert_return(m
->n_containers
> 0, -EINVAL
);
2196 assert_return(!m
->poisoned
, -ESTALE
);
2198 c
= message_get_container(m
);
2200 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2201 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2206 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2207 r
= bus_message_close_array(m
, c
);
2208 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2209 r
= bus_message_close_variant(m
, c
);
2210 else if (IN_SET(c
->enclosing
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
))
2211 r
= bus_message_close_struct(m
, c
, true);
2213 assert_not_reached("Unknown container type");
2227 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2234 stack
[*i
].types
= types
;
2235 stack
[*i
].n_struct
= n_struct
;
2236 stack
[*i
].n_array
= n_array
;
2242 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2253 *types
= stack
[*i
].types
;
2254 *n_struct
= stack
[*i
].n_struct
;
2255 *n_array
= stack
[*i
].n_array
;
2260 _public_
int sd_bus_message_appendv(
2265 unsigned n_array
, n_struct
;
2266 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2267 unsigned stack_ptr
= 0;
2270 assert_return(m
, -EINVAL
);
2271 assert_return(types
, -EINVAL
);
2272 assert_return(!m
->sealed
, -EPERM
);
2273 assert_return(!m
->poisoned
, -ESTALE
);
2275 n_array
= (unsigned) -1;
2276 n_struct
= strlen(types
);
2281 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2282 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2288 r
= sd_bus_message_close_container(m
);
2296 if (n_array
!= (unsigned) -1)
2305 case SD_BUS_TYPE_BYTE
: {
2308 x
= (uint8_t) va_arg(ap
, int);
2309 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2313 case SD_BUS_TYPE_BOOLEAN
:
2314 case SD_BUS_TYPE_INT32
:
2315 case SD_BUS_TYPE_UINT32
:
2316 case SD_BUS_TYPE_UNIX_FD
: {
2319 /* We assume a boolean is the same as int32_t */
2320 assert_cc(sizeof(int32_t) == sizeof(int));
2322 x
= va_arg(ap
, uint32_t);
2323 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2327 case SD_BUS_TYPE_INT16
:
2328 case SD_BUS_TYPE_UINT16
: {
2331 x
= (uint16_t) va_arg(ap
, int);
2332 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2336 case SD_BUS_TYPE_INT64
:
2337 case SD_BUS_TYPE_UINT64
: {
2340 x
= va_arg(ap
, uint64_t);
2341 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2345 case SD_BUS_TYPE_DOUBLE
: {
2348 x
= va_arg(ap
, double);
2349 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2353 case SD_BUS_TYPE_STRING
:
2354 case SD_BUS_TYPE_OBJECT_PATH
:
2355 case SD_BUS_TYPE_SIGNATURE
: {
2358 x
= va_arg(ap
, const char*);
2359 r
= sd_bus_message_append_basic(m
, *t
, x
);
2363 case SD_BUS_TYPE_ARRAY
: {
2366 r
= signature_element_length(t
+ 1, &k
);
2372 memcpy(s
, t
+ 1, k
);
2375 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2380 if (n_array
== (unsigned) -1) {
2385 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2391 n_array
= va_arg(ap
, unsigned);
2396 case SD_BUS_TYPE_VARIANT
: {
2399 s
= va_arg(ap
, const char*);
2403 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2407 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2412 n_struct
= strlen(s
);
2413 n_array
= (unsigned) -1;
2418 case SD_BUS_TYPE_STRUCT_BEGIN
:
2419 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2422 r
= signature_element_length(t
, &k
);
2429 memcpy(s
, t
+ 1, k
- 2);
2432 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2437 if (n_array
== (unsigned) -1) {
2442 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2448 n_array
= (unsigned) -1;
2464 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2468 assert_return(m
, -EINVAL
);
2469 assert_return(types
, -EINVAL
);
2470 assert_return(!m
->sealed
, -EPERM
);
2471 assert_return(!m
->poisoned
, -ESTALE
);
2473 va_start(ap
, types
);
2474 r
= sd_bus_message_appendv(m
, types
, ap
);
2480 _public_
int sd_bus_message_append_array_space(
2490 assert_return(m
, -EINVAL
);
2491 assert_return(!m
->sealed
, -EPERM
);
2492 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2493 assert_return(ptr
|| size
== 0, -EINVAL
);
2494 assert_return(!m
->poisoned
, -ESTALE
);
2496 /* alignment and size of the trivial types (except bool) is
2497 * identical for gvariant and dbus1 marshalling */
2498 align
= bus_type_get_alignment(type
);
2499 sz
= bus_type_get_size(type
);
2501 assert_se(align
> 0);
2507 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2511 a
= message_extend_body(m
, align
, size
, false, false);
2515 r
= sd_bus_message_close_container(m
);
2523 _public_
int sd_bus_message_append_array(
2531 assert_return(m
, -EINVAL
);
2532 assert_return(!m
->sealed
, -EPERM
);
2533 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2534 assert_return(ptr
|| size
== 0, -EINVAL
);
2535 assert_return(!m
->poisoned
, -ESTALE
);
2537 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2541 memcpy_safe(p
, ptr
, size
);
2546 _public_
int sd_bus_message_append_array_iovec(
2549 const struct iovec
*iov
,
2550 unsigned n
/* should be size_t, but is API now… 😞 */) {
2557 assert_return(m
, -EINVAL
);
2558 assert_return(!m
->sealed
, -EPERM
);
2559 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2560 assert_return(iov
|| n
== 0, -EINVAL
);
2561 assert_return(!m
->poisoned
, -ESTALE
);
2563 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2565 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2569 for (i
= 0; i
< n
; i
++) {
2571 if (iov
[i
].iov_base
)
2572 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2574 memzero(p
, iov
[i
].iov_len
);
2576 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2582 _public_
int sd_bus_message_append_array_memfd(
2589 _cleanup_close_
int copy_fd
= -1;
2590 struct bus_body_part
*part
;
2596 assert_return(m
, -EINVAL
);
2597 assert_return(memfd
>= 0, -EBADF
);
2598 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2599 assert_return(size
> 0, -EINVAL
);
2600 assert_return(!m
->sealed
, -EPERM
);
2601 assert_return(!m
->poisoned
, -ESTALE
);
2603 r
= memfd_set_sealed(memfd
);
2607 copy_fd
= fcntl(memfd
, F_DUPFD_CLOEXEC
, 3);
2611 r
= memfd_get_size(memfd
, &real_size
);
2615 if (offset
== 0 && size
== (uint64_t) -1)
2617 else if (offset
+ size
> real_size
)
2620 align
= bus_type_get_alignment(type
);
2621 sz
= bus_type_get_size(type
);
2623 assert_se(align
> 0);
2626 if (offset
% align
!= 0)
2632 if (size
> (uint64_t) (uint32_t) -1)
2635 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2639 a
= message_extend_body(m
, align
, 0, false, false);
2643 part
= message_append_part(m
);
2647 part
->memfd
= copy_fd
;
2648 part
->memfd_offset
= offset
;
2649 part
->sealed
= true;
2653 m
->body_size
+= size
;
2654 message_extend_containers(m
, size
);
2656 return sd_bus_message_close_container(m
);
2659 _public_
int sd_bus_message_append_string_memfd(
2665 _cleanup_close_
int copy_fd
= -1;
2666 struct bus_body_part
*part
;
2667 struct bus_container
*c
;
2672 assert_return(m
, -EINVAL
);
2673 assert_return(memfd
>= 0, -EBADF
);
2674 assert_return(size
> 0, -EINVAL
);
2675 assert_return(!m
->sealed
, -EPERM
);
2676 assert_return(!m
->poisoned
, -ESTALE
);
2678 r
= memfd_set_sealed(memfd
);
2682 copy_fd
= fcntl(memfd
, FD_CLOEXEC
, 3);
2686 r
= memfd_get_size(memfd
, &real_size
);
2690 if (offset
== 0 && size
== (uint64_t) -1)
2692 else if (offset
+ size
> real_size
)
2695 /* We require this to be NUL terminated */
2699 if (size
> (uint64_t) (uint32_t) -1)
2702 c
= message_get_container(m
);
2703 if (c
->signature
&& c
->signature
[c
->index
]) {
2704 /* Container signature is already set */
2706 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2711 /* Maybe we can append to the signature? But only if this is the top-level container */
2712 if (c
->enclosing
!= 0)
2715 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2722 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2723 a
= message_extend_body(m
, 4, 4, false, false);
2727 *(uint32_t*) a
= size
- 1;
2730 part
= message_append_part(m
);
2734 part
->memfd
= copy_fd
;
2735 part
->memfd_offset
= offset
;
2736 part
->sealed
= true;
2740 m
->body_size
+= size
;
2741 message_extend_containers(m
, size
);
2743 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2744 r
= message_add_offset(m
, m
->body_size
);
2751 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2757 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2761 assert_return(m
, -EINVAL
);
2762 assert_return(!m
->sealed
, -EPERM
);
2763 assert_return(!m
->poisoned
, -ESTALE
);
2765 r
= sd_bus_message_open_container(m
, 'a', "s");
2769 STRV_FOREACH(i
, l
) {
2770 r
= sd_bus_message_append_basic(m
, 's', *i
);
2775 return sd_bus_message_close_container(m
);
2778 static int bus_message_close_header(sd_bus_message
*m
) {
2782 /* The actual user data is finished now, we just complete the
2783 variant and struct now (at least on gvariant). Remember
2784 this position, so that during parsing we know where to
2785 put the outer container end. */
2786 m
->user_body_size
= m
->body_size
;
2788 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2789 const char *signature
;
2793 /* Add offset table to end of fields array */
2794 if (m
->n_header_offsets
>= 1) {
2798 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2800 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2801 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2805 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2806 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2809 /* Add gvariant NUL byte plus signature to the end of
2810 * the body, followed by the final offset pointing to
2811 * the end of the fields array */
2813 signature
= strempty(m
->root_container
.signature
);
2814 l
= strlen(signature
);
2816 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2817 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2822 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2823 memcpy((uint8_t*) d
+ 2, signature
, l
);
2824 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2826 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2829 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2831 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2832 m
->header
->dbus1
.body_size
= m
->body_size
;
2838 _public_
int sd_bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, uint64_t timeout_usec
) {
2839 struct bus_body_part
*part
;
2844 assert_return(m
, -EINVAL
);
2849 if (m
->n_containers
> 0)
2855 if (cookie
> 0xffffffffULL
&&
2856 !BUS_MESSAGE_IS_GVARIANT(m
))
2859 /* In vtables the return signature of method calls is listed,
2860 * let's check if they match if this is a response */
2861 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2862 m
->enforced_reply_signature
&&
2863 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2866 /* If gvariant marshalling is used we need to close the body structure */
2867 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2871 /* If there's a non-trivial signature set, then add it in
2872 * here, but only on dbus1 */
2873 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2874 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2880 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2885 r
= bus_message_close_header(m
);
2889 if (BUS_MESSAGE_IS_GVARIANT(m
))
2890 m
->header
->dbus2
.cookie
= cookie
;
2892 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2894 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout_usec
;
2896 /* Add padding at the end of the fields part, since we know
2897 * the body needs to start at an 8 byte alignment. We made
2898 * sure we allocated enough space for this, so all we need to
2899 * do here is to zero it out. */
2900 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2902 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2904 /* If this is something we can send as memfd, then let's seal
2905 the memfd now. Note that we can send memfds as payload only
2906 for directed messages, and not for broadcasts. */
2907 if (m
->destination
&& m
->bus
->use_memfd
) {
2908 MESSAGE_FOREACH_PART(part
, i
, m
)
2909 if (part
->memfd
>= 0 &&
2911 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
2912 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
2915 /* Try to seal it if that makes
2916 * sense. First, unmap our own map to
2917 * make sure we don't keep it busy. */
2918 bus_body_part_unmap(part
);
2920 /* Then, sync up real memfd size */
2922 r
= memfd_set_size(part
->memfd
, sz
);
2926 /* Finally, try to seal */
2927 if (memfd_set_sealed(part
->memfd
) >= 0)
2928 part
->sealed
= true;
2932 m
->root_container
.end
= m
->user_body_size
;
2933 m
->root_container
.index
= 0;
2934 m
->root_container
.offset_index
= 0;
2935 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
2942 int bus_body_part_map(struct bus_body_part
*part
) {
2951 if (part
->size
<= 0)
2954 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2955 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
2956 static const uint8_t zeroes
[7] = { };
2957 part
->data
= (void*) zeroes
;
2961 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
2962 psz
= PAGE_ALIGN(part
->size
+ shift
);
2964 if (part
->memfd
>= 0)
2965 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
2966 else if (part
->is_zero
)
2967 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
2971 if (p
== MAP_FAILED
)
2975 part
->mmap_begin
= p
;
2976 part
->data
= (uint8_t*) p
+ shift
;
2977 part
->munmap_this
= true;
2982 void bus_body_part_unmap(struct bus_body_part
*part
) {
2986 if (part
->memfd
< 0)
2989 if (!part
->mmap_begin
)
2992 if (!part
->munmap_this
)
2995 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
2997 part
->mmap_begin
= NULL
;
3000 part
->munmap_this
= false;
3005 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3006 size_t k
, start
, end
;
3011 start
= ALIGN_TO((size_t) *rindex
, align
);
3012 end
= start
+ nbytes
;
3017 /* Verify that padding is 0 */
3018 for (k
= *rindex
; k
< start
; k
++)
3019 if (((const uint8_t*) p
)[k
] != 0)
3023 *r
= (uint8_t*) p
+ start
;
3030 static bool message_end_of_signature(sd_bus_message
*m
) {
3031 struct bus_container
*c
;
3035 c
= message_get_container(m
);
3036 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3039 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3040 struct bus_container
*c
;
3044 c
= message_get_container(m
);
3045 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3048 if (BUS_MESSAGE_IS_GVARIANT(m
))
3049 return index
>= c
->end
;
3051 assert(c
->array_size
);
3052 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3056 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3057 assert_return(m
, -EINVAL
);
3058 assert_return(m
->sealed
, -EPERM
);
3060 if (complete
&& m
->n_containers
> 0)
3063 if (message_end_of_signature(m
))
3066 if (message_end_of_array(m
, m
->rindex
))
3072 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3073 struct bus_body_part
*part
;
3079 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3080 part
= m
->cached_rindex_part
;
3081 begin
= m
->cached_rindex_part_begin
;
3091 if (index
+ sz
<= begin
+ part
->size
) {
3093 r
= bus_body_part_map(part
);
3098 *p
= (uint8_t*) part
->data
+ index
- begin
;
3100 m
->cached_rindex_part
= part
;
3101 m
->cached_rindex_part_begin
= begin
;
3106 begin
+= part
->size
;
3113 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3120 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3123 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3126 sz
= bus_gvariant_get_size(c
->signature
);
3130 if (c
->offset_index
+1 >= c
->n_offsets
)
3133 /* Variable-size array */
3135 alignment
= bus_gvariant_get_alignment(c
->signature
);
3136 assert(alignment
> 0);
3138 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3139 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3142 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3145 /* Fixed-size array */
3146 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3152 } else if (IN_SET(c
->enclosing
, 0, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
3157 if (c
->offset_index
+1 >= c
->n_offsets
)
3160 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3164 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3169 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3172 alignment
= bus_gvariant_get_alignment(t
);
3175 assert(alignment
> 0);
3177 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3178 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3182 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3185 assert_not_reached("Unknown container type");
3190 /* Reached the end */
3196 static int message_peek_body(
3203 size_t k
, start
, end
, padding
;
3204 struct bus_body_part
*part
;
3211 start
= ALIGN_TO((size_t) *rindex
, align
);
3212 padding
= start
- *rindex
;
3213 end
= start
+ nbytes
;
3215 if (end
> m
->user_body_size
)
3218 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3223 /* Verify padding */
3224 for (k
= 0; k
< padding
; k
++)
3229 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3230 if (!part
|| (nbytes
> 0 && !q
))
3241 static bool validate_nul(const char *s
, size_t l
) {
3243 /* Check for NUL chars in the string */
3244 if (memchr(s
, 0, l
))
3247 /* Check for NUL termination */
3254 static bool validate_string(const char *s
, size_t l
) {
3256 if (!validate_nul(s
, l
))
3259 /* Check if valid UTF8 */
3260 if (!utf8_is_valid(s
))
3266 static bool validate_signature(const char *s
, size_t l
) {
3268 if (!validate_nul(s
, l
))
3271 /* Check if valid signature */
3272 if (!signature_is_valid(s
, true))
3278 static bool validate_object_path(const char *s
, size_t l
) {
3280 if (!validate_nul(s
, l
))
3283 if (!object_path_is_valid(s
))
3289 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3290 struct bus_container
*c
;
3295 assert_return(m
, -EINVAL
);
3296 assert_return(m
->sealed
, -EPERM
);
3297 assert_return(bus_type_is_basic(type
), -EINVAL
);
3299 if (message_end_of_signature(m
))
3302 if (message_end_of_array(m
, m
->rindex
))
3305 c
= message_get_container(m
);
3306 if (c
->signature
[c
->index
] != type
)
3311 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3313 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3316 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3320 if (type
== SD_BUS_TYPE_STRING
)
3321 ok
= validate_string(q
, c
->item_size
-1);
3322 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3323 ok
= validate_object_path(q
, c
->item_size
-1);
3325 ok
= validate_signature(q
, c
->item_size
-1);
3331 *(const char**) p
= q
;
3335 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3337 if ((size_t) sz
!= c
->item_size
)
3340 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3343 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3349 case SD_BUS_TYPE_BYTE
:
3351 *(uint8_t*) p
= *(uint8_t*) q
;
3354 case SD_BUS_TYPE_BOOLEAN
:
3356 *(int*) p
= !!*(uint8_t*) q
;
3359 case SD_BUS_TYPE_INT16
:
3360 case SD_BUS_TYPE_UINT16
:
3362 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3365 case SD_BUS_TYPE_INT32
:
3366 case SD_BUS_TYPE_UINT32
:
3368 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3371 case SD_BUS_TYPE_INT64
:
3372 case SD_BUS_TYPE_UINT64
:
3373 case SD_BUS_TYPE_DOUBLE
:
3375 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3378 case SD_BUS_TYPE_UNIX_FD
: {
3381 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3386 *(int*) p
= m
->fds
[j
];
3392 assert_not_reached("unexpected type");
3396 r
= container_next_item(m
, c
, &rindex
);
3401 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3405 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3409 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3410 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3414 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3415 ok
= validate_object_path(q
, l
);
3417 ok
= validate_string(q
, l
);
3422 *(const char**) p
= q
;
3424 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3427 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3432 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3436 if (!validate_signature(q
, l
))
3440 *(const char**) p
= q
;
3445 align
= bus_type_get_alignment(type
);
3448 sz
= bus_type_get_size(type
);
3451 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3457 case SD_BUS_TYPE_BYTE
:
3459 *(uint8_t*) p
= *(uint8_t*) q
;
3462 case SD_BUS_TYPE_BOOLEAN
:
3464 *(int*) p
= !!*(uint32_t*) q
;
3467 case SD_BUS_TYPE_INT16
:
3468 case SD_BUS_TYPE_UINT16
:
3470 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3473 case SD_BUS_TYPE_INT32
:
3474 case SD_BUS_TYPE_UINT32
:
3476 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3479 case SD_BUS_TYPE_INT64
:
3480 case SD_BUS_TYPE_UINT64
:
3481 case SD_BUS_TYPE_DOUBLE
:
3483 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3486 case SD_BUS_TYPE_UNIX_FD
: {
3489 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3494 *(int*) p
= m
->fds
[j
];
3499 assert_not_reached("Unknown basic type...");
3506 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3512 static int bus_message_enter_array(
3514 struct bus_container
*c
,
3515 const char *contents
,
3516 uint32_t **array_size
,
3519 size_t *n_offsets
) {
3533 if (!signature_is_single(contents
, true))
3536 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3539 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3542 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3547 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3550 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3554 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3557 alignment
= bus_type_get_alignment(contents
[0]);
3561 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3565 *array_size
= (uint32_t*) q
;
3567 } else if (c
->item_size
<= 0) {
3569 /* gvariant: empty array */
3574 } else if (bus_gvariant_is_fixed_size(contents
)) {
3576 /* gvariant: fixed length array */
3577 *item_size
= bus_gvariant_get_size(contents
);
3582 size_t where
, p
= 0, framing
, sz
;
3585 /* gvariant: variable length array */
3586 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3588 where
= rindex
+ c
->item_size
- sz
;
3589 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3593 framing
= bus_gvariant_read_word_le(q
, sz
);
3594 if (framing
> c
->item_size
- sz
)
3596 if ((c
->item_size
- framing
) % sz
!= 0)
3599 *n_offsets
= (c
->item_size
- framing
) / sz
;
3601 where
= rindex
+ framing
;
3602 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3606 *offsets
= new(size_t, *n_offsets
);
3610 for (i
= 0; i
< *n_offsets
; i
++) {
3613 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3614 if (x
> c
->item_size
- sz
)
3619 (*offsets
)[i
] = rindex
+ x
;
3623 *item_size
= (*offsets
)[0] - rindex
;
3628 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3629 c
->index
+= 1 + strlen(contents
);
3634 static int bus_message_enter_variant(
3636 struct bus_container
*c
,
3637 const char *contents
,
3638 size_t *item_size
) {
3650 if (!signature_is_single(contents
, false))
3653 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3656 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3659 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3664 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3667 k
= strlen(contents
);
3668 if (1+k
> c
->item_size
)
3671 where
= rindex
+ c
->item_size
- (1+k
);
3672 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3676 if (*(char*) q
!= 0)
3679 if (memcmp((uint8_t*) q
+1, contents
, k
))
3682 *item_size
= c
->item_size
- (1+k
);
3685 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3690 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3694 if (!validate_signature(q
, l
))
3697 if (!streq(q
, contents
))
3703 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3709 static int build_struct_offsets(
3711 const char *signature
,
3715 size_t *n_offsets
) {
3717 unsigned n_variable
= 0, n_total
= 0, v
;
3718 size_t previous
= 0, where
;
3729 if (isempty(signature
)) {
3730 /* Unary type is encoded as *fixed* 1 byte padding */
3731 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3735 if (*(uint8_t *) q
!= 0)
3744 sz
= bus_gvariant_determine_word_size(size
, 0);
3748 /* First, loop over signature and count variable elements and
3749 * elements in general. We use this to know how large the
3750 * offset array is at the end of the structure. Note that
3751 * GVariant only stores offsets for all variable size elements
3752 * that are not the last item. */
3758 r
= signature_element_length(p
, &n
);
3767 r
= bus_gvariant_is_fixed_size(t
);
3772 if (r
== 0 && p
[n
] != 0) /* except the last item */
3779 if (size
< n_variable
* sz
)
3782 where
= m
->rindex
+ size
- (n_variable
* sz
);
3783 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3789 *offsets
= new(size_t, n_total
);
3795 /* Second, loop again and build an offset table */
3801 r
= signature_element_length(p
, &n
);
3810 k
= bus_gvariant_get_size(t
);
3818 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3821 if (m
->rindex
+ x
< previous
)
3824 /* The last item's end
3825 * is determined from
3828 x
= size
- (n_variable
* sz
);
3830 offset
= m
->rindex
+ x
;
3836 align
= bus_gvariant_get_alignment(t
);
3839 offset
= (*n_offsets
== 0 ? m
->rindex
: ALIGN_TO((*offsets
)[*n_offsets
-1], align
)) + k
;
3843 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3848 assert(*n_offsets
== n_total
);
3850 *item_size
= (*offsets
)[0] - m
->rindex
;
3854 static int enter_struct_or_dict_entry(
3856 struct bus_container
*c
,
3857 const char *contents
,
3860 size_t *n_offsets
) {
3871 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3874 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3879 /* gvariant with contents */
3880 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3885 static int bus_message_enter_struct(
3887 struct bus_container
*c
,
3888 const char *contents
,
3891 size_t *n_offsets
) {
3903 if (!signature_is_valid(contents
, false))
3906 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3909 l
= strlen(contents
);
3911 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
3912 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3913 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
3916 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3920 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3921 c
->index
+= 1 + l
+ 1;
3926 static int bus_message_enter_dict_entry(
3928 struct bus_container
*c
,
3929 const char *contents
,
3932 size_t *n_offsets
) {
3941 if (!signature_is_pair(contents
))
3944 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3947 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3950 l
= strlen(contents
);
3952 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
3953 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3954 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
3957 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3961 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3962 c
->index
+= 1 + l
+ 1;
3967 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
3969 const char *contents
) {
3970 struct bus_container
*c
, *w
;
3971 uint32_t *array_size
= NULL
;
3972 _cleanup_free_
char *signature
= NULL
;
3974 _cleanup_free_
size_t *offsets
= NULL
;
3975 size_t n_offsets
= 0, item_size
= 0;
3978 assert_return(m
, -EINVAL
);
3979 assert_return(m
->sealed
, -EPERM
);
3980 assert_return(type
!= 0 || !contents
, -EINVAL
);
3982 if (type
== 0 || !contents
) {
3986 /* Allow entering into anonymous containers */
3987 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
3991 if (type
!= 0 && type
!= tt
)
3994 if (contents
&& !streq(contents
, cc
))
4002 * We enforce a global limit on container depth, that is much
4003 * higher than the 32 structs and 32 arrays the specification
4004 * mandates. This is simpler to implement for us, and we need
4005 * this only to ensure our container array doesn't grow
4006 * without bounds. We are happy to return any data from a
4007 * message as long as the data itself is valid, even if the
4008 * overall message might be not.
4010 * Note that the message signature is validated when
4011 * parsing the headers, and that validation does check the
4014 * Note that the specification defines no limits on the depth
4015 * of stacked variants, but we do.
4017 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4020 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4023 if (message_end_of_signature(m
))
4026 if (message_end_of_array(m
, m
->rindex
))
4029 c
= message_get_container(m
);
4031 signature
= strdup(contents
);
4035 c
->saved_index
= c
->index
;
4038 if (type
== SD_BUS_TYPE_ARRAY
)
4039 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4040 else if (type
== SD_BUS_TYPE_VARIANT
)
4041 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4042 else if (type
== SD_BUS_TYPE_STRUCT
)
4043 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4044 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4045 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4051 /* OK, let's fill it in */
4052 w
= m
->containers
+ m
->n_containers
++;
4053 w
->enclosing
= type
;
4054 w
->signature
= TAKE_PTR(signature
);
4055 w
->peeked_signature
= NULL
;
4059 w
->begin
= m
->rindex
;
4061 /* Unary type has fixed size of 1, but virtual size of 0 */
4062 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4063 type
== SD_BUS_TYPE_STRUCT
&&
4065 w
->end
= m
->rindex
+ 0;
4067 w
->end
= m
->rindex
+ c
->item_size
;
4069 w
->array_size
= array_size
;
4070 w
->item_size
= item_size
;
4071 w
->offsets
= TAKE_PTR(offsets
);
4072 w
->n_offsets
= n_offsets
;
4073 w
->offset_index
= 0;
4078 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4079 struct bus_container
*c
;
4083 assert_return(m
, -EINVAL
);
4084 assert_return(m
->sealed
, -EPERM
);
4085 assert_return(m
->n_containers
> 0, -ENXIO
);
4087 c
= message_get_container(m
);
4089 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4090 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4094 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4095 if (m
->rindex
< c
->end
)
4098 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4101 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4102 if (c
->begin
+ l
!= m
->rindex
)
4107 free(c
->peeked_signature
);
4111 c
= message_get_container(m
);
4114 c
->index
= c
->saved_index
;
4115 r
= container_next_item(m
, c
, &m
->rindex
);
4123 static void message_quit_container(sd_bus_message
*m
) {
4124 struct bus_container
*c
;
4128 assert(m
->n_containers
> 0);
4130 c
= message_get_container(m
);
4133 assert(m
->rindex
>= c
->before
);
4134 m
->rindex
= c
->before
;
4136 /* Free container */
4141 /* Correct index of new top-level container */
4142 c
= message_get_container(m
);
4143 c
->index
= c
->saved_index
;
4146 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4147 struct bus_container
*c
;
4150 assert_return(m
, -EINVAL
);
4151 assert_return(m
->sealed
, -EPERM
);
4153 if (message_end_of_signature(m
))
4156 if (message_end_of_array(m
, m
->rindex
))
4159 c
= message_get_container(m
);
4161 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4165 *type
= c
->signature
[c
->index
];
4169 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4175 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4181 sig
= strndup(c
->signature
+ c
->index
+ 1, l
);
4185 free(c
->peeked_signature
);
4186 *contents
= c
->peeked_signature
= sig
;
4190 *type
= SD_BUS_TYPE_ARRAY
;
4195 if (IN_SET(c
->signature
[c
->index
], SD_BUS_TYPE_STRUCT_BEGIN
, SD_BUS_TYPE_DICT_ENTRY_BEGIN
)) {
4201 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4206 sig
= strndup(c
->signature
+ c
->index
+ 1, l
- 2);
4210 free(c
->peeked_signature
);
4211 *contents
= c
->peeked_signature
= sig
;
4215 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4220 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4224 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4227 if (c
->item_size
< 2)
4230 /* Look for the NUL delimiter that
4231 separates the payload from the
4232 signature. Since the body might be
4233 in a different part that then the
4234 signature we map byte by byte. */
4236 for (k
= 2; k
<= c
->item_size
; k
++) {
4239 where
= m
->rindex
+ c
->item_size
- k
;
4240 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4244 if (*(char*) q
== 0)
4248 if (k
> c
->item_size
)
4251 free(c
->peeked_signature
);
4252 c
->peeked_signature
= strndup((char*) q
+ 1, k
- 1);
4253 if (!c
->peeked_signature
)
4256 if (!signature_is_valid(c
->peeked_signature
, true))
4259 *contents
= c
->peeked_signature
;
4264 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4269 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4273 if (!validate_signature(q
, l
))
4281 *type
= SD_BUS_TYPE_VARIANT
;
4296 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4297 struct bus_container
*c
;
4299 assert_return(m
, -EINVAL
);
4300 assert_return(m
->sealed
, -EPERM
);
4303 message_reset_containers(m
);
4306 c
= message_get_container(m
);
4308 c
= message_get_container(m
);
4310 c
->offset_index
= 0;
4312 m
->rindex
= c
->begin
;
4315 c
->offset_index
= 0;
4316 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4318 return !isempty(c
->signature
);
4321 static int message_read_ap(
4326 unsigned n_array
, n_struct
;
4327 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4328 unsigned stack_ptr
= 0;
4329 unsigned n_loop
= 0;
4337 /* Ideally, we'd just call ourselves recursively on every
4338 * complex type. However, the state of a va_list that is
4339 * passed to a function is undefined after that function
4340 * returns. This means we need to docode the va_list linearly
4341 * in a single stackframe. We hence implement our own
4342 * home-grown stack in an array. */
4344 n_array
= (unsigned) -1; /* length of current array entries */
4345 n_struct
= strlen(types
); /* length of current struct contents signature */
4352 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4353 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4359 r
= sd_bus_message_exit_container(m
);
4367 if (n_array
!= (unsigned) -1)
4376 case SD_BUS_TYPE_BYTE
:
4377 case SD_BUS_TYPE_BOOLEAN
:
4378 case SD_BUS_TYPE_INT16
:
4379 case SD_BUS_TYPE_UINT16
:
4380 case SD_BUS_TYPE_INT32
:
4381 case SD_BUS_TYPE_UINT32
:
4382 case SD_BUS_TYPE_INT64
:
4383 case SD_BUS_TYPE_UINT64
:
4384 case SD_BUS_TYPE_DOUBLE
:
4385 case SD_BUS_TYPE_STRING
:
4386 case SD_BUS_TYPE_OBJECT_PATH
:
4387 case SD_BUS_TYPE_SIGNATURE
:
4388 case SD_BUS_TYPE_UNIX_FD
: {
4391 p
= va_arg(ap
, void*);
4392 r
= sd_bus_message_read_basic(m
, *t
, p
);
4405 case SD_BUS_TYPE_ARRAY
: {
4408 r
= signature_element_length(t
+ 1, &k
);
4414 memcpy(s
, t
+ 1, k
);
4417 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4428 if (n_array
== (unsigned) -1) {
4433 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4439 n_array
= va_arg(ap
, unsigned);
4444 case SD_BUS_TYPE_VARIANT
: {
4447 s
= va_arg(ap
, const char *);
4451 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4461 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4466 n_struct
= strlen(s
);
4467 n_array
= (unsigned) -1;
4472 case SD_BUS_TYPE_STRUCT_BEGIN
:
4473 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4476 r
= signature_element_length(t
, &k
);
4482 memcpy(s
, t
+ 1, k
- 2);
4485 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4495 if (n_array
== (unsigned) -1) {
4500 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4506 n_array
= (unsigned) -1;
4519 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4523 assert_return(m
, -EINVAL
);
4524 assert_return(m
->sealed
, -EPERM
);
4525 assert_return(types
, -EINVAL
);
4527 va_start(ap
, types
);
4528 r
= message_read_ap(m
, types
, ap
);
4534 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4537 assert_return(m
, -EINVAL
);
4538 assert_return(m
->sealed
, -EPERM
);
4540 /* If types is NULL, read exactly one element */
4542 struct bus_container
*c
;
4545 if (message_end_of_signature(m
))
4548 if (message_end_of_array(m
, m
->rindex
))
4551 c
= message_get_container(m
);
4553 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4557 types
= strndupa(c
->signature
+ c
->index
, l
);
4562 case 0: /* Nothing to drop */
4565 case SD_BUS_TYPE_BYTE
:
4566 case SD_BUS_TYPE_BOOLEAN
:
4567 case SD_BUS_TYPE_INT16
:
4568 case SD_BUS_TYPE_UINT16
:
4569 case SD_BUS_TYPE_INT32
:
4570 case SD_BUS_TYPE_UINT32
:
4571 case SD_BUS_TYPE_INT64
:
4572 case SD_BUS_TYPE_UINT64
:
4573 case SD_BUS_TYPE_DOUBLE
:
4574 case SD_BUS_TYPE_STRING
:
4575 case SD_BUS_TYPE_OBJECT_PATH
:
4576 case SD_BUS_TYPE_SIGNATURE
:
4577 case SD_BUS_TYPE_UNIX_FD
:
4579 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4583 r
= sd_bus_message_skip(m
, types
+ 1);
4589 case SD_BUS_TYPE_ARRAY
: {
4592 r
= signature_element_length(types
+ 1, &k
);
4598 memcpy(s
, types
+1, k
);
4601 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4606 r
= sd_bus_message_skip(m
, s
);
4613 r
= sd_bus_message_exit_container(m
);
4618 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4625 case SD_BUS_TYPE_VARIANT
: {
4626 const char *contents
;
4629 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4633 if (x
!= SD_BUS_TYPE_VARIANT
)
4636 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4640 r
= sd_bus_message_skip(m
, contents
);
4645 r
= sd_bus_message_exit_container(m
);
4649 r
= sd_bus_message_skip(m
, types
+ 1);
4656 case SD_BUS_TYPE_STRUCT_BEGIN
:
4657 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4660 r
= signature_element_length(types
, &k
);
4666 memcpy(s
, types
+1, k
-2);
4669 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4673 r
= sd_bus_message_skip(m
, s
);
4677 r
= sd_bus_message_exit_container(m
);
4682 r
= sd_bus_message_skip(m
, types
+ k
);
4694 _public_
int sd_bus_message_read_array(
4700 struct bus_container
*c
;
4706 assert_return(m
, -EINVAL
);
4707 assert_return(m
->sealed
, -EPERM
);
4708 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4709 assert_return(ptr
, -EINVAL
);
4710 assert_return(size
, -EINVAL
);
4711 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4713 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4717 c
= message_get_container(m
);
4719 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4720 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4724 sz
= c
->end
- c
->begin
;
4726 align
= bus_type_get_alignment(type
);
4730 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4734 /* Zero length array, let's return some aligned
4735 * pointer that is not NULL */
4736 p
= (uint8_t*) align
;
4738 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4743 r
= sd_bus_message_exit_container(m
);
4747 *ptr
= (const void*) p
;
4753 message_quit_container(m
);
4757 static int message_peek_fields(
4768 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4771 static int message_peek_field_uint32(
4783 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4786 /* identical for gvariant and dbus1 */
4788 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4793 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4798 static int message_peek_field_uint64(
4810 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4813 /* identical for gvariant and dbus1 */
4815 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4820 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4825 static int message_peek_field_string(
4827 bool (*validate
)(const char *p
),
4839 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4844 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4850 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4854 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4860 if (!validate_nul(q
, l
))
4866 if (!validate_string(q
, l
))
4876 static int message_peek_field_signature(
4889 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4894 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4900 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
4905 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4910 if (!validate_signature(q
, l
))
4919 static int message_skip_fields(
4922 uint32_t array_size
,
4923 const char **signature
) {
4925 size_t original_index
;
4931 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
4933 original_index
= *ri
;
4939 if (array_size
!= (uint32_t) -1 &&
4940 array_size
<= *ri
- original_index
)
4947 if (t
== SD_BUS_TYPE_STRING
) {
4949 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
4955 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
4957 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
4963 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
4965 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
4971 } else if (bus_type_is_basic(t
)) {
4974 align
= bus_type_get_alignment(t
);
4975 k
= bus_type_get_size(t
);
4976 assert(align
> 0 && k
> 0);
4978 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
4984 } else if (t
== SD_BUS_TYPE_ARRAY
) {
4986 r
= signature_element_length(*signature
+1, &l
);
4996 strncpy(sig
, *signature
+ 1, l
-1);
4999 alignment
= bus_type_get_alignment(sig
[0]);
5003 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5006 if (nas
> BUS_ARRAY_MAX_SIZE
)
5009 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5013 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5018 (*signature
) += 1 + l
;
5020 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5023 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5027 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5033 } else if (IN_SET(t
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
5035 r
= signature_element_length(*signature
, &l
);
5042 strncpy(sig
, *signature
+ 1, l
-1);
5045 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5056 int bus_message_parse_fields(sd_bus_message
*m
) {
5059 uint32_t unix_fds
= 0;
5060 bool unix_fds_set
= false;
5061 void *offsets
= NULL
;
5062 unsigned n_offsets
= 0;
5068 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5071 /* Read the signature from the end of the body variant first */
5072 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5073 if (m
->footer_accessible
< 1 + sz
)
5076 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5078 if (p
< (char*) m
->footer
)
5085 /* We found the beginning of the signature
5086 * string, yay! We require the body to be a
5087 * structure, so verify it and then strip the
5088 * opening/closing brackets. */
5090 l
= ((char*) m
->footer
+ m
->footer_accessible
) - p
- (1 + sz
);
5092 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5093 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5096 c
= strndup(p
+ 1 + 1, l
- 2);
5100 free(m
->root_container
.signature
);
5101 m
->root_container
.signature
= c
;
5108 /* Calculate the actual user body size, by removing
5109 * the trailing variant signature and struct offset
5111 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5113 /* Pull out the offset table for the fields array */
5114 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5119 ri
= m
->fields_size
- sz
;
5120 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5124 framing
= bus_gvariant_read_word_le(q
, sz
);
5125 if (framing
>= m
->fields_size
- sz
)
5127 if ((m
->fields_size
- framing
) % sz
!= 0)
5131 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5135 n_offsets
= (m
->fields_size
- framing
) / sz
;
5138 m
->user_body_size
= m
->body_size
;
5141 while (ri
< m
->fields_size
) {
5142 _cleanup_free_
char *sig
= NULL
;
5143 const char *signature
;
5144 uint64_t field_type
;
5145 size_t item_size
= (size_t) -1;
5147 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5156 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5158 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5162 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5166 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5173 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5178 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5183 where
= ri
= ALIGN_TO(ri
, 8);
5184 item_size
= end
- ri
;
5185 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5189 b
= memrchr(q
, 0, item_size
);
5193 sig
= strndup(b
+1, item_size
- (b
+1-(char*) q
));
5198 item_size
= b
- (char*) q
;
5200 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5205 switch (field_type
) {
5207 case _BUS_MESSAGE_HEADER_INVALID
:
5210 case BUS_MESSAGE_HEADER_PATH
:
5215 if (!streq(signature
, "o"))
5218 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5221 case BUS_MESSAGE_HEADER_INTERFACE
:
5226 if (!streq(signature
, "s"))
5229 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5232 case BUS_MESSAGE_HEADER_MEMBER
:
5237 if (!streq(signature
, "s"))
5240 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5243 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5248 if (!streq(signature
, "s"))
5251 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5253 m
->error
._need_free
= -1;
5257 case BUS_MESSAGE_HEADER_DESTINATION
:
5262 if (!streq(signature
, "s"))
5265 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5268 case BUS_MESSAGE_HEADER_SENDER
:
5273 if (!streq(signature
, "s"))
5276 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5278 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
) {
5279 m
->creds
.unique_name
= (char*) m
->sender
;
5280 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5285 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5289 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5292 if (m
->root_container
.signature
)
5295 if (!streq(signature
, "g"))
5298 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5306 free_and_replace(m
->root_container
.signature
, c
);
5310 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5312 if (m
->reply_cookie
!= 0)
5315 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5316 /* 64bit on dbus2 */
5318 if (!streq(signature
, "t"))
5321 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5325 /* 32bit on dbus1 */
5328 if (!streq(signature
, "u"))
5331 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5335 m
->reply_cookie
= serial
;
5338 if (m
->reply_cookie
== 0)
5343 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5347 if (!streq(signature
, "u"))
5350 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5354 unix_fds_set
= true;
5358 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5359 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5368 if (m
->n_fds
!= unix_fds
)
5371 switch (m
->header
->type
) {
5373 case SD_BUS_MESSAGE_SIGNAL
:
5374 if (!m
->path
|| !m
->interface
|| !m
->member
)
5377 if (m
->reply_cookie
!= 0)
5382 case SD_BUS_MESSAGE_METHOD_CALL
:
5384 if (!m
->path
|| !m
->member
)
5387 if (m
->reply_cookie
!= 0)
5392 case SD_BUS_MESSAGE_METHOD_RETURN
:
5394 if (m
->reply_cookie
== 0)
5398 case SD_BUS_MESSAGE_METHOD_ERROR
:
5400 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5405 /* Refuse non-local messages that claim they are local */
5406 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5408 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5410 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5413 m
->root_container
.end
= m
->user_body_size
;
5415 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5416 r
= build_struct_offsets(
5418 m
->root_container
.signature
,
5420 &m
->root_container
.item_size
,
5421 &m
->root_container
.offsets
,
5422 &m
->root_container
.n_offsets
);
5427 /* Try to read the error message, but if we can't it's a non-issue */
5428 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5429 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5434 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5435 assert_return(m
, -EINVAL
);
5436 assert_return(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(!m
->sealed
, -EPERM
);
5447 assert_return(!m
->sender
, -EEXIST
);
5449 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5452 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5456 struct bus_body_part
*part
;
5462 total
= BUS_MESSAGE_SIZE(m
);
5468 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5469 MESSAGE_FOREACH_PART(part
, i
, m
)
5470 e
= mempcpy(e
, part
->data
, part
->size
);
5472 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5480 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5487 r
= sd_bus_message_enter_container(m
, 'a', "s");
5491 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5492 r
= strv_extend(l
, s
);
5499 r
= sd_bus_message_exit_container(m
);
5506 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5507 _cleanup_strv_free_
char **strv
= NULL
;
5510 assert_return(m
, -EINVAL
);
5511 assert_return(m
->sealed
, -EPERM
);
5512 assert_return(l
, -EINVAL
);
5514 r
= bus_message_read_strv_extend(m
, &strv
);
5518 *l
= TAKE_PTR(strv
);
5522 static int bus_message_get_arg_skip(
5526 const char **_contents
) {
5531 r
= sd_bus_message_rewind(m
, true);
5536 const char *contents
;
5539 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5545 /* Don't match against arguments after the first one we don't understand */
5546 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5547 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5552 *_contents
= contents
;
5558 r
= sd_bus_message_skip(m
, NULL
);
5565 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5572 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5576 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5579 return sd_bus_message_read_basic(m
, type
, str
);
5582 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5583 const char *contents
;
5590 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5594 if (type
!= SD_BUS_TYPE_ARRAY
)
5596 if (!STR_IN_SET(contents
, "s", "o", "g"))
5599 return sd_bus_message_read_strv(m
, strv
);
5602 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5603 assert_return(m
, EINVAL
);
5605 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5608 return sd_bus_error_get_errno(&m
->error
);
5611 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5612 struct bus_container
*c
;
5614 assert_return(m
, NULL
);
5616 c
= complete
? &m
->root_container
: message_get_container(m
);
5617 return strempty(c
->signature
);
5620 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5621 assert_return(m
, -EINVAL
);
5623 return isempty(m
->root_container
.signature
);
5626 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5627 assert_return(m
, -EINVAL
);
5629 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5632 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5633 bool done_something
= false;
5636 assert_return(m
, -EINVAL
);
5637 assert_return(source
, -EINVAL
);
5638 assert_return(!m
->sealed
, -EPERM
);
5639 assert_return(source
->sealed
, -EPERM
);
5642 const char *contents
;
5657 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5663 done_something
= true;
5665 if (bus_type_is_container(type
) > 0) {
5667 r
= sd_bus_message_enter_container(source
, type
, contents
);
5671 r
= sd_bus_message_open_container(m
, type
, contents
);
5675 r
= sd_bus_message_copy(m
, source
, true);
5679 r
= sd_bus_message_close_container(m
);
5683 r
= sd_bus_message_exit_container(source
);
5690 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5696 if (IN_SET(type
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
, SD_BUS_TYPE_STRING
))
5697 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5699 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5706 return done_something
;
5709 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5714 assert_return(m
, -EINVAL
);
5715 assert_return(m
->sealed
, -EPERM
);
5716 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5717 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5718 assert_return(type
|| contents
, -EINVAL
);
5719 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5721 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5725 if (type
!= 0 && type
!= t
)
5728 if (contents
&& !streq_ptr(contents
, c
))
5734 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5735 assert_return(m
, NULL
);
5740 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5741 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
5749 switch ((*m
)->header
->type
) {
5751 case SD_BUS_MESSAGE_SIGNAL
:
5752 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5758 case SD_BUS_MESSAGE_METHOD_CALL
:
5759 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5765 case SD_BUS_MESSAGE_METHOD_RETURN
:
5766 case SD_BUS_MESSAGE_METHOD_ERROR
:
5768 r
= sd_bus_message_new(bus
, &n
, (*m
)->header
->type
);
5774 n
->reply_cookie
= (*m
)->reply_cookie
;
5776 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5780 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5781 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5785 n
->error
._need_free
= -1;
5794 if ((*m
)->destination
&& !n
->destination
) {
5795 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5800 if ((*m
)->sender
&& !n
->sender
) {
5801 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5806 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5808 r
= sd_bus_message_copy(n
, *m
, true);
5812 timeout
= (*m
)->timeout
;
5813 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
))
5814 timeout
= BUS_DEFAULT_TIMEOUT
;
5816 r
= sd_bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5820 sd_bus_message_unref(*m
);
5826 int bus_message_append_sender(sd_bus_message
*m
, const char *sender
) {
5830 assert_return(!m
->sealed
, -EPERM
);
5831 assert_return(!m
->sender
, -EPERM
);
5833 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5836 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5837 assert_return(m
, -EINVAL
);
5838 assert_return(priority
, -EINVAL
);
5840 *priority
= m
->priority
;
5844 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5845 assert_return(m
, -EINVAL
);
5846 assert_return(!m
->sealed
, -EPERM
);
5848 m
->priority
= priority
;