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 "memory-util.h"
20 #include "string-util.h"
22 #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 /* Note that we don't unref m->bus here. That's already done by sd_bus_message_unref() as each user
122 * reference to the bus message also is considered a reference to the bus connection itself. */
125 close_many(m
->fds
, m
->n_fds
);
129 if (m
->iovec
!= m
->iovec_fixed
)
132 message_reset_containers(m
);
133 assert(m
->n_containers
== 0);
134 message_free_last_container(m
);
136 bus_creds_done(&m
->creds
);
140 static void *message_extend_fields(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
142 size_t old_size
, new_size
, start
;
149 old_size
= sizeof(struct bus_header
) + m
->fields_size
;
150 start
= ALIGN_TO(old_size
, align
);
151 new_size
= start
+ sz
;
153 if (new_size
< start
||
154 new_size
> (size_t) ((uint32_t) -1))
157 if (old_size
== new_size
)
158 return (uint8_t*) m
->header
+ old_size
;
160 if (m
->free_header
) {
161 np
= realloc(m
->header
, ALIGN8(new_size
));
165 /* Initially, the header is allocated as part of
166 * the sd_bus_message itself, let's replace it by
169 np
= malloc(ALIGN8(new_size
));
173 memcpy(np
, m
->header
, sizeof(struct bus_header
));
176 /* Zero out padding */
177 if (start
> old_size
)
178 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
182 m
->fields_size
= new_size
- sizeof(struct bus_header
);
184 /* Adjust quick access pointers */
185 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
186 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
187 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
188 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
189 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
190 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
192 m
->free_header
= true;
195 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
198 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
201 return (uint8_t*) np
+ start
;
208 static int message_append_field_string(
220 /* dbus1 only allows 8bit header field ids */
224 /* dbus1 doesn't allow strings over 32bit, let's enforce this
225 * globally, to not risk convertability */
230 /* Signature "(yv)" where the variant contains "s" */
232 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
234 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
235 p
= message_extend_fields(m
, 8, 8 + l
+ 1 + 1 + 1, true);
239 *((uint64_t*) p
) = h
;
246 *ret
= (char*) p
+ 8;
249 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
250 p
= message_extend_fields(m
, 8, 4 + 4 + l
+ 1, false);
259 ((uint32_t*) p
)[1] = l
;
260 memcpy(p
+ 8, s
, l
+ 1);
263 *ret
= (char*) p
+ 8;
269 static int message_append_field_signature(
280 /* dbus1 only allows 8bit header field ids */
284 /* dbus1 doesn't allow signatures over 8bit, let's enforce
285 * this globally, to not risk convertability */
287 if (l
> SD_BUS_MAXIMUM_SIGNATURE_LENGTH
)
290 /* Signature "(yv)" where the variant contains "g" */
292 if (BUS_MESSAGE_IS_GVARIANT(m
))
293 /* For gvariant the serialization is the same as for normal strings */
294 return message_append_field_string(m
, h
, 'g', s
, ret
);
296 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
297 p
= message_extend_fields(m
, 8, 4 + 1 + l
+ 1, false);
303 p
[2] = SD_BUS_TYPE_SIGNATURE
;
306 memcpy(p
+ 5, s
, l
+ 1);
309 *ret
= (const char*) p
+ 5;
315 static int message_append_field_uint32(sd_bus_message
*m
, uint64_t h
, uint32_t x
) {
320 /* dbus1 only allows 8bit header field ids */
324 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
325 /* (field id 64bit + ((value + NUL + signature string 'u') */
327 p
= message_extend_fields(m
, 8, 8 + 4 + 1 + 1, true);
331 *((uint64_t*) p
) = h
;
332 *((uint32_t*) (p
+ 8)) = x
;
336 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
337 p
= message_extend_fields(m
, 8, 4 + 4, false);
346 ((uint32_t*) p
)[1] = x
;
352 static int message_append_field_uint64(sd_bus_message
*m
, uint64_t h
, uint64_t x
) {
357 /* dbus1 only allows 8bit header field ids */
361 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
362 /* (field id 64bit + ((value + NUL + signature string 't') */
364 p
= message_extend_fields(m
, 8, 8 + 8 + 1 + 1, true);
368 *((uint64_t*) p
) = h
;
369 *((uint64_t*) (p
+ 8)) = x
;
373 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
374 p
= message_extend_fields(m
, 8, 4 + 4 + 8, false);
387 ((uint64_t*) p
)[1] = x
;
393 static int message_append_reply_cookie(sd_bus_message
*m
, uint64_t cookie
) {
396 if (BUS_MESSAGE_IS_GVARIANT(m
))
397 return message_append_field_uint64(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, cookie
);
399 /* 64bit cookies are not supported on dbus1 */
400 if (cookie
> 0xffffffffUL
)
403 return message_append_field_uint32(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) cookie
);
407 int bus_message_from_header(
410 size_t header_accessible
,
412 size_t footer_accessible
,
418 sd_bus_message
**ret
) {
420 _cleanup_free_ sd_bus_message
*m
= NULL
;
421 struct bus_header
*h
;
425 assert(header
|| header_accessible
<= 0);
426 assert(footer
|| footer_accessible
<= 0);
427 assert(fds
|| n_fds
<= 0);
430 if (header_accessible
< sizeof(struct bus_header
))
433 if (header_accessible
> message_size
)
435 if (footer_accessible
> message_size
)
439 if (!IN_SET(h
->version
, 1, 2))
442 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
445 if (!IN_SET(h
->endian
, BUS_LITTLE_ENDIAN
, BUS_BIG_ENDIAN
))
448 /* Note that we are happy with unknown flags in the flags header! */
450 a
= ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
453 label_sz
= strlen(label
);
463 m
->header_accessible
= header_accessible
;
465 m
->footer_accessible
= footer_accessible
;
467 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
470 if (h
->dbus2
.cookie
== 0)
473 /* dbus2 derives the sizes from the message size and
474 the offset table at the end, since it is formatted as
475 gvariant "yyyyuta{tv}v". Since the message itself is a
476 structure with precisely to variable sized entries,
477 there's only one offset in the table, which marks the
478 end of the fields array. */
480 ws
= bus_gvariant_determine_word_size(message_size
, 0);
481 if (footer_accessible
< ws
)
484 m
->fields_size
= bus_gvariant_read_word_le((uint8_t*) footer
+ footer_accessible
- ws
, ws
);
485 if (ALIGN8(m
->fields_size
) > message_size
- ws
)
487 if (m
->fields_size
< sizeof(struct bus_header
))
490 m
->fields_size
-= sizeof(struct bus_header
);
491 m
->body_size
= message_size
- (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
));
493 if (h
->dbus1
.serial
== 0)
496 /* dbus1 has the sizes in the header */
497 m
->fields_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.fields_size
);
498 m
->body_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.body_size
);
500 if (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
!= message_size
)
508 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
509 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
511 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
515 m
->bus
= sd_bus_ref(bus
);
522 int bus_message_from_malloc(
529 sd_bus_message
**ret
) {
531 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
535 r
= bus_message_from_header(
537 buffer
, length
, /* in this case the initial bytes and the final bytes are the same */
546 sz
= length
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
);
549 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(m
->fields_size
);
551 m
->body
.sealed
= true;
556 m
->iovec
= m
->iovec_fixed
;
557 m
->iovec
[0] = IOVEC_MAKE(buffer
, length
);
559 r
= bus_message_parse_fields(m
);
563 /* We take possession of the memory and fds now */
564 m
->free_header
= true;
571 _public_
int sd_bus_message_new(
578 assert_return(bus
, -ENOTCONN
);
579 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
580 assert_return(m
, -EINVAL
);
581 assert_return(type
< _SD_BUS_MESSAGE_TYPE_MAX
, -EINVAL
);
583 t
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
588 t
->bus
= sd_bus_ref(bus
);
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
);
596 if (bus
->allow_interactive_authorization
)
597 t
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
603 _public_
int sd_bus_message_new_signal(
607 const char *interface
,
608 const char *member
) {
610 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
613 assert_return(bus
, -ENOTCONN
);
614 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
615 assert_return(object_path_is_valid(path
), -EINVAL
);
616 assert_return(interface_name_is_valid(interface
), -EINVAL
);
617 assert_return(member_name_is_valid(member
), -EINVAL
);
618 assert_return(m
, -EINVAL
);
620 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_SIGNAL
);
626 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
628 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
631 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
634 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
642 _public_
int sd_bus_message_new_method_call(
645 const char *destination
,
647 const char *interface
,
648 const char *member
) {
650 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
653 assert_return(bus
, -ENOTCONN
);
654 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
655 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
656 assert_return(object_path_is_valid(path
), -EINVAL
);
657 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
658 assert_return(member_name_is_valid(member
), -EINVAL
);
659 assert_return(m
, -EINVAL
);
661 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_CALL
);
667 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
670 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
675 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
681 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
690 static int message_new_reply(
691 sd_bus_message
*call
,
693 sd_bus_message
**m
) {
695 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
699 assert_return(call
, -EINVAL
);
700 assert_return(call
->sealed
, -EPERM
);
701 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
702 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
703 assert_return(m
, -EINVAL
);
705 cookie
= BUS_MESSAGE_COOKIE(call
);
709 r
= sd_bus_message_new(call
->bus
, &t
, type
);
715 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
716 t
->reply_cookie
= cookie
;
717 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
722 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
727 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
728 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
734 _public_
int sd_bus_message_new_method_return(
735 sd_bus_message
*call
,
736 sd_bus_message
**m
) {
738 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
741 _public_
int sd_bus_message_new_method_error(
742 sd_bus_message
*call
,
744 const sd_bus_error
*e
) {
746 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
749 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
750 assert_return(m
, -EINVAL
);
752 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
756 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
761 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
766 t
->error
._need_free
= -1;
772 _public_
int sd_bus_message_new_method_errorf(
773 sd_bus_message
*call
,
779 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
782 assert_return(name
, -EINVAL
);
783 assert_return(m
, -EINVAL
);
785 va_start(ap
, format
);
786 bus_error_setfv(&error
, name
, format
, ap
);
789 return sd_bus_message_new_method_error(call
, m
, &error
);
792 _public_
int sd_bus_message_new_method_errno(
793 sd_bus_message
*call
,
796 const sd_bus_error
*p
) {
798 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
800 if (sd_bus_error_is_set(p
))
801 return sd_bus_message_new_method_error(call
, m
, p
);
803 sd_bus_error_set_errno(&berror
, error
);
805 return sd_bus_message_new_method_error(call
, m
, &berror
);
808 _public_
int sd_bus_message_new_method_errnof(
809 sd_bus_message
*call
,
815 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
818 va_start(ap
, format
);
819 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
822 return sd_bus_message_new_method_error(call
, m
, &berror
);
825 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
829 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
830 m
->creds
.well_known_names_local
= true;
831 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
834 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
838 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
839 m
->creds
.well_known_names_driver
= true;
840 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
843 int bus_message_new_synthetic_error(
846 const sd_bus_error
*e
,
847 sd_bus_message
**m
) {
849 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
853 assert(sd_bus_error_is_set(e
));
856 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_ERROR
);
862 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
863 t
->reply_cookie
= cookie
;
865 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
869 if (bus
&& bus
->unique_name
) {
870 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
875 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
880 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
885 t
->error
._need_free
= -1;
887 bus_message_set_sender_driver(bus
, t
);
894 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
898 /* We are fine if this message so far was either explicitly reffed or not reffed but queued into at
899 * least one bus connection object. */
900 assert(m
->n_ref
> 0 || m
->n_queued
> 0);
904 /* Each user reference to a bus message shall also be considered a ref on the bus */
909 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
913 assert(m
->n_ref
> 0);
915 sd_bus_unref(m
->bus
); /* Each regular ref is also a ref on the bus connection. Let's hence drop it
916 * here. Note we have to do this before decrementing our own n_ref here, since
917 * otherwise, if this message is currently queued sd_bus_unref() might call
918 * bus_message_unref_queued() for this which might then destroy the message
919 * while we are still processing it. */
922 if (m
->n_ref
> 0 || m
->n_queued
> 0)
925 /* Unset the bus field if neither the user has a reference nor this message is queued. We are careful
926 * to reset the field only after the last reference to the bus is dropped, after all we might keep
927 * multiple references to the bus, once for each reference kept on ourselves. */
930 return message_free(m
);
933 sd_bus_message
* bus_message_ref_queued(sd_bus_message
*m
, sd_bus
*bus
) {
937 /* If this is a different bus than the message is associated with, then implicitly turn this into a
938 * regular reference. This means that you can create a memory leak by enqueuing a message generated
939 * on one bus onto another at the same time as enqueueing a message from the second one on the first,
940 * as we'll not detect the cyclic references there. */
942 return sd_bus_message_ref(m
);
944 assert(m
->n_ref
> 0 || m
->n_queued
> 0);
950 sd_bus_message
* bus_message_unref_queued(sd_bus_message
*m
, sd_bus
*bus
) {
955 return sd_bus_message_unref(m
);
957 assert(m
->n_queued
> 0);
960 if (m
->n_ref
> 0 || m
->n_queued
> 0)
965 return message_free(m
);
968 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
969 assert_return(m
, -EINVAL
);
970 assert_return(type
, -EINVAL
);
972 *type
= m
->header
->type
;
976 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
979 assert_return(m
, -EINVAL
);
980 assert_return(cookie
, -EINVAL
);
982 c
= BUS_MESSAGE_COOKIE(m
);
986 *cookie
= BUS_MESSAGE_COOKIE(m
);
990 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
991 assert_return(m
, -EINVAL
);
992 assert_return(cookie
, -EINVAL
);
994 if (m
->reply_cookie
== 0)
997 *cookie
= m
->reply_cookie
;
1001 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
1002 assert_return(m
, -EINVAL
);
1004 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
1005 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
1008 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
1009 assert_return(m
, -EINVAL
);
1011 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
1014 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
1015 assert_return(m
, -EINVAL
);
1017 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
1018 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
1021 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
1022 assert_return(m
, NULL
);
1027 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
1028 assert_return(m
, NULL
);
1030 return m
->interface
;
1033 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
1034 assert_return(m
, NULL
);
1039 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
1040 assert_return(m
, NULL
);
1042 return m
->destination
;
1045 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
1046 assert_return(m
, NULL
);
1051 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
1052 assert_return(m
, NULL
);
1054 if (!sd_bus_error_is_set(&m
->error
))
1060 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
1061 assert_return(m
, -EINVAL
);
1062 assert_return(usec
, -EINVAL
);
1064 if (m
->monotonic
<= 0)
1067 *usec
= m
->monotonic
;
1071 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1072 assert_return(m
, -EINVAL
);
1073 assert_return(usec
, -EINVAL
);
1075 if (m
->realtime
<= 0)
1078 *usec
= m
->realtime
;
1082 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1083 assert_return(m
, -EINVAL
);
1084 assert_return(seqnum
, -EINVAL
);
1089 *seqnum
= m
->seqnum
;
1093 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1094 assert_return(m
, NULL
);
1096 if (m
->creds
.mask
== 0)
1102 _public_
int sd_bus_message_is_signal(
1104 const char *interface
,
1105 const char *member
) {
1107 assert_return(m
, -EINVAL
);
1109 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1112 if (interface
&& !streq_ptr(m
->interface
, interface
))
1115 if (member
&& !streq_ptr(m
->member
, member
))
1121 _public_
int sd_bus_message_is_method_call(
1123 const char *interface
,
1124 const char *member
) {
1126 assert_return(m
, -EINVAL
);
1128 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1131 if (interface
&& !streq_ptr(m
->interface
, interface
))
1134 if (member
&& !streq_ptr(m
->member
, member
))
1140 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1141 assert_return(m
, -EINVAL
);
1143 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1146 if (name
&& !streq_ptr(m
->error
.name
, name
))
1152 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1153 assert_return(m
, -EINVAL
);
1154 assert_return(!m
->sealed
, -EPERM
);
1155 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1157 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_REPLY_EXPECTED
, !b
);
1162 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1163 assert_return(m
, -EINVAL
);
1164 assert_return(!m
->sealed
, -EPERM
);
1166 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_AUTO_START
, !b
);
1171 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1172 assert_return(m
, -EINVAL
);
1173 assert_return(!m
->sealed
, -EPERM
);
1175 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
, b
);
1180 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1181 struct bus_body_part
*part
;
1188 if (m
->n_body_parts
<= 0) {
1192 assert(m
->body_end
);
1194 part
= new0(struct bus_body_part
, 1);
1200 m
->body_end
->next
= part
;
1210 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1215 /* All other fields can be left in their defaults */
1216 assert(!part
->data
);
1217 assert(part
->memfd
< 0);
1220 part
->is_zero
= true;
1221 part
->sealed
= true;
1224 static int part_make_space(
1225 struct sd_bus_message
*m
,
1226 struct bus_body_part
*part
,
1234 assert(!part
->sealed
);
1239 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1240 size_t new_allocated
;
1242 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1243 n
= realloc(part
->data
, new_allocated
);
1250 part
->allocated
= new_allocated
;
1251 part
->free_this
= true;
1255 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1261 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1262 struct bus_container
*c
;
1265 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1267 /* Add offset to current container, unless this is the first
1268 * item in it, which will have the 0 offset, which we can
1270 c
= message_get_last_container(m
);
1272 if (!c
->need_offsets
)
1275 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1278 c
->offsets
[c
->n_offsets
++] = offset
;
1282 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1283 struct bus_container
*c
;
1290 /* Update counters */
1291 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++) {
1294 *c
->array_size
+= expand
;
1298 static void *message_extend_body(
1303 bool force_inline
) {
1305 size_t start_body
, end_body
, padding
, added
;
1316 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1317 end_body
= start_body
+ sz
;
1319 padding
= start_body
- m
->body_size
;
1320 added
= padding
+ sz
;
1322 /* Check for 32bit overflows */
1323 if (end_body
> (size_t) ((uint32_t) -1) ||
1324 end_body
< start_body
) {
1330 struct bus_body_part
*part
= NULL
;
1334 m
->n_body_parts
<= 0 ||
1335 m
->body_end
->sealed
||
1336 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1337 (force_inline
&& m
->body_end
->size
> MEMFD_MIN_SIZE
);
1338 /* If this must be an inlined extension, let's create a new part if
1339 * the previous part is large enough to be inlined. */
1343 part
= message_append_part(m
);
1347 part_zero(part
, padding
);
1350 part
= message_append_part(m
);
1354 r
= part_make_space(m
, part
, sz
, &p
);
1358 struct bus_container
*c
;
1360 size_t os
, start_part
, end_part
;
1366 start_part
= ALIGN_TO(part
->size
, align
);
1367 end_part
= start_part
+ sz
;
1369 r
= part_make_space(m
, part
, end_part
, &p
);
1374 memzero(p
, padding
);
1375 p
= (uint8_t*) p
+ padding
;
1378 /* Readjust pointers */
1379 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1380 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1382 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1385 /* Return something that is not NULL and is aligned */
1386 p
= (uint8_t*) align
;
1388 m
->body_size
= end_body
;
1389 message_extend_containers(m
, added
);
1392 r
= message_add_offset(m
, end_body
);
1402 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1413 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1417 f
= reallocarray(m
->fds
, sizeof(int), m
->n_fds
+ 1);
1425 m
->fds
[m
->n_fds
] = copy
;
1431 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1432 _cleanup_close_
int fd
= -1;
1433 struct bus_container
*c
;
1437 assert_return(m
, -EINVAL
);
1438 assert_return(!m
->sealed
, -EPERM
);
1439 assert_return(bus_type_is_basic(type
), -EINVAL
);
1440 assert_return(!m
->poisoned
, -ESTALE
);
1442 c
= message_get_last_container(m
);
1444 if (c
->signature
&& c
->signature
[c
->index
]) {
1445 /* Container signature is already set */
1447 if (c
->signature
[c
->index
] != type
)
1452 /* Maybe we can append to the signature? But only if this is the top-level container */
1453 if (c
->enclosing
!= 0)
1456 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1463 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1469 case SD_BUS_TYPE_SIGNATURE
:
1470 case SD_BUS_TYPE_STRING
:
1474 case SD_BUS_TYPE_OBJECT_PATH
:
1482 case SD_BUS_TYPE_BOOLEAN
:
1484 u8
= p
&& *(int*) p
;
1490 case SD_BUS_TYPE_UNIX_FD
:
1495 fd
= message_push_fd(m
, *(int*) p
);
1506 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1507 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1514 a
= message_extend_body(m
, align
, sz
, true, false);
1521 *stored
= (const uint8_t*) a
;
1528 case SD_BUS_TYPE_STRING
:
1529 /* To make things easy we'll serialize a NULL string
1530 * into the empty string */
1534 case SD_BUS_TYPE_OBJECT_PATH
:
1540 sz
= 4 + strlen(p
) + 1;
1543 case SD_BUS_TYPE_SIGNATURE
:
1548 sz
= 1 + strlen(p
) + 1;
1551 case SD_BUS_TYPE_BOOLEAN
:
1553 u32
= p
&& *(int*) p
;
1559 case SD_BUS_TYPE_UNIX_FD
:
1564 fd
= message_push_fd(m
, *(int*) p
);
1575 align
= bus_type_get_alignment(type
);
1576 sz
= bus_type_get_size(type
);
1583 a
= message_extend_body(m
, align
, sz
, false, false);
1587 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
1588 *(uint32_t*) a
= sz
- 5;
1589 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1592 *stored
= (const uint8_t*) a
+ 4;
1594 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1595 *(uint8_t*) a
= sz
- 2;
1596 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1599 *stored
= (const uint8_t*) a
+ 1;
1608 if (type
== SD_BUS_TYPE_UNIX_FD
)
1611 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1618 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1619 return message_append_basic(m
, type
, p
, NULL
);
1622 _public_
int sd_bus_message_append_string_space(
1627 struct bus_container
*c
;
1630 assert_return(m
, -EINVAL
);
1631 assert_return(s
, -EINVAL
);
1632 assert_return(!m
->sealed
, -EPERM
);
1633 assert_return(!m
->poisoned
, -ESTALE
);
1635 c
= message_get_last_container(m
);
1637 if (c
->signature
&& c
->signature
[c
->index
]) {
1638 /* Container signature is already set */
1640 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1645 /* Maybe we can append to the signature? But only if this is the top-level container */
1646 if (c
->enclosing
!= 0)
1649 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1656 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1657 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1663 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1667 *(uint32_t*) a
= size
;
1673 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1679 _public_
int sd_bus_message_append_string_iovec(
1681 const struct iovec
*iov
,
1682 unsigned n
/* should be size_t, but is API now… 😞 */) {
1689 assert_return(m
, -EINVAL
);
1690 assert_return(!m
->sealed
, -EPERM
);
1691 assert_return(iov
|| n
== 0, -EINVAL
);
1692 assert_return(!m
->poisoned
, -ESTALE
);
1694 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1696 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1700 for (i
= 0; i
< n
; i
++) {
1702 if (iov
[i
].iov_base
)
1703 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1705 memset(p
, ' ', iov
[i
].iov_len
);
1707 p
+= iov
[i
].iov_len
;
1713 static int bus_message_open_array(
1715 struct bus_container
*c
,
1716 const char *contents
,
1717 uint32_t **array_size
,
1719 bool *need_offsets
) {
1729 assert(need_offsets
);
1731 if (!signature_is_single(contents
, true))
1734 if (c
->signature
&& c
->signature
[c
->index
]) {
1736 /* Verify the existing signature */
1738 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1741 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1744 nindex
= c
->index
+ 1 + strlen(contents
);
1748 if (c
->enclosing
!= 0)
1751 /* Extend the existing signature */
1753 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1759 nindex
= e
- c
->signature
;
1762 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1763 alignment
= bus_gvariant_get_alignment(contents
);
1767 /* Add alignment padding and add to offset list */
1768 if (!message_extend_body(m
, alignment
, 0, false, false))
1771 r
= bus_gvariant_is_fixed_size(contents
);
1775 *begin
= m
->body_size
;
1776 *need_offsets
= r
== 0;
1780 struct bus_body_part
*o
;
1782 alignment
= bus_type_get_alignment(contents
[0]);
1786 a
= message_extend_body(m
, 4, 4, false, false);
1791 op
= m
->body_end
->data
;
1792 os
= m
->body_end
->size
;
1794 /* Add alignment between size and first element */
1795 if (!message_extend_body(m
, alignment
, 0, false, false))
1798 /* location of array size might have changed so let's readjust a */
1799 if (o
== m
->body_end
)
1800 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1806 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1812 static int bus_message_open_variant(
1814 struct bus_container
*c
,
1815 const char *contents
) {
1821 if (!signature_is_single(contents
, false))
1824 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1827 if (c
->signature
&& c
->signature
[c
->index
]) {
1829 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1835 if (c
->enclosing
!= 0)
1838 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1845 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1846 /* Variants are always aligned to 8 */
1848 if (!message_extend_body(m
, 8, 0, false, false))
1855 l
= strlen(contents
);
1856 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1861 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1864 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1870 static int bus_message_open_struct(
1872 struct bus_container
*c
,
1873 const char *contents
,
1875 bool *need_offsets
) {
1884 assert(need_offsets
);
1886 if (!signature_is_valid(contents
, false))
1889 if (c
->signature
&& c
->signature
[c
->index
]) {
1892 l
= strlen(contents
);
1894 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1895 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1896 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1899 nindex
= c
->index
+ 1 + l
+ 1;
1903 if (c
->enclosing
!= 0)
1906 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1912 nindex
= e
- c
->signature
;
1915 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1918 alignment
= bus_gvariant_get_alignment(contents
);
1922 if (!message_extend_body(m
, alignment
, 0, false, false))
1925 r
= bus_gvariant_is_fixed_size(contents
);
1929 *begin
= m
->body_size
;
1930 *need_offsets
= r
== 0;
1932 /* Align contents to 8 byte boundary */
1933 if (!message_extend_body(m
, 8, 0, false, false))
1937 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1943 static int bus_message_open_dict_entry(
1945 struct bus_container
*c
,
1946 const char *contents
,
1948 bool *need_offsets
) {
1956 assert(need_offsets
);
1958 if (!signature_is_pair(contents
))
1961 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1964 if (c
->signature
&& c
->signature
[c
->index
]) {
1967 l
= strlen(contents
);
1969 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
1970 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1971 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
1976 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1979 alignment
= bus_gvariant_get_alignment(contents
);
1983 if (!message_extend_body(m
, alignment
, 0, false, false))
1986 r
= bus_gvariant_is_fixed_size(contents
);
1990 *begin
= m
->body_size
;
1991 *need_offsets
= r
== 0;
1993 /* Align contents to 8 byte boundary */
1994 if (!message_extend_body(m
, 8, 0, false, false))
2001 _public_
int sd_bus_message_open_container(
2004 const char *contents
) {
2006 struct bus_container
*c
;
2007 uint32_t *array_size
= NULL
;
2008 _cleanup_free_
char *signature
= NULL
;
2009 size_t before
, begin
= 0;
2010 bool need_offsets
= false;
2013 assert_return(m
, -EINVAL
);
2014 assert_return(!m
->sealed
, -EPERM
);
2015 assert_return(contents
, -EINVAL
);
2016 assert_return(!m
->poisoned
, -ESTALE
);
2018 /* Make sure we have space for one more container */
2019 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
2024 c
= message_get_last_container(m
);
2026 signature
= strdup(contents
);
2032 /* Save old index in the parent container, in case we have to
2033 * abort this container */
2034 c
->saved_index
= c
->index
;
2035 before
= m
->body_size
;
2037 if (type
== SD_BUS_TYPE_ARRAY
)
2038 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
2039 else if (type
== SD_BUS_TYPE_VARIANT
)
2040 r
= bus_message_open_variant(m
, c
, contents
);
2041 else if (type
== SD_BUS_TYPE_STRUCT
)
2042 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
2043 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
2044 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
2050 /* OK, let's fill it in */
2051 m
->containers
[m
->n_containers
++] = (struct bus_container
) {
2053 .signature
= TAKE_PTR(signature
),
2054 .array_size
= array_size
,
2057 .need_offsets
= need_offsets
,
2063 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2068 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2071 if (c
->need_offsets
) {
2072 size_t payload
, sz
, i
;
2075 /* Variable-width arrays */
2077 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2078 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2080 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2084 for (i
= 0; i
< c
->n_offsets
; i
++)
2085 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2089 /* Fixed-width or empty arrays */
2091 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2099 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2105 assert(c
->signature
);
2107 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2110 l
= strlen(c
->signature
);
2112 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2117 memcpy(a
+1, c
->signature
, l
);
2122 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2123 bool fixed_size
= true;
2124 size_t n_variable
= 0;
2133 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2136 p
= strempty(c
->signature
);
2140 r
= signature_element_length(p
, &n
);
2149 r
= bus_gvariant_is_fixed_size(t
);
2154 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2156 /* We need to add an offset for each item that has a
2157 * variable size and that is not the last one in the
2161 if (r
== 0 && p
[n
] != 0)
2168 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2169 assert(c
->need_offsets
|| n_variable
== 0);
2171 if (isempty(c
->signature
)) {
2172 /* The unary type is encoded as fixed 1 byte padding */
2173 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2178 } else if (n_variable
<= 0) {
2181 /* Structures with fixed-size members only have to be
2182 * fixed-size themselves. But gvariant requires all fixed-size
2183 * elements to be sized a multiple of their alignment. Hence,
2184 * we must *always* add final padding after the last member so
2185 * the overall size of the structure is properly aligned. */
2187 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2189 assert(alignment
> 0);
2191 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2198 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2200 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2202 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2206 p
= strempty(c
->signature
);
2207 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2211 r
= signature_element_length(p
, &n
);
2222 r
= bus_gvariant_is_fixed_size(t
);
2225 if (r
> 0 || p
[0] == 0)
2229 k
= n_variable
- 1 - j
;
2231 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2240 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2241 struct bus_container
*c
;
2244 assert_return(m
, -EINVAL
);
2245 assert_return(!m
->sealed
, -EPERM
);
2246 assert_return(m
->n_containers
> 0, -EINVAL
);
2247 assert_return(!m
->poisoned
, -ESTALE
);
2249 c
= message_get_last_container(m
);
2251 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2252 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2257 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2258 r
= bus_message_close_array(m
, c
);
2259 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2260 r
= bus_message_close_variant(m
, c
);
2261 else if (IN_SET(c
->enclosing
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
))
2262 r
= bus_message_close_struct(m
, c
, true);
2264 assert_not_reached("Unknown container type");
2278 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2285 stack
[*i
].types
= types
;
2286 stack
[*i
].n_struct
= n_struct
;
2287 stack
[*i
].n_array
= n_array
;
2293 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2304 *types
= stack
[*i
].types
;
2305 *n_struct
= stack
[*i
].n_struct
;
2306 *n_array
= stack
[*i
].n_array
;
2311 _public_
int sd_bus_message_appendv(
2316 unsigned n_array
, n_struct
;
2317 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2318 unsigned stack_ptr
= 0;
2321 assert_return(m
, -EINVAL
);
2322 assert_return(types
, -EINVAL
);
2323 assert_return(!m
->sealed
, -EPERM
);
2324 assert_return(!m
->poisoned
, -ESTALE
);
2326 n_array
= (unsigned) -1;
2327 n_struct
= strlen(types
);
2332 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2333 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2339 r
= sd_bus_message_close_container(m
);
2347 if (n_array
!= (unsigned) -1)
2356 case SD_BUS_TYPE_BYTE
: {
2359 x
= (uint8_t) va_arg(ap
, int);
2360 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2364 case SD_BUS_TYPE_BOOLEAN
:
2365 case SD_BUS_TYPE_INT32
:
2366 case SD_BUS_TYPE_UINT32
:
2367 case SD_BUS_TYPE_UNIX_FD
: {
2370 /* We assume a boolean is the same as int32_t */
2371 assert_cc(sizeof(int32_t) == sizeof(int));
2373 x
= va_arg(ap
, uint32_t);
2374 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2378 case SD_BUS_TYPE_INT16
:
2379 case SD_BUS_TYPE_UINT16
: {
2382 x
= (uint16_t) va_arg(ap
, int);
2383 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2387 case SD_BUS_TYPE_INT64
:
2388 case SD_BUS_TYPE_UINT64
: {
2391 x
= va_arg(ap
, uint64_t);
2392 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2396 case SD_BUS_TYPE_DOUBLE
: {
2399 x
= va_arg(ap
, double);
2400 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2404 case SD_BUS_TYPE_STRING
:
2405 case SD_BUS_TYPE_OBJECT_PATH
:
2406 case SD_BUS_TYPE_SIGNATURE
: {
2409 x
= va_arg(ap
, const char*);
2410 r
= sd_bus_message_append_basic(m
, *t
, x
);
2414 case SD_BUS_TYPE_ARRAY
: {
2417 r
= signature_element_length(t
+ 1, &k
);
2423 memcpy(s
, t
+ 1, k
);
2426 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2431 if (n_array
== (unsigned) -1) {
2436 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2442 n_array
= va_arg(ap
, unsigned);
2447 case SD_BUS_TYPE_VARIANT
: {
2450 s
= va_arg(ap
, const char*);
2454 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2458 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2463 n_struct
= strlen(s
);
2464 n_array
= (unsigned) -1;
2469 case SD_BUS_TYPE_STRUCT_BEGIN
:
2470 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2473 r
= signature_element_length(t
, &k
);
2480 memcpy(s
, t
+ 1, k
- 2);
2483 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2488 if (n_array
== (unsigned) -1) {
2493 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2499 n_array
= (unsigned) -1;
2515 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2519 va_start(ap
, types
);
2520 r
= sd_bus_message_appendv(m
, types
, ap
);
2526 _public_
int sd_bus_message_append_array_space(
2536 assert_return(m
, -EINVAL
);
2537 assert_return(!m
->sealed
, -EPERM
);
2538 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2539 assert_return(ptr
|| size
== 0, -EINVAL
);
2540 assert_return(!m
->poisoned
, -ESTALE
);
2542 /* alignment and size of the trivial types (except bool) is
2543 * identical for gvariant and dbus1 marshalling */
2544 align
= bus_type_get_alignment(type
);
2545 sz
= bus_type_get_size(type
);
2547 assert_se(align
> 0);
2553 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2557 a
= message_extend_body(m
, align
, size
, false, false);
2561 r
= sd_bus_message_close_container(m
);
2569 _public_
int sd_bus_message_append_array(
2577 assert_return(m
, -EINVAL
);
2578 assert_return(!m
->sealed
, -EPERM
);
2579 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2580 assert_return(ptr
|| size
== 0, -EINVAL
);
2581 assert_return(!m
->poisoned
, -ESTALE
);
2583 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2587 memcpy_safe(p
, ptr
, size
);
2592 _public_
int sd_bus_message_append_array_iovec(
2595 const struct iovec
*iov
,
2596 unsigned n
/* should be size_t, but is API now… 😞 */) {
2603 assert_return(m
, -EINVAL
);
2604 assert_return(!m
->sealed
, -EPERM
);
2605 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2606 assert_return(iov
|| n
== 0, -EINVAL
);
2607 assert_return(!m
->poisoned
, -ESTALE
);
2609 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2611 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2615 for (i
= 0; i
< n
; i
++) {
2617 if (iov
[i
].iov_base
)
2618 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2620 memzero(p
, iov
[i
].iov_len
);
2622 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2628 _public_
int sd_bus_message_append_array_memfd(
2635 _cleanup_close_
int copy_fd
= -1;
2636 struct bus_body_part
*part
;
2642 assert_return(m
, -EINVAL
);
2643 assert_return(memfd
>= 0, -EBADF
);
2644 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2645 assert_return(size
> 0, -EINVAL
);
2646 assert_return(!m
->sealed
, -EPERM
);
2647 assert_return(!m
->poisoned
, -ESTALE
);
2649 r
= memfd_set_sealed(memfd
);
2653 copy_fd
= fcntl(memfd
, F_DUPFD_CLOEXEC
, 3);
2657 r
= memfd_get_size(memfd
, &real_size
);
2661 if (offset
== 0 && size
== (uint64_t) -1)
2663 else if (offset
+ size
> real_size
)
2666 align
= bus_type_get_alignment(type
);
2667 sz
= bus_type_get_size(type
);
2669 assert_se(align
> 0);
2672 if (offset
% align
!= 0)
2678 if (size
> (uint64_t) (uint32_t) -1)
2681 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2685 a
= message_extend_body(m
, align
, 0, false, false);
2689 part
= message_append_part(m
);
2693 part
->memfd
= copy_fd
;
2694 part
->memfd_offset
= offset
;
2695 part
->sealed
= true;
2699 m
->body_size
+= size
;
2700 message_extend_containers(m
, size
);
2702 return sd_bus_message_close_container(m
);
2705 _public_
int sd_bus_message_append_string_memfd(
2711 _cleanup_close_
int copy_fd
= -1;
2712 struct bus_body_part
*part
;
2713 struct bus_container
*c
;
2718 assert_return(m
, -EINVAL
);
2719 assert_return(memfd
>= 0, -EBADF
);
2720 assert_return(size
> 0, -EINVAL
);
2721 assert_return(!m
->sealed
, -EPERM
);
2722 assert_return(!m
->poisoned
, -ESTALE
);
2724 r
= memfd_set_sealed(memfd
);
2728 copy_fd
= fcntl(memfd
, FD_CLOEXEC
, 3);
2732 r
= memfd_get_size(memfd
, &real_size
);
2736 if (offset
== 0 && size
== (uint64_t) -1)
2738 else if (offset
+ size
> real_size
)
2741 /* We require this to be NUL terminated */
2745 if (size
> (uint64_t) (uint32_t) -1)
2748 c
= message_get_last_container(m
);
2749 if (c
->signature
&& c
->signature
[c
->index
]) {
2750 /* Container signature is already set */
2752 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2757 /* Maybe we can append to the signature? But only if this is the top-level container */
2758 if (c
->enclosing
!= 0)
2761 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2768 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2769 a
= message_extend_body(m
, 4, 4, false, false);
2773 *(uint32_t*) a
= size
- 1;
2776 part
= message_append_part(m
);
2780 part
->memfd
= copy_fd
;
2781 part
->memfd_offset
= offset
;
2782 part
->sealed
= true;
2786 m
->body_size
+= size
;
2787 message_extend_containers(m
, size
);
2789 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2790 r
= message_add_offset(m
, m
->body_size
);
2797 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2803 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2807 assert_return(m
, -EINVAL
);
2808 assert_return(!m
->sealed
, -EPERM
);
2809 assert_return(!m
->poisoned
, -ESTALE
);
2811 r
= sd_bus_message_open_container(m
, 'a', "s");
2815 STRV_FOREACH(i
, l
) {
2816 r
= sd_bus_message_append_basic(m
, 's', *i
);
2821 return sd_bus_message_close_container(m
);
2824 static int bus_message_close_header(sd_bus_message
*m
) {
2828 /* The actual user data is finished now, we just complete the
2829 variant and struct now (at least on gvariant). Remember
2830 this position, so that during parsing we know where to
2831 put the outer container end. */
2832 m
->user_body_size
= m
->body_size
;
2834 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2835 const char *signature
;
2839 /* Add offset table to end of fields array */
2840 if (m
->n_header_offsets
>= 1) {
2844 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2846 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2847 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2851 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2852 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2855 /* Add gvariant NUL byte plus signature to the end of
2856 * the body, followed by the final offset pointing to
2857 * the end of the fields array */
2859 signature
= strempty(m
->root_container
.signature
);
2860 l
= strlen(signature
);
2862 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2863 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2868 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2869 memcpy((uint8_t*) d
+ 2, signature
, l
);
2870 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2872 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2875 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2877 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2878 m
->header
->dbus1
.body_size
= m
->body_size
;
2884 _public_
int sd_bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, uint64_t timeout_usec
) {
2885 struct bus_body_part
*part
;
2890 assert_return(m
, -EINVAL
);
2895 if (m
->n_containers
> 0)
2901 if (cookie
> 0xffffffffULL
&&
2902 !BUS_MESSAGE_IS_GVARIANT(m
))
2905 /* In vtables the return signature of method calls is listed,
2906 * let's check if they match if this is a response */
2907 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2908 m
->enforced_reply_signature
&&
2909 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2912 /* If gvariant marshalling is used we need to close the body structure */
2913 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2917 /* If there's a non-trivial signature set, then add it in
2918 * here, but only on dbus1 */
2919 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2920 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2926 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2931 r
= bus_message_close_header(m
);
2935 if (BUS_MESSAGE_IS_GVARIANT(m
))
2936 m
->header
->dbus2
.cookie
= cookie
;
2938 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2940 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout_usec
;
2942 /* Add padding at the end of the fields part, since we know
2943 * the body needs to start at an 8 byte alignment. We made
2944 * sure we allocated enough space for this, so all we need to
2945 * do here is to zero it out. */
2946 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2948 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2950 /* If this is something we can send as memfd, then let's seal
2951 the memfd now. Note that we can send memfds as payload only
2952 for directed messages, and not for broadcasts. */
2953 if (m
->destination
&& m
->bus
->use_memfd
) {
2954 MESSAGE_FOREACH_PART(part
, i
, m
)
2955 if (part
->memfd
>= 0 &&
2957 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
2958 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
2961 /* Try to seal it if that makes
2962 * sense. First, unmap our own map to
2963 * make sure we don't keep it busy. */
2964 bus_body_part_unmap(part
);
2966 /* Then, sync up real memfd size */
2968 r
= memfd_set_size(part
->memfd
, sz
);
2972 /* Finally, try to seal */
2973 if (memfd_set_sealed(part
->memfd
) >= 0)
2974 part
->sealed
= true;
2978 m
->root_container
.end
= m
->user_body_size
;
2979 m
->root_container
.index
= 0;
2980 m
->root_container
.offset_index
= 0;
2981 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
2988 int bus_body_part_map(struct bus_body_part
*part
) {
2997 if (part
->size
<= 0)
3000 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3001 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
3002 static const uint8_t zeroes
[7] = { };
3003 part
->data
= (void*) zeroes
;
3007 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
3008 psz
= PAGE_ALIGN(part
->size
+ shift
);
3010 if (part
->memfd
>= 0)
3011 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
3012 else if (part
->is_zero
)
3013 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
3017 if (p
== MAP_FAILED
)
3021 part
->mmap_begin
= p
;
3022 part
->data
= (uint8_t*) p
+ shift
;
3023 part
->munmap_this
= true;
3028 void bus_body_part_unmap(struct bus_body_part
*part
) {
3032 if (part
->memfd
< 0)
3035 if (!part
->mmap_begin
)
3038 if (!part
->munmap_this
)
3041 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
3043 part
->mmap_begin
= NULL
;
3046 part
->munmap_this
= false;
3051 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3052 size_t k
, start
, end
;
3057 start
= ALIGN_TO((size_t) *rindex
, align
);
3058 end
= start
+ nbytes
;
3063 /* Verify that padding is 0 */
3064 for (k
= *rindex
; k
< start
; k
++)
3065 if (((const uint8_t*) p
)[k
] != 0)
3069 *r
= (uint8_t*) p
+ start
;
3076 static bool message_end_of_signature(sd_bus_message
*m
) {
3077 struct bus_container
*c
;
3081 c
= message_get_last_container(m
);
3082 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3085 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3086 struct bus_container
*c
;
3090 c
= message_get_last_container(m
);
3091 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3094 if (BUS_MESSAGE_IS_GVARIANT(m
))
3095 return index
>= c
->end
;
3097 assert(c
->array_size
);
3098 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3102 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3103 assert_return(m
, -EINVAL
);
3104 assert_return(m
->sealed
, -EPERM
);
3106 if (complete
&& m
->n_containers
> 0)
3109 if (message_end_of_signature(m
))
3112 if (message_end_of_array(m
, m
->rindex
))
3118 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3119 struct bus_body_part
*part
;
3125 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3126 part
= m
->cached_rindex_part
;
3127 begin
= m
->cached_rindex_part_begin
;
3137 if (index
+ sz
<= begin
+ part
->size
) {
3139 r
= bus_body_part_map(part
);
3144 *p
= (uint8_t*) part
->data
+ index
- begin
;
3146 m
->cached_rindex_part
= part
;
3147 m
->cached_rindex_part_begin
= begin
;
3152 begin
+= part
->size
;
3159 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3166 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3169 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3172 sz
= bus_gvariant_get_size(c
->signature
);
3176 if (c
->offset_index
+1 >= c
->n_offsets
)
3179 /* Variable-size array */
3181 alignment
= bus_gvariant_get_alignment(c
->signature
);
3182 assert(alignment
> 0);
3184 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3185 assert(c
->offsets
[c
->offset_index
+1] >= *rindex
);
3186 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3189 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3192 /* Fixed-size array */
3193 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3199 } else if (IN_SET(c
->enclosing
, 0, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
3204 if (c
->offset_index
+1 >= c
->n_offsets
)
3207 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3211 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3216 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3219 alignment
= bus_gvariant_get_alignment(t
);
3222 assert(alignment
> 0);
3224 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3225 assert(c
->offsets
[c
->offset_index
+1] >= *rindex
);
3226 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3230 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3233 assert_not_reached("Unknown container type");
3238 /* Reached the end */
3244 static int message_peek_body(
3251 size_t k
, start
, end
, padding
;
3252 struct bus_body_part
*part
;
3259 start
= ALIGN_TO((size_t) *rindex
, align
);
3260 padding
= start
- *rindex
;
3261 end
= start
+ nbytes
;
3263 if (end
> m
->user_body_size
)
3266 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3271 /* Verify padding */
3272 for (k
= 0; k
< padding
; k
++)
3277 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3278 if (!part
|| (nbytes
> 0 && !q
))
3289 static bool validate_nul(const char *s
, size_t l
) {
3291 /* Check for NUL chars in the string */
3292 if (memchr(s
, 0, l
))
3295 /* Check for NUL termination */
3302 static bool validate_string(const char *s
, size_t l
) {
3304 if (!validate_nul(s
, l
))
3307 /* Check if valid UTF8 */
3308 if (!utf8_is_valid(s
))
3314 static bool validate_signature(const char *s
, size_t l
) {
3316 if (!validate_nul(s
, l
))
3319 /* Check if valid signature */
3320 if (!signature_is_valid(s
, true))
3326 static bool validate_object_path(const char *s
, size_t l
) {
3328 if (!validate_nul(s
, l
))
3331 if (!object_path_is_valid(s
))
3337 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3338 struct bus_container
*c
;
3343 assert_return(m
, -EINVAL
);
3344 assert_return(m
->sealed
, -EPERM
);
3345 assert_return(bus_type_is_basic(type
), -EINVAL
);
3347 if (message_end_of_signature(m
))
3350 if (message_end_of_array(m
, m
->rindex
))
3353 c
= message_get_last_container(m
);
3354 if (c
->signature
[c
->index
] != type
)
3359 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3361 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3364 /* D-Bus spec: The marshalling formats for the string-like types all end
3365 * with a single zero (NUL) byte, but that byte is not considered to be part
3367 if (c
->item_size
== 0)
3370 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3374 if (type
== SD_BUS_TYPE_STRING
)
3375 ok
= validate_string(q
, c
->item_size
-1);
3376 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3377 ok
= validate_object_path(q
, c
->item_size
-1);
3379 ok
= validate_signature(q
, c
->item_size
-1);
3385 *(const char**) p
= q
;
3389 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3391 if ((size_t) sz
!= c
->item_size
)
3394 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3397 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3403 case SD_BUS_TYPE_BYTE
:
3405 *(uint8_t*) p
= *(uint8_t*) q
;
3408 case SD_BUS_TYPE_BOOLEAN
:
3410 *(int*) p
= !!*(uint8_t*) q
;
3413 case SD_BUS_TYPE_INT16
:
3414 case SD_BUS_TYPE_UINT16
:
3416 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3419 case SD_BUS_TYPE_INT32
:
3420 case SD_BUS_TYPE_UINT32
:
3422 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3425 case SD_BUS_TYPE_INT64
:
3426 case SD_BUS_TYPE_UINT64
:
3427 case SD_BUS_TYPE_DOUBLE
:
3429 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3432 case SD_BUS_TYPE_UNIX_FD
: {
3435 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3440 *(int*) p
= m
->fds
[j
];
3446 assert_not_reached("unexpected type");
3450 r
= container_next_item(m
, c
, &rindex
);
3455 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3459 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3463 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3464 if (l
== UINT32_MAX
)
3465 /* avoid overflow right below */
3468 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3472 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3473 ok
= validate_object_path(q
, l
);
3475 ok
= validate_string(q
, l
);
3480 *(const char**) p
= q
;
3482 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3485 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3491 /* avoid overflow right below */
3494 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3498 if (!validate_signature(q
, l
))
3502 *(const char**) p
= q
;
3507 align
= bus_type_get_alignment(type
);
3510 sz
= bus_type_get_size(type
);
3513 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3519 case SD_BUS_TYPE_BYTE
:
3521 *(uint8_t*) p
= *(uint8_t*) q
;
3524 case SD_BUS_TYPE_BOOLEAN
:
3526 *(int*) p
= !!*(uint32_t*) q
;
3529 case SD_BUS_TYPE_INT16
:
3530 case SD_BUS_TYPE_UINT16
:
3532 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3535 case SD_BUS_TYPE_INT32
:
3536 case SD_BUS_TYPE_UINT32
:
3538 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3541 case SD_BUS_TYPE_INT64
:
3542 case SD_BUS_TYPE_UINT64
:
3543 case SD_BUS_TYPE_DOUBLE
:
3545 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3548 case SD_BUS_TYPE_UNIX_FD
: {
3551 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3556 *(int*) p
= m
->fds
[j
];
3561 assert_not_reached("Unknown basic type...");
3568 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3574 static int bus_message_enter_array(
3576 struct bus_container
*c
,
3577 const char *contents
,
3578 uint32_t **array_size
,
3581 size_t *n_offsets
) {
3595 if (!signature_is_single(contents
, true))
3598 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3601 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3604 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3609 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3613 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3617 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3620 alignment
= bus_type_get_alignment(contents
[0]);
3624 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3628 *array_size
= (uint32_t*) q
;
3630 } else if (c
->item_size
<= 0) {
3632 /* gvariant: empty array */
3637 } else if (bus_gvariant_is_fixed_size(contents
)) {
3639 /* gvariant: fixed length array */
3640 *item_size
= bus_gvariant_get_size(contents
);
3645 size_t where
, previous
= 0, framing
, sz
;
3649 /* gvariant: variable length array */
3650 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3652 where
= rindex
+ c
->item_size
- sz
;
3653 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3657 framing
= bus_gvariant_read_word_le(q
, sz
);
3658 if (framing
> c
->item_size
- sz
)
3660 if ((c
->item_size
- framing
) % sz
!= 0)
3663 *n_offsets
= (c
->item_size
- framing
) / sz
;
3665 where
= rindex
+ framing
;
3666 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3670 *offsets
= new(size_t, *n_offsets
);
3674 alignment
= bus_gvariant_get_alignment(c
->signature
);
3675 assert(alignment
> 0);
3677 for (i
= 0; i
< *n_offsets
; i
++) {
3680 start
= ALIGN_TO(previous
, alignment
);
3682 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3683 if (x
> c
->item_size
- sz
)
3688 (*offsets
)[i
] = rindex
+ x
;
3692 *item_size
= (*offsets
)[0] - rindex
;
3697 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3698 c
->index
+= 1 + strlen(contents
);
3703 static int bus_message_enter_variant(
3705 struct bus_container
*c
,
3706 const char *contents
,
3707 size_t *item_size
) {
3719 if (!signature_is_single(contents
, false))
3722 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3725 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3728 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3733 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3736 k
= strlen(contents
);
3737 if (1+k
> c
->item_size
)
3740 where
= rindex
+ c
->item_size
- (1+k
);
3741 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3745 if (*(char*) q
!= 0)
3748 if (memcmp((uint8_t*) q
+1, contents
, k
))
3751 *item_size
= c
->item_size
- (1+k
);
3754 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3760 /* avoid overflow right below */
3763 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3767 if (!validate_signature(q
, l
))
3770 if (!streq(q
, contents
))
3776 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3782 static int build_struct_offsets(
3784 const char *signature
,
3788 size_t *n_offsets
) {
3790 unsigned n_variable
= 0, n_total
= 0, v
;
3791 size_t previous
, where
;
3802 if (isempty(signature
)) {
3803 /* Unary type is encoded as *fixed* 1 byte padding */
3804 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3808 if (*(uint8_t *) q
!= 0)
3817 sz
= bus_gvariant_determine_word_size(size
, 0);
3821 /* First, loop over signature and count variable elements and
3822 * elements in general. We use this to know how large the
3823 * offset array is at the end of the structure. Note that
3824 * GVariant only stores offsets for all variable size elements
3825 * that are not the last item. */
3831 r
= signature_element_length(p
, &n
);
3840 r
= bus_gvariant_is_fixed_size(t
);
3845 if (r
== 0 && p
[n
] != 0) /* except the last item */
3852 if (size
< n_variable
* sz
)
3855 where
= m
->rindex
+ size
- (n_variable
* sz
);
3856 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3862 *offsets
= new(size_t, n_total
);
3868 /* Second, loop again and build an offset table */
3870 previous
= m
->rindex
;
3875 r
= signature_element_length(p
, &n
);
3884 size_t align
= bus_gvariant_get_alignment(t
);
3887 /* The possible start of this member after including alignment */
3888 size_t start
= ALIGN_TO(previous
, align
);
3890 k
= bus_gvariant_get_size(t
);
3898 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3902 /* The last item's end is determined
3903 * from the start of the offset array */
3904 x
= size
- (n_variable
* sz
);
3906 offset
= m
->rindex
+ x
;
3908 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG
),
3909 "For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu",
3919 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3924 assert(*n_offsets
== n_total
);
3926 *item_size
= (*offsets
)[0] - m
->rindex
;
3930 static int enter_struct_or_dict_entry(
3932 struct bus_container
*c
,
3933 const char *contents
,
3936 size_t *n_offsets
) {
3947 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3950 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3955 /* gvariant with contents */
3956 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3961 static int bus_message_enter_struct(
3963 struct bus_container
*c
,
3964 const char *contents
,
3967 size_t *n_offsets
) {
3979 if (!signature_is_valid(contents
, false))
3982 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3985 l
= strlen(contents
);
3987 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
3988 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3989 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
3992 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3996 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3997 c
->index
+= 1 + l
+ 1;
4002 static int bus_message_enter_dict_entry(
4004 struct bus_container
*c
,
4005 const char *contents
,
4008 size_t *n_offsets
) {
4017 if (!signature_is_pair(contents
))
4020 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4023 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4026 l
= strlen(contents
);
4028 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
4029 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4030 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
4033 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4037 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4038 c
->index
+= 1 + l
+ 1;
4043 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
4045 const char *contents
) {
4046 struct bus_container
*c
;
4047 uint32_t *array_size
= NULL
;
4048 _cleanup_free_
char *signature
= NULL
;
4050 _cleanup_free_
size_t *offsets
= NULL
;
4051 size_t n_offsets
= 0, item_size
= 0;
4054 assert_return(m
, -EINVAL
);
4055 assert_return(m
->sealed
, -EPERM
);
4056 assert_return(type
!= 0 || !contents
, -EINVAL
);
4058 if (type
== 0 || !contents
) {
4062 /* Allow entering into anonymous containers */
4063 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
4067 if (type
!= 0 && type
!= tt
)
4070 if (contents
&& !streq(contents
, cc
))
4078 * We enforce a global limit on container depth, that is much
4079 * higher than the 32 structs and 32 arrays the specification
4080 * mandates. This is simpler to implement for us, and we need
4081 * this only to ensure our container array doesn't grow
4082 * without bounds. We are happy to return any data from a
4083 * message as long as the data itself is valid, even if the
4084 * overall message might be not.
4086 * Note that the message signature is validated when
4087 * parsing the headers, and that validation does check the
4090 * Note that the specification defines no limits on the depth
4091 * of stacked variants, but we do.
4093 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4096 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4099 if (message_end_of_signature(m
))
4102 if (message_end_of_array(m
, m
->rindex
))
4105 c
= message_get_last_container(m
);
4107 signature
= strdup(contents
);
4111 c
->saved_index
= c
->index
;
4114 if (type
== SD_BUS_TYPE_ARRAY
)
4115 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4116 else if (type
== SD_BUS_TYPE_VARIANT
)
4117 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4118 else if (type
== SD_BUS_TYPE_STRUCT
)
4119 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4120 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4121 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4127 /* OK, let's fill it in */
4128 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4129 type
== SD_BUS_TYPE_STRUCT
&&
4131 end
= m
->rindex
+ 0;
4133 end
= m
->rindex
+ c
->item_size
;
4135 m
->containers
[m
->n_containers
++] = (struct bus_container
) {
4137 .signature
= TAKE_PTR(signature
),
4141 /* Unary type has fixed size of 1, but virtual size of 0 */
4143 .array_size
= array_size
,
4144 .item_size
= item_size
,
4145 .offsets
= TAKE_PTR(offsets
),
4146 .n_offsets
= n_offsets
,
4152 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4153 struct bus_container
*c
;
4157 assert_return(m
, -EINVAL
);
4158 assert_return(m
->sealed
, -EPERM
);
4159 assert_return(m
->n_containers
> 0, -ENXIO
);
4161 c
= message_get_last_container(m
);
4163 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4164 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4168 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4169 if (m
->rindex
< c
->end
)
4172 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4175 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4176 if (c
->begin
+ l
!= m
->rindex
)
4180 message_free_last_container(m
);
4182 c
= message_get_last_container(m
);
4184 c
->index
= c
->saved_index
;
4185 r
= container_next_item(m
, c
, &m
->rindex
);
4193 static void message_quit_container(sd_bus_message
*m
) {
4194 struct bus_container
*c
;
4198 assert(m
->n_containers
> 0);
4201 c
= message_get_last_container(m
);
4202 assert(m
->rindex
>= c
->before
);
4203 m
->rindex
= c
->before
;
4205 /* Free container */
4206 message_free_last_container(m
);
4208 /* Correct index of new top-level container */
4209 c
= message_get_last_container(m
);
4210 c
->index
= c
->saved_index
;
4213 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4214 struct bus_container
*c
;
4217 assert_return(m
, -EINVAL
);
4218 assert_return(m
->sealed
, -EPERM
);
4220 if (message_end_of_signature(m
))
4223 if (message_end_of_array(m
, m
->rindex
))
4226 c
= message_get_last_container(m
);
4228 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4232 *type
= c
->signature
[c
->index
];
4236 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4241 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4245 /* signature_element_length does verification internally */
4247 /* The array element must not be empty */
4249 if (free_and_strndup(&c
->peeked_signature
,
4250 c
->signature
+ c
->index
+ 1, l
) < 0)
4253 *contents
= c
->peeked_signature
;
4257 *type
= SD_BUS_TYPE_ARRAY
;
4262 if (IN_SET(c
->signature
[c
->index
], SD_BUS_TYPE_STRUCT_BEGIN
, SD_BUS_TYPE_DICT_ENTRY_BEGIN
)) {
4267 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4272 if (free_and_strndup(&c
->peeked_signature
,
4273 c
->signature
+ c
->index
+ 1, l
- 2) < 0)
4276 *contents
= c
->peeked_signature
;
4280 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4285 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4289 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4292 if (c
->item_size
< 2)
4295 /* Look for the NUL delimiter that
4296 separates the payload from the
4297 signature. Since the body might be
4298 in a different part that then the
4299 signature we map byte by byte. */
4301 for (k
= 2; k
<= c
->item_size
; k
++) {
4304 where
= m
->rindex
+ c
->item_size
- k
;
4305 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4309 if (*(char*) q
== 0)
4313 if (k
> c
->item_size
)
4316 if (free_and_strndup(&c
->peeked_signature
,
4317 (char*) q
+ 1, k
- 1) < 0)
4320 if (!signature_is_valid(c
->peeked_signature
, true))
4323 *contents
= c
->peeked_signature
;
4328 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4334 /* avoid overflow right below */
4337 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4341 if (!validate_signature(q
, l
))
4349 *type
= SD_BUS_TYPE_VARIANT
;
4364 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4365 struct bus_container
*c
;
4367 assert_return(m
, -EINVAL
);
4368 assert_return(m
->sealed
, -EPERM
);
4371 message_reset_containers(m
);
4374 c
= message_get_last_container(m
);
4376 c
= message_get_last_container(m
);
4379 m
->rindex
= c
->begin
;
4382 c
->offset_index
= 0;
4383 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4385 return !isempty(c
->signature
);
4388 _public_
int sd_bus_message_readv(
4393 unsigned n_array
, n_struct
;
4394 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4395 unsigned stack_ptr
= 0;
4396 unsigned n_loop
= 0;
4399 assert_return(m
, -EINVAL
);
4400 assert_return(m
->sealed
, -EPERM
);
4401 assert_return(types
, -EINVAL
);
4406 /* Ideally, we'd just call ourselves recursively on every
4407 * complex type. However, the state of a va_list that is
4408 * passed to a function is undefined after that function
4409 * returns. This means we need to decode the va_list linearly
4410 * in a single stackframe. We hence implement our own
4411 * home-grown stack in an array. */
4413 n_array
= (unsigned) -1; /* length of current array entries */
4414 n_struct
= strlen(types
); /* length of current struct contents signature */
4421 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4422 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4428 r
= sd_bus_message_exit_container(m
);
4436 if (n_array
!= (unsigned) -1)
4445 case SD_BUS_TYPE_BYTE
:
4446 case SD_BUS_TYPE_BOOLEAN
:
4447 case SD_BUS_TYPE_INT16
:
4448 case SD_BUS_TYPE_UINT16
:
4449 case SD_BUS_TYPE_INT32
:
4450 case SD_BUS_TYPE_UINT32
:
4451 case SD_BUS_TYPE_INT64
:
4452 case SD_BUS_TYPE_UINT64
:
4453 case SD_BUS_TYPE_DOUBLE
:
4454 case SD_BUS_TYPE_STRING
:
4455 case SD_BUS_TYPE_OBJECT_PATH
:
4456 case SD_BUS_TYPE_SIGNATURE
:
4457 case SD_BUS_TYPE_UNIX_FD
: {
4460 p
= va_arg(ap
, void*);
4461 r
= sd_bus_message_read_basic(m
, *t
, p
);
4474 case SD_BUS_TYPE_ARRAY
: {
4477 r
= signature_element_length(t
+ 1, &k
);
4483 memcpy(s
, t
+ 1, k
);
4486 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4497 if (n_array
== (unsigned) -1) {
4502 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4508 n_array
= va_arg(ap
, unsigned);
4513 case SD_BUS_TYPE_VARIANT
: {
4516 s
= va_arg(ap
, const char *);
4520 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4530 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4535 n_struct
= strlen(s
);
4536 n_array
= (unsigned) -1;
4541 case SD_BUS_TYPE_STRUCT_BEGIN
:
4542 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4545 r
= signature_element_length(t
, &k
);
4551 memcpy(s
, t
+ 1, k
- 2);
4554 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4564 if (n_array
== (unsigned) -1) {
4569 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4575 n_array
= (unsigned) -1;
4588 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4592 va_start(ap
, types
);
4593 r
= sd_bus_message_readv(m
, types
, ap
);
4599 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4602 assert_return(m
, -EINVAL
);
4603 assert_return(m
->sealed
, -EPERM
);
4605 /* If types is NULL, read exactly one element */
4607 struct bus_container
*c
;
4610 if (message_end_of_signature(m
))
4613 if (message_end_of_array(m
, m
->rindex
))
4616 c
= message_get_last_container(m
);
4618 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4622 types
= strndupa(c
->signature
+ c
->index
, l
);
4627 case 0: /* Nothing to drop */
4630 case SD_BUS_TYPE_BYTE
:
4631 case SD_BUS_TYPE_BOOLEAN
:
4632 case SD_BUS_TYPE_INT16
:
4633 case SD_BUS_TYPE_UINT16
:
4634 case SD_BUS_TYPE_INT32
:
4635 case SD_BUS_TYPE_UINT32
:
4636 case SD_BUS_TYPE_INT64
:
4637 case SD_BUS_TYPE_UINT64
:
4638 case SD_BUS_TYPE_DOUBLE
:
4639 case SD_BUS_TYPE_STRING
:
4640 case SD_BUS_TYPE_OBJECT_PATH
:
4641 case SD_BUS_TYPE_SIGNATURE
:
4642 case SD_BUS_TYPE_UNIX_FD
:
4644 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4648 r
= sd_bus_message_skip(m
, types
+ 1);
4654 case SD_BUS_TYPE_ARRAY
: {
4657 r
= signature_element_length(types
+ 1, &k
);
4663 memcpy(s
, types
+1, k
);
4666 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4671 r
= sd_bus_message_skip(m
, s
);
4678 r
= sd_bus_message_exit_container(m
);
4683 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4690 case SD_BUS_TYPE_VARIANT
: {
4691 const char *contents
;
4694 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4698 if (x
!= SD_BUS_TYPE_VARIANT
)
4701 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4705 r
= sd_bus_message_skip(m
, contents
);
4710 r
= sd_bus_message_exit_container(m
);
4714 r
= sd_bus_message_skip(m
, types
+ 1);
4721 case SD_BUS_TYPE_STRUCT_BEGIN
:
4722 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4725 r
= signature_element_length(types
, &k
);
4731 memcpy(s
, types
+1, k
-2);
4734 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4738 r
= sd_bus_message_skip(m
, s
);
4742 r
= sd_bus_message_exit_container(m
);
4747 r
= sd_bus_message_skip(m
, types
+ k
);
4759 _public_
int sd_bus_message_read_array(
4765 struct bus_container
*c
;
4771 assert_return(m
, -EINVAL
);
4772 assert_return(m
->sealed
, -EPERM
);
4773 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4774 assert_return(ptr
, -EINVAL
);
4775 assert_return(size
, -EINVAL
);
4776 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4778 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4782 c
= message_get_last_container(m
);
4784 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4785 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4789 sz
= c
->end
- c
->begin
;
4791 align
= bus_type_get_alignment(type
);
4795 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4799 /* Zero length array, let's return some aligned
4800 * pointer that is not NULL */
4801 p
= (uint8_t*) align
;
4803 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4808 r
= sd_bus_message_exit_container(m
);
4812 *ptr
= (const void*) p
;
4818 message_quit_container(m
);
4822 static int message_peek_fields(
4833 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4836 static int message_peek_field_uint32(
4848 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4851 /* identical for gvariant and dbus1 */
4853 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4858 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4863 static int message_peek_field_uint64(
4875 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4878 /* identical for gvariant and dbus1 */
4880 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4885 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4890 static int message_peek_field_string(
4892 bool (*validate
)(const char *p
),
4904 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4909 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4915 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4919 if (l
== UINT32_MAX
)
4920 /* avoid overflow right below */
4923 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4929 if (!validate_nul(q
, l
))
4935 if (!validate_string(q
, l
))
4945 static int message_peek_field_signature(
4958 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4963 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4969 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
4975 /* avoid overflow right below */
4978 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4983 if (!validate_signature(q
, l
))
4992 static int message_skip_fields(
4995 uint32_t array_size
,
4996 const char **signature
) {
4998 size_t original_index
;
5004 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
5006 original_index
= *ri
;
5012 if (array_size
!= (uint32_t) -1 &&
5013 array_size
<= *ri
- original_index
)
5020 if (t
== SD_BUS_TYPE_STRING
) {
5022 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
5028 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
5030 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
5036 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
5038 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
5044 } else if (bus_type_is_basic(t
)) {
5047 align
= bus_type_get_alignment(t
);
5048 k
= bus_type_get_size(t
);
5049 assert(align
> 0 && k
> 0);
5051 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
5057 } else if (t
== SD_BUS_TYPE_ARRAY
) {
5059 r
= signature_element_length(*signature
+ 1, &l
);
5065 char sig
[l
+ 1], *s
= sig
;
5069 strncpy(sig
, *signature
+ 1, l
);
5072 alignment
= bus_type_get_alignment(sig
[0]);
5076 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5079 if (nas
> BUS_ARRAY_MAX_SIZE
)
5082 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5086 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5091 (*signature
) += 1 + l
;
5093 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5096 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5100 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5106 } else if (IN_SET(t
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
5108 r
= signature_element_length(*signature
, &l
);
5114 char sig
[l
+ 1], *s
= sig
;
5115 strncpy(sig
, *signature
+ 1, l
);
5118 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5129 int bus_message_parse_fields(sd_bus_message
*m
) {
5132 uint32_t unix_fds
= 0;
5133 bool unix_fds_set
= false;
5134 void *offsets
= NULL
;
5135 unsigned n_offsets
= 0;
5141 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5144 /* Read the signature from the end of the body variant first */
5145 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5146 if (m
->footer_accessible
< 1 + sz
)
5149 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5151 if (p
< (char*) m
->footer
)
5155 _cleanup_free_
char *k
= NULL
;
5158 /* We found the beginning of the signature
5159 * string, yay! We require the body to be a
5160 * structure, so verify it and then strip the
5161 * opening/closing brackets. */
5163 l
= (char*) m
->footer
+ m
->footer_accessible
- p
- (1 + sz
);
5165 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5166 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5169 k
= memdup_suffix0(p
+ 1 + 1, l
- 2);
5173 if (!signature_is_valid(k
, true))
5176 free_and_replace(m
->root_container
.signature
, k
);
5183 /* Calculate the actual user body size, by removing
5184 * the trailing variant signature and struct offset
5186 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5188 /* Pull out the offset table for the fields array */
5189 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5194 ri
= m
->fields_size
- sz
;
5195 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5199 framing
= bus_gvariant_read_word_le(q
, sz
);
5200 if (framing
>= m
->fields_size
- sz
)
5202 if ((m
->fields_size
- framing
) % sz
!= 0)
5206 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5210 n_offsets
= (m
->fields_size
- framing
) / sz
;
5213 m
->user_body_size
= m
->body_size
;
5216 while (ri
< m
->fields_size
) {
5217 _cleanup_free_
char *sig
= NULL
;
5218 const char *signature
;
5219 uint64_t field_type
;
5220 size_t item_size
= (size_t) -1;
5222 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5231 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5233 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5237 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5241 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5248 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5253 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5258 where
= ri
= ALIGN_TO(ri
, 8);
5259 item_size
= end
- ri
;
5260 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5264 b
= memrchr(q
, 0, item_size
);
5268 sig
= memdup_suffix0(b
+1, item_size
- (b
+1-(char*) q
));
5273 item_size
= b
- (char*) q
;
5275 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5280 switch (field_type
) {
5282 case _BUS_MESSAGE_HEADER_INVALID
:
5285 case BUS_MESSAGE_HEADER_PATH
:
5290 if (!streq(signature
, "o"))
5293 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5296 case BUS_MESSAGE_HEADER_INTERFACE
:
5301 if (!streq(signature
, "s"))
5304 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5307 case BUS_MESSAGE_HEADER_MEMBER
:
5312 if (!streq(signature
, "s"))
5315 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5318 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5323 if (!streq(signature
, "s"))
5326 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5328 m
->error
._need_free
= -1;
5332 case BUS_MESSAGE_HEADER_DESTINATION
:
5337 if (!streq(signature
, "s"))
5340 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5343 case BUS_MESSAGE_HEADER_SENDER
:
5348 if (!streq(signature
, "s"))
5351 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5353 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
) {
5354 m
->creds
.unique_name
= (char*) m
->sender
;
5355 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5360 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5364 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5367 if (m
->root_container
.signature
)
5370 if (!streq(signature
, "g"))
5373 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5381 free_and_replace(m
->root_container
.signature
, c
);
5385 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5387 if (m
->reply_cookie
!= 0)
5390 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5391 /* 64bit on dbus2 */
5393 if (!streq(signature
, "t"))
5396 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5400 /* 32bit on dbus1 */
5403 if (!streq(signature
, "u"))
5406 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5410 m
->reply_cookie
= serial
;
5413 if (m
->reply_cookie
== 0)
5418 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5422 if (!streq(signature
, "u"))
5425 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5429 unix_fds_set
= true;
5433 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5434 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5443 if (m
->n_fds
!= unix_fds
)
5446 switch (m
->header
->type
) {
5448 case SD_BUS_MESSAGE_SIGNAL
:
5449 if (!m
->path
|| !m
->interface
|| !m
->member
)
5452 if (m
->reply_cookie
!= 0)
5457 case SD_BUS_MESSAGE_METHOD_CALL
:
5459 if (!m
->path
|| !m
->member
)
5462 if (m
->reply_cookie
!= 0)
5467 case SD_BUS_MESSAGE_METHOD_RETURN
:
5469 if (m
->reply_cookie
== 0)
5473 case SD_BUS_MESSAGE_METHOD_ERROR
:
5475 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5480 /* Refuse non-local messages that claim they are local */
5481 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5483 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5485 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5488 m
->root_container
.end
= m
->user_body_size
;
5490 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5491 r
= build_struct_offsets(
5493 m
->root_container
.signature
,
5495 &m
->root_container
.item_size
,
5496 &m
->root_container
.offsets
,
5497 &m
->root_container
.n_offsets
);
5504 /* Try to read the error message, but if we can't it's a non-issue */
5505 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5506 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5511 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5512 assert_return(m
, -EINVAL
);
5513 assert_return(destination
, -EINVAL
);
5514 assert_return(service_name_is_valid(destination
), -EINVAL
);
5515 assert_return(!m
->sealed
, -EPERM
);
5516 assert_return(!m
->destination
, -EEXIST
);
5518 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5521 _public_
int sd_bus_message_set_sender(sd_bus_message
*m
, const char *sender
) {
5522 assert_return(m
, -EINVAL
);
5523 assert_return(sender
, -EINVAL
);
5524 assert_return(service_name_is_valid(sender
), -EINVAL
);
5525 assert_return(!m
->sealed
, -EPERM
);
5526 assert_return(!m
->sender
, -EEXIST
);
5528 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5531 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5535 struct bus_body_part
*part
;
5541 total
= BUS_MESSAGE_SIZE(m
);
5547 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5548 MESSAGE_FOREACH_PART(part
, i
, m
)
5549 e
= mempcpy(e
, part
->data
, part
->size
);
5551 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5559 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5566 r
= sd_bus_message_enter_container(m
, 'a', "s");
5570 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5571 r
= strv_extend(l
, s
);
5578 r
= sd_bus_message_exit_container(m
);
5585 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5586 _cleanup_strv_free_
char **strv
= NULL
;
5589 assert_return(m
, -EINVAL
);
5590 assert_return(m
->sealed
, -EPERM
);
5591 assert_return(l
, -EINVAL
);
5593 r
= bus_message_read_strv_extend(m
, &strv
);
5597 *l
= TAKE_PTR(strv
);
5601 static int bus_message_get_arg_skip(
5605 const char **_contents
) {
5610 r
= sd_bus_message_rewind(m
, true);
5615 const char *contents
;
5618 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5624 /* Don't match against arguments after the first one we don't understand */
5625 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5626 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5631 *_contents
= contents
;
5637 r
= sd_bus_message_skip(m
, NULL
);
5644 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5651 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5655 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5658 return sd_bus_message_read_basic(m
, type
, str
);
5661 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5662 const char *contents
;
5669 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5673 if (type
!= SD_BUS_TYPE_ARRAY
)
5675 if (!STR_IN_SET(contents
, "s", "o", "g"))
5678 return sd_bus_message_read_strv(m
, strv
);
5681 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5682 assert_return(m
, EINVAL
);
5684 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5687 return sd_bus_error_get_errno(&m
->error
);
5690 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5691 struct bus_container
*c
;
5693 assert_return(m
, NULL
);
5695 c
= complete
? &m
->root_container
: message_get_last_container(m
);
5696 return strempty(c
->signature
);
5699 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5700 assert_return(m
, -EINVAL
);
5702 return isempty(m
->root_container
.signature
);
5705 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5706 assert_return(m
, -EINVAL
);
5708 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5711 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5712 bool done_something
= false;
5715 assert_return(m
, -EINVAL
);
5716 assert_return(source
, -EINVAL
);
5717 assert_return(!m
->sealed
, -EPERM
);
5718 assert_return(source
->sealed
, -EPERM
);
5721 const char *contents
;
5736 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5742 done_something
= true;
5744 if (bus_type_is_container(type
) > 0) {
5746 r
= sd_bus_message_enter_container(source
, type
, contents
);
5750 r
= sd_bus_message_open_container(m
, type
, contents
);
5754 r
= sd_bus_message_copy(m
, source
, true);
5758 r
= sd_bus_message_close_container(m
);
5762 r
= sd_bus_message_exit_container(source
);
5769 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5775 if (IN_SET(type
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
, SD_BUS_TYPE_STRING
))
5776 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5778 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5785 return done_something
;
5788 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5793 assert_return(m
, -EINVAL
);
5794 assert_return(m
->sealed
, -EPERM
);
5795 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5796 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5797 assert_return(type
|| contents
, -EINVAL
);
5798 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5800 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5804 if (type
!= 0 && type
!= t
)
5807 if (contents
&& !streq_ptr(contents
, c
))
5813 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5814 assert_return(m
, NULL
);
5819 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5820 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
5828 switch ((*m
)->header
->type
) {
5830 case SD_BUS_MESSAGE_SIGNAL
:
5831 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5837 case SD_BUS_MESSAGE_METHOD_CALL
:
5838 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5844 case SD_BUS_MESSAGE_METHOD_RETURN
:
5845 case SD_BUS_MESSAGE_METHOD_ERROR
:
5847 r
= sd_bus_message_new(bus
, &n
, (*m
)->header
->type
);
5853 n
->reply_cookie
= (*m
)->reply_cookie
;
5855 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5859 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5860 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5864 n
->error
._need_free
= -1;
5873 if ((*m
)->destination
&& !n
->destination
) {
5874 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5879 if ((*m
)->sender
&& !n
->sender
) {
5880 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5885 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5887 r
= sd_bus_message_copy(n
, *m
, true);
5891 timeout
= (*m
)->timeout
;
5892 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
)) {
5893 r
= sd_bus_get_method_call_timeout(bus
, &timeout
);
5898 r
= sd_bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5902 sd_bus_message_unref(*m
);
5908 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5909 assert_return(m
, -EINVAL
);
5910 assert_return(priority
, -EINVAL
);
5912 *priority
= m
->priority
;
5916 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5917 assert_return(m
, -EINVAL
);
5918 assert_return(!m
->sealed
, -EPERM
);
5920 m
->priority
= priority
;