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].iov_base
= buffer
;
558 m
->iovec
[0].iov_len
= length
;
560 r
= bus_message_parse_fields(m
);
564 /* We take possession of the memory and fds now */
565 m
->free_header
= true;
572 _public_
int sd_bus_message_new(
579 assert_return(bus
, -ENOTCONN
);
580 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
581 assert_return(m
, -EINVAL
);
582 assert_return(type
< _SD_BUS_MESSAGE_TYPE_MAX
, -EINVAL
);
584 t
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
589 t
->header
= (struct bus_header
*) ((uint8_t*) t
+ ALIGN(sizeof(struct sd_bus_message
)));
590 t
->header
->endian
= BUS_NATIVE_ENDIAN
;
591 t
->header
->type
= type
;
592 t
->header
->version
= bus
->message_version
;
593 t
->allow_fds
= bus
->can_fds
|| !IN_SET(bus
->state
, BUS_HELLO
, BUS_RUNNING
);
594 t
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(t
);
595 t
->bus
= sd_bus_ref(bus
);
597 if (bus
->allow_interactive_authorization
)
598 t
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
604 _public_
int sd_bus_message_new_signal(
608 const char *interface
,
609 const char *member
) {
611 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
614 assert_return(bus
, -ENOTCONN
);
615 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
616 assert_return(object_path_is_valid(path
), -EINVAL
);
617 assert_return(interface_name_is_valid(interface
), -EINVAL
);
618 assert_return(member_name_is_valid(member
), -EINVAL
);
619 assert_return(m
, -EINVAL
);
621 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_SIGNAL
);
627 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
629 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
632 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
635 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
643 _public_
int sd_bus_message_new_method_call(
646 const char *destination
,
648 const char *interface
,
649 const char *member
) {
651 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
654 assert_return(bus
, -ENOTCONN
);
655 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
656 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
657 assert_return(object_path_is_valid(path
), -EINVAL
);
658 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
659 assert_return(member_name_is_valid(member
), -EINVAL
);
660 assert_return(m
, -EINVAL
);
662 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_CALL
);
668 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
671 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
676 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
682 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
691 static int message_new_reply(
692 sd_bus_message
*call
,
694 sd_bus_message
**m
) {
696 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
700 assert_return(call
, -EINVAL
);
701 assert_return(call
->sealed
, -EPERM
);
702 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
703 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
704 assert_return(m
, -EINVAL
);
706 cookie
= BUS_MESSAGE_COOKIE(call
);
710 r
= sd_bus_message_new(call
->bus
, &t
, type
);
716 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
717 t
->reply_cookie
= cookie
;
718 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
723 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
728 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
729 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
735 _public_
int sd_bus_message_new_method_return(
736 sd_bus_message
*call
,
737 sd_bus_message
**m
) {
739 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
742 _public_
int sd_bus_message_new_method_error(
743 sd_bus_message
*call
,
745 const sd_bus_error
*e
) {
747 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
750 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
751 assert_return(m
, -EINVAL
);
753 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
757 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
762 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
767 t
->error
._need_free
= -1;
773 _public_
int sd_bus_message_new_method_errorf(
774 sd_bus_message
*call
,
780 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
783 assert_return(name
, -EINVAL
);
784 assert_return(m
, -EINVAL
);
786 va_start(ap
, format
);
787 bus_error_setfv(&error
, name
, format
, ap
);
790 return sd_bus_message_new_method_error(call
, m
, &error
);
793 _public_
int sd_bus_message_new_method_errno(
794 sd_bus_message
*call
,
797 const sd_bus_error
*p
) {
799 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
801 if (sd_bus_error_is_set(p
))
802 return sd_bus_message_new_method_error(call
, m
, p
);
804 sd_bus_error_set_errno(&berror
, error
);
806 return sd_bus_message_new_method_error(call
, m
, &berror
);
809 _public_
int sd_bus_message_new_method_errnof(
810 sd_bus_message
*call
,
816 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
819 va_start(ap
, format
);
820 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
823 return sd_bus_message_new_method_error(call
, m
, &berror
);
826 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
830 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
831 m
->creds
.well_known_names_local
= true;
832 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
835 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
839 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
840 m
->creds
.well_known_names_driver
= true;
841 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
844 int bus_message_new_synthetic_error(
847 const sd_bus_error
*e
,
848 sd_bus_message
**m
) {
850 _cleanup_(message_freep
) sd_bus_message
*t
= NULL
;
854 assert(sd_bus_error_is_set(e
));
857 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_ERROR
);
863 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
864 t
->reply_cookie
= cookie
;
866 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
870 if (bus
&& bus
->unique_name
) {
871 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
876 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
881 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
886 t
->error
._need_free
= -1;
888 bus_message_set_sender_driver(bus
, t
);
894 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus_message
, sd_bus_message
, message_free
);
896 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
897 assert_return(m
, -EINVAL
);
898 assert_return(type
, -EINVAL
);
900 *type
= m
->header
->type
;
904 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
907 assert_return(m
, -EINVAL
);
908 assert_return(cookie
, -EINVAL
);
910 c
= BUS_MESSAGE_COOKIE(m
);
914 *cookie
= BUS_MESSAGE_COOKIE(m
);
918 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
919 assert_return(m
, -EINVAL
);
920 assert_return(cookie
, -EINVAL
);
922 if (m
->reply_cookie
== 0)
925 *cookie
= m
->reply_cookie
;
929 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
930 assert_return(m
, -EINVAL
);
932 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
933 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
936 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
937 assert_return(m
, -EINVAL
);
939 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
942 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
943 assert_return(m
, -EINVAL
);
945 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
946 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
949 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
950 assert_return(m
, NULL
);
955 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
956 assert_return(m
, NULL
);
961 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
962 assert_return(m
, NULL
);
967 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
968 assert_return(m
, NULL
);
970 return m
->destination
;
973 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
974 assert_return(m
, NULL
);
979 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
980 assert_return(m
, NULL
);
982 if (!sd_bus_error_is_set(&m
->error
))
988 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
989 assert_return(m
, -EINVAL
);
990 assert_return(usec
, -EINVAL
);
992 if (m
->monotonic
<= 0)
995 *usec
= m
->monotonic
;
999 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1000 assert_return(m
, -EINVAL
);
1001 assert_return(usec
, -EINVAL
);
1003 if (m
->realtime
<= 0)
1006 *usec
= m
->realtime
;
1010 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1011 assert_return(m
, -EINVAL
);
1012 assert_return(seqnum
, -EINVAL
);
1017 *seqnum
= m
->seqnum
;
1021 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1022 assert_return(m
, NULL
);
1024 if (m
->creds
.mask
== 0)
1030 _public_
int sd_bus_message_is_signal(
1032 const char *interface
,
1033 const char *member
) {
1035 assert_return(m
, -EINVAL
);
1037 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1040 if (interface
&& !streq_ptr(m
->interface
, interface
))
1043 if (member
&& !streq_ptr(m
->member
, member
))
1049 _public_
int sd_bus_message_is_method_call(
1051 const char *interface
,
1052 const char *member
) {
1054 assert_return(m
, -EINVAL
);
1056 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1059 if (interface
&& !streq_ptr(m
->interface
, interface
))
1062 if (member
&& !streq_ptr(m
->member
, member
))
1068 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1069 assert_return(m
, -EINVAL
);
1071 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1074 if (name
&& !streq_ptr(m
->error
.name
, name
))
1080 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1081 assert_return(m
, -EINVAL
);
1082 assert_return(!m
->sealed
, -EPERM
);
1083 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1085 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_REPLY_EXPECTED
, !b
);
1090 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1091 assert_return(m
, -EINVAL
);
1092 assert_return(!m
->sealed
, -EPERM
);
1094 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_AUTO_START
, !b
);
1099 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1100 assert_return(m
, -EINVAL
);
1101 assert_return(!m
->sealed
, -EPERM
);
1103 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
, b
);
1108 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1109 struct bus_body_part
*part
;
1116 if (m
->n_body_parts
<= 0) {
1120 assert(m
->body_end
);
1122 part
= new0(struct bus_body_part
, 1);
1128 m
->body_end
->next
= part
;
1138 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1143 /* All other fields can be left in their defaults */
1144 assert(!part
->data
);
1145 assert(part
->memfd
< 0);
1148 part
->is_zero
= true;
1149 part
->sealed
= true;
1152 static int part_make_space(
1153 struct sd_bus_message
*m
,
1154 struct bus_body_part
*part
,
1162 assert(!part
->sealed
);
1167 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1168 size_t new_allocated
;
1170 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1171 n
= realloc(part
->data
, new_allocated
);
1178 part
->allocated
= new_allocated
;
1179 part
->free_this
= true;
1183 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1189 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1190 struct bus_container
*c
;
1193 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1195 /* Add offset to current container, unless this is the first
1196 * item in it, which will have the 0 offset, which we can
1198 c
= message_get_last_container(m
);
1200 if (!c
->need_offsets
)
1203 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1206 c
->offsets
[c
->n_offsets
++] = offset
;
1210 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1211 struct bus_container
*c
;
1218 /* Update counters */
1219 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++) {
1222 *c
->array_size
+= expand
;
1226 static void *message_extend_body(
1231 bool force_inline
) {
1233 size_t start_body
, end_body
, padding
, added
;
1244 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1245 end_body
= start_body
+ sz
;
1247 padding
= start_body
- m
->body_size
;
1248 added
= padding
+ sz
;
1250 /* Check for 32bit overflows */
1251 if (end_body
> (size_t) ((uint32_t) -1) ||
1252 end_body
< start_body
) {
1258 struct bus_body_part
*part
= NULL
;
1262 m
->n_body_parts
<= 0 ||
1263 m
->body_end
->sealed
||
1264 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1265 (force_inline
&& m
->body_end
->size
> MEMFD_MIN_SIZE
);
1266 /* If this must be an inlined extension, let's create a new part if
1267 * the previous part is large enough to be inlined. */
1271 part
= message_append_part(m
);
1275 part_zero(part
, padding
);
1278 part
= message_append_part(m
);
1282 r
= part_make_space(m
, part
, sz
, &p
);
1286 struct bus_container
*c
;
1288 size_t os
, start_part
, end_part
;
1294 start_part
= ALIGN_TO(part
->size
, align
);
1295 end_part
= start_part
+ sz
;
1297 r
= part_make_space(m
, part
, end_part
, &p
);
1302 memzero(p
, padding
);
1303 p
= (uint8_t*) p
+ padding
;
1306 /* Readjust pointers */
1307 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1308 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1310 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1313 /* Return something that is not NULL and is aligned */
1314 p
= (uint8_t*) align
;
1316 m
->body_size
= end_body
;
1317 message_extend_containers(m
, added
);
1320 r
= message_add_offset(m
, end_body
);
1330 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1341 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1345 f
= reallocarray(m
->fds
, sizeof(int), m
->n_fds
+ 1);
1353 m
->fds
[m
->n_fds
] = copy
;
1359 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1360 _cleanup_close_
int fd
= -1;
1361 struct bus_container
*c
;
1365 assert_return(m
, -EINVAL
);
1366 assert_return(!m
->sealed
, -EPERM
);
1367 assert_return(bus_type_is_basic(type
), -EINVAL
);
1368 assert_return(!m
->poisoned
, -ESTALE
);
1370 c
= message_get_last_container(m
);
1372 if (c
->signature
&& c
->signature
[c
->index
]) {
1373 /* Container signature is already set */
1375 if (c
->signature
[c
->index
] != type
)
1380 /* Maybe we can append to the signature? But only if this is the top-level container */
1381 if (c
->enclosing
!= 0)
1384 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1391 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1397 case SD_BUS_TYPE_SIGNATURE
:
1398 case SD_BUS_TYPE_STRING
:
1402 case SD_BUS_TYPE_OBJECT_PATH
:
1410 case SD_BUS_TYPE_BOOLEAN
:
1412 u8
= p
&& *(int*) p
;
1418 case SD_BUS_TYPE_UNIX_FD
:
1423 fd
= message_push_fd(m
, *(int*) p
);
1434 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1435 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1442 a
= message_extend_body(m
, align
, sz
, true, false);
1449 *stored
= (const uint8_t*) a
;
1456 case SD_BUS_TYPE_STRING
:
1457 /* To make things easy we'll serialize a NULL string
1458 * into the empty string */
1462 case SD_BUS_TYPE_OBJECT_PATH
:
1468 sz
= 4 + strlen(p
) + 1;
1471 case SD_BUS_TYPE_SIGNATURE
:
1476 sz
= 1 + strlen(p
) + 1;
1479 case SD_BUS_TYPE_BOOLEAN
:
1481 u32
= p
&& *(int*) p
;
1487 case SD_BUS_TYPE_UNIX_FD
:
1492 fd
= message_push_fd(m
, *(int*) p
);
1503 align
= bus_type_get_alignment(type
);
1504 sz
= bus_type_get_size(type
);
1511 a
= message_extend_body(m
, align
, sz
, false, false);
1515 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
1516 *(uint32_t*) a
= sz
- 5;
1517 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1520 *stored
= (const uint8_t*) a
+ 4;
1522 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1523 *(uint8_t*) a
= sz
- 2;
1524 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1527 *stored
= (const uint8_t*) a
+ 1;
1536 if (type
== SD_BUS_TYPE_UNIX_FD
)
1539 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1546 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1547 return message_append_basic(m
, type
, p
, NULL
);
1550 _public_
int sd_bus_message_append_string_space(
1555 struct bus_container
*c
;
1558 assert_return(m
, -EINVAL
);
1559 assert_return(s
, -EINVAL
);
1560 assert_return(!m
->sealed
, -EPERM
);
1561 assert_return(!m
->poisoned
, -ESTALE
);
1563 c
= message_get_last_container(m
);
1565 if (c
->signature
&& c
->signature
[c
->index
]) {
1566 /* Container signature is already set */
1568 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1573 /* Maybe we can append to the signature? But only if this is the top-level container */
1574 if (c
->enclosing
!= 0)
1577 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1584 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1585 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1591 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1595 *(uint32_t*) a
= size
;
1601 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1607 _public_
int sd_bus_message_append_string_iovec(
1609 const struct iovec
*iov
,
1610 unsigned n
/* should be size_t, but is API now… 😞 */) {
1617 assert_return(m
, -EINVAL
);
1618 assert_return(!m
->sealed
, -EPERM
);
1619 assert_return(iov
|| n
== 0, -EINVAL
);
1620 assert_return(!m
->poisoned
, -ESTALE
);
1622 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1624 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1628 for (i
= 0; i
< n
; i
++) {
1630 if (iov
[i
].iov_base
)
1631 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1633 memset(p
, ' ', iov
[i
].iov_len
);
1635 p
+= iov
[i
].iov_len
;
1641 static int bus_message_open_array(
1643 struct bus_container
*c
,
1644 const char *contents
,
1645 uint32_t **array_size
,
1647 bool *need_offsets
) {
1657 assert(need_offsets
);
1659 if (!signature_is_single(contents
, true))
1662 if (c
->signature
&& c
->signature
[c
->index
]) {
1664 /* Verify the existing signature */
1666 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1669 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1672 nindex
= c
->index
+ 1 + strlen(contents
);
1676 if (c
->enclosing
!= 0)
1679 /* Extend the existing signature */
1681 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1687 nindex
= e
- c
->signature
;
1690 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1691 alignment
= bus_gvariant_get_alignment(contents
);
1695 /* Add alignment padding and add to offset list */
1696 if (!message_extend_body(m
, alignment
, 0, false, false))
1699 r
= bus_gvariant_is_fixed_size(contents
);
1703 *begin
= m
->body_size
;
1704 *need_offsets
= r
== 0;
1708 struct bus_body_part
*o
;
1710 alignment
= bus_type_get_alignment(contents
[0]);
1714 a
= message_extend_body(m
, 4, 4, false, false);
1719 op
= m
->body_end
->data
;
1720 os
= m
->body_end
->size
;
1722 /* Add alignment between size and first element */
1723 if (!message_extend_body(m
, alignment
, 0, false, false))
1726 /* location of array size might have changed so let's readjust a */
1727 if (o
== m
->body_end
)
1728 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1734 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1740 static int bus_message_open_variant(
1742 struct bus_container
*c
,
1743 const char *contents
) {
1749 if (!signature_is_single(contents
, false))
1752 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1755 if (c
->signature
&& c
->signature
[c
->index
]) {
1757 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1763 if (c
->enclosing
!= 0)
1766 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1773 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1774 /* Variants are always aligned to 8 */
1776 if (!message_extend_body(m
, 8, 0, false, false))
1783 l
= strlen(contents
);
1784 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1789 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1792 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1798 static int bus_message_open_struct(
1800 struct bus_container
*c
,
1801 const char *contents
,
1803 bool *need_offsets
) {
1812 assert(need_offsets
);
1814 if (!signature_is_valid(contents
, false))
1817 if (c
->signature
&& c
->signature
[c
->index
]) {
1820 l
= strlen(contents
);
1822 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1823 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1824 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1827 nindex
= c
->index
+ 1 + l
+ 1;
1831 if (c
->enclosing
!= 0)
1834 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1840 nindex
= e
- c
->signature
;
1843 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1846 alignment
= bus_gvariant_get_alignment(contents
);
1850 if (!message_extend_body(m
, alignment
, 0, false, false))
1853 r
= bus_gvariant_is_fixed_size(contents
);
1857 *begin
= m
->body_size
;
1858 *need_offsets
= r
== 0;
1860 /* Align contents to 8 byte boundary */
1861 if (!message_extend_body(m
, 8, 0, false, false))
1865 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1871 static int bus_message_open_dict_entry(
1873 struct bus_container
*c
,
1874 const char *contents
,
1876 bool *need_offsets
) {
1884 assert(need_offsets
);
1886 if (!signature_is_pair(contents
))
1889 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1892 if (c
->signature
&& c
->signature
[c
->index
]) {
1895 l
= strlen(contents
);
1897 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
1898 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1899 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
1904 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1907 alignment
= bus_gvariant_get_alignment(contents
);
1911 if (!message_extend_body(m
, alignment
, 0, false, false))
1914 r
= bus_gvariant_is_fixed_size(contents
);
1918 *begin
= m
->body_size
;
1919 *need_offsets
= r
== 0;
1921 /* Align contents to 8 byte boundary */
1922 if (!message_extend_body(m
, 8, 0, false, false))
1929 _public_
int sd_bus_message_open_container(
1932 const char *contents
) {
1934 struct bus_container
*c
;
1935 uint32_t *array_size
= NULL
;
1936 _cleanup_free_
char *signature
= NULL
;
1937 size_t before
, begin
= 0;
1938 bool need_offsets
= false;
1941 assert_return(m
, -EINVAL
);
1942 assert_return(!m
->sealed
, -EPERM
);
1943 assert_return(contents
, -EINVAL
);
1944 assert_return(!m
->poisoned
, -ESTALE
);
1946 /* Make sure we have space for one more container */
1947 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
1952 c
= message_get_last_container(m
);
1954 signature
= strdup(contents
);
1960 /* Save old index in the parent container, in case we have to
1961 * abort this container */
1962 c
->saved_index
= c
->index
;
1963 before
= m
->body_size
;
1965 if (type
== SD_BUS_TYPE_ARRAY
)
1966 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
1967 else if (type
== SD_BUS_TYPE_VARIANT
)
1968 r
= bus_message_open_variant(m
, c
, contents
);
1969 else if (type
== SD_BUS_TYPE_STRUCT
)
1970 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
1971 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
1972 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
1978 /* OK, let's fill it in */
1979 m
->containers
[m
->n_containers
++] = (struct bus_container
) {
1981 .signature
= TAKE_PTR(signature
),
1982 .array_size
= array_size
,
1985 .need_offsets
= need_offsets
,
1991 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
1996 if (!BUS_MESSAGE_IS_GVARIANT(m
))
1999 if (c
->need_offsets
) {
2000 size_t payload
, sz
, i
;
2003 /* Variable-width arrays */
2005 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2006 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2008 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2012 for (i
= 0; i
< c
->n_offsets
; i
++)
2013 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2017 /* Fixed-width or empty arrays */
2019 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2027 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2033 assert(c
->signature
);
2035 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2038 l
= strlen(c
->signature
);
2040 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2045 memcpy(a
+1, c
->signature
, l
);
2050 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2051 bool fixed_size
= true;
2052 size_t n_variable
= 0;
2061 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2064 p
= strempty(c
->signature
);
2068 r
= signature_element_length(p
, &n
);
2077 r
= bus_gvariant_is_fixed_size(t
);
2082 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2084 /* We need to add an offset for each item that has a
2085 * variable size and that is not the last one in the
2089 if (r
== 0 && p
[n
] != 0)
2096 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2097 assert(c
->need_offsets
|| n_variable
== 0);
2099 if (isempty(c
->signature
)) {
2100 /* The unary type is encoded as fixed 1 byte padding */
2101 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2106 } else if (n_variable
<= 0) {
2109 /* Structures with fixed-size members only have to be
2110 * fixed-size themselves. But gvariant requires all fixed-size
2111 * elements to be sized a multiple of their alignment. Hence,
2112 * we must *always* add final padding after the last member so
2113 * the overall size of the structure is properly aligned. */
2115 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2117 assert(alignment
> 0);
2119 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2126 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2128 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2130 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2134 p
= strempty(c
->signature
);
2135 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2139 r
= signature_element_length(p
, &n
);
2150 r
= bus_gvariant_is_fixed_size(t
);
2153 if (r
> 0 || p
[0] == 0)
2157 k
= n_variable
- 1 - j
;
2159 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2168 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2169 struct bus_container
*c
;
2172 assert_return(m
, -EINVAL
);
2173 assert_return(!m
->sealed
, -EPERM
);
2174 assert_return(m
->n_containers
> 0, -EINVAL
);
2175 assert_return(!m
->poisoned
, -ESTALE
);
2177 c
= message_get_last_container(m
);
2179 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2180 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2185 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2186 r
= bus_message_close_array(m
, c
);
2187 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2188 r
= bus_message_close_variant(m
, c
);
2189 else if (IN_SET(c
->enclosing
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
))
2190 r
= bus_message_close_struct(m
, c
, true);
2192 assert_not_reached("Unknown container type");
2206 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2213 stack
[*i
].types
= types
;
2214 stack
[*i
].n_struct
= n_struct
;
2215 stack
[*i
].n_array
= n_array
;
2221 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2232 *types
= stack
[*i
].types
;
2233 *n_struct
= stack
[*i
].n_struct
;
2234 *n_array
= stack
[*i
].n_array
;
2239 _public_
int sd_bus_message_appendv(
2244 unsigned n_array
, n_struct
;
2245 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2246 unsigned stack_ptr
= 0;
2249 assert_return(m
, -EINVAL
);
2250 assert_return(types
, -EINVAL
);
2251 assert_return(!m
->sealed
, -EPERM
);
2252 assert_return(!m
->poisoned
, -ESTALE
);
2254 n_array
= (unsigned) -1;
2255 n_struct
= strlen(types
);
2260 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2261 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2267 r
= sd_bus_message_close_container(m
);
2275 if (n_array
!= (unsigned) -1)
2284 case SD_BUS_TYPE_BYTE
: {
2287 x
= (uint8_t) va_arg(ap
, int);
2288 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2292 case SD_BUS_TYPE_BOOLEAN
:
2293 case SD_BUS_TYPE_INT32
:
2294 case SD_BUS_TYPE_UINT32
:
2295 case SD_BUS_TYPE_UNIX_FD
: {
2298 /* We assume a boolean is the same as int32_t */
2299 assert_cc(sizeof(int32_t) == sizeof(int));
2301 x
= va_arg(ap
, uint32_t);
2302 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2306 case SD_BUS_TYPE_INT16
:
2307 case SD_BUS_TYPE_UINT16
: {
2310 x
= (uint16_t) va_arg(ap
, int);
2311 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2315 case SD_BUS_TYPE_INT64
:
2316 case SD_BUS_TYPE_UINT64
: {
2319 x
= va_arg(ap
, uint64_t);
2320 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2324 case SD_BUS_TYPE_DOUBLE
: {
2327 x
= va_arg(ap
, double);
2328 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2332 case SD_BUS_TYPE_STRING
:
2333 case SD_BUS_TYPE_OBJECT_PATH
:
2334 case SD_BUS_TYPE_SIGNATURE
: {
2337 x
= va_arg(ap
, const char*);
2338 r
= sd_bus_message_append_basic(m
, *t
, x
);
2342 case SD_BUS_TYPE_ARRAY
: {
2345 r
= signature_element_length(t
+ 1, &k
);
2351 memcpy(s
, t
+ 1, k
);
2354 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2359 if (n_array
== (unsigned) -1) {
2364 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2370 n_array
= va_arg(ap
, unsigned);
2375 case SD_BUS_TYPE_VARIANT
: {
2378 s
= va_arg(ap
, const char*);
2382 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2386 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2391 n_struct
= strlen(s
);
2392 n_array
= (unsigned) -1;
2397 case SD_BUS_TYPE_STRUCT_BEGIN
:
2398 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2401 r
= signature_element_length(t
, &k
);
2408 memcpy(s
, t
+ 1, k
- 2);
2411 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2416 if (n_array
== (unsigned) -1) {
2421 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2427 n_array
= (unsigned) -1;
2443 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2447 va_start(ap
, types
);
2448 r
= sd_bus_message_appendv(m
, types
, ap
);
2454 _public_
int sd_bus_message_append_array_space(
2464 assert_return(m
, -EINVAL
);
2465 assert_return(!m
->sealed
, -EPERM
);
2466 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2467 assert_return(ptr
|| size
== 0, -EINVAL
);
2468 assert_return(!m
->poisoned
, -ESTALE
);
2470 /* alignment and size of the trivial types (except bool) is
2471 * identical for gvariant and dbus1 marshalling */
2472 align
= bus_type_get_alignment(type
);
2473 sz
= bus_type_get_size(type
);
2475 assert_se(align
> 0);
2481 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2485 a
= message_extend_body(m
, align
, size
, false, false);
2489 r
= sd_bus_message_close_container(m
);
2497 _public_
int sd_bus_message_append_array(
2505 assert_return(m
, -EINVAL
);
2506 assert_return(!m
->sealed
, -EPERM
);
2507 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2508 assert_return(ptr
|| size
== 0, -EINVAL
);
2509 assert_return(!m
->poisoned
, -ESTALE
);
2511 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2515 memcpy_safe(p
, ptr
, size
);
2520 _public_
int sd_bus_message_append_array_iovec(
2523 const struct iovec
*iov
,
2524 unsigned n
/* should be size_t, but is API now… 😞 */) {
2531 assert_return(m
, -EINVAL
);
2532 assert_return(!m
->sealed
, -EPERM
);
2533 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2534 assert_return(iov
|| n
== 0, -EINVAL
);
2535 assert_return(!m
->poisoned
, -ESTALE
);
2537 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2539 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2543 for (i
= 0; i
< n
; i
++) {
2545 if (iov
[i
].iov_base
)
2546 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2548 memzero(p
, iov
[i
].iov_len
);
2550 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2556 _public_
int sd_bus_message_append_array_memfd(
2563 _cleanup_close_
int copy_fd
= -1;
2564 struct bus_body_part
*part
;
2570 assert_return(m
, -EINVAL
);
2571 assert_return(memfd
>= 0, -EBADF
);
2572 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2573 assert_return(size
> 0, -EINVAL
);
2574 assert_return(!m
->sealed
, -EPERM
);
2575 assert_return(!m
->poisoned
, -ESTALE
);
2577 r
= memfd_set_sealed(memfd
);
2581 copy_fd
= fcntl(memfd
, F_DUPFD_CLOEXEC
, 3);
2585 r
= memfd_get_size(memfd
, &real_size
);
2589 if (offset
== 0 && size
== (uint64_t) -1)
2591 else if (offset
+ size
> real_size
)
2594 align
= bus_type_get_alignment(type
);
2595 sz
= bus_type_get_size(type
);
2597 assert_se(align
> 0);
2600 if (offset
% align
!= 0)
2606 if (size
> (uint64_t) (uint32_t) -1)
2609 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2613 a
= message_extend_body(m
, align
, 0, false, false);
2617 part
= message_append_part(m
);
2621 part
->memfd
= copy_fd
;
2622 part
->memfd_offset
= offset
;
2623 part
->sealed
= true;
2627 m
->body_size
+= size
;
2628 message_extend_containers(m
, size
);
2630 return sd_bus_message_close_container(m
);
2633 _public_
int sd_bus_message_append_string_memfd(
2639 _cleanup_close_
int copy_fd
= -1;
2640 struct bus_body_part
*part
;
2641 struct bus_container
*c
;
2646 assert_return(m
, -EINVAL
);
2647 assert_return(memfd
>= 0, -EBADF
);
2648 assert_return(size
> 0, -EINVAL
);
2649 assert_return(!m
->sealed
, -EPERM
);
2650 assert_return(!m
->poisoned
, -ESTALE
);
2652 r
= memfd_set_sealed(memfd
);
2656 copy_fd
= fcntl(memfd
, FD_CLOEXEC
, 3);
2660 r
= memfd_get_size(memfd
, &real_size
);
2664 if (offset
== 0 && size
== (uint64_t) -1)
2666 else if (offset
+ size
> real_size
)
2669 /* We require this to be NUL terminated */
2673 if (size
> (uint64_t) (uint32_t) -1)
2676 c
= message_get_last_container(m
);
2677 if (c
->signature
&& c
->signature
[c
->index
]) {
2678 /* Container signature is already set */
2680 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2685 /* Maybe we can append to the signature? But only if this is the top-level container */
2686 if (c
->enclosing
!= 0)
2689 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2696 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2697 a
= message_extend_body(m
, 4, 4, false, false);
2701 *(uint32_t*) a
= size
- 1;
2704 part
= message_append_part(m
);
2708 part
->memfd
= copy_fd
;
2709 part
->memfd_offset
= offset
;
2710 part
->sealed
= true;
2714 m
->body_size
+= size
;
2715 message_extend_containers(m
, size
);
2717 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2718 r
= message_add_offset(m
, m
->body_size
);
2725 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2731 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2735 assert_return(m
, -EINVAL
);
2736 assert_return(!m
->sealed
, -EPERM
);
2737 assert_return(!m
->poisoned
, -ESTALE
);
2739 r
= sd_bus_message_open_container(m
, 'a', "s");
2743 STRV_FOREACH(i
, l
) {
2744 r
= sd_bus_message_append_basic(m
, 's', *i
);
2749 return sd_bus_message_close_container(m
);
2752 static int bus_message_close_header(sd_bus_message
*m
) {
2756 /* The actual user data is finished now, we just complete the
2757 variant and struct now (at least on gvariant). Remember
2758 this position, so that during parsing we know where to
2759 put the outer container end. */
2760 m
->user_body_size
= m
->body_size
;
2762 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2763 const char *signature
;
2767 /* Add offset table to end of fields array */
2768 if (m
->n_header_offsets
>= 1) {
2772 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2774 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2775 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2779 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2780 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2783 /* Add gvariant NUL byte plus signature to the end of
2784 * the body, followed by the final offset pointing to
2785 * the end of the fields array */
2787 signature
= strempty(m
->root_container
.signature
);
2788 l
= strlen(signature
);
2790 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2791 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2796 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2797 memcpy((uint8_t*) d
+ 2, signature
, l
);
2798 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2800 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2803 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2805 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2806 m
->header
->dbus1
.body_size
= m
->body_size
;
2812 _public_
int sd_bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, uint64_t timeout_usec
) {
2813 struct bus_body_part
*part
;
2818 assert_return(m
, -EINVAL
);
2823 if (m
->n_containers
> 0)
2829 if (cookie
> 0xffffffffULL
&&
2830 !BUS_MESSAGE_IS_GVARIANT(m
))
2833 /* In vtables the return signature of method calls is listed,
2834 * let's check if they match if this is a response */
2835 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2836 m
->enforced_reply_signature
&&
2837 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2840 /* If gvariant marshalling is used we need to close the body structure */
2841 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2845 /* If there's a non-trivial signature set, then add it in
2846 * here, but only on dbus1 */
2847 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2848 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2854 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2859 r
= bus_message_close_header(m
);
2863 if (BUS_MESSAGE_IS_GVARIANT(m
))
2864 m
->header
->dbus2
.cookie
= cookie
;
2866 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2868 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout_usec
;
2870 /* Add padding at the end of the fields part, since we know
2871 * the body needs to start at an 8 byte alignment. We made
2872 * sure we allocated enough space for this, so all we need to
2873 * do here is to zero it out. */
2874 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2876 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2878 /* If this is something we can send as memfd, then let's seal
2879 the memfd now. Note that we can send memfds as payload only
2880 for directed messages, and not for broadcasts. */
2881 if (m
->destination
&& m
->bus
->use_memfd
) {
2882 MESSAGE_FOREACH_PART(part
, i
, m
)
2883 if (part
->memfd
>= 0 &&
2885 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
2886 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
2889 /* Try to seal it if that makes
2890 * sense. First, unmap our own map to
2891 * make sure we don't keep it busy. */
2892 bus_body_part_unmap(part
);
2894 /* Then, sync up real memfd size */
2896 r
= memfd_set_size(part
->memfd
, sz
);
2900 /* Finally, try to seal */
2901 if (memfd_set_sealed(part
->memfd
) >= 0)
2902 part
->sealed
= true;
2906 m
->root_container
.end
= m
->user_body_size
;
2907 m
->root_container
.index
= 0;
2908 m
->root_container
.offset_index
= 0;
2909 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
2916 int bus_body_part_map(struct bus_body_part
*part
) {
2925 if (part
->size
<= 0)
2928 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2929 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
2930 static const uint8_t zeroes
[7] = { };
2931 part
->data
= (void*) zeroes
;
2935 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
2936 psz
= PAGE_ALIGN(part
->size
+ shift
);
2938 if (part
->memfd
>= 0)
2939 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
2940 else if (part
->is_zero
)
2941 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
2945 if (p
== MAP_FAILED
)
2949 part
->mmap_begin
= p
;
2950 part
->data
= (uint8_t*) p
+ shift
;
2951 part
->munmap_this
= true;
2956 void bus_body_part_unmap(struct bus_body_part
*part
) {
2960 if (part
->memfd
< 0)
2963 if (!part
->mmap_begin
)
2966 if (!part
->munmap_this
)
2969 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
2971 part
->mmap_begin
= NULL
;
2974 part
->munmap_this
= false;
2979 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
2980 size_t k
, start
, end
;
2985 start
= ALIGN_TO((size_t) *rindex
, align
);
2986 end
= start
+ nbytes
;
2991 /* Verify that padding is 0 */
2992 for (k
= *rindex
; k
< start
; k
++)
2993 if (((const uint8_t*) p
)[k
] != 0)
2997 *r
= (uint8_t*) p
+ start
;
3004 static bool message_end_of_signature(sd_bus_message
*m
) {
3005 struct bus_container
*c
;
3009 c
= message_get_last_container(m
);
3010 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3013 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3014 struct bus_container
*c
;
3018 c
= message_get_last_container(m
);
3019 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3022 if (BUS_MESSAGE_IS_GVARIANT(m
))
3023 return index
>= c
->end
;
3025 assert(c
->array_size
);
3026 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3030 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3031 assert_return(m
, -EINVAL
);
3032 assert_return(m
->sealed
, -EPERM
);
3034 if (complete
&& m
->n_containers
> 0)
3037 if (message_end_of_signature(m
))
3040 if (message_end_of_array(m
, m
->rindex
))
3046 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3047 struct bus_body_part
*part
;
3053 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3054 part
= m
->cached_rindex_part
;
3055 begin
= m
->cached_rindex_part_begin
;
3065 if (index
+ sz
<= begin
+ part
->size
) {
3067 r
= bus_body_part_map(part
);
3072 *p
= (uint8_t*) part
->data
+ index
- begin
;
3074 m
->cached_rindex_part
= part
;
3075 m
->cached_rindex_part_begin
= begin
;
3080 begin
+= part
->size
;
3087 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3094 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3097 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3100 sz
= bus_gvariant_get_size(c
->signature
);
3104 if (c
->offset_index
+1 >= c
->n_offsets
)
3107 /* Variable-size array */
3109 alignment
= bus_gvariant_get_alignment(c
->signature
);
3110 assert(alignment
> 0);
3112 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3113 assert(c
->offsets
[c
->offset_index
+1] >= *rindex
);
3114 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3117 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3120 /* Fixed-size array */
3121 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3127 } else if (IN_SET(c
->enclosing
, 0, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
3132 if (c
->offset_index
+1 >= c
->n_offsets
)
3135 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3139 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3144 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3147 alignment
= bus_gvariant_get_alignment(t
);
3150 assert(alignment
> 0);
3152 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3153 assert(c
->offsets
[c
->offset_index
+1] >= *rindex
);
3154 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3158 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3161 assert_not_reached("Unknown container type");
3166 /* Reached the end */
3172 static int message_peek_body(
3179 size_t k
, start
, end
, padding
;
3180 struct bus_body_part
*part
;
3187 start
= ALIGN_TO((size_t) *rindex
, align
);
3188 padding
= start
- *rindex
;
3189 end
= start
+ nbytes
;
3191 if (end
> m
->user_body_size
)
3194 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3199 /* Verify padding */
3200 for (k
= 0; k
< padding
; k
++)
3205 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3206 if (!part
|| (nbytes
> 0 && !q
))
3217 static bool validate_nul(const char *s
, size_t l
) {
3219 /* Check for NUL chars in the string */
3220 if (memchr(s
, 0, l
))
3223 /* Check for NUL termination */
3230 static bool validate_string(const char *s
, size_t l
) {
3232 if (!validate_nul(s
, l
))
3235 /* Check if valid UTF8 */
3236 if (!utf8_is_valid(s
))
3242 static bool validate_signature(const char *s
, size_t l
) {
3244 if (!validate_nul(s
, l
))
3247 /* Check if valid signature */
3248 if (!signature_is_valid(s
, true))
3254 static bool validate_object_path(const char *s
, size_t l
) {
3256 if (!validate_nul(s
, l
))
3259 if (!object_path_is_valid(s
))
3265 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3266 struct bus_container
*c
;
3271 assert_return(m
, -EINVAL
);
3272 assert_return(m
->sealed
, -EPERM
);
3273 assert_return(bus_type_is_basic(type
), -EINVAL
);
3275 if (message_end_of_signature(m
))
3278 if (message_end_of_array(m
, m
->rindex
))
3281 c
= message_get_last_container(m
);
3282 if (c
->signature
[c
->index
] != type
)
3287 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3289 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3292 /* D-Bus spec: The marshalling formats for the string-like types all end
3293 * with a single zero (NUL) byte, but that byte is not considered to be part
3295 if (c
->item_size
== 0)
3298 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3302 if (type
== SD_BUS_TYPE_STRING
)
3303 ok
= validate_string(q
, c
->item_size
-1);
3304 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3305 ok
= validate_object_path(q
, c
->item_size
-1);
3307 ok
= validate_signature(q
, c
->item_size
-1);
3313 *(const char**) p
= q
;
3317 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3319 if ((size_t) sz
!= c
->item_size
)
3322 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3325 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3331 case SD_BUS_TYPE_BYTE
:
3333 *(uint8_t*) p
= *(uint8_t*) q
;
3336 case SD_BUS_TYPE_BOOLEAN
:
3338 *(int*) p
= !!*(uint8_t*) q
;
3341 case SD_BUS_TYPE_INT16
:
3342 case SD_BUS_TYPE_UINT16
:
3344 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3347 case SD_BUS_TYPE_INT32
:
3348 case SD_BUS_TYPE_UINT32
:
3350 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3353 case SD_BUS_TYPE_INT64
:
3354 case SD_BUS_TYPE_UINT64
:
3355 case SD_BUS_TYPE_DOUBLE
:
3357 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3360 case SD_BUS_TYPE_UNIX_FD
: {
3363 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3368 *(int*) p
= m
->fds
[j
];
3374 assert_not_reached("unexpected type");
3378 r
= container_next_item(m
, c
, &rindex
);
3383 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3387 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3391 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3392 if (l
== UINT32_MAX
)
3393 /* avoid overflow right below */
3396 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3400 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3401 ok
= validate_object_path(q
, l
);
3403 ok
= validate_string(q
, l
);
3408 *(const char**) p
= q
;
3410 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3413 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3419 /* avoid overflow right below */
3422 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3426 if (!validate_signature(q
, l
))
3430 *(const char**) p
= q
;
3435 align
= bus_type_get_alignment(type
);
3438 sz
= bus_type_get_size(type
);
3441 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3447 case SD_BUS_TYPE_BYTE
:
3449 *(uint8_t*) p
= *(uint8_t*) q
;
3452 case SD_BUS_TYPE_BOOLEAN
:
3454 *(int*) p
= !!*(uint32_t*) q
;
3457 case SD_BUS_TYPE_INT16
:
3458 case SD_BUS_TYPE_UINT16
:
3460 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3463 case SD_BUS_TYPE_INT32
:
3464 case SD_BUS_TYPE_UINT32
:
3466 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3469 case SD_BUS_TYPE_INT64
:
3470 case SD_BUS_TYPE_UINT64
:
3471 case SD_BUS_TYPE_DOUBLE
:
3473 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3476 case SD_BUS_TYPE_UNIX_FD
: {
3479 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3484 *(int*) p
= m
->fds
[j
];
3489 assert_not_reached("Unknown basic type...");
3496 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3502 static int bus_message_enter_array(
3504 struct bus_container
*c
,
3505 const char *contents
,
3506 uint32_t **array_size
,
3509 size_t *n_offsets
) {
3523 if (!signature_is_single(contents
, true))
3526 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3529 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3532 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3537 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3541 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3545 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3548 alignment
= bus_type_get_alignment(contents
[0]);
3552 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3556 *array_size
= (uint32_t*) q
;
3558 } else if (c
->item_size
<= 0) {
3560 /* gvariant: empty array */
3565 } else if (bus_gvariant_is_fixed_size(contents
)) {
3567 /* gvariant: fixed length array */
3568 *item_size
= bus_gvariant_get_size(contents
);
3573 size_t where
, previous
= 0, framing
, sz
;
3577 /* gvariant: variable length array */
3578 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3580 where
= rindex
+ c
->item_size
- sz
;
3581 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3585 framing
= bus_gvariant_read_word_le(q
, sz
);
3586 if (framing
> c
->item_size
- sz
)
3588 if ((c
->item_size
- framing
) % sz
!= 0)
3591 *n_offsets
= (c
->item_size
- framing
) / sz
;
3593 where
= rindex
+ framing
;
3594 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3598 *offsets
= new(size_t, *n_offsets
);
3602 alignment
= bus_gvariant_get_alignment(c
->signature
);
3603 assert(alignment
> 0);
3605 for (i
= 0; i
< *n_offsets
; i
++) {
3608 start
= ALIGN_TO(previous
, alignment
);
3610 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3611 if (x
> c
->item_size
- sz
)
3616 (*offsets
)[i
] = rindex
+ x
;
3620 *item_size
= (*offsets
)[0] - rindex
;
3625 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3626 c
->index
+= 1 + strlen(contents
);
3631 static int bus_message_enter_variant(
3633 struct bus_container
*c
,
3634 const char *contents
,
3635 size_t *item_size
) {
3647 if (!signature_is_single(contents
, false))
3650 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3653 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3656 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3661 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3664 k
= strlen(contents
);
3665 if (1+k
> c
->item_size
)
3668 where
= rindex
+ c
->item_size
- (1+k
);
3669 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3673 if (*(char*) q
!= 0)
3676 if (memcmp((uint8_t*) q
+1, contents
, k
))
3679 *item_size
= c
->item_size
- (1+k
);
3682 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3688 /* avoid overflow right below */
3691 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3695 if (!validate_signature(q
, l
))
3698 if (!streq(q
, contents
))
3704 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3710 static int build_struct_offsets(
3712 const char *signature
,
3716 size_t *n_offsets
) {
3718 unsigned n_variable
= 0, n_total
= 0, v
;
3719 size_t previous
, where
;
3730 if (isempty(signature
)) {
3731 /* Unary type is encoded as *fixed* 1 byte padding */
3732 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3736 if (*(uint8_t *) q
!= 0)
3745 sz
= bus_gvariant_determine_word_size(size
, 0);
3749 /* First, loop over signature and count variable elements and
3750 * elements in general. We use this to know how large the
3751 * offset array is at the end of the structure. Note that
3752 * GVariant only stores offsets for all variable size elements
3753 * that are not the last item. */
3759 r
= signature_element_length(p
, &n
);
3768 r
= bus_gvariant_is_fixed_size(t
);
3773 if (r
== 0 && p
[n
] != 0) /* except the last item */
3780 if (size
< n_variable
* sz
)
3783 where
= m
->rindex
+ size
- (n_variable
* sz
);
3784 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3790 *offsets
= new(size_t, n_total
);
3796 /* Second, loop again and build an offset table */
3798 previous
= m
->rindex
;
3803 r
= signature_element_length(p
, &n
);
3812 size_t align
= bus_gvariant_get_alignment(t
);
3815 /* The possible start of this member after including alignment */
3816 size_t start
= ALIGN_TO(previous
, align
);
3818 k
= bus_gvariant_get_size(t
);
3826 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3830 /* The last item's end is determined
3831 * from the start of the offset array */
3832 x
= size
- (n_variable
* sz
);
3834 offset
= m
->rindex
+ x
;
3835 if (offset
< start
) {
3836 log_debug("For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu",
3837 t
, align
, offset
, previous
, start
);
3845 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3850 assert(*n_offsets
== n_total
);
3852 *item_size
= (*offsets
)[0] - m
->rindex
;
3856 static int enter_struct_or_dict_entry(
3858 struct bus_container
*c
,
3859 const char *contents
,
3862 size_t *n_offsets
) {
3873 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3876 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3881 /* gvariant with contents */
3882 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3887 static int bus_message_enter_struct(
3889 struct bus_container
*c
,
3890 const char *contents
,
3893 size_t *n_offsets
) {
3905 if (!signature_is_valid(contents
, false))
3908 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3911 l
= strlen(contents
);
3913 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
3914 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3915 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
3918 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3922 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3923 c
->index
+= 1 + l
+ 1;
3928 static int bus_message_enter_dict_entry(
3930 struct bus_container
*c
,
3931 const char *contents
,
3934 size_t *n_offsets
) {
3943 if (!signature_is_pair(contents
))
3946 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3949 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3952 l
= strlen(contents
);
3954 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
3955 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3956 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
3959 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3963 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3964 c
->index
+= 1 + l
+ 1;
3969 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
3971 const char *contents
) {
3972 struct bus_container
*c
;
3973 uint32_t *array_size
= NULL
;
3974 _cleanup_free_
char *signature
= NULL
;
3976 _cleanup_free_
size_t *offsets
= NULL
;
3977 size_t n_offsets
= 0, item_size
= 0;
3980 assert_return(m
, -EINVAL
);
3981 assert_return(m
->sealed
, -EPERM
);
3982 assert_return(type
!= 0 || !contents
, -EINVAL
);
3984 if (type
== 0 || !contents
) {
3988 /* Allow entering into anonymous containers */
3989 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
3993 if (type
!= 0 && type
!= tt
)
3996 if (contents
&& !streq(contents
, cc
))
4004 * We enforce a global limit on container depth, that is much
4005 * higher than the 32 structs and 32 arrays the specification
4006 * mandates. This is simpler to implement for us, and we need
4007 * this only to ensure our container array doesn't grow
4008 * without bounds. We are happy to return any data from a
4009 * message as long as the data itself is valid, even if the
4010 * overall message might be not.
4012 * Note that the message signature is validated when
4013 * parsing the headers, and that validation does check the
4016 * Note that the specification defines no limits on the depth
4017 * of stacked variants, but we do.
4019 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4022 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4025 if (message_end_of_signature(m
))
4028 if (message_end_of_array(m
, m
->rindex
))
4031 c
= message_get_last_container(m
);
4033 signature
= strdup(contents
);
4037 c
->saved_index
= c
->index
;
4040 if (type
== SD_BUS_TYPE_ARRAY
)
4041 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4042 else if (type
== SD_BUS_TYPE_VARIANT
)
4043 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4044 else if (type
== SD_BUS_TYPE_STRUCT
)
4045 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4046 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4047 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4053 /* OK, let's fill it in */
4054 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4055 type
== SD_BUS_TYPE_STRUCT
&&
4057 end
= m
->rindex
+ 0;
4059 end
= m
->rindex
+ c
->item_size
;
4061 m
->containers
[m
->n_containers
++] = (struct bus_container
) {
4063 .signature
= TAKE_PTR(signature
),
4067 /* Unary type has fixed size of 1, but virtual size of 0 */
4069 .array_size
= array_size
,
4070 .item_size
= item_size
,
4071 .offsets
= TAKE_PTR(offsets
),
4072 .n_offsets
= n_offsets
,
4078 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4079 struct bus_container
*c
;
4083 assert_return(m
, -EINVAL
);
4084 assert_return(m
->sealed
, -EPERM
);
4085 assert_return(m
->n_containers
> 0, -ENXIO
);
4087 c
= message_get_last_container(m
);
4089 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4090 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4094 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4095 if (m
->rindex
< c
->end
)
4098 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4101 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4102 if (c
->begin
+ l
!= m
->rindex
)
4106 message_free_last_container(m
);
4108 c
= message_get_last_container(m
);
4110 c
->index
= c
->saved_index
;
4111 r
= container_next_item(m
, c
, &m
->rindex
);
4119 static void message_quit_container(sd_bus_message
*m
) {
4120 struct bus_container
*c
;
4124 assert(m
->n_containers
> 0);
4127 c
= message_get_last_container(m
);
4128 assert(m
->rindex
>= c
->before
);
4129 m
->rindex
= c
->before
;
4131 /* Free container */
4132 message_free_last_container(m
);
4134 /* Correct index of new top-level container */
4135 c
= message_get_last_container(m
);
4136 c
->index
= c
->saved_index
;
4139 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4140 struct bus_container
*c
;
4143 assert_return(m
, -EINVAL
);
4144 assert_return(m
->sealed
, -EPERM
);
4146 if (message_end_of_signature(m
))
4149 if (message_end_of_array(m
, m
->rindex
))
4152 c
= message_get_last_container(m
);
4154 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4158 *type
= c
->signature
[c
->index
];
4162 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4167 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4171 /* signature_element_length does verification internally */
4173 /* The array element must not be empty */
4175 if (free_and_strndup(&c
->peeked_signature
,
4176 c
->signature
+ c
->index
+ 1, l
) < 0)
4179 *contents
= c
->peeked_signature
;
4183 *type
= SD_BUS_TYPE_ARRAY
;
4188 if (IN_SET(c
->signature
[c
->index
], SD_BUS_TYPE_STRUCT_BEGIN
, SD_BUS_TYPE_DICT_ENTRY_BEGIN
)) {
4193 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4198 if (free_and_strndup(&c
->peeked_signature
,
4199 c
->signature
+ c
->index
+ 1, l
- 2) < 0)
4202 *contents
= c
->peeked_signature
;
4206 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4211 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4215 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4218 if (c
->item_size
< 2)
4221 /* Look for the NUL delimiter that
4222 separates the payload from the
4223 signature. Since the body might be
4224 in a different part that then the
4225 signature we map byte by byte. */
4227 for (k
= 2; k
<= c
->item_size
; k
++) {
4230 where
= m
->rindex
+ c
->item_size
- k
;
4231 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4235 if (*(char*) q
== 0)
4239 if (k
> c
->item_size
)
4242 if (free_and_strndup(&c
->peeked_signature
,
4243 (char*) q
+ 1, k
- 1) < 0)
4246 if (!signature_is_valid(c
->peeked_signature
, true))
4249 *contents
= c
->peeked_signature
;
4254 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4260 /* avoid overflow right below */
4263 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4267 if (!validate_signature(q
, l
))
4275 *type
= SD_BUS_TYPE_VARIANT
;
4290 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4291 struct bus_container
*c
;
4293 assert_return(m
, -EINVAL
);
4294 assert_return(m
->sealed
, -EPERM
);
4297 message_reset_containers(m
);
4300 c
= message_get_last_container(m
);
4302 c
= message_get_last_container(m
);
4305 m
->rindex
= c
->begin
;
4308 c
->offset_index
= 0;
4309 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4311 return !isempty(c
->signature
);
4314 _public_
int sd_bus_message_readv(
4319 unsigned n_array
, n_struct
;
4320 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4321 unsigned stack_ptr
= 0;
4322 unsigned n_loop
= 0;
4325 assert_return(m
, -EINVAL
);
4326 assert_return(m
->sealed
, -EPERM
);
4327 assert_return(types
, -EINVAL
);
4332 /* Ideally, we'd just call ourselves recursively on every
4333 * complex type. However, the state of a va_list that is
4334 * passed to a function is undefined after that function
4335 * returns. This means we need to decode the va_list linearly
4336 * in a single stackframe. We hence implement our own
4337 * home-grown stack in an array. */
4339 n_array
= (unsigned) -1; /* length of current array entries */
4340 n_struct
= strlen(types
); /* length of current struct contents signature */
4347 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4348 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4354 r
= sd_bus_message_exit_container(m
);
4362 if (n_array
!= (unsigned) -1)
4371 case SD_BUS_TYPE_BYTE
:
4372 case SD_BUS_TYPE_BOOLEAN
:
4373 case SD_BUS_TYPE_INT16
:
4374 case SD_BUS_TYPE_UINT16
:
4375 case SD_BUS_TYPE_INT32
:
4376 case SD_BUS_TYPE_UINT32
:
4377 case SD_BUS_TYPE_INT64
:
4378 case SD_BUS_TYPE_UINT64
:
4379 case SD_BUS_TYPE_DOUBLE
:
4380 case SD_BUS_TYPE_STRING
:
4381 case SD_BUS_TYPE_OBJECT_PATH
:
4382 case SD_BUS_TYPE_SIGNATURE
:
4383 case SD_BUS_TYPE_UNIX_FD
: {
4386 p
= va_arg(ap
, void*);
4387 r
= sd_bus_message_read_basic(m
, *t
, p
);
4400 case SD_BUS_TYPE_ARRAY
: {
4403 r
= signature_element_length(t
+ 1, &k
);
4409 memcpy(s
, t
+ 1, k
);
4412 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4423 if (n_array
== (unsigned) -1) {
4428 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4434 n_array
= va_arg(ap
, unsigned);
4439 case SD_BUS_TYPE_VARIANT
: {
4442 s
= va_arg(ap
, const char *);
4446 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4456 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4461 n_struct
= strlen(s
);
4462 n_array
= (unsigned) -1;
4467 case SD_BUS_TYPE_STRUCT_BEGIN
:
4468 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4471 r
= signature_element_length(t
, &k
);
4477 memcpy(s
, t
+ 1, k
- 2);
4480 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4490 if (n_array
== (unsigned) -1) {
4495 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4501 n_array
= (unsigned) -1;
4514 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4518 va_start(ap
, types
);
4519 r
= sd_bus_message_readv(m
, types
, ap
);
4525 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4528 assert_return(m
, -EINVAL
);
4529 assert_return(m
->sealed
, -EPERM
);
4531 /* If types is NULL, read exactly one element */
4533 struct bus_container
*c
;
4536 if (message_end_of_signature(m
))
4539 if (message_end_of_array(m
, m
->rindex
))
4542 c
= message_get_last_container(m
);
4544 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4548 types
= strndupa(c
->signature
+ c
->index
, l
);
4553 case 0: /* Nothing to drop */
4556 case SD_BUS_TYPE_BYTE
:
4557 case SD_BUS_TYPE_BOOLEAN
:
4558 case SD_BUS_TYPE_INT16
:
4559 case SD_BUS_TYPE_UINT16
:
4560 case SD_BUS_TYPE_INT32
:
4561 case SD_BUS_TYPE_UINT32
:
4562 case SD_BUS_TYPE_INT64
:
4563 case SD_BUS_TYPE_UINT64
:
4564 case SD_BUS_TYPE_DOUBLE
:
4565 case SD_BUS_TYPE_STRING
:
4566 case SD_BUS_TYPE_OBJECT_PATH
:
4567 case SD_BUS_TYPE_SIGNATURE
:
4568 case SD_BUS_TYPE_UNIX_FD
:
4570 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4574 r
= sd_bus_message_skip(m
, types
+ 1);
4580 case SD_BUS_TYPE_ARRAY
: {
4583 r
= signature_element_length(types
+ 1, &k
);
4589 memcpy(s
, types
+1, k
);
4592 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4597 r
= sd_bus_message_skip(m
, s
);
4604 r
= sd_bus_message_exit_container(m
);
4609 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4616 case SD_BUS_TYPE_VARIANT
: {
4617 const char *contents
;
4620 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4624 if (x
!= SD_BUS_TYPE_VARIANT
)
4627 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4631 r
= sd_bus_message_skip(m
, contents
);
4636 r
= sd_bus_message_exit_container(m
);
4640 r
= sd_bus_message_skip(m
, types
+ 1);
4647 case SD_BUS_TYPE_STRUCT_BEGIN
:
4648 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4651 r
= signature_element_length(types
, &k
);
4657 memcpy(s
, types
+1, k
-2);
4660 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4664 r
= sd_bus_message_skip(m
, s
);
4668 r
= sd_bus_message_exit_container(m
);
4673 r
= sd_bus_message_skip(m
, types
+ k
);
4685 _public_
int sd_bus_message_read_array(
4691 struct bus_container
*c
;
4697 assert_return(m
, -EINVAL
);
4698 assert_return(m
->sealed
, -EPERM
);
4699 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4700 assert_return(ptr
, -EINVAL
);
4701 assert_return(size
, -EINVAL
);
4702 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4704 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4708 c
= message_get_last_container(m
);
4710 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4711 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4715 sz
= c
->end
- c
->begin
;
4717 align
= bus_type_get_alignment(type
);
4721 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4725 /* Zero length array, let's return some aligned
4726 * pointer that is not NULL */
4727 p
= (uint8_t*) align
;
4729 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4734 r
= sd_bus_message_exit_container(m
);
4738 *ptr
= (const void*) p
;
4744 message_quit_container(m
);
4748 static int message_peek_fields(
4759 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4762 static int message_peek_field_uint32(
4774 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4777 /* identical for gvariant and dbus1 */
4779 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4784 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4789 static int message_peek_field_uint64(
4801 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4804 /* identical for gvariant and dbus1 */
4806 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4811 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4816 static int message_peek_field_string(
4818 bool (*validate
)(const char *p
),
4830 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4835 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4841 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4845 if (l
== UINT32_MAX
)
4846 /* avoid overflow right below */
4849 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4855 if (!validate_nul(q
, l
))
4861 if (!validate_string(q
, l
))
4871 static int message_peek_field_signature(
4884 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4889 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4895 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
4901 /* avoid overflow right below */
4904 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4909 if (!validate_signature(q
, l
))
4918 static int message_skip_fields(
4921 uint32_t array_size
,
4922 const char **signature
) {
4924 size_t original_index
;
4930 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
4932 original_index
= *ri
;
4938 if (array_size
!= (uint32_t) -1 &&
4939 array_size
<= *ri
- original_index
)
4946 if (t
== SD_BUS_TYPE_STRING
) {
4948 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
4954 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
4956 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
4962 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
4964 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
4970 } else if (bus_type_is_basic(t
)) {
4973 align
= bus_type_get_alignment(t
);
4974 k
= bus_type_get_size(t
);
4975 assert(align
> 0 && k
> 0);
4977 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
4983 } else if (t
== SD_BUS_TYPE_ARRAY
) {
4985 r
= signature_element_length(*signature
+ 1, &l
);
4991 char sig
[l
+ 1], *s
= sig
;
4995 strncpy(sig
, *signature
+ 1, l
);
4998 alignment
= bus_type_get_alignment(sig
[0]);
5002 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5005 if (nas
> BUS_ARRAY_MAX_SIZE
)
5008 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5012 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5017 (*signature
) += 1 + l
;
5019 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5022 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5026 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5032 } else if (IN_SET(t
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
5034 r
= signature_element_length(*signature
, &l
);
5040 char sig
[l
+ 1], *s
= sig
;
5041 strncpy(sig
, *signature
+ 1, l
);
5044 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5055 int bus_message_parse_fields(sd_bus_message
*m
) {
5058 uint32_t unix_fds
= 0;
5059 bool unix_fds_set
= false;
5060 void *offsets
= NULL
;
5061 unsigned n_offsets
= 0;
5067 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5070 /* Read the signature from the end of the body variant first */
5071 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5072 if (m
->footer_accessible
< 1 + sz
)
5075 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5077 if (p
< (char*) m
->footer
)
5084 /* We found the beginning of the signature
5085 * string, yay! We require the body to be a
5086 * structure, so verify it and then strip the
5087 * opening/closing brackets. */
5089 l
= (char*) m
->footer
+ m
->footer_accessible
- p
- (1 + sz
);
5091 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5092 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5095 k
= memdup_suffix0(p
+ 1 + 1, l
- 2);
5099 free_and_replace(m
->root_container
.signature
, k
);
5106 /* Calculate the actual user body size, by removing
5107 * the trailing variant signature and struct offset
5109 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5111 /* Pull out the offset table for the fields array */
5112 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5117 ri
= m
->fields_size
- sz
;
5118 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5122 framing
= bus_gvariant_read_word_le(q
, sz
);
5123 if (framing
>= m
->fields_size
- sz
)
5125 if ((m
->fields_size
- framing
) % sz
!= 0)
5129 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5133 n_offsets
= (m
->fields_size
- framing
) / sz
;
5136 m
->user_body_size
= m
->body_size
;
5139 while (ri
< m
->fields_size
) {
5140 _cleanup_free_
char *sig
= NULL
;
5141 const char *signature
;
5142 uint64_t field_type
;
5143 size_t item_size
= (size_t) -1;
5145 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5154 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5156 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5160 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5164 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5171 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5176 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5181 where
= ri
= ALIGN_TO(ri
, 8);
5182 item_size
= end
- ri
;
5183 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5187 b
= memrchr(q
, 0, item_size
);
5191 sig
= strndup(b
+1, item_size
- (b
+1-(char*) q
));
5196 item_size
= b
- (char*) q
;
5198 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5203 switch (field_type
) {
5205 case _BUS_MESSAGE_HEADER_INVALID
:
5208 case BUS_MESSAGE_HEADER_PATH
:
5213 if (!streq(signature
, "o"))
5216 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5219 case BUS_MESSAGE_HEADER_INTERFACE
:
5224 if (!streq(signature
, "s"))
5227 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5230 case BUS_MESSAGE_HEADER_MEMBER
:
5235 if (!streq(signature
, "s"))
5238 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5241 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5246 if (!streq(signature
, "s"))
5249 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5251 m
->error
._need_free
= -1;
5255 case BUS_MESSAGE_HEADER_DESTINATION
:
5260 if (!streq(signature
, "s"))
5263 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5266 case BUS_MESSAGE_HEADER_SENDER
:
5271 if (!streq(signature
, "s"))
5274 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5276 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
) {
5277 m
->creds
.unique_name
= (char*) m
->sender
;
5278 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5283 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5287 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5290 if (m
->root_container
.signature
)
5293 if (!streq(signature
, "g"))
5296 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5304 free_and_replace(m
->root_container
.signature
, c
);
5308 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5310 if (m
->reply_cookie
!= 0)
5313 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5314 /* 64bit on dbus2 */
5316 if (!streq(signature
, "t"))
5319 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5323 /* 32bit on dbus1 */
5326 if (!streq(signature
, "u"))
5329 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5333 m
->reply_cookie
= serial
;
5336 if (m
->reply_cookie
== 0)
5341 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5345 if (!streq(signature
, "u"))
5348 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5352 unix_fds_set
= true;
5356 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5357 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5366 if (m
->n_fds
!= unix_fds
)
5369 switch (m
->header
->type
) {
5371 case SD_BUS_MESSAGE_SIGNAL
:
5372 if (!m
->path
|| !m
->interface
|| !m
->member
)
5375 if (m
->reply_cookie
!= 0)
5380 case SD_BUS_MESSAGE_METHOD_CALL
:
5382 if (!m
->path
|| !m
->member
)
5385 if (m
->reply_cookie
!= 0)
5390 case SD_BUS_MESSAGE_METHOD_RETURN
:
5392 if (m
->reply_cookie
== 0)
5396 case SD_BUS_MESSAGE_METHOD_ERROR
:
5398 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5403 /* Refuse non-local messages that claim they are local */
5404 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5406 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5408 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5411 m
->root_container
.end
= m
->user_body_size
;
5413 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5414 r
= build_struct_offsets(
5416 m
->root_container
.signature
,
5418 &m
->root_container
.item_size
,
5419 &m
->root_container
.offsets
,
5420 &m
->root_container
.n_offsets
);
5427 /* Try to read the error message, but if we can't it's a non-issue */
5428 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5429 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5434 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5435 assert_return(m
, -EINVAL
);
5436 assert_return(destination
, -EINVAL
);
5437 assert_return(service_name_is_valid(destination
), -EINVAL
);
5438 assert_return(!m
->sealed
, -EPERM
);
5439 assert_return(!m
->destination
, -EEXIST
);
5441 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5444 _public_
int sd_bus_message_set_sender(sd_bus_message
*m
, const char *sender
) {
5445 assert_return(m
, -EINVAL
);
5446 assert_return(sender
, -EINVAL
);
5447 assert_return(service_name_is_valid(sender
), -EINVAL
);
5448 assert_return(!m
->sealed
, -EPERM
);
5449 assert_return(!m
->sender
, -EEXIST
);
5451 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5454 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5458 struct bus_body_part
*part
;
5464 total
= BUS_MESSAGE_SIZE(m
);
5470 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5471 MESSAGE_FOREACH_PART(part
, i
, m
)
5472 e
= mempcpy(e
, part
->data
, part
->size
);
5474 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5482 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5489 r
= sd_bus_message_enter_container(m
, 'a', "s");
5493 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5494 r
= strv_extend(l
, s
);
5501 r
= sd_bus_message_exit_container(m
);
5508 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5509 _cleanup_strv_free_
char **strv
= NULL
;
5512 assert_return(m
, -EINVAL
);
5513 assert_return(m
->sealed
, -EPERM
);
5514 assert_return(l
, -EINVAL
);
5516 r
= bus_message_read_strv_extend(m
, &strv
);
5520 *l
= TAKE_PTR(strv
);
5524 static int bus_message_get_arg_skip(
5528 const char **_contents
) {
5533 r
= sd_bus_message_rewind(m
, true);
5538 const char *contents
;
5541 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5547 /* Don't match against arguments after the first one we don't understand */
5548 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5549 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5554 *_contents
= contents
;
5560 r
= sd_bus_message_skip(m
, NULL
);
5567 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5574 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5578 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5581 return sd_bus_message_read_basic(m
, type
, str
);
5584 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5585 const char *contents
;
5592 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5596 if (type
!= SD_BUS_TYPE_ARRAY
)
5598 if (!STR_IN_SET(contents
, "s", "o", "g"))
5601 return sd_bus_message_read_strv(m
, strv
);
5604 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5605 assert_return(m
, EINVAL
);
5607 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5610 return sd_bus_error_get_errno(&m
->error
);
5613 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5614 struct bus_container
*c
;
5616 assert_return(m
, NULL
);
5618 c
= complete
? &m
->root_container
: message_get_last_container(m
);
5619 return strempty(c
->signature
);
5622 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5623 assert_return(m
, -EINVAL
);
5625 return isempty(m
->root_container
.signature
);
5628 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5629 assert_return(m
, -EINVAL
);
5631 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5634 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5635 bool done_something
= false;
5638 assert_return(m
, -EINVAL
);
5639 assert_return(source
, -EINVAL
);
5640 assert_return(!m
->sealed
, -EPERM
);
5641 assert_return(source
->sealed
, -EPERM
);
5644 const char *contents
;
5659 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5665 done_something
= true;
5667 if (bus_type_is_container(type
) > 0) {
5669 r
= sd_bus_message_enter_container(source
, type
, contents
);
5673 r
= sd_bus_message_open_container(m
, type
, contents
);
5677 r
= sd_bus_message_copy(m
, source
, true);
5681 r
= sd_bus_message_close_container(m
);
5685 r
= sd_bus_message_exit_container(source
);
5692 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5698 if (IN_SET(type
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
, SD_BUS_TYPE_STRING
))
5699 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5701 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5708 return done_something
;
5711 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5716 assert_return(m
, -EINVAL
);
5717 assert_return(m
->sealed
, -EPERM
);
5718 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5719 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5720 assert_return(type
|| contents
, -EINVAL
);
5721 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5723 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5727 if (type
!= 0 && type
!= t
)
5730 if (contents
&& !streq_ptr(contents
, c
))
5736 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5737 assert_return(m
, NULL
);
5742 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5743 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
5751 switch ((*m
)->header
->type
) {
5753 case SD_BUS_MESSAGE_SIGNAL
:
5754 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5760 case SD_BUS_MESSAGE_METHOD_CALL
:
5761 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5767 case SD_BUS_MESSAGE_METHOD_RETURN
:
5768 case SD_BUS_MESSAGE_METHOD_ERROR
:
5770 r
= sd_bus_message_new(bus
, &n
, (*m
)->header
->type
);
5776 n
->reply_cookie
= (*m
)->reply_cookie
;
5778 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5782 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5783 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5787 n
->error
._need_free
= -1;
5796 if ((*m
)->destination
&& !n
->destination
) {
5797 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5802 if ((*m
)->sender
&& !n
->sender
) {
5803 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5808 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5810 r
= sd_bus_message_copy(n
, *m
, true);
5814 timeout
= (*m
)->timeout
;
5815 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
)) {
5816 r
= sd_bus_get_method_call_timeout(bus
, &timeout
);
5821 r
= sd_bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5825 sd_bus_message_unref(*m
);
5831 int bus_message_append_sender(sd_bus_message
*m
, const char *sender
) {
5835 assert_return(!m
->sealed
, -EPERM
);
5836 assert_return(!m
->sender
, -EPERM
);
5838 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5841 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5842 assert_return(m
, -EINVAL
);
5843 assert_return(priority
, -EINVAL
);
5845 *priority
= m
->priority
;
5849 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5850 assert_return(m
, -EINVAL
);
5851 assert_return(!m
->sealed
, -EPERM
);
5853 m
->priority
= priority
;