1 /* SPDX-License-Identifier: LGPL-2.1+ */
9 #include "alloc-util.h"
10 #include "bus-gvariant.h"
11 #include "bus-internal.h"
12 #include "bus-message.h"
13 #include "bus-signature.h"
18 #include "memfd-util.h"
19 #include "string-util.h"
21 #include "time-util.h"
25 static int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
);
27 static void *adjust_pointer(const void *p
, void *old_base
, size_t sz
, void *new_base
) {
32 if (old_base
== new_base
)
35 if ((uint8_t*) p
< (uint8_t*) old_base
)
38 if ((uint8_t*) p
>= (uint8_t*) old_base
+ sz
)
41 return (uint8_t*) new_base
+ ((uint8_t*) p
- (uint8_t*) old_base
);
44 static void message_free_part(sd_bus_message
*m
, struct bus_body_part
*part
) {
49 close_and_munmap(part
->memfd
, part
->mmap_begin
, part
->mapped
);
50 else if (part
->munmap_this
)
51 munmap(part
->mmap_begin
, part
->mapped
);
52 else if (part
->free_this
)
59 static void message_reset_parts(sd_bus_message
*m
) {
60 struct bus_body_part
*part
;
65 while (m
->n_body_parts
> 0) {
66 struct bus_body_part
*next
= part
->next
;
67 message_free_part(m
, part
);
74 m
->cached_rindex_part
= NULL
;
75 m
->cached_rindex_part_begin
= 0;
78 static struct bus_container
*message_get_last_container(sd_bus_message
*m
) {
81 if (m
->n_containers
== 0)
82 return &m
->root_container
;
84 assert(m
->containers
);
85 return m
->containers
+ m
->n_containers
- 1;
88 static void message_free_last_container(sd_bus_message
*m
) {
89 struct bus_container
*c
;
91 c
= message_get_last_container(m
);
94 free(c
->peeked_signature
);
97 /* Move to previous container, but not if we are on root container */
98 if (m
->n_containers
> 0)
102 static void message_reset_containers(sd_bus_message
*m
) {
105 while (m
->n_containers
> 0)
106 message_free_last_container(m
);
108 m
->containers
= mfree(m
->containers
);
109 m
->containers_allocated
= 0;
110 m
->root_container
.index
= 0;
113 static sd_bus_message
* message_free(sd_bus_message
*m
) {
119 message_reset_parts(m
);
121 sd_bus_unref(m
->bus
);
124 close_many(m
->fds
, m
->n_fds
);
128 if (m
->iovec
!= m
->iovec_fixed
)
131 message_reset_containers(m
);
132 assert(m
->n_containers
== 0);
133 message_free_last_container(m
);
135 bus_creds_done(&m
->creds
);
139 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message
*, message_free
);
141 static void *message_extend_fields(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
143 size_t old_size
, new_size
, start
;
150 old_size
= sizeof(struct bus_header
) + m
->fields_size
;
151 start
= ALIGN_TO(old_size
, align
);
152 new_size
= start
+ sz
;
154 if (new_size
< start
||
155 new_size
> (size_t) ((uint32_t) -1))
158 if (old_size
== new_size
)
159 return (uint8_t*) m
->header
+ old_size
;
161 if (m
->free_header
) {
162 np
= realloc(m
->header
, ALIGN8(new_size
));
166 /* Initially, the header is allocated as part of
167 * the sd_bus_message itself, let's replace it by
170 np
= malloc(ALIGN8(new_size
));
174 memcpy(np
, m
->header
, sizeof(struct bus_header
));
177 /* Zero out padding */
178 if (start
> old_size
)
179 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
183 m
->fields_size
= new_size
- sizeof(struct bus_header
);
185 /* Adjust quick access pointers */
186 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
187 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
188 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
189 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
190 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
191 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
193 m
->free_header
= true;
196 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
199 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
202 return (uint8_t*) np
+ start
;
209 static int message_append_field_string(
221 /* dbus1 only allows 8bit header field ids */
225 /* dbus1 doesn't allow strings over 32bit, let's enforce this
226 * globally, to not risk convertability */
231 /* Signature "(yv)" where the variant contains "s" */
233 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
235 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
236 p
= message_extend_fields(m
, 8, 8 + l
+ 1 + 1 + 1, true);
240 *((uint64_t*) p
) = h
;
247 *ret
= (char*) p
+ 8;
250 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
251 p
= message_extend_fields(m
, 8, 4 + 4 + l
+ 1, false);
260 ((uint32_t*) p
)[1] = l
;
261 memcpy(p
+ 8, s
, l
+ 1);
264 *ret
= (char*) p
+ 8;
270 static int message_append_field_signature(
281 /* dbus1 only allows 8bit header field ids */
285 /* dbus1 doesn't allow signatures over 8bit, let's enforce
286 * this globally, to not risk convertability */
291 /* Signature "(yv)" where the variant contains "g" */
293 if (BUS_MESSAGE_IS_GVARIANT(m
))
294 /* For gvariant the serialization is the same as for normal strings */
295 return message_append_field_string(m
, h
, 'g', s
, ret
);
297 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
298 p
= message_extend_fields(m
, 8, 4 + 1 + l
+ 1, false);
304 p
[2] = SD_BUS_TYPE_SIGNATURE
;
307 memcpy(p
+ 5, s
, l
+ 1);
310 *ret
= (const char*) p
+ 5;
316 static int message_append_field_uint32(sd_bus_message
*m
, uint64_t h
, uint32_t x
) {
321 /* dbus1 only allows 8bit header field ids */
325 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
326 /* (field id 64bit + ((value + NUL + signature string 'u') */
328 p
= message_extend_fields(m
, 8, 8 + 4 + 1 + 1, true);
332 *((uint64_t*) p
) = h
;
333 *((uint32_t*) (p
+ 8)) = x
;
337 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
338 p
= message_extend_fields(m
, 8, 4 + 4, false);
347 ((uint32_t*) p
)[1] = x
;
353 static int message_append_field_uint64(sd_bus_message
*m
, uint64_t h
, uint64_t x
) {
358 /* dbus1 only allows 8bit header field ids */
362 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
363 /* (field id 64bit + ((value + NUL + signature string 't') */
365 p
= message_extend_fields(m
, 8, 8 + 8 + 1 + 1, true);
369 *((uint64_t*) p
) = h
;
370 *((uint64_t*) (p
+ 8)) = x
;
374 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
375 p
= message_extend_fields(m
, 8, 4 + 4 + 8, false);
388 ((uint64_t*) p
)[1] = x
;
394 static int message_append_reply_cookie(sd_bus_message
*m
, uint64_t cookie
) {
397 if (BUS_MESSAGE_IS_GVARIANT(m
))
398 return message_append_field_uint64(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, cookie
);
400 /* 64bit cookies are not supported on dbus1 */
401 if (cookie
> 0xffffffffUL
)
404 return message_append_field_uint32(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) cookie
);
408 int bus_message_from_header(
411 size_t header_accessible
,
413 size_t footer_accessible
,
419 sd_bus_message
**ret
) {
421 _cleanup_free_ sd_bus_message
*m
= NULL
;
422 struct bus_header
*h
;
426 assert(header
|| header_accessible
<= 0);
427 assert(footer
|| footer_accessible
<= 0);
428 assert(fds
|| n_fds
<= 0);
431 if (header_accessible
< sizeof(struct bus_header
))
434 if (header_accessible
> message_size
)
436 if (footer_accessible
> message_size
)
440 if (!IN_SET(h
->version
, 1, 2))
443 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
446 if (!IN_SET(h
->endian
, BUS_LITTLE_ENDIAN
, BUS_BIG_ENDIAN
))
449 /* Note that we are happy with unknown flags in the flags header! */
451 a
= ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
454 label_sz
= strlen(label
);
465 m
->header_accessible
= header_accessible
;
467 m
->footer_accessible
= footer_accessible
;
469 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
472 if (h
->dbus2
.cookie
== 0)
475 /* dbus2 derives the sizes from the message size and
476 the offset table at the end, since it is formatted as
477 gvariant "yyyyuta{tv}v". Since the message itself is a
478 structure with precisely to variable sized entries,
479 there's only one offset in the table, which marks the
480 end of the fields array. */
482 ws
= bus_gvariant_determine_word_size(message_size
, 0);
483 if (footer_accessible
< ws
)
486 m
->fields_size
= bus_gvariant_read_word_le((uint8_t*) footer
+ footer_accessible
- ws
, ws
);
487 if (ALIGN8(m
->fields_size
) > message_size
- ws
)
489 if (m
->fields_size
< sizeof(struct bus_header
))
492 m
->fields_size
-= sizeof(struct bus_header
);
493 m
->body_size
= message_size
- (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
));
495 if (h
->dbus1
.serial
== 0)
498 /* dbus1 has the sizes in the header */
499 m
->fields_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.fields_size
);
500 m
->body_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.body_size
);
502 if (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
!= message_size
)
510 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
511 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
513 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
516 m
->bus
= sd_bus_ref(bus
);
522 int bus_message_from_malloc(
529 sd_bus_message
**ret
) {
531 _cleanup_(message_freep
) sd_bus_message
*m
= NULL
;
535 r
= bus_message_from_header(
537 buffer
, length
, /* in this case the initial bytes and the final bytes are the same */
546 sz
= length
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
);
549 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(m
->fields_size
);
551 m
->body
.sealed
= true;
556 m
->iovec
= m
->iovec_fixed
;
557 m
->iovec
[0] = IOVEC_MAKE(buffer
, length
);
559 r
= bus_message_parse_fields(m
);
563 /* We take possession of the memory and fds now */
564 m
->free_header
= true;
571 _public_
int sd_bus_message_new(
578 assert_return(bus
, -ENOTCONN
);
579 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
580 assert_return(m
, -EINVAL
);
581 assert_return(type
< _SD_BUS_MESSAGE_TYPE_MAX
, -EINVAL
);
583 t
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
588 t
->header
= (struct bus_header
*) ((uint8_t*) t
+ ALIGN(sizeof(struct sd_bus_message
)));
589 t
->header
->endian
= BUS_NATIVE_ENDIAN
;
590 t
->header
->type
= type
;
591 t
->header
->version
= bus
->message_version
;
592 t
->allow_fds
= bus
->can_fds
|| !IN_SET(bus
->state
, BUS_HELLO
, BUS_RUNNING
);
593 t
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(t
);
594 t
->bus
= sd_bus_ref(bus
);
596 if (bus
->allow_interactive_authorization
)
597 t
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
603 _public_
int sd_bus_message_new_signal(
607 const char *interface
,
608 const char *member
) {
610 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
613 assert_return(bus
, -ENOTCONN
);
614 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
615 assert_return(object_path_is_valid(path
), -EINVAL
);
616 assert_return(interface_name_is_valid(interface
), -EINVAL
);
617 assert_return(member_name_is_valid(member
), -EINVAL
);
618 assert_return(m
, -EINVAL
);
620 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_SIGNAL
);
626 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
628 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
631 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
634 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
642 _public_
int sd_bus_message_new_method_call(
645 const char *destination
,
647 const char *interface
,
648 const char *member
) {
650 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
653 assert_return(bus
, -ENOTCONN
);
654 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
655 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
656 assert_return(object_path_is_valid(path
), -EINVAL
);
657 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
658 assert_return(member_name_is_valid(member
), -EINVAL
);
659 assert_return(m
, -EINVAL
);
661 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_CALL
);
667 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
670 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
675 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
681 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
690 static int message_new_reply(
691 sd_bus_message
*call
,
693 sd_bus_message
**m
) {
695 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
699 assert_return(call
, -EINVAL
);
700 assert_return(call
->sealed
, -EPERM
);
701 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
702 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
703 assert_return(m
, -EINVAL
);
705 cookie
= BUS_MESSAGE_COOKIE(call
);
709 r
= sd_bus_message_new(call
->bus
, &t
, type
);
715 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
716 t
->reply_cookie
= cookie
;
717 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
722 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
727 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
728 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
734 _public_
int sd_bus_message_new_method_return(
735 sd_bus_message
*call
,
736 sd_bus_message
**m
) {
738 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
741 _public_
int sd_bus_message_new_method_error(
742 sd_bus_message
*call
,
744 const sd_bus_error
*e
) {
746 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
749 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
750 assert_return(m
, -EINVAL
);
752 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
756 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
761 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
766 t
->error
._need_free
= -1;
772 _public_
int sd_bus_message_new_method_errorf(
773 sd_bus_message
*call
,
779 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
782 assert_return(name
, -EINVAL
);
783 assert_return(m
, -EINVAL
);
785 va_start(ap
, format
);
786 bus_error_setfv(&error
, name
, format
, ap
);
789 return sd_bus_message_new_method_error(call
, m
, &error
);
792 _public_
int sd_bus_message_new_method_errno(
793 sd_bus_message
*call
,
796 const sd_bus_error
*p
) {
798 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
800 if (sd_bus_error_is_set(p
))
801 return sd_bus_message_new_method_error(call
, m
, p
);
803 sd_bus_error_set_errno(&berror
, error
);
805 return sd_bus_message_new_method_error(call
, m
, &berror
);
808 _public_
int sd_bus_message_new_method_errnof(
809 sd_bus_message
*call
,
815 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
818 va_start(ap
, format
);
819 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
822 return sd_bus_message_new_method_error(call
, m
, &berror
);
825 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
829 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
830 m
->creds
.well_known_names_local
= true;
831 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
834 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
838 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
839 m
->creds
.well_known_names_driver
= true;
840 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
843 int bus_message_new_synthetic_error(
846 const sd_bus_error
*e
,
847 sd_bus_message
**m
) {
849 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
853 assert(sd_bus_error_is_set(e
));
856 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_ERROR
);
862 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
863 t
->reply_cookie
= cookie
;
865 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
869 if (bus
&& bus
->unique_name
) {
870 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
875 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
880 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
885 t
->error
._need_free
= -1;
887 bus_message_set_sender_driver(bus
, t
);
893 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus_message
, sd_bus_message
, message_free
);
895 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
896 assert_return(m
, -EINVAL
);
897 assert_return(type
, -EINVAL
);
899 *type
= m
->header
->type
;
903 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
906 assert_return(m
, -EINVAL
);
907 assert_return(cookie
, -EINVAL
);
909 c
= BUS_MESSAGE_COOKIE(m
);
913 *cookie
= BUS_MESSAGE_COOKIE(m
);
917 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
918 assert_return(m
, -EINVAL
);
919 assert_return(cookie
, -EINVAL
);
921 if (m
->reply_cookie
== 0)
924 *cookie
= m
->reply_cookie
;
928 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
929 assert_return(m
, -EINVAL
);
931 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
932 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
935 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
936 assert_return(m
, -EINVAL
);
938 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
941 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
942 assert_return(m
, -EINVAL
);
944 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
945 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
948 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
949 assert_return(m
, NULL
);
954 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
955 assert_return(m
, NULL
);
960 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
961 assert_return(m
, NULL
);
966 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
967 assert_return(m
, NULL
);
969 return m
->destination
;
972 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
973 assert_return(m
, NULL
);
978 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
979 assert_return(m
, NULL
);
981 if (!sd_bus_error_is_set(&m
->error
))
987 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
988 assert_return(m
, -EINVAL
);
989 assert_return(usec
, -EINVAL
);
991 if (m
->monotonic
<= 0)
994 *usec
= m
->monotonic
;
998 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
999 assert_return(m
, -EINVAL
);
1000 assert_return(usec
, -EINVAL
);
1002 if (m
->realtime
<= 0)
1005 *usec
= m
->realtime
;
1009 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1010 assert_return(m
, -EINVAL
);
1011 assert_return(seqnum
, -EINVAL
);
1016 *seqnum
= m
->seqnum
;
1020 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1021 assert_return(m
, NULL
);
1023 if (m
->creds
.mask
== 0)
1029 _public_
int sd_bus_message_is_signal(
1031 const char *interface
,
1032 const char *member
) {
1034 assert_return(m
, -EINVAL
);
1036 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1039 if (interface
&& !streq_ptr(m
->interface
, interface
))
1042 if (member
&& !streq_ptr(m
->member
, member
))
1048 _public_
int sd_bus_message_is_method_call(
1050 const char *interface
,
1051 const char *member
) {
1053 assert_return(m
, -EINVAL
);
1055 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1058 if (interface
&& !streq_ptr(m
->interface
, interface
))
1061 if (member
&& !streq_ptr(m
->member
, member
))
1067 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1068 assert_return(m
, -EINVAL
);
1070 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1073 if (name
&& !streq_ptr(m
->error
.name
, name
))
1079 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1080 assert_return(m
, -EINVAL
);
1081 assert_return(!m
->sealed
, -EPERM
);
1082 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1084 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_REPLY_EXPECTED
, !b
);
1089 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1090 assert_return(m
, -EINVAL
);
1091 assert_return(!m
->sealed
, -EPERM
);
1093 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_AUTO_START
, !b
);
1098 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1099 assert_return(m
, -EINVAL
);
1100 assert_return(!m
->sealed
, -EPERM
);
1102 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
, b
);
1107 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1108 struct bus_body_part
*part
;
1115 if (m
->n_body_parts
<= 0) {
1119 assert(m
->body_end
);
1121 part
= new0(struct bus_body_part
, 1);
1127 m
->body_end
->next
= part
;
1137 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1142 /* All other fields can be left in their defaults */
1143 assert(!part
->data
);
1144 assert(part
->memfd
< 0);
1147 part
->is_zero
= true;
1148 part
->sealed
= true;
1151 static int part_make_space(
1152 struct sd_bus_message
*m
,
1153 struct bus_body_part
*part
,
1161 assert(!part
->sealed
);
1166 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1167 size_t new_allocated
;
1169 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1170 n
= realloc(part
->data
, new_allocated
);
1177 part
->allocated
= new_allocated
;
1178 part
->free_this
= true;
1182 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1188 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1189 struct bus_container
*c
;
1192 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1194 /* Add offset to current container, unless this is the first
1195 * item in it, which will have the 0 offset, which we can
1197 c
= message_get_last_container(m
);
1199 if (!c
->need_offsets
)
1202 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1205 c
->offsets
[c
->n_offsets
++] = offset
;
1209 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1210 struct bus_container
*c
;
1217 /* Update counters */
1218 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++) {
1221 *c
->array_size
+= expand
;
1225 static void *message_extend_body(
1230 bool force_inline
) {
1232 size_t start_body
, end_body
, padding
, added
;
1243 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1244 end_body
= start_body
+ sz
;
1246 padding
= start_body
- m
->body_size
;
1247 added
= padding
+ sz
;
1249 /* Check for 32bit overflows */
1250 if (end_body
> (size_t) ((uint32_t) -1) ||
1251 end_body
< start_body
) {
1257 struct bus_body_part
*part
= NULL
;
1261 m
->n_body_parts
<= 0 ||
1262 m
->body_end
->sealed
||
1263 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1264 (force_inline
&& m
->body_end
->size
> MEMFD_MIN_SIZE
);
1265 /* If this must be an inlined extension, let's create a new part if
1266 * the previous part is large enough to be inlined. */
1270 part
= message_append_part(m
);
1274 part_zero(part
, padding
);
1277 part
= message_append_part(m
);
1281 r
= part_make_space(m
, part
, sz
, &p
);
1285 struct bus_container
*c
;
1287 size_t os
, start_part
, end_part
;
1293 start_part
= ALIGN_TO(part
->size
, align
);
1294 end_part
= start_part
+ sz
;
1296 r
= part_make_space(m
, part
, end_part
, &p
);
1301 memzero(p
, padding
);
1302 p
= (uint8_t*) p
+ padding
;
1305 /* Readjust pointers */
1306 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1307 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1309 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1312 /* Return something that is not NULL and is aligned */
1313 p
= (uint8_t*) align
;
1315 m
->body_size
= end_body
;
1316 message_extend_containers(m
, added
);
1319 r
= message_add_offset(m
, end_body
);
1329 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1340 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1344 f
= reallocarray(m
->fds
, sizeof(int), m
->n_fds
+ 1);
1352 m
->fds
[m
->n_fds
] = copy
;
1358 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1359 _cleanup_close_
int fd
= -1;
1360 struct bus_container
*c
;
1364 assert_return(m
, -EINVAL
);
1365 assert_return(!m
->sealed
, -EPERM
);
1366 assert_return(bus_type_is_basic(type
), -EINVAL
);
1367 assert_return(!m
->poisoned
, -ESTALE
);
1369 c
= message_get_last_container(m
);
1371 if (c
->signature
&& c
->signature
[c
->index
]) {
1372 /* Container signature is already set */
1374 if (c
->signature
[c
->index
] != type
)
1379 /* Maybe we can append to the signature? But only if this is the top-level container */
1380 if (c
->enclosing
!= 0)
1383 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1390 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1396 case SD_BUS_TYPE_SIGNATURE
:
1397 case SD_BUS_TYPE_STRING
:
1401 case SD_BUS_TYPE_OBJECT_PATH
:
1409 case SD_BUS_TYPE_BOOLEAN
:
1411 u8
= p
&& *(int*) p
;
1417 case SD_BUS_TYPE_UNIX_FD
:
1422 fd
= message_push_fd(m
, *(int*) p
);
1433 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1434 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1441 a
= message_extend_body(m
, align
, sz
, true, false);
1448 *stored
= (const uint8_t*) a
;
1455 case SD_BUS_TYPE_STRING
:
1456 /* To make things easy we'll serialize a NULL string
1457 * into the empty string */
1461 case SD_BUS_TYPE_OBJECT_PATH
:
1467 sz
= 4 + strlen(p
) + 1;
1470 case SD_BUS_TYPE_SIGNATURE
:
1475 sz
= 1 + strlen(p
) + 1;
1478 case SD_BUS_TYPE_BOOLEAN
:
1480 u32
= p
&& *(int*) p
;
1486 case SD_BUS_TYPE_UNIX_FD
:
1491 fd
= message_push_fd(m
, *(int*) p
);
1502 align
= bus_type_get_alignment(type
);
1503 sz
= bus_type_get_size(type
);
1510 a
= message_extend_body(m
, align
, sz
, false, false);
1514 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
1515 *(uint32_t*) a
= sz
- 5;
1516 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1519 *stored
= (const uint8_t*) a
+ 4;
1521 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1522 *(uint8_t*) a
= sz
- 2;
1523 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1526 *stored
= (const uint8_t*) a
+ 1;
1535 if (type
== SD_BUS_TYPE_UNIX_FD
)
1538 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1545 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1546 return message_append_basic(m
, type
, p
, NULL
);
1549 _public_
int sd_bus_message_append_string_space(
1554 struct bus_container
*c
;
1557 assert_return(m
, -EINVAL
);
1558 assert_return(s
, -EINVAL
);
1559 assert_return(!m
->sealed
, -EPERM
);
1560 assert_return(!m
->poisoned
, -ESTALE
);
1562 c
= message_get_last_container(m
);
1564 if (c
->signature
&& c
->signature
[c
->index
]) {
1565 /* Container signature is already set */
1567 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1572 /* Maybe we can append to the signature? But only if this is the top-level container */
1573 if (c
->enclosing
!= 0)
1576 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1583 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1584 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1590 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1594 *(uint32_t*) a
= size
;
1600 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1606 _public_
int sd_bus_message_append_string_iovec(
1608 const struct iovec
*iov
,
1609 unsigned n
/* should be size_t, but is API now… 😞 */) {
1616 assert_return(m
, -EINVAL
);
1617 assert_return(!m
->sealed
, -EPERM
);
1618 assert_return(iov
|| n
== 0, -EINVAL
);
1619 assert_return(!m
->poisoned
, -ESTALE
);
1621 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1623 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1627 for (i
= 0; i
< n
; i
++) {
1629 if (iov
[i
].iov_base
)
1630 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1632 memset(p
, ' ', iov
[i
].iov_len
);
1634 p
+= iov
[i
].iov_len
;
1640 static int bus_message_open_array(
1642 struct bus_container
*c
,
1643 const char *contents
,
1644 uint32_t **array_size
,
1646 bool *need_offsets
) {
1656 assert(need_offsets
);
1658 if (!signature_is_single(contents
, true))
1661 if (c
->signature
&& c
->signature
[c
->index
]) {
1663 /* Verify the existing signature */
1665 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1668 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1671 nindex
= c
->index
+ 1 + strlen(contents
);
1675 if (c
->enclosing
!= 0)
1678 /* Extend the existing signature */
1680 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1686 nindex
= e
- c
->signature
;
1689 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1690 alignment
= bus_gvariant_get_alignment(contents
);
1694 /* Add alignment padding and add to offset list */
1695 if (!message_extend_body(m
, alignment
, 0, false, false))
1698 r
= bus_gvariant_is_fixed_size(contents
);
1702 *begin
= m
->body_size
;
1703 *need_offsets
= r
== 0;
1707 struct bus_body_part
*o
;
1709 alignment
= bus_type_get_alignment(contents
[0]);
1713 a
= message_extend_body(m
, 4, 4, false, false);
1718 op
= m
->body_end
->data
;
1719 os
= m
->body_end
->size
;
1721 /* Add alignment between size and first element */
1722 if (!message_extend_body(m
, alignment
, 0, false, false))
1725 /* location of array size might have changed so let's readjust a */
1726 if (o
== m
->body_end
)
1727 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1733 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1739 static int bus_message_open_variant(
1741 struct bus_container
*c
,
1742 const char *contents
) {
1748 if (!signature_is_single(contents
, false))
1751 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1754 if (c
->signature
&& c
->signature
[c
->index
]) {
1756 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1762 if (c
->enclosing
!= 0)
1765 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1772 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1773 /* Variants are always aligned to 8 */
1775 if (!message_extend_body(m
, 8, 0, false, false))
1782 l
= strlen(contents
);
1783 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1788 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1791 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1797 static int bus_message_open_struct(
1799 struct bus_container
*c
,
1800 const char *contents
,
1802 bool *need_offsets
) {
1811 assert(need_offsets
);
1813 if (!signature_is_valid(contents
, false))
1816 if (c
->signature
&& c
->signature
[c
->index
]) {
1819 l
= strlen(contents
);
1821 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1822 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1823 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1826 nindex
= c
->index
+ 1 + l
+ 1;
1830 if (c
->enclosing
!= 0)
1833 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1839 nindex
= e
- c
->signature
;
1842 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1845 alignment
= bus_gvariant_get_alignment(contents
);
1849 if (!message_extend_body(m
, alignment
, 0, false, false))
1852 r
= bus_gvariant_is_fixed_size(contents
);
1856 *begin
= m
->body_size
;
1857 *need_offsets
= r
== 0;
1859 /* Align contents to 8 byte boundary */
1860 if (!message_extend_body(m
, 8, 0, false, false))
1864 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1870 static int bus_message_open_dict_entry(
1872 struct bus_container
*c
,
1873 const char *contents
,
1875 bool *need_offsets
) {
1883 assert(need_offsets
);
1885 if (!signature_is_pair(contents
))
1888 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1891 if (c
->signature
&& c
->signature
[c
->index
]) {
1894 l
= strlen(contents
);
1896 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
1897 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1898 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
1903 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1906 alignment
= bus_gvariant_get_alignment(contents
);
1910 if (!message_extend_body(m
, alignment
, 0, false, false))
1913 r
= bus_gvariant_is_fixed_size(contents
);
1917 *begin
= m
->body_size
;
1918 *need_offsets
= r
== 0;
1920 /* Align contents to 8 byte boundary */
1921 if (!message_extend_body(m
, 8, 0, false, false))
1928 _public_
int sd_bus_message_open_container(
1931 const char *contents
) {
1933 struct bus_container
*c
;
1934 uint32_t *array_size
= NULL
;
1935 _cleanup_free_
char *signature
= NULL
;
1936 size_t before
, begin
= 0;
1937 bool need_offsets
= false;
1940 assert_return(m
, -EINVAL
);
1941 assert_return(!m
->sealed
, -EPERM
);
1942 assert_return(contents
, -EINVAL
);
1943 assert_return(!m
->poisoned
, -ESTALE
);
1945 /* Make sure we have space for one more container */
1946 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
1951 c
= message_get_last_container(m
);
1953 signature
= strdup(contents
);
1959 /* Save old index in the parent container, in case we have to
1960 * abort this container */
1961 c
->saved_index
= c
->index
;
1962 before
= m
->body_size
;
1964 if (type
== SD_BUS_TYPE_ARRAY
)
1965 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
1966 else if (type
== SD_BUS_TYPE_VARIANT
)
1967 r
= bus_message_open_variant(m
, c
, contents
);
1968 else if (type
== SD_BUS_TYPE_STRUCT
)
1969 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
1970 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
1971 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
1977 /* OK, let's fill it in */
1978 m
->containers
[m
->n_containers
++] = (struct bus_container
) {
1980 .signature
= TAKE_PTR(signature
),
1981 .array_size
= array_size
,
1984 .need_offsets
= need_offsets
,
1990 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
1995 if (!BUS_MESSAGE_IS_GVARIANT(m
))
1998 if (c
->need_offsets
) {
1999 size_t payload
, sz
, i
;
2002 /* Variable-width arrays */
2004 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2005 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2007 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2011 for (i
= 0; i
< c
->n_offsets
; i
++)
2012 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2016 /* Fixed-width or empty arrays */
2018 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2026 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2032 assert(c
->signature
);
2034 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2037 l
= strlen(c
->signature
);
2039 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2044 memcpy(a
+1, c
->signature
, l
);
2049 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2050 bool fixed_size
= true;
2051 size_t n_variable
= 0;
2060 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2063 p
= strempty(c
->signature
);
2067 r
= signature_element_length(p
, &n
);
2076 r
= bus_gvariant_is_fixed_size(t
);
2081 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2083 /* We need to add an offset for each item that has a
2084 * variable size and that is not the last one in the
2088 if (r
== 0 && p
[n
] != 0)
2095 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2096 assert(c
->need_offsets
|| n_variable
== 0);
2098 if (isempty(c
->signature
)) {
2099 /* The unary type is encoded as fixed 1 byte padding */
2100 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2105 } else if (n_variable
<= 0) {
2108 /* Structures with fixed-size members only have to be
2109 * fixed-size themselves. But gvariant requires all fixed-size
2110 * elements to be sized a multiple of their alignment. Hence,
2111 * we must *always* add final padding after the last member so
2112 * the overall size of the structure is properly aligned. */
2114 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2116 assert(alignment
> 0);
2118 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2125 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2127 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2129 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2133 p
= strempty(c
->signature
);
2134 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2138 r
= signature_element_length(p
, &n
);
2149 r
= bus_gvariant_is_fixed_size(t
);
2152 if (r
> 0 || p
[0] == 0)
2156 k
= n_variable
- 1 - j
;
2158 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2167 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2168 struct bus_container
*c
;
2171 assert_return(m
, -EINVAL
);
2172 assert_return(!m
->sealed
, -EPERM
);
2173 assert_return(m
->n_containers
> 0, -EINVAL
);
2174 assert_return(!m
->poisoned
, -ESTALE
);
2176 c
= message_get_last_container(m
);
2178 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2179 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2184 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2185 r
= bus_message_close_array(m
, c
);
2186 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2187 r
= bus_message_close_variant(m
, c
);
2188 else if (IN_SET(c
->enclosing
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
))
2189 r
= bus_message_close_struct(m
, c
, true);
2191 assert_not_reached("Unknown container type");
2205 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2212 stack
[*i
].types
= types
;
2213 stack
[*i
].n_struct
= n_struct
;
2214 stack
[*i
].n_array
= n_array
;
2220 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2231 *types
= stack
[*i
].types
;
2232 *n_struct
= stack
[*i
].n_struct
;
2233 *n_array
= stack
[*i
].n_array
;
2238 _public_
int sd_bus_message_appendv(
2243 unsigned n_array
, n_struct
;
2244 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2245 unsigned stack_ptr
= 0;
2248 assert_return(m
, -EINVAL
);
2249 assert_return(types
, -EINVAL
);
2250 assert_return(!m
->sealed
, -EPERM
);
2251 assert_return(!m
->poisoned
, -ESTALE
);
2253 n_array
= (unsigned) -1;
2254 n_struct
= strlen(types
);
2259 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2260 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2266 r
= sd_bus_message_close_container(m
);
2274 if (n_array
!= (unsigned) -1)
2283 case SD_BUS_TYPE_BYTE
: {
2286 x
= (uint8_t) va_arg(ap
, int);
2287 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2291 case SD_BUS_TYPE_BOOLEAN
:
2292 case SD_BUS_TYPE_INT32
:
2293 case SD_BUS_TYPE_UINT32
:
2294 case SD_BUS_TYPE_UNIX_FD
: {
2297 /* We assume a boolean is the same as int32_t */
2298 assert_cc(sizeof(int32_t) == sizeof(int));
2300 x
= va_arg(ap
, uint32_t);
2301 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2305 case SD_BUS_TYPE_INT16
:
2306 case SD_BUS_TYPE_UINT16
: {
2309 x
= (uint16_t) va_arg(ap
, int);
2310 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2314 case SD_BUS_TYPE_INT64
:
2315 case SD_BUS_TYPE_UINT64
: {
2318 x
= va_arg(ap
, uint64_t);
2319 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2323 case SD_BUS_TYPE_DOUBLE
: {
2326 x
= va_arg(ap
, double);
2327 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2331 case SD_BUS_TYPE_STRING
:
2332 case SD_BUS_TYPE_OBJECT_PATH
:
2333 case SD_BUS_TYPE_SIGNATURE
: {
2336 x
= va_arg(ap
, const char*);
2337 r
= sd_bus_message_append_basic(m
, *t
, x
);
2341 case SD_BUS_TYPE_ARRAY
: {
2344 r
= signature_element_length(t
+ 1, &k
);
2350 memcpy(s
, t
+ 1, k
);
2353 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2358 if (n_array
== (unsigned) -1) {
2363 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2369 n_array
= va_arg(ap
, unsigned);
2374 case SD_BUS_TYPE_VARIANT
: {
2377 s
= va_arg(ap
, const char*);
2381 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2385 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2390 n_struct
= strlen(s
);
2391 n_array
= (unsigned) -1;
2396 case SD_BUS_TYPE_STRUCT_BEGIN
:
2397 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2400 r
= signature_element_length(t
, &k
);
2407 memcpy(s
, t
+ 1, k
- 2);
2410 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2415 if (n_array
== (unsigned) -1) {
2420 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2426 n_array
= (unsigned) -1;
2442 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2446 va_start(ap
, types
);
2447 r
= sd_bus_message_appendv(m
, types
, ap
);
2453 _public_
int sd_bus_message_append_array_space(
2463 assert_return(m
, -EINVAL
);
2464 assert_return(!m
->sealed
, -EPERM
);
2465 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2466 assert_return(ptr
|| size
== 0, -EINVAL
);
2467 assert_return(!m
->poisoned
, -ESTALE
);
2469 /* alignment and size of the trivial types (except bool) is
2470 * identical for gvariant and dbus1 marshalling */
2471 align
= bus_type_get_alignment(type
);
2472 sz
= bus_type_get_size(type
);
2474 assert_se(align
> 0);
2480 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2484 a
= message_extend_body(m
, align
, size
, false, false);
2488 r
= sd_bus_message_close_container(m
);
2496 _public_
int sd_bus_message_append_array(
2504 assert_return(m
, -EINVAL
);
2505 assert_return(!m
->sealed
, -EPERM
);
2506 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2507 assert_return(ptr
|| size
== 0, -EINVAL
);
2508 assert_return(!m
->poisoned
, -ESTALE
);
2510 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2514 memcpy_safe(p
, ptr
, size
);
2519 _public_
int sd_bus_message_append_array_iovec(
2522 const struct iovec
*iov
,
2523 unsigned n
/* should be size_t, but is API now… 😞 */) {
2530 assert_return(m
, -EINVAL
);
2531 assert_return(!m
->sealed
, -EPERM
);
2532 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2533 assert_return(iov
|| n
== 0, -EINVAL
);
2534 assert_return(!m
->poisoned
, -ESTALE
);
2536 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2538 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2542 for (i
= 0; i
< n
; i
++) {
2544 if (iov
[i
].iov_base
)
2545 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2547 memzero(p
, iov
[i
].iov_len
);
2549 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2555 _public_
int sd_bus_message_append_array_memfd(
2562 _cleanup_close_
int copy_fd
= -1;
2563 struct bus_body_part
*part
;
2569 assert_return(m
, -EINVAL
);
2570 assert_return(memfd
>= 0, -EBADF
);
2571 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2572 assert_return(size
> 0, -EINVAL
);
2573 assert_return(!m
->sealed
, -EPERM
);
2574 assert_return(!m
->poisoned
, -ESTALE
);
2576 r
= memfd_set_sealed(memfd
);
2580 copy_fd
= fcntl(memfd
, F_DUPFD_CLOEXEC
, 3);
2584 r
= memfd_get_size(memfd
, &real_size
);
2588 if (offset
== 0 && size
== (uint64_t) -1)
2590 else if (offset
+ size
> real_size
)
2593 align
= bus_type_get_alignment(type
);
2594 sz
= bus_type_get_size(type
);
2596 assert_se(align
> 0);
2599 if (offset
% align
!= 0)
2605 if (size
> (uint64_t) (uint32_t) -1)
2608 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2612 a
= message_extend_body(m
, align
, 0, false, false);
2616 part
= message_append_part(m
);
2620 part
->memfd
= copy_fd
;
2621 part
->memfd_offset
= offset
;
2622 part
->sealed
= true;
2626 m
->body_size
+= size
;
2627 message_extend_containers(m
, size
);
2629 return sd_bus_message_close_container(m
);
2632 _public_
int sd_bus_message_append_string_memfd(
2638 _cleanup_close_
int copy_fd
= -1;
2639 struct bus_body_part
*part
;
2640 struct bus_container
*c
;
2645 assert_return(m
, -EINVAL
);
2646 assert_return(memfd
>= 0, -EBADF
);
2647 assert_return(size
> 0, -EINVAL
);
2648 assert_return(!m
->sealed
, -EPERM
);
2649 assert_return(!m
->poisoned
, -ESTALE
);
2651 r
= memfd_set_sealed(memfd
);
2655 copy_fd
= fcntl(memfd
, FD_CLOEXEC
, 3);
2659 r
= memfd_get_size(memfd
, &real_size
);
2663 if (offset
== 0 && size
== (uint64_t) -1)
2665 else if (offset
+ size
> real_size
)
2668 /* We require this to be NUL terminated */
2672 if (size
> (uint64_t) (uint32_t) -1)
2675 c
= message_get_last_container(m
);
2676 if (c
->signature
&& c
->signature
[c
->index
]) {
2677 /* Container signature is already set */
2679 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2684 /* Maybe we can append to the signature? But only if this is the top-level container */
2685 if (c
->enclosing
!= 0)
2688 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2695 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2696 a
= message_extend_body(m
, 4, 4, false, false);
2700 *(uint32_t*) a
= size
- 1;
2703 part
= message_append_part(m
);
2707 part
->memfd
= copy_fd
;
2708 part
->memfd_offset
= offset
;
2709 part
->sealed
= true;
2713 m
->body_size
+= size
;
2714 message_extend_containers(m
, size
);
2716 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2717 r
= message_add_offset(m
, m
->body_size
);
2724 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2730 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2734 assert_return(m
, -EINVAL
);
2735 assert_return(!m
->sealed
, -EPERM
);
2736 assert_return(!m
->poisoned
, -ESTALE
);
2738 r
= sd_bus_message_open_container(m
, 'a', "s");
2742 STRV_FOREACH(i
, l
) {
2743 r
= sd_bus_message_append_basic(m
, 's', *i
);
2748 return sd_bus_message_close_container(m
);
2751 static int bus_message_close_header(sd_bus_message
*m
) {
2755 /* The actual user data is finished now, we just complete the
2756 variant and struct now (at least on gvariant). Remember
2757 this position, so that during parsing we know where to
2758 put the outer container end. */
2759 m
->user_body_size
= m
->body_size
;
2761 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2762 const char *signature
;
2766 /* Add offset table to end of fields array */
2767 if (m
->n_header_offsets
>= 1) {
2771 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2773 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2774 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2778 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2779 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2782 /* Add gvariant NUL byte plus signature to the end of
2783 * the body, followed by the final offset pointing to
2784 * the end of the fields array */
2786 signature
= strempty(m
->root_container
.signature
);
2787 l
= strlen(signature
);
2789 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2790 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2795 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2796 memcpy((uint8_t*) d
+ 2, signature
, l
);
2797 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2799 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2802 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2804 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2805 m
->header
->dbus1
.body_size
= m
->body_size
;
2811 _public_
int sd_bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, uint64_t timeout_usec
) {
2812 struct bus_body_part
*part
;
2817 assert_return(m
, -EINVAL
);
2822 if (m
->n_containers
> 0)
2828 if (cookie
> 0xffffffffULL
&&
2829 !BUS_MESSAGE_IS_GVARIANT(m
))
2832 /* In vtables the return signature of method calls is listed,
2833 * let's check if they match if this is a response */
2834 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2835 m
->enforced_reply_signature
&&
2836 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2839 /* If gvariant marshalling is used we need to close the body structure */
2840 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2844 /* If there's a non-trivial signature set, then add it in
2845 * here, but only on dbus1 */
2846 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2847 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2853 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2858 r
= bus_message_close_header(m
);
2862 if (BUS_MESSAGE_IS_GVARIANT(m
))
2863 m
->header
->dbus2
.cookie
= cookie
;
2865 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2867 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout_usec
;
2869 /* Add padding at the end of the fields part, since we know
2870 * the body needs to start at an 8 byte alignment. We made
2871 * sure we allocated enough space for this, so all we need to
2872 * do here is to zero it out. */
2873 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2875 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2877 /* If this is something we can send as memfd, then let's seal
2878 the memfd now. Note that we can send memfds as payload only
2879 for directed messages, and not for broadcasts. */
2880 if (m
->destination
&& m
->bus
->use_memfd
) {
2881 MESSAGE_FOREACH_PART(part
, i
, m
)
2882 if (part
->memfd
>= 0 &&
2884 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
2885 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
2888 /* Try to seal it if that makes
2889 * sense. First, unmap our own map to
2890 * make sure we don't keep it busy. */
2891 bus_body_part_unmap(part
);
2893 /* Then, sync up real memfd size */
2895 r
= memfd_set_size(part
->memfd
, sz
);
2899 /* Finally, try to seal */
2900 if (memfd_set_sealed(part
->memfd
) >= 0)
2901 part
->sealed
= true;
2905 m
->root_container
.end
= m
->user_body_size
;
2906 m
->root_container
.index
= 0;
2907 m
->root_container
.offset_index
= 0;
2908 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
2915 int bus_body_part_map(struct bus_body_part
*part
) {
2924 if (part
->size
<= 0)
2927 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2928 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
2929 static const uint8_t zeroes
[7] = { };
2930 part
->data
= (void*) zeroes
;
2934 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
2935 psz
= PAGE_ALIGN(part
->size
+ shift
);
2937 if (part
->memfd
>= 0)
2938 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
2939 else if (part
->is_zero
)
2940 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
2944 if (p
== MAP_FAILED
)
2948 part
->mmap_begin
= p
;
2949 part
->data
= (uint8_t*) p
+ shift
;
2950 part
->munmap_this
= true;
2955 void bus_body_part_unmap(struct bus_body_part
*part
) {
2959 if (part
->memfd
< 0)
2962 if (!part
->mmap_begin
)
2965 if (!part
->munmap_this
)
2968 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
2970 part
->mmap_begin
= NULL
;
2973 part
->munmap_this
= false;
2978 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
2979 size_t k
, start
, end
;
2984 start
= ALIGN_TO((size_t) *rindex
, align
);
2985 end
= start
+ nbytes
;
2990 /* Verify that padding is 0 */
2991 for (k
= *rindex
; k
< start
; k
++)
2992 if (((const uint8_t*) p
)[k
] != 0)
2996 *r
= (uint8_t*) p
+ start
;
3003 static bool message_end_of_signature(sd_bus_message
*m
) {
3004 struct bus_container
*c
;
3008 c
= message_get_last_container(m
);
3009 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3012 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3013 struct bus_container
*c
;
3017 c
= message_get_last_container(m
);
3018 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3021 if (BUS_MESSAGE_IS_GVARIANT(m
))
3022 return index
>= c
->end
;
3024 assert(c
->array_size
);
3025 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3029 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3030 assert_return(m
, -EINVAL
);
3031 assert_return(m
->sealed
, -EPERM
);
3033 if (complete
&& m
->n_containers
> 0)
3036 if (message_end_of_signature(m
))
3039 if (message_end_of_array(m
, m
->rindex
))
3045 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3046 struct bus_body_part
*part
;
3052 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3053 part
= m
->cached_rindex_part
;
3054 begin
= m
->cached_rindex_part_begin
;
3064 if (index
+ sz
<= begin
+ part
->size
) {
3066 r
= bus_body_part_map(part
);
3071 *p
= (uint8_t*) part
->data
+ index
- begin
;
3073 m
->cached_rindex_part
= part
;
3074 m
->cached_rindex_part_begin
= begin
;
3079 begin
+= part
->size
;
3086 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3093 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3096 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3099 sz
= bus_gvariant_get_size(c
->signature
);
3103 if (c
->offset_index
+1 >= c
->n_offsets
)
3106 /* Variable-size array */
3108 alignment
= bus_gvariant_get_alignment(c
->signature
);
3109 assert(alignment
> 0);
3111 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3112 assert(c
->offsets
[c
->offset_index
+1] >= *rindex
);
3113 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3116 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3119 /* Fixed-size array */
3120 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3126 } else if (IN_SET(c
->enclosing
, 0, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
3131 if (c
->offset_index
+1 >= c
->n_offsets
)
3134 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3138 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3143 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3146 alignment
= bus_gvariant_get_alignment(t
);
3149 assert(alignment
> 0);
3151 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3152 assert(c
->offsets
[c
->offset_index
+1] >= *rindex
);
3153 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3157 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3160 assert_not_reached("Unknown container type");
3165 /* Reached the end */
3171 static int message_peek_body(
3178 size_t k
, start
, end
, padding
;
3179 struct bus_body_part
*part
;
3186 start
= ALIGN_TO((size_t) *rindex
, align
);
3187 padding
= start
- *rindex
;
3188 end
= start
+ nbytes
;
3190 if (end
> m
->user_body_size
)
3193 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3198 /* Verify padding */
3199 for (k
= 0; k
< padding
; k
++)
3204 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3205 if (!part
|| (nbytes
> 0 && !q
))
3216 static bool validate_nul(const char *s
, size_t l
) {
3218 /* Check for NUL chars in the string */
3219 if (memchr(s
, 0, l
))
3222 /* Check for NUL termination */
3229 static bool validate_string(const char *s
, size_t l
) {
3231 if (!validate_nul(s
, l
))
3234 /* Check if valid UTF8 */
3235 if (!utf8_is_valid(s
))
3241 static bool validate_signature(const char *s
, size_t l
) {
3243 if (!validate_nul(s
, l
))
3246 /* Check if valid signature */
3247 if (!signature_is_valid(s
, true))
3253 static bool validate_object_path(const char *s
, size_t l
) {
3255 if (!validate_nul(s
, l
))
3258 if (!object_path_is_valid(s
))
3264 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3265 struct bus_container
*c
;
3270 assert_return(m
, -EINVAL
);
3271 assert_return(m
->sealed
, -EPERM
);
3272 assert_return(bus_type_is_basic(type
), -EINVAL
);
3274 if (message_end_of_signature(m
))
3277 if (message_end_of_array(m
, m
->rindex
))
3280 c
= message_get_last_container(m
);
3281 if (c
->signature
[c
->index
] != type
)
3286 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3288 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3291 /* D-Bus spec: The marshalling formats for the string-like types all end
3292 * with a single zero (NUL) byte, but that byte is not considered to be part
3294 if (c
->item_size
== 0)
3297 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3301 if (type
== SD_BUS_TYPE_STRING
)
3302 ok
= validate_string(q
, c
->item_size
-1);
3303 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3304 ok
= validate_object_path(q
, c
->item_size
-1);
3306 ok
= validate_signature(q
, c
->item_size
-1);
3312 *(const char**) p
= q
;
3316 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3318 if ((size_t) sz
!= c
->item_size
)
3321 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3324 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3330 case SD_BUS_TYPE_BYTE
:
3332 *(uint8_t*) p
= *(uint8_t*) q
;
3335 case SD_BUS_TYPE_BOOLEAN
:
3337 *(int*) p
= !!*(uint8_t*) q
;
3340 case SD_BUS_TYPE_INT16
:
3341 case SD_BUS_TYPE_UINT16
:
3343 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3346 case SD_BUS_TYPE_INT32
:
3347 case SD_BUS_TYPE_UINT32
:
3349 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3352 case SD_BUS_TYPE_INT64
:
3353 case SD_BUS_TYPE_UINT64
:
3354 case SD_BUS_TYPE_DOUBLE
:
3356 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3359 case SD_BUS_TYPE_UNIX_FD
: {
3362 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3367 *(int*) p
= m
->fds
[j
];
3373 assert_not_reached("unexpected type");
3377 r
= container_next_item(m
, c
, &rindex
);
3382 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3386 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3390 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3391 if (l
== UINT32_MAX
)
3392 /* avoid overflow right below */
3395 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3399 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3400 ok
= validate_object_path(q
, l
);
3402 ok
= validate_string(q
, l
);
3407 *(const char**) p
= q
;
3409 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3412 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3418 /* avoid overflow right below */
3421 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3425 if (!validate_signature(q
, l
))
3429 *(const char**) p
= q
;
3434 align
= bus_type_get_alignment(type
);
3437 sz
= bus_type_get_size(type
);
3440 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3446 case SD_BUS_TYPE_BYTE
:
3448 *(uint8_t*) p
= *(uint8_t*) q
;
3451 case SD_BUS_TYPE_BOOLEAN
:
3453 *(int*) p
= !!*(uint32_t*) q
;
3456 case SD_BUS_TYPE_INT16
:
3457 case SD_BUS_TYPE_UINT16
:
3459 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3462 case SD_BUS_TYPE_INT32
:
3463 case SD_BUS_TYPE_UINT32
:
3465 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3468 case SD_BUS_TYPE_INT64
:
3469 case SD_BUS_TYPE_UINT64
:
3470 case SD_BUS_TYPE_DOUBLE
:
3472 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3475 case SD_BUS_TYPE_UNIX_FD
: {
3478 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3483 *(int*) p
= m
->fds
[j
];
3488 assert_not_reached("Unknown basic type...");
3495 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3501 static int bus_message_enter_array(
3503 struct bus_container
*c
,
3504 const char *contents
,
3505 uint32_t **array_size
,
3508 size_t *n_offsets
) {
3522 if (!signature_is_single(contents
, true))
3525 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3528 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3531 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3536 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3540 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3544 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3547 alignment
= bus_type_get_alignment(contents
[0]);
3551 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3555 *array_size
= (uint32_t*) q
;
3557 } else if (c
->item_size
<= 0) {
3559 /* gvariant: empty array */
3564 } else if (bus_gvariant_is_fixed_size(contents
)) {
3566 /* gvariant: fixed length array */
3567 *item_size
= bus_gvariant_get_size(contents
);
3572 size_t where
, previous
= 0, framing
, sz
;
3576 /* gvariant: variable length array */
3577 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3579 where
= rindex
+ c
->item_size
- sz
;
3580 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3584 framing
= bus_gvariant_read_word_le(q
, sz
);
3585 if (framing
> c
->item_size
- sz
)
3587 if ((c
->item_size
- framing
) % sz
!= 0)
3590 *n_offsets
= (c
->item_size
- framing
) / sz
;
3592 where
= rindex
+ framing
;
3593 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3597 *offsets
= new(size_t, *n_offsets
);
3601 alignment
= bus_gvariant_get_alignment(c
->signature
);
3602 assert(alignment
> 0);
3604 for (i
= 0; i
< *n_offsets
; i
++) {
3607 start
= ALIGN_TO(previous
, alignment
);
3609 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3610 if (x
> c
->item_size
- sz
)
3615 (*offsets
)[i
] = rindex
+ x
;
3619 *item_size
= (*offsets
)[0] - rindex
;
3624 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3625 c
->index
+= 1 + strlen(contents
);
3630 static int bus_message_enter_variant(
3632 struct bus_container
*c
,
3633 const char *contents
,
3634 size_t *item_size
) {
3646 if (!signature_is_single(contents
, false))
3649 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3652 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3655 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3660 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3663 k
= strlen(contents
);
3664 if (1+k
> c
->item_size
)
3667 where
= rindex
+ c
->item_size
- (1+k
);
3668 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3672 if (*(char*) q
!= 0)
3675 if (memcmp((uint8_t*) q
+1, contents
, k
))
3678 *item_size
= c
->item_size
- (1+k
);
3681 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3687 /* avoid overflow right below */
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
, 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 */
3797 previous
= m
->rindex
;
3802 r
= signature_element_length(p
, &n
);
3811 size_t align
= bus_gvariant_get_alignment(t
);
3814 /* The possible start of this member after including alignment */
3815 size_t start
= ALIGN_TO(previous
, align
);
3817 k
= bus_gvariant_get_size(t
);
3825 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3829 /* The last item's end is determined
3830 * from the start of the offset array */
3831 x
= size
- (n_variable
* sz
);
3833 offset
= m
->rindex
+ x
;
3835 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG
),
3836 "For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu",
3846 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3851 assert(*n_offsets
== n_total
);
3853 *item_size
= (*offsets
)[0] - m
->rindex
;
3857 static int enter_struct_or_dict_entry(
3859 struct bus_container
*c
,
3860 const char *contents
,
3863 size_t *n_offsets
) {
3874 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3877 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3882 /* gvariant with contents */
3883 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3888 static int bus_message_enter_struct(
3890 struct bus_container
*c
,
3891 const char *contents
,
3894 size_t *n_offsets
) {
3906 if (!signature_is_valid(contents
, false))
3909 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3912 l
= strlen(contents
);
3914 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
3915 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3916 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
3919 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3923 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3924 c
->index
+= 1 + l
+ 1;
3929 static int bus_message_enter_dict_entry(
3931 struct bus_container
*c
,
3932 const char *contents
,
3935 size_t *n_offsets
) {
3944 if (!signature_is_pair(contents
))
3947 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3950 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3953 l
= strlen(contents
);
3955 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
3956 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3957 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
3960 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3964 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3965 c
->index
+= 1 + l
+ 1;
3970 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
3972 const char *contents
) {
3973 struct bus_container
*c
;
3974 uint32_t *array_size
= NULL
;
3975 _cleanup_free_
char *signature
= NULL
;
3977 _cleanup_free_
size_t *offsets
= NULL
;
3978 size_t n_offsets
= 0, item_size
= 0;
3981 assert_return(m
, -EINVAL
);
3982 assert_return(m
->sealed
, -EPERM
);
3983 assert_return(type
!= 0 || !contents
, -EINVAL
);
3985 if (type
== 0 || !contents
) {
3989 /* Allow entering into anonymous containers */
3990 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
3994 if (type
!= 0 && type
!= tt
)
3997 if (contents
&& !streq(contents
, cc
))
4005 * We enforce a global limit on container depth, that is much
4006 * higher than the 32 structs and 32 arrays the specification
4007 * mandates. This is simpler to implement for us, and we need
4008 * this only to ensure our container array doesn't grow
4009 * without bounds. We are happy to return any data from a
4010 * message as long as the data itself is valid, even if the
4011 * overall message might be not.
4013 * Note that the message signature is validated when
4014 * parsing the headers, and that validation does check the
4017 * Note that the specification defines no limits on the depth
4018 * of stacked variants, but we do.
4020 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4023 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4026 if (message_end_of_signature(m
))
4029 if (message_end_of_array(m
, m
->rindex
))
4032 c
= message_get_last_container(m
);
4034 signature
= strdup(contents
);
4038 c
->saved_index
= c
->index
;
4041 if (type
== SD_BUS_TYPE_ARRAY
)
4042 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4043 else if (type
== SD_BUS_TYPE_VARIANT
)
4044 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4045 else if (type
== SD_BUS_TYPE_STRUCT
)
4046 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4047 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4048 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4054 /* OK, let's fill it in */
4055 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4056 type
== SD_BUS_TYPE_STRUCT
&&
4058 end
= m
->rindex
+ 0;
4060 end
= m
->rindex
+ c
->item_size
;
4062 m
->containers
[m
->n_containers
++] = (struct bus_container
) {
4064 .signature
= TAKE_PTR(signature
),
4068 /* Unary type has fixed size of 1, but virtual size of 0 */
4070 .array_size
= array_size
,
4071 .item_size
= item_size
,
4072 .offsets
= TAKE_PTR(offsets
),
4073 .n_offsets
= n_offsets
,
4079 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4080 struct bus_container
*c
;
4084 assert_return(m
, -EINVAL
);
4085 assert_return(m
->sealed
, -EPERM
);
4086 assert_return(m
->n_containers
> 0, -ENXIO
);
4088 c
= message_get_last_container(m
);
4090 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4091 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4095 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4096 if (m
->rindex
< c
->end
)
4099 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4102 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4103 if (c
->begin
+ l
!= m
->rindex
)
4107 message_free_last_container(m
);
4109 c
= message_get_last_container(m
);
4111 c
->index
= c
->saved_index
;
4112 r
= container_next_item(m
, c
, &m
->rindex
);
4120 static void message_quit_container(sd_bus_message
*m
) {
4121 struct bus_container
*c
;
4125 assert(m
->n_containers
> 0);
4128 c
= message_get_last_container(m
);
4129 assert(m
->rindex
>= c
->before
);
4130 m
->rindex
= c
->before
;
4132 /* Free container */
4133 message_free_last_container(m
);
4135 /* Correct index of new top-level container */
4136 c
= message_get_last_container(m
);
4137 c
->index
= c
->saved_index
;
4140 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4141 struct bus_container
*c
;
4144 assert_return(m
, -EINVAL
);
4145 assert_return(m
->sealed
, -EPERM
);
4147 if (message_end_of_signature(m
))
4150 if (message_end_of_array(m
, m
->rindex
))
4153 c
= message_get_last_container(m
);
4155 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4159 *type
= c
->signature
[c
->index
];
4163 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4168 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4172 /* signature_element_length does verification internally */
4174 /* The array element must not be empty */
4176 if (free_and_strndup(&c
->peeked_signature
,
4177 c
->signature
+ c
->index
+ 1, l
) < 0)
4180 *contents
= c
->peeked_signature
;
4184 *type
= SD_BUS_TYPE_ARRAY
;
4189 if (IN_SET(c
->signature
[c
->index
], SD_BUS_TYPE_STRUCT_BEGIN
, SD_BUS_TYPE_DICT_ENTRY_BEGIN
)) {
4194 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4199 if (free_and_strndup(&c
->peeked_signature
,
4200 c
->signature
+ c
->index
+ 1, l
- 2) < 0)
4203 *contents
= c
->peeked_signature
;
4207 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4212 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4216 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4219 if (c
->item_size
< 2)
4222 /* Look for the NUL delimiter that
4223 separates the payload from the
4224 signature. Since the body might be
4225 in a different part that then the
4226 signature we map byte by byte. */
4228 for (k
= 2; k
<= c
->item_size
; k
++) {
4231 where
= m
->rindex
+ c
->item_size
- k
;
4232 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4236 if (*(char*) q
== 0)
4240 if (k
> c
->item_size
)
4243 if (free_and_strndup(&c
->peeked_signature
,
4244 (char*) q
+ 1, k
- 1) < 0)
4247 if (!signature_is_valid(c
->peeked_signature
, true))
4250 *contents
= c
->peeked_signature
;
4255 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4261 /* avoid overflow right below */
4264 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4268 if (!validate_signature(q
, l
))
4276 *type
= SD_BUS_TYPE_VARIANT
;
4291 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4292 struct bus_container
*c
;
4294 assert_return(m
, -EINVAL
);
4295 assert_return(m
->sealed
, -EPERM
);
4298 message_reset_containers(m
);
4301 c
= message_get_last_container(m
);
4303 c
= message_get_last_container(m
);
4306 m
->rindex
= c
->begin
;
4309 c
->offset_index
= 0;
4310 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4312 return !isempty(c
->signature
);
4315 _public_
int sd_bus_message_readv(
4320 unsigned n_array
, n_struct
;
4321 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4322 unsigned stack_ptr
= 0;
4323 unsigned n_loop
= 0;
4326 assert_return(m
, -EINVAL
);
4327 assert_return(m
->sealed
, -EPERM
);
4328 assert_return(types
, -EINVAL
);
4333 /* Ideally, we'd just call ourselves recursively on every
4334 * complex type. However, the state of a va_list that is
4335 * passed to a function is undefined after that function
4336 * returns. This means we need to decode the va_list linearly
4337 * in a single stackframe. We hence implement our own
4338 * home-grown stack in an array. */
4340 n_array
= (unsigned) -1; /* length of current array entries */
4341 n_struct
= strlen(types
); /* length of current struct contents signature */
4348 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4349 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4355 r
= sd_bus_message_exit_container(m
);
4363 if (n_array
!= (unsigned) -1)
4372 case SD_BUS_TYPE_BYTE
:
4373 case SD_BUS_TYPE_BOOLEAN
:
4374 case SD_BUS_TYPE_INT16
:
4375 case SD_BUS_TYPE_UINT16
:
4376 case SD_BUS_TYPE_INT32
:
4377 case SD_BUS_TYPE_UINT32
:
4378 case SD_BUS_TYPE_INT64
:
4379 case SD_BUS_TYPE_UINT64
:
4380 case SD_BUS_TYPE_DOUBLE
:
4381 case SD_BUS_TYPE_STRING
:
4382 case SD_BUS_TYPE_OBJECT_PATH
:
4383 case SD_BUS_TYPE_SIGNATURE
:
4384 case SD_BUS_TYPE_UNIX_FD
: {
4387 p
= va_arg(ap
, void*);
4388 r
= sd_bus_message_read_basic(m
, *t
, p
);
4401 case SD_BUS_TYPE_ARRAY
: {
4404 r
= signature_element_length(t
+ 1, &k
);
4410 memcpy(s
, t
+ 1, k
);
4413 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4424 if (n_array
== (unsigned) -1) {
4429 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4435 n_array
= va_arg(ap
, unsigned);
4440 case SD_BUS_TYPE_VARIANT
: {
4443 s
= va_arg(ap
, const char *);
4447 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4457 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4462 n_struct
= strlen(s
);
4463 n_array
= (unsigned) -1;
4468 case SD_BUS_TYPE_STRUCT_BEGIN
:
4469 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4472 r
= signature_element_length(t
, &k
);
4478 memcpy(s
, t
+ 1, k
- 2);
4481 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4491 if (n_array
== (unsigned) -1) {
4496 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4502 n_array
= (unsigned) -1;
4515 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4519 va_start(ap
, types
);
4520 r
= sd_bus_message_readv(m
, types
, ap
);
4526 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4529 assert_return(m
, -EINVAL
);
4530 assert_return(m
->sealed
, -EPERM
);
4532 /* If types is NULL, read exactly one element */
4534 struct bus_container
*c
;
4537 if (message_end_of_signature(m
))
4540 if (message_end_of_array(m
, m
->rindex
))
4543 c
= message_get_last_container(m
);
4545 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4549 types
= strndupa(c
->signature
+ c
->index
, l
);
4554 case 0: /* Nothing to drop */
4557 case SD_BUS_TYPE_BYTE
:
4558 case SD_BUS_TYPE_BOOLEAN
:
4559 case SD_BUS_TYPE_INT16
:
4560 case SD_BUS_TYPE_UINT16
:
4561 case SD_BUS_TYPE_INT32
:
4562 case SD_BUS_TYPE_UINT32
:
4563 case SD_BUS_TYPE_INT64
:
4564 case SD_BUS_TYPE_UINT64
:
4565 case SD_BUS_TYPE_DOUBLE
:
4566 case SD_BUS_TYPE_STRING
:
4567 case SD_BUS_TYPE_OBJECT_PATH
:
4568 case SD_BUS_TYPE_SIGNATURE
:
4569 case SD_BUS_TYPE_UNIX_FD
:
4571 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4575 r
= sd_bus_message_skip(m
, types
+ 1);
4581 case SD_BUS_TYPE_ARRAY
: {
4584 r
= signature_element_length(types
+ 1, &k
);
4590 memcpy(s
, types
+1, k
);
4593 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4598 r
= sd_bus_message_skip(m
, s
);
4605 r
= sd_bus_message_exit_container(m
);
4610 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4617 case SD_BUS_TYPE_VARIANT
: {
4618 const char *contents
;
4621 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4625 if (x
!= SD_BUS_TYPE_VARIANT
)
4628 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4632 r
= sd_bus_message_skip(m
, contents
);
4637 r
= sd_bus_message_exit_container(m
);
4641 r
= sd_bus_message_skip(m
, types
+ 1);
4648 case SD_BUS_TYPE_STRUCT_BEGIN
:
4649 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4652 r
= signature_element_length(types
, &k
);
4658 memcpy(s
, types
+1, k
-2);
4661 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4665 r
= sd_bus_message_skip(m
, s
);
4669 r
= sd_bus_message_exit_container(m
);
4674 r
= sd_bus_message_skip(m
, types
+ k
);
4686 _public_
int sd_bus_message_read_array(
4692 struct bus_container
*c
;
4698 assert_return(m
, -EINVAL
);
4699 assert_return(m
->sealed
, -EPERM
);
4700 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4701 assert_return(ptr
, -EINVAL
);
4702 assert_return(size
, -EINVAL
);
4703 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4705 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4709 c
= message_get_last_container(m
);
4711 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4712 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4716 sz
= c
->end
- c
->begin
;
4718 align
= bus_type_get_alignment(type
);
4722 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4726 /* Zero length array, let's return some aligned
4727 * pointer that is not NULL */
4728 p
= (uint8_t*) align
;
4730 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4735 r
= sd_bus_message_exit_container(m
);
4739 *ptr
= (const void*) p
;
4745 message_quit_container(m
);
4749 static int message_peek_fields(
4760 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4763 static int message_peek_field_uint32(
4775 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4778 /* identical for gvariant and dbus1 */
4780 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4785 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4790 static int message_peek_field_uint64(
4802 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4805 /* identical for gvariant and dbus1 */
4807 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4812 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4817 static int message_peek_field_string(
4819 bool (*validate
)(const char *p
),
4831 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4836 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4842 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4846 if (l
== UINT32_MAX
)
4847 /* avoid overflow right below */
4850 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4856 if (!validate_nul(q
, l
))
4862 if (!validate_string(q
, l
))
4872 static int message_peek_field_signature(
4885 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4890 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4896 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
4902 /* avoid overflow right below */
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
);
4992 char sig
[l
+ 1], *s
= sig
;
4996 strncpy(sig
, *signature
+ 1, l
);
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
);
5041 char sig
[l
+ 1], *s
= sig
;
5042 strncpy(sig
, *signature
+ 1, l
);
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 k
= memdup_suffix0(p
+ 1 + 1, l
- 2);
5100 free_and_replace(m
->root_container
.signature
, k
);
5107 /* Calculate the actual user body size, by removing
5108 * the trailing variant signature and struct offset
5110 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5112 /* Pull out the offset table for the fields array */
5113 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5118 ri
= m
->fields_size
- sz
;
5119 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5123 framing
= bus_gvariant_read_word_le(q
, sz
);
5124 if (framing
>= m
->fields_size
- sz
)
5126 if ((m
->fields_size
- framing
) % sz
!= 0)
5130 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5134 n_offsets
= (m
->fields_size
- framing
) / sz
;
5137 m
->user_body_size
= m
->body_size
;
5140 while (ri
< m
->fields_size
) {
5141 _cleanup_free_
char *sig
= NULL
;
5142 const char *signature
;
5143 uint64_t field_type
;
5144 size_t item_size
= (size_t) -1;
5146 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5155 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5157 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5161 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5165 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5172 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5177 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5182 where
= ri
= ALIGN_TO(ri
, 8);
5183 item_size
= end
- ri
;
5184 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5188 b
= memrchr(q
, 0, item_size
);
5192 sig
= strndup(b
+1, item_size
- (b
+1-(char*) q
));
5197 item_size
= b
- (char*) q
;
5199 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5204 switch (field_type
) {
5206 case _BUS_MESSAGE_HEADER_INVALID
:
5209 case BUS_MESSAGE_HEADER_PATH
:
5214 if (!streq(signature
, "o"))
5217 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5220 case BUS_MESSAGE_HEADER_INTERFACE
:
5225 if (!streq(signature
, "s"))
5228 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5231 case BUS_MESSAGE_HEADER_MEMBER
:
5236 if (!streq(signature
, "s"))
5239 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5242 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5247 if (!streq(signature
, "s"))
5250 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5252 m
->error
._need_free
= -1;
5256 case BUS_MESSAGE_HEADER_DESTINATION
:
5261 if (!streq(signature
, "s"))
5264 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5267 case BUS_MESSAGE_HEADER_SENDER
:
5272 if (!streq(signature
, "s"))
5275 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5277 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
) {
5278 m
->creds
.unique_name
= (char*) m
->sender
;
5279 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5284 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5288 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5291 if (m
->root_container
.signature
)
5294 if (!streq(signature
, "g"))
5297 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5305 free_and_replace(m
->root_container
.signature
, c
);
5309 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5311 if (m
->reply_cookie
!= 0)
5314 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5315 /* 64bit on dbus2 */
5317 if (!streq(signature
, "t"))
5320 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5324 /* 32bit on dbus1 */
5327 if (!streq(signature
, "u"))
5330 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5334 m
->reply_cookie
= serial
;
5337 if (m
->reply_cookie
== 0)
5342 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5346 if (!streq(signature
, "u"))
5349 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5353 unix_fds_set
= true;
5357 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5358 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5367 if (m
->n_fds
!= unix_fds
)
5370 switch (m
->header
->type
) {
5372 case SD_BUS_MESSAGE_SIGNAL
:
5373 if (!m
->path
|| !m
->interface
|| !m
->member
)
5376 if (m
->reply_cookie
!= 0)
5381 case SD_BUS_MESSAGE_METHOD_CALL
:
5383 if (!m
->path
|| !m
->member
)
5386 if (m
->reply_cookie
!= 0)
5391 case SD_BUS_MESSAGE_METHOD_RETURN
:
5393 if (m
->reply_cookie
== 0)
5397 case SD_BUS_MESSAGE_METHOD_ERROR
:
5399 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5404 /* Refuse non-local messages that claim they are local */
5405 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5407 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5409 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5412 m
->root_container
.end
= m
->user_body_size
;
5414 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5415 r
= build_struct_offsets(
5417 m
->root_container
.signature
,
5419 &m
->root_container
.item_size
,
5420 &m
->root_container
.offsets
,
5421 &m
->root_container
.n_offsets
);
5428 /* Try to read the error message, but if we can't it's a non-issue */
5429 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5430 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5435 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5436 assert_return(m
, -EINVAL
);
5437 assert_return(destination
, -EINVAL
);
5438 assert_return(service_name_is_valid(destination
), -EINVAL
);
5439 assert_return(!m
->sealed
, -EPERM
);
5440 assert_return(!m
->destination
, -EEXIST
);
5442 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5445 _public_
int sd_bus_message_set_sender(sd_bus_message
*m
, const char *sender
) {
5446 assert_return(m
, -EINVAL
);
5447 assert_return(sender
, -EINVAL
);
5448 assert_return(service_name_is_valid(sender
), -EINVAL
);
5449 assert_return(!m
->sealed
, -EPERM
);
5450 assert_return(!m
->sender
, -EEXIST
);
5452 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5455 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5459 struct bus_body_part
*part
;
5465 total
= BUS_MESSAGE_SIZE(m
);
5471 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5472 MESSAGE_FOREACH_PART(part
, i
, m
)
5473 e
= mempcpy(e
, part
->data
, part
->size
);
5475 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5483 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5490 r
= sd_bus_message_enter_container(m
, 'a', "s");
5494 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5495 r
= strv_extend(l
, s
);
5502 r
= sd_bus_message_exit_container(m
);
5509 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5510 _cleanup_strv_free_
char **strv
= NULL
;
5513 assert_return(m
, -EINVAL
);
5514 assert_return(m
->sealed
, -EPERM
);
5515 assert_return(l
, -EINVAL
);
5517 r
= bus_message_read_strv_extend(m
, &strv
);
5521 *l
= TAKE_PTR(strv
);
5525 static int bus_message_get_arg_skip(
5529 const char **_contents
) {
5534 r
= sd_bus_message_rewind(m
, true);
5539 const char *contents
;
5542 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5548 /* Don't match against arguments after the first one we don't understand */
5549 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5550 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5555 *_contents
= contents
;
5561 r
= sd_bus_message_skip(m
, NULL
);
5568 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5575 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5579 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5582 return sd_bus_message_read_basic(m
, type
, str
);
5585 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5586 const char *contents
;
5593 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5597 if (type
!= SD_BUS_TYPE_ARRAY
)
5599 if (!STR_IN_SET(contents
, "s", "o", "g"))
5602 return sd_bus_message_read_strv(m
, strv
);
5605 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5606 assert_return(m
, EINVAL
);
5608 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5611 return sd_bus_error_get_errno(&m
->error
);
5614 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5615 struct bus_container
*c
;
5617 assert_return(m
, NULL
);
5619 c
= complete
? &m
->root_container
: message_get_last_container(m
);
5620 return strempty(c
->signature
);
5623 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5624 assert_return(m
, -EINVAL
);
5626 return isempty(m
->root_container
.signature
);
5629 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5630 assert_return(m
, -EINVAL
);
5632 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5635 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5636 bool done_something
= false;
5639 assert_return(m
, -EINVAL
);
5640 assert_return(source
, -EINVAL
);
5641 assert_return(!m
->sealed
, -EPERM
);
5642 assert_return(source
->sealed
, -EPERM
);
5645 const char *contents
;
5660 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5666 done_something
= true;
5668 if (bus_type_is_container(type
) > 0) {
5670 r
= sd_bus_message_enter_container(source
, type
, contents
);
5674 r
= sd_bus_message_open_container(m
, type
, contents
);
5678 r
= sd_bus_message_copy(m
, source
, true);
5682 r
= sd_bus_message_close_container(m
);
5686 r
= sd_bus_message_exit_container(source
);
5693 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5699 if (IN_SET(type
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
, SD_BUS_TYPE_STRING
))
5700 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5702 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5709 return done_something
;
5712 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5717 assert_return(m
, -EINVAL
);
5718 assert_return(m
->sealed
, -EPERM
);
5719 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5720 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5721 assert_return(type
|| contents
, -EINVAL
);
5722 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5724 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5728 if (type
!= 0 && type
!= t
)
5731 if (contents
&& !streq_ptr(contents
, c
))
5737 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5738 assert_return(m
, NULL
);
5743 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5744 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
5752 switch ((*m
)->header
->type
) {
5754 case SD_BUS_MESSAGE_SIGNAL
:
5755 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5761 case SD_BUS_MESSAGE_METHOD_CALL
:
5762 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5768 case SD_BUS_MESSAGE_METHOD_RETURN
:
5769 case SD_BUS_MESSAGE_METHOD_ERROR
:
5771 r
= sd_bus_message_new(bus
, &n
, (*m
)->header
->type
);
5777 n
->reply_cookie
= (*m
)->reply_cookie
;
5779 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5783 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5784 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5788 n
->error
._need_free
= -1;
5797 if ((*m
)->destination
&& !n
->destination
) {
5798 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5803 if ((*m
)->sender
&& !n
->sender
) {
5804 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5809 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5811 r
= sd_bus_message_copy(n
, *m
, true);
5815 timeout
= (*m
)->timeout
;
5816 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
)) {
5817 r
= sd_bus_get_method_call_timeout(bus
, &timeout
);
5822 r
= sd_bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5826 sd_bus_message_unref(*m
);
5832 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5833 assert_return(m
, -EINVAL
);
5834 assert_return(priority
, -EINVAL
);
5836 *priority
= m
->priority
;
5840 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5841 assert_return(m
, -EINVAL
);
5842 assert_return(!m
->sealed
, -EPERM
);
5844 m
->priority
= priority
;