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
) {
48 if (part
->memfd
>= 0) {
49 /* erase if requested, but only if the memfd is not sealed yet, i.e. is writable */
50 if (m
->sensitive
&& !m
->sealed
)
51 explicit_bzero_safe(part
->data
, part
->size
);
53 close_and_munmap(part
->memfd
, part
->mmap_begin
, part
->mapped
);
54 } else if (part
->munmap_this
)
55 /* We don't erase sensitive data here, since the data is memory mapped from someone else, and
56 * we just don't know if it's OK to write to it */
57 munmap(part
->mmap_begin
, part
->mapped
);
59 /* Erase this if that is requested. Since this is regular memory we know we can write it. */
61 explicit_bzero_safe(part
->data
, part
->size
);
71 static void message_reset_parts(sd_bus_message
*m
) {
72 struct bus_body_part
*part
;
77 while (m
->n_body_parts
> 0) {
78 struct bus_body_part
*next
= part
->next
;
79 message_free_part(m
, part
);
86 m
->cached_rindex_part
= NULL
;
87 m
->cached_rindex_part_begin
= 0;
90 static struct bus_container
*message_get_last_container(sd_bus_message
*m
) {
93 if (m
->n_containers
== 0)
94 return &m
->root_container
;
96 assert(m
->containers
);
97 return m
->containers
+ m
->n_containers
- 1;
100 static void message_free_last_container(sd_bus_message
*m
) {
101 struct bus_container
*c
;
103 c
= message_get_last_container(m
);
106 free(c
->peeked_signature
);
109 /* Move to previous container, but not if we are on root container */
110 if (m
->n_containers
> 0)
114 static void message_reset_containers(sd_bus_message
*m
) {
117 while (m
->n_containers
> 0)
118 message_free_last_container(m
);
120 m
->containers
= mfree(m
->containers
);
121 m
->containers_allocated
= 0;
122 m
->root_container
.index
= 0;
125 static sd_bus_message
* message_free(sd_bus_message
*m
) {
128 message_reset_parts(m
);
133 /* Note that we don't unref m->bus here. That's already done by sd_bus_message_unref() as each user
134 * reference to the bus message also is considered a reference to the bus connection itself. */
137 close_many(m
->fds
, m
->n_fds
);
141 if (m
->iovec
!= m
->iovec_fixed
)
144 message_reset_containers(m
);
145 assert(m
->n_containers
== 0);
146 message_free_last_container(m
);
148 bus_creds_done(&m
->creds
);
152 static void *message_extend_fields(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
154 size_t old_size
, new_size
, start
;
161 old_size
= sizeof(struct bus_header
) + m
->fields_size
;
162 start
= ALIGN_TO(old_size
, align
);
163 new_size
= start
+ sz
;
165 if (new_size
< start
||
166 new_size
> (size_t) ((uint32_t) -1))
169 if (old_size
== new_size
)
170 return (uint8_t*) m
->header
+ old_size
;
172 if (m
->free_header
) {
173 np
= realloc(m
->header
, ALIGN8(new_size
));
177 /* Initially, the header is allocated as part of
178 * the sd_bus_message itself, let's replace it by
181 np
= malloc(ALIGN8(new_size
));
185 memcpy(np
, m
->header
, sizeof(struct bus_header
));
188 /* Zero out padding */
189 if (start
> old_size
)
190 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
194 m
->fields_size
= new_size
- sizeof(struct bus_header
);
196 /* Adjust quick access pointers */
197 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
198 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
199 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
200 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
201 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
202 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
204 m
->free_header
= true;
207 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
210 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
213 return (uint8_t*) np
+ start
;
220 static int message_append_field_string(
232 /* dbus1 only allows 8bit header field ids */
236 /* dbus1 doesn't allow strings over 32bit, let's enforce this
237 * globally, to not risk convertability */
242 /* Signature "(yv)" where the variant contains "s" */
244 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
246 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
247 p
= message_extend_fields(m
, 8, 8 + l
+ 1 + 1 + 1, true);
251 *((uint64_t*) p
) = h
;
258 *ret
= (char*) p
+ 8;
261 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
262 p
= message_extend_fields(m
, 8, 4 + 4 + l
+ 1, false);
271 ((uint32_t*) p
)[1] = l
;
272 memcpy(p
+ 8, s
, l
+ 1);
275 *ret
= (char*) p
+ 8;
281 static int message_append_field_signature(
292 /* dbus1 only allows 8bit header field ids */
296 /* dbus1 doesn't allow signatures over 8bit, let's enforce
297 * this globally, to not risk convertability */
299 if (l
> SD_BUS_MAXIMUM_SIGNATURE_LENGTH
)
302 /* Signature "(yv)" where the variant contains "g" */
304 if (BUS_MESSAGE_IS_GVARIANT(m
))
305 /* For gvariant the serialization is the same as for normal strings */
306 return message_append_field_string(m
, h
, 'g', s
, ret
);
308 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
309 p
= message_extend_fields(m
, 8, 4 + 1 + l
+ 1, false);
315 p
[2] = SD_BUS_TYPE_SIGNATURE
;
318 memcpy(p
+ 5, s
, l
+ 1);
321 *ret
= (const char*) p
+ 5;
327 static int message_append_field_uint32(sd_bus_message
*m
, uint64_t h
, uint32_t x
) {
332 /* dbus1 only allows 8bit header field ids */
336 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
337 /* (field id 64bit + ((value + NUL + signature string 'u') */
339 p
= message_extend_fields(m
, 8, 8 + 4 + 1 + 1, true);
343 *((uint64_t*) p
) = h
;
344 *((uint32_t*) (p
+ 8)) = x
;
348 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
349 p
= message_extend_fields(m
, 8, 4 + 4, false);
358 ((uint32_t*) p
)[1] = x
;
364 static int message_append_field_uint64(sd_bus_message
*m
, uint64_t h
, uint64_t x
) {
369 /* dbus1 only allows 8bit header field ids */
373 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
374 /* (field id 64bit + ((value + NUL + signature string 't') */
376 p
= message_extend_fields(m
, 8, 8 + 8 + 1 + 1, true);
380 *((uint64_t*) p
) = h
;
381 *((uint64_t*) (p
+ 8)) = x
;
385 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
386 p
= message_extend_fields(m
, 8, 4 + 4 + 8, false);
399 ((uint64_t*) p
)[1] = x
;
405 static int message_append_reply_cookie(sd_bus_message
*m
, uint64_t cookie
) {
408 if (BUS_MESSAGE_IS_GVARIANT(m
))
409 return message_append_field_uint64(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, cookie
);
411 /* 64bit cookies are not supported on dbus1 */
412 if (cookie
> 0xffffffffUL
)
415 return message_append_field_uint32(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) cookie
);
419 int bus_message_from_header(
422 size_t header_accessible
,
424 size_t footer_accessible
,
430 sd_bus_message
**ret
) {
432 _cleanup_free_ sd_bus_message
*m
= NULL
;
433 struct bus_header
*h
;
437 assert(header
|| header_accessible
<= 0);
438 assert(footer
|| footer_accessible
<= 0);
439 assert(fds
|| n_fds
<= 0);
442 if (header_accessible
< sizeof(struct bus_header
))
445 if (header_accessible
> message_size
)
447 if (footer_accessible
> message_size
)
451 if (!IN_SET(h
->version
, 1, 2))
454 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
457 if (!IN_SET(h
->endian
, BUS_LITTLE_ENDIAN
, BUS_BIG_ENDIAN
))
460 /* Note that we are happy with unknown flags in the flags header! */
462 a
= ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
465 label_sz
= strlen(label
);
475 m
->header_accessible
= header_accessible
;
477 m
->footer_accessible
= footer_accessible
;
479 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
482 if (h
->dbus2
.cookie
== 0)
485 /* dbus2 derives the sizes from the message size and
486 the offset table at the end, since it is formatted as
487 gvariant "yyyyuta{tv}v". Since the message itself is a
488 structure with precisely to variable sized entries,
489 there's only one offset in the table, which marks the
490 end of the fields array. */
492 ws
= bus_gvariant_determine_word_size(message_size
, 0);
493 if (footer_accessible
< ws
)
496 m
->fields_size
= bus_gvariant_read_word_le((uint8_t*) footer
+ footer_accessible
- ws
, ws
);
497 if (ALIGN8(m
->fields_size
) > message_size
- ws
)
499 if (m
->fields_size
< sizeof(struct bus_header
))
502 m
->fields_size
-= sizeof(struct bus_header
);
503 m
->body_size
= message_size
- (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
));
505 if (h
->dbus1
.serial
== 0)
508 /* dbus1 has the sizes in the header */
509 m
->fields_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.fields_size
);
510 m
->body_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.body_size
);
512 if (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
!= message_size
)
520 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
521 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
523 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
527 m
->bus
= sd_bus_ref(bus
);
534 int bus_message_from_malloc(
541 sd_bus_message
**ret
) {
543 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
547 r
= bus_message_from_header(
549 buffer
, length
, /* in this case the initial bytes and the final bytes are the same */
558 sz
= length
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
);
561 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(m
->fields_size
);
563 m
->body
.sealed
= true;
568 m
->iovec
= m
->iovec_fixed
;
569 m
->iovec
[0] = IOVEC_MAKE(buffer
, length
);
571 r
= bus_message_parse_fields(m
);
575 /* We take possession of the memory and fds now */
576 m
->free_header
= true;
583 _public_
int sd_bus_message_new(
588 assert_return(bus
, -ENOTCONN
);
589 assert_return(bus
= bus_resolve(bus
), -ENOPKG
);
590 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
591 assert_return(m
, -EINVAL
);
592 /* Creation of messages with _SD_BUS_MESSAGE_TYPE_INVALID is allowed. */
593 assert_return(type
< _SD_BUS_MESSAGE_TYPE_MAX
, -EINVAL
);
595 sd_bus_message
*t
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
600 t
->bus
= sd_bus_ref(bus
);
601 t
->header
= (struct bus_header
*) ((uint8_t*) t
+ ALIGN(sizeof(struct sd_bus_message
)));
602 t
->header
->endian
= BUS_NATIVE_ENDIAN
;
603 t
->header
->type
= type
;
604 t
->header
->version
= bus
->message_version
;
605 t
->allow_fds
= bus
->can_fds
|| !IN_SET(bus
->state
, BUS_HELLO
, BUS_RUNNING
);
606 t
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(t
);
608 if (bus
->allow_interactive_authorization
)
609 t
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
615 _public_
int sd_bus_message_new_signal(
619 const char *interface
,
620 const char *member
) {
622 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
625 assert_return(bus
, -ENOTCONN
);
626 assert_return(bus
= bus_resolve(bus
), -ENOPKG
);
627 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
628 assert_return(object_path_is_valid(path
), -EINVAL
);
629 assert_return(interface_name_is_valid(interface
), -EINVAL
);
630 assert_return(member_name_is_valid(member
), -EINVAL
);
631 assert_return(m
, -EINVAL
);
633 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_SIGNAL
);
639 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
641 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
644 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
647 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
655 _public_
int sd_bus_message_new_method_call(
658 const char *destination
,
660 const char *interface
,
661 const char *member
) {
663 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
666 assert_return(bus
, -ENOTCONN
);
667 assert_return(bus
= bus_resolve(bus
), -ENOPKG
);
668 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
669 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
670 assert_return(object_path_is_valid(path
), -EINVAL
);
671 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
672 assert_return(member_name_is_valid(member
), -EINVAL
);
673 assert_return(m
, -EINVAL
);
675 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_CALL
);
681 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
684 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
689 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
695 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
704 static int message_new_reply(
705 sd_bus_message
*call
,
707 sd_bus_message
**m
) {
709 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
713 assert_return(call
, -EINVAL
);
714 assert_return(call
->sealed
, -EPERM
);
715 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
716 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
717 assert_return(m
, -EINVAL
);
719 cookie
= BUS_MESSAGE_COOKIE(call
);
723 r
= sd_bus_message_new(call
->bus
, &t
, type
);
729 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
730 t
->reply_cookie
= cookie
;
731 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
736 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
741 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
742 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
744 /* let's copy the sensitive flag over. Let's do that as a safety precaution to keep a transaction
745 * wholly sensitive if already the incoming message was sensitive. This is particularly useful when a
746 * vtable record sets the SD_BUS_VTABLE_SENSITIVE flag on a method call, since this means it applies
747 * to both the message call and the reply. */
748 t
->sensitive
= call
->sensitive
;
754 _public_
int sd_bus_message_new_method_return(
755 sd_bus_message
*call
,
756 sd_bus_message
**m
) {
758 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
761 _public_
int sd_bus_message_new_method_error(
762 sd_bus_message
*call
,
764 const sd_bus_error
*e
) {
766 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
769 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
770 assert_return(m
, -EINVAL
);
772 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
776 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
781 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
786 t
->error
._need_free
= -1;
792 _public_
int sd_bus_message_new_method_errorf(
793 sd_bus_message
*call
,
799 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
802 assert_return(name
, -EINVAL
);
803 assert_return(m
, -EINVAL
);
805 va_start(ap
, format
);
806 bus_error_setfv(&error
, name
, format
, ap
);
809 return sd_bus_message_new_method_error(call
, m
, &error
);
812 _public_
int sd_bus_message_new_method_errno(
813 sd_bus_message
*call
,
816 const sd_bus_error
*p
) {
818 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
820 if (sd_bus_error_is_set(p
))
821 return sd_bus_message_new_method_error(call
, m
, p
);
823 sd_bus_error_set_errno(&berror
, error
);
825 return sd_bus_message_new_method_error(call
, m
, &berror
);
828 _public_
int sd_bus_message_new_method_errnof(
829 sd_bus_message
*call
,
835 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
838 va_start(ap
, format
);
839 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
842 return sd_bus_message_new_method_error(call
, m
, &berror
);
845 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
849 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
850 m
->creds
.well_known_names_local
= true;
851 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
854 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
858 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
859 m
->creds
.well_known_names_driver
= true;
860 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
863 int bus_message_new_synthetic_error(
866 const sd_bus_error
*e
,
867 sd_bus_message
**m
) {
869 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
873 assert(sd_bus_error_is_set(e
));
876 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_ERROR
);
882 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
883 t
->reply_cookie
= cookie
;
885 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
889 if (bus
&& bus
->unique_name
) {
890 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
895 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
900 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
905 t
->error
._need_free
= -1;
907 bus_message_set_sender_driver(bus
, t
);
913 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
917 /* We are fine if this message so far was either explicitly reffed or not reffed but queued into at
918 * least one bus connection object. */
919 assert(m
->n_ref
> 0 || m
->n_queued
> 0);
923 /* Each user reference to a bus message shall also be considered a ref on the bus */
928 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
932 assert(m
->n_ref
> 0);
934 sd_bus_unref(m
->bus
); /* Each regular ref is also a ref on the bus connection. Let's hence drop it
935 * here. Note we have to do this before decrementing our own n_ref here, since
936 * otherwise, if this message is currently queued sd_bus_unref() might call
937 * bus_message_unref_queued() for this which might then destroy the message
938 * while we are still processing it. */
941 if (m
->n_ref
> 0 || m
->n_queued
> 0)
944 /* Unset the bus field if neither the user has a reference nor this message is queued. We are careful
945 * to reset the field only after the last reference to the bus is dropped, after all we might keep
946 * multiple references to the bus, once for each reference kept on ourselves. */
949 return message_free(m
);
952 sd_bus_message
* bus_message_ref_queued(sd_bus_message
*m
, sd_bus
*bus
) {
956 /* If this is a different bus than the message is associated with, then implicitly turn this into a
957 * regular reference. This means that you can create a memory leak by enqueuing a message generated
958 * on one bus onto another at the same time as enqueueing a message from the second one on the first,
959 * as we'll not detect the cyclic references there. */
961 return sd_bus_message_ref(m
);
963 assert(m
->n_ref
> 0 || m
->n_queued
> 0);
969 sd_bus_message
* bus_message_unref_queued(sd_bus_message
*m
, sd_bus
*bus
) {
974 return sd_bus_message_unref(m
);
976 assert(m
->n_queued
> 0);
979 if (m
->n_ref
> 0 || m
->n_queued
> 0)
984 return message_free(m
);
987 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
988 assert_return(m
, -EINVAL
);
989 assert_return(type
, -EINVAL
);
991 *type
= m
->header
->type
;
995 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
998 assert_return(m
, -EINVAL
);
999 assert_return(cookie
, -EINVAL
);
1001 c
= BUS_MESSAGE_COOKIE(m
);
1005 *cookie
= BUS_MESSAGE_COOKIE(m
);
1009 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
1010 assert_return(m
, -EINVAL
);
1011 assert_return(cookie
, -EINVAL
);
1013 if (m
->reply_cookie
== 0)
1016 *cookie
= m
->reply_cookie
;
1020 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
1021 assert_return(m
, -EINVAL
);
1023 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
1024 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
1027 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
1028 assert_return(m
, -EINVAL
);
1030 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
1033 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
1034 assert_return(m
, -EINVAL
);
1036 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
1037 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
1040 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
1041 assert_return(m
, NULL
);
1046 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
1047 assert_return(m
, NULL
);
1049 return m
->interface
;
1052 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
1053 assert_return(m
, NULL
);
1058 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
1059 assert_return(m
, NULL
);
1061 return m
->destination
;
1064 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
1065 assert_return(m
, NULL
);
1070 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
1071 assert_return(m
, NULL
);
1073 if (!sd_bus_error_is_set(&m
->error
))
1079 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
1080 assert_return(m
, -EINVAL
);
1081 assert_return(usec
, -EINVAL
);
1083 if (m
->monotonic
<= 0)
1086 *usec
= m
->monotonic
;
1090 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1091 assert_return(m
, -EINVAL
);
1092 assert_return(usec
, -EINVAL
);
1094 if (m
->realtime
<= 0)
1097 *usec
= m
->realtime
;
1101 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1102 assert_return(m
, -EINVAL
);
1103 assert_return(seqnum
, -EINVAL
);
1108 *seqnum
= m
->seqnum
;
1112 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1113 assert_return(m
, NULL
);
1115 if (m
->creds
.mask
== 0)
1121 _public_
int sd_bus_message_is_signal(
1123 const char *interface
,
1124 const char *member
) {
1126 assert_return(m
, -EINVAL
);
1128 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1131 if (interface
&& !streq_ptr(m
->interface
, interface
))
1134 if (member
&& !streq_ptr(m
->member
, member
))
1140 _public_
int sd_bus_message_is_method_call(
1142 const char *interface
,
1143 const char *member
) {
1145 assert_return(m
, -EINVAL
);
1147 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1150 if (interface
&& !streq_ptr(m
->interface
, interface
))
1153 if (member
&& !streq_ptr(m
->member
, member
))
1159 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1160 assert_return(m
, -EINVAL
);
1162 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1165 if (name
&& !streq_ptr(m
->error
.name
, name
))
1171 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1172 assert_return(m
, -EINVAL
);
1173 assert_return(!m
->sealed
, -EPERM
);
1174 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1176 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_REPLY_EXPECTED
, !b
);
1181 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1182 assert_return(m
, -EINVAL
);
1183 assert_return(!m
->sealed
, -EPERM
);
1185 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_AUTO_START
, !b
);
1190 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1191 assert_return(m
, -EINVAL
);
1192 assert_return(!m
->sealed
, -EPERM
);
1194 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
, b
);
1199 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1200 struct bus_body_part
*part
;
1207 if (m
->n_body_parts
<= 0) {
1211 assert(m
->body_end
);
1213 part
= new0(struct bus_body_part
, 1);
1219 m
->body_end
->next
= part
;
1229 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1234 /* All other fields can be left in their defaults */
1235 assert(!part
->data
);
1236 assert(part
->memfd
< 0);
1239 part
->is_zero
= true;
1240 part
->sealed
= true;
1243 static int part_make_space(
1244 struct sd_bus_message
*m
,
1245 struct bus_body_part
*part
,
1253 assert(!part
->sealed
);
1258 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1259 size_t new_allocated
;
1261 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1262 n
= realloc(part
->data
, new_allocated
);
1269 part
->allocated
= new_allocated
;
1270 part
->free_this
= true;
1274 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1280 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1281 struct bus_container
*c
;
1284 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1286 /* Add offset to current container, unless this is the first
1287 * item in it, which will have the 0 offset, which we can
1289 c
= message_get_last_container(m
);
1291 if (!c
->need_offsets
)
1294 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1297 c
->offsets
[c
->n_offsets
++] = offset
;
1301 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1307 if (m
->n_containers
<= 0)
1310 /* Update counters */
1311 for (struct bus_container
*c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1313 *c
->array_size
+= expand
;
1316 static void *message_extend_body(
1321 bool force_inline
) {
1323 size_t start_body
, end_body
, padding
, added
;
1334 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1335 end_body
= start_body
+ sz
;
1337 padding
= start_body
- m
->body_size
;
1338 added
= padding
+ sz
;
1340 /* Check for 32bit overflows */
1341 if (end_body
> (size_t) ((uint32_t) -1) ||
1342 end_body
< start_body
) {
1348 struct bus_body_part
*part
= NULL
;
1352 m
->n_body_parts
<= 0 ||
1353 m
->body_end
->sealed
||
1354 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1355 (force_inline
&& m
->body_end
->size
> MEMFD_MIN_SIZE
);
1356 /* If this must be an inlined extension, let's create a new part if
1357 * the previous part is large enough to be inlined. */
1361 part
= message_append_part(m
);
1365 part_zero(part
, padding
);
1368 part
= message_append_part(m
);
1372 r
= part_make_space(m
, part
, sz
, &p
);
1377 size_t os
, start_part
, end_part
;
1383 start_part
= ALIGN_TO(part
->size
, align
);
1384 end_part
= start_part
+ sz
;
1386 r
= part_make_space(m
, part
, end_part
, &p
);
1391 memzero(p
, padding
);
1392 p
= (uint8_t*) p
+ padding
;
1395 /* Readjust pointers */
1396 if (m
->n_containers
> 0)
1397 for (struct bus_container
*c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1398 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1400 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1403 /* Return something that is not NULL and is aligned */
1404 p
= (uint8_t*) align
;
1406 m
->body_size
= end_body
;
1407 message_extend_containers(m
, added
);
1410 r
= message_add_offset(m
, end_body
);
1420 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1431 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1435 f
= reallocarray(m
->fds
, sizeof(int), m
->n_fds
+ 1);
1443 m
->fds
[m
->n_fds
] = copy
;
1449 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1450 _cleanup_close_
int fd
= -1;
1451 struct bus_container
*c
;
1455 assert_return(m
, -EINVAL
);
1456 assert_return(!m
->sealed
, -EPERM
);
1457 assert_return(bus_type_is_basic(type
), -EINVAL
);
1458 assert_return(!m
->poisoned
, -ESTALE
);
1460 c
= message_get_last_container(m
);
1462 if (c
->signature
&& c
->signature
[c
->index
]) {
1463 /* Container signature is already set */
1465 if (c
->signature
[c
->index
] != type
)
1470 /* Maybe we can append to the signature? But only if this is the top-level container */
1471 if (c
->enclosing
!= 0)
1474 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1481 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1487 case SD_BUS_TYPE_SIGNATURE
:
1488 case SD_BUS_TYPE_STRING
:
1492 case SD_BUS_TYPE_OBJECT_PATH
:
1500 case SD_BUS_TYPE_BOOLEAN
:
1502 u8
= p
&& *(int*) p
;
1508 case SD_BUS_TYPE_UNIX_FD
:
1513 fd
= message_push_fd(m
, *(int*) p
);
1524 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1525 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1532 a
= message_extend_body(m
, align
, sz
, true, false);
1539 *stored
= (const uint8_t*) a
;
1546 case SD_BUS_TYPE_STRING
:
1547 /* To make things easy we'll serialize a NULL string
1548 * into the empty string */
1552 case SD_BUS_TYPE_OBJECT_PATH
:
1558 sz
= 4 + strlen(p
) + 1;
1561 case SD_BUS_TYPE_SIGNATURE
:
1566 sz
= 1 + strlen(p
) + 1;
1569 case SD_BUS_TYPE_BOOLEAN
:
1571 u32
= p
&& *(int*) p
;
1577 case SD_BUS_TYPE_UNIX_FD
:
1582 fd
= message_push_fd(m
, *(int*) p
);
1593 align
= bus_type_get_alignment(type
);
1594 sz
= bus_type_get_size(type
);
1601 a
= message_extend_body(m
, align
, sz
, false, false);
1605 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
1606 *(uint32_t*) a
= sz
- 5;
1607 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1610 *stored
= (const uint8_t*) a
+ 4;
1612 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1613 *(uint8_t*) a
= sz
- 2;
1614 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1617 *stored
= (const uint8_t*) a
+ 1;
1626 if (type
== SD_BUS_TYPE_UNIX_FD
)
1629 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1636 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1637 return message_append_basic(m
, type
, p
, NULL
);
1640 _public_
int sd_bus_message_append_string_space(
1645 struct bus_container
*c
;
1648 assert_return(m
, -EINVAL
);
1649 assert_return(s
, -EINVAL
);
1650 assert_return(!m
->sealed
, -EPERM
);
1651 assert_return(!m
->poisoned
, -ESTALE
);
1653 c
= message_get_last_container(m
);
1655 if (c
->signature
&& c
->signature
[c
->index
]) {
1656 /* Container signature is already set */
1658 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1663 /* Maybe we can append to the signature? But only if this is the top-level container */
1664 if (c
->enclosing
!= 0)
1667 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1674 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1675 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1681 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1685 *(uint32_t*) a
= size
;
1691 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1697 _public_
int sd_bus_message_append_string_iovec(
1699 const struct iovec
*iov
,
1700 unsigned n
/* should be size_t, but is API now… 😞 */) {
1707 assert_return(m
, -EINVAL
);
1708 assert_return(!m
->sealed
, -EPERM
);
1709 assert_return(iov
|| n
== 0, -EINVAL
);
1710 assert_return(!m
->poisoned
, -ESTALE
);
1712 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1714 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1718 for (i
= 0; i
< n
; i
++) {
1720 if (iov
[i
].iov_base
)
1721 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1723 memset(p
, ' ', iov
[i
].iov_len
);
1725 p
+= iov
[i
].iov_len
;
1731 static int bus_message_open_array(
1733 struct bus_container
*c
,
1734 const char *contents
,
1735 uint32_t **array_size
,
1737 bool *need_offsets
) {
1747 assert(need_offsets
);
1749 if (!signature_is_single(contents
, true))
1752 if (c
->signature
&& c
->signature
[c
->index
]) {
1754 /* Verify the existing signature */
1756 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1759 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1762 nindex
= c
->index
+ 1 + strlen(contents
);
1766 if (c
->enclosing
!= 0)
1769 /* Extend the existing signature */
1771 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1777 nindex
= e
- c
->signature
;
1780 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1781 alignment
= bus_gvariant_get_alignment(contents
);
1785 /* Add alignment padding and add to offset list */
1786 if (!message_extend_body(m
, alignment
, 0, false, false))
1789 r
= bus_gvariant_is_fixed_size(contents
);
1793 *begin
= m
->body_size
;
1794 *need_offsets
= r
== 0;
1798 struct bus_body_part
*o
;
1800 alignment
= bus_type_get_alignment(contents
[0]);
1804 a
= message_extend_body(m
, 4, 4, false, false);
1809 op
= m
->body_end
->data
;
1810 os
= m
->body_end
->size
;
1812 /* Add alignment between size and first element */
1813 if (!message_extend_body(m
, alignment
, 0, false, false))
1816 /* location of array size might have changed so let's readjust a */
1817 if (o
== m
->body_end
)
1818 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1824 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1830 static int bus_message_open_variant(
1832 struct bus_container
*c
,
1833 const char *contents
) {
1839 if (!signature_is_single(contents
, false))
1842 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1845 if (c
->signature
&& c
->signature
[c
->index
]) {
1847 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1853 if (c
->enclosing
!= 0)
1856 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1863 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1864 /* Variants are always aligned to 8 */
1866 if (!message_extend_body(m
, 8, 0, false, false))
1873 l
= strlen(contents
);
1874 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1879 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1882 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1888 static int bus_message_open_struct(
1890 struct bus_container
*c
,
1891 const char *contents
,
1893 bool *need_offsets
) {
1902 assert(need_offsets
);
1904 if (!signature_is_valid(contents
, false))
1907 if (c
->signature
&& c
->signature
[c
->index
]) {
1910 l
= strlen(contents
);
1912 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1913 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1914 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1917 nindex
= c
->index
+ 1 + l
+ 1;
1921 if (c
->enclosing
!= 0)
1924 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1930 nindex
= e
- c
->signature
;
1933 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1936 alignment
= bus_gvariant_get_alignment(contents
);
1940 if (!message_extend_body(m
, alignment
, 0, false, false))
1943 r
= bus_gvariant_is_fixed_size(contents
);
1947 *begin
= m
->body_size
;
1948 *need_offsets
= r
== 0;
1950 /* Align contents to 8 byte boundary */
1951 if (!message_extend_body(m
, 8, 0, false, false))
1955 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1961 static int bus_message_open_dict_entry(
1963 struct bus_container
*c
,
1964 const char *contents
,
1966 bool *need_offsets
) {
1974 assert(need_offsets
);
1976 if (!signature_is_pair(contents
))
1979 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1982 if (c
->signature
&& c
->signature
[c
->index
]) {
1985 l
= strlen(contents
);
1987 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
1988 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1989 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
1994 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1997 alignment
= bus_gvariant_get_alignment(contents
);
2001 if (!message_extend_body(m
, alignment
, 0, false, false))
2004 r
= bus_gvariant_is_fixed_size(contents
);
2008 *begin
= m
->body_size
;
2009 *need_offsets
= r
== 0;
2011 /* Align contents to 8 byte boundary */
2012 if (!message_extend_body(m
, 8, 0, false, false))
2019 _public_
int sd_bus_message_open_container(
2022 const char *contents
) {
2024 struct bus_container
*c
;
2025 uint32_t *array_size
= NULL
;
2026 _cleanup_free_
char *signature
= NULL
;
2027 size_t before
, begin
= 0;
2028 bool need_offsets
= false;
2031 assert_return(m
, -EINVAL
);
2032 assert_return(!m
->sealed
, -EPERM
);
2033 assert_return(contents
, -EINVAL
);
2034 assert_return(!m
->poisoned
, -ESTALE
);
2036 /* Make sure we have space for one more container */
2037 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
2042 c
= message_get_last_container(m
);
2044 signature
= strdup(contents
);
2050 /* Save old index in the parent container, in case we have to
2051 * abort this container */
2052 c
->saved_index
= c
->index
;
2053 before
= m
->body_size
;
2055 if (type
== SD_BUS_TYPE_ARRAY
)
2056 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
2057 else if (type
== SD_BUS_TYPE_VARIANT
)
2058 r
= bus_message_open_variant(m
, c
, contents
);
2059 else if (type
== SD_BUS_TYPE_STRUCT
)
2060 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
2061 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
2062 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
2068 /* OK, let's fill it in */
2069 m
->containers
[m
->n_containers
++] = (struct bus_container
) {
2071 .signature
= TAKE_PTR(signature
),
2072 .array_size
= array_size
,
2075 .need_offsets
= need_offsets
,
2081 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2086 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2089 if (c
->need_offsets
) {
2090 size_t payload
, sz
, i
;
2093 /* Variable-width arrays */
2095 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2096 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2098 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2102 for (i
= 0; i
< c
->n_offsets
; i
++)
2103 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2107 /* Fixed-width or empty arrays */
2109 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2117 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2123 assert(c
->signature
);
2125 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2128 l
= strlen(c
->signature
);
2130 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2135 memcpy(a
+1, c
->signature
, l
);
2140 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2141 bool fixed_size
= true;
2142 size_t n_variable
= 0;
2151 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2154 p
= strempty(c
->signature
);
2158 r
= signature_element_length(p
, &n
);
2167 r
= bus_gvariant_is_fixed_size(t
);
2172 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2174 /* We need to add an offset for each item that has a
2175 * variable size and that is not the last one in the
2179 if (r
== 0 && p
[n
] != 0)
2186 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2187 assert(c
->need_offsets
|| n_variable
== 0);
2189 if (isempty(c
->signature
)) {
2190 /* The unary type is encoded as fixed 1 byte padding */
2191 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2196 } else if (n_variable
<= 0) {
2199 /* Structures with fixed-size members only have to be
2200 * fixed-size themselves. But gvariant requires all fixed-size
2201 * elements to be sized a multiple of their alignment. Hence,
2202 * we must *always* add final padding after the last member so
2203 * the overall size of the structure is properly aligned. */
2205 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2207 assert(alignment
> 0);
2209 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2216 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2218 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2220 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2224 p
= strempty(c
->signature
);
2225 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2229 r
= signature_element_length(p
, &n
);
2240 r
= bus_gvariant_is_fixed_size(t
);
2243 if (r
> 0 || p
[0] == 0)
2247 k
= n_variable
- 1 - j
;
2249 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2258 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2259 struct bus_container
*c
;
2262 assert_return(m
, -EINVAL
);
2263 assert_return(!m
->sealed
, -EPERM
);
2264 assert_return(m
->n_containers
> 0, -EINVAL
);
2265 assert_return(!m
->poisoned
, -ESTALE
);
2267 c
= message_get_last_container(m
);
2269 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2270 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2275 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2276 r
= bus_message_close_array(m
, c
);
2277 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2278 r
= bus_message_close_variant(m
, c
);
2279 else if (IN_SET(c
->enclosing
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
))
2280 r
= bus_message_close_struct(m
, c
, true);
2282 assert_not_reached("Unknown container type");
2296 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2303 stack
[*i
].types
= types
;
2304 stack
[*i
].n_struct
= n_struct
;
2305 stack
[*i
].n_array
= n_array
;
2311 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2322 *types
= stack
[*i
].types
;
2323 *n_struct
= stack
[*i
].n_struct
;
2324 *n_array
= stack
[*i
].n_array
;
2329 _public_
int sd_bus_message_appendv(
2334 unsigned n_array
, n_struct
;
2335 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2336 unsigned stack_ptr
= 0;
2339 assert_return(m
, -EINVAL
);
2340 assert_return(types
, -EINVAL
);
2341 assert_return(!m
->sealed
, -EPERM
);
2342 assert_return(!m
->poisoned
, -ESTALE
);
2344 n_array
= (unsigned) -1;
2345 n_struct
= strlen(types
);
2350 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2351 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2357 r
= sd_bus_message_close_container(m
);
2365 if (n_array
!= (unsigned) -1)
2374 case SD_BUS_TYPE_BYTE
: {
2377 x
= (uint8_t) va_arg(ap
, int);
2378 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2382 case SD_BUS_TYPE_BOOLEAN
:
2383 case SD_BUS_TYPE_INT32
:
2384 case SD_BUS_TYPE_UINT32
:
2385 case SD_BUS_TYPE_UNIX_FD
: {
2388 /* We assume a boolean is the same as int32_t */
2389 assert_cc(sizeof(int32_t) == sizeof(int));
2391 x
= va_arg(ap
, uint32_t);
2392 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2396 case SD_BUS_TYPE_INT16
:
2397 case SD_BUS_TYPE_UINT16
: {
2400 x
= (uint16_t) va_arg(ap
, int);
2401 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2405 case SD_BUS_TYPE_INT64
:
2406 case SD_BUS_TYPE_UINT64
: {
2409 x
= va_arg(ap
, uint64_t);
2410 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2414 case SD_BUS_TYPE_DOUBLE
: {
2417 x
= va_arg(ap
, double);
2418 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2422 case SD_BUS_TYPE_STRING
:
2423 case SD_BUS_TYPE_OBJECT_PATH
:
2424 case SD_BUS_TYPE_SIGNATURE
: {
2427 x
= va_arg(ap
, const char*);
2428 r
= sd_bus_message_append_basic(m
, *t
, x
);
2432 case SD_BUS_TYPE_ARRAY
: {
2435 r
= signature_element_length(t
+ 1, &k
);
2441 memcpy(s
, t
+ 1, k
);
2444 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2449 if (n_array
== (unsigned) -1) {
2454 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2460 n_array
= va_arg(ap
, unsigned);
2465 case SD_BUS_TYPE_VARIANT
: {
2468 s
= va_arg(ap
, const char*);
2472 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2476 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2481 n_struct
= strlen(s
);
2482 n_array
= (unsigned) -1;
2487 case SD_BUS_TYPE_STRUCT_BEGIN
:
2488 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2491 r
= signature_element_length(t
, &k
);
2498 memcpy(s
, t
+ 1, k
- 2);
2501 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2506 if (n_array
== (unsigned) -1) {
2511 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2517 n_array
= (unsigned) -1;
2533 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2537 va_start(ap
, types
);
2538 r
= sd_bus_message_appendv(m
, types
, ap
);
2544 _public_
int sd_bus_message_append_array_space(
2554 assert_return(m
, -EINVAL
);
2555 assert_return(!m
->sealed
, -EPERM
);
2556 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2557 assert_return(ptr
|| size
== 0, -EINVAL
);
2558 assert_return(!m
->poisoned
, -ESTALE
);
2560 /* alignment and size of the trivial types (except bool) is
2561 * identical for gvariant and dbus1 marshalling */
2562 align
= bus_type_get_alignment(type
);
2563 sz
= bus_type_get_size(type
);
2565 assert_se(align
> 0);
2571 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2575 a
= message_extend_body(m
, align
, size
, false, false);
2579 r
= sd_bus_message_close_container(m
);
2587 _public_
int sd_bus_message_append_array(
2595 assert_return(m
, -EINVAL
);
2596 assert_return(!m
->sealed
, -EPERM
);
2597 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2598 assert_return(ptr
|| size
== 0, -EINVAL
);
2599 assert_return(!m
->poisoned
, -ESTALE
);
2601 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2605 memcpy_safe(p
, ptr
, size
);
2610 _public_
int sd_bus_message_append_array_iovec(
2613 const struct iovec
*iov
,
2614 unsigned n
/* should be size_t, but is API now… 😞 */) {
2621 assert_return(m
, -EINVAL
);
2622 assert_return(!m
->sealed
, -EPERM
);
2623 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2624 assert_return(iov
|| n
== 0, -EINVAL
);
2625 assert_return(!m
->poisoned
, -ESTALE
);
2627 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2629 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2633 for (i
= 0; i
< n
; i
++) {
2635 if (iov
[i
].iov_base
)
2636 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2638 memzero(p
, iov
[i
].iov_len
);
2640 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2646 _public_
int sd_bus_message_append_array_memfd(
2653 _cleanup_close_
int copy_fd
= -1;
2654 struct bus_body_part
*part
;
2660 assert_return(m
, -EINVAL
);
2661 assert_return(memfd
>= 0, -EBADF
);
2662 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2663 assert_return(size
> 0, -EINVAL
);
2664 assert_return(!m
->sealed
, -EPERM
);
2665 assert_return(!m
->poisoned
, -ESTALE
);
2667 r
= memfd_set_sealed(memfd
);
2671 copy_fd
= fcntl(memfd
, F_DUPFD_CLOEXEC
, 3);
2675 r
= memfd_get_size(memfd
, &real_size
);
2679 if (offset
== 0 && size
== (uint64_t) -1)
2681 else if (offset
+ size
> real_size
)
2684 align
= bus_type_get_alignment(type
);
2685 sz
= bus_type_get_size(type
);
2687 assert_se(align
> 0);
2690 if (offset
% align
!= 0)
2696 if (size
> (uint64_t) (uint32_t) -1)
2699 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2703 a
= message_extend_body(m
, align
, 0, false, false);
2707 part
= message_append_part(m
);
2711 part
->memfd
= copy_fd
;
2712 part
->memfd_offset
= offset
;
2713 part
->sealed
= true;
2717 m
->body_size
+= size
;
2718 message_extend_containers(m
, size
);
2720 return sd_bus_message_close_container(m
);
2723 _public_
int sd_bus_message_append_string_memfd(
2729 _cleanup_close_
int copy_fd
= -1;
2730 struct bus_body_part
*part
;
2731 struct bus_container
*c
;
2736 assert_return(m
, -EINVAL
);
2737 assert_return(memfd
>= 0, -EBADF
);
2738 assert_return(size
> 0, -EINVAL
);
2739 assert_return(!m
->sealed
, -EPERM
);
2740 assert_return(!m
->poisoned
, -ESTALE
);
2742 r
= memfd_set_sealed(memfd
);
2746 copy_fd
= fcntl(memfd
, FD_CLOEXEC
, 3);
2750 r
= memfd_get_size(memfd
, &real_size
);
2754 if (offset
== 0 && size
== (uint64_t) -1)
2756 else if (offset
+ size
> real_size
)
2759 /* We require this to be NUL terminated */
2763 if (size
> (uint64_t) (uint32_t) -1)
2766 c
= message_get_last_container(m
);
2767 if (c
->signature
&& c
->signature
[c
->index
]) {
2768 /* Container signature is already set */
2770 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2775 /* Maybe we can append to the signature? But only if this is the top-level container */
2776 if (c
->enclosing
!= 0)
2779 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2786 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2787 a
= message_extend_body(m
, 4, 4, false, false);
2791 *(uint32_t*) a
= size
- 1;
2794 part
= message_append_part(m
);
2798 part
->memfd
= copy_fd
;
2799 part
->memfd_offset
= offset
;
2800 part
->sealed
= true;
2804 m
->body_size
+= size
;
2805 message_extend_containers(m
, size
);
2807 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2808 r
= message_add_offset(m
, m
->body_size
);
2815 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2821 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2825 assert_return(m
, -EINVAL
);
2826 assert_return(!m
->sealed
, -EPERM
);
2827 assert_return(!m
->poisoned
, -ESTALE
);
2829 r
= sd_bus_message_open_container(m
, 'a', "s");
2833 STRV_FOREACH(i
, l
) {
2834 r
= sd_bus_message_append_basic(m
, 's', *i
);
2839 return sd_bus_message_close_container(m
);
2842 static int bus_message_close_header(sd_bus_message
*m
) {
2846 /* The actual user data is finished now, we just complete the
2847 variant and struct now (at least on gvariant). Remember
2848 this position, so that during parsing we know where to
2849 put the outer container end. */
2850 m
->user_body_size
= m
->body_size
;
2852 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2853 const char *signature
;
2857 /* Add offset table to end of fields array */
2858 if (m
->n_header_offsets
>= 1) {
2862 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2864 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2865 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2869 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2870 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2873 /* Add gvariant NUL byte plus signature to the end of
2874 * the body, followed by the final offset pointing to
2875 * the end of the fields array */
2877 signature
= strempty(m
->root_container
.signature
);
2878 l
= strlen(signature
);
2880 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2881 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2886 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2887 memcpy((uint8_t*) d
+ 2, signature
, l
);
2888 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2890 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2893 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2895 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2896 m
->header
->dbus1
.body_size
= m
->body_size
;
2902 _public_
int sd_bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, uint64_t timeout_usec
) {
2903 struct bus_body_part
*part
;
2908 assert_return(m
, -EINVAL
);
2913 if (m
->n_containers
> 0)
2919 if (cookie
> 0xffffffffULL
&&
2920 !BUS_MESSAGE_IS_GVARIANT(m
))
2923 /* In vtables the return signature of method calls is listed,
2924 * let's check if they match if this is a response */
2925 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2926 m
->enforced_reply_signature
&&
2927 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2930 /* If gvariant marshalling is used we need to close the body structure */
2931 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2935 /* If there's a non-trivial signature set, then add it in
2936 * here, but only on dbus1 */
2937 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2938 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2944 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2949 r
= bus_message_close_header(m
);
2953 if (BUS_MESSAGE_IS_GVARIANT(m
))
2954 m
->header
->dbus2
.cookie
= cookie
;
2956 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2958 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout_usec
;
2960 /* Add padding at the end of the fields part, since we know
2961 * the body needs to start at an 8 byte alignment. We made
2962 * sure we allocated enough space for this, so all we need to
2963 * do here is to zero it out. */
2964 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2966 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2968 /* If this is something we can send as memfd, then let's seal
2969 the memfd now. Note that we can send memfds as payload only
2970 for directed messages, and not for broadcasts. */
2971 if (m
->destination
&& m
->bus
->use_memfd
) {
2972 MESSAGE_FOREACH_PART(part
, i
, m
)
2973 if (part
->memfd
>= 0 &&
2975 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
2976 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
2979 /* Try to seal it if that makes
2980 * sense. First, unmap our own map to
2981 * make sure we don't keep it busy. */
2982 bus_body_part_unmap(part
);
2984 /* Then, sync up real memfd size */
2986 r
= memfd_set_size(part
->memfd
, sz
);
2990 /* Finally, try to seal */
2991 if (memfd_set_sealed(part
->memfd
) >= 0)
2992 part
->sealed
= true;
2996 m
->root_container
.end
= m
->user_body_size
;
2997 m
->root_container
.index
= 0;
2998 m
->root_container
.offset_index
= 0;
2999 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
3006 int bus_body_part_map(struct bus_body_part
*part
) {
3015 if (part
->size
<= 0)
3018 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3019 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
3020 static const uint8_t zeroes
[7] = { };
3021 part
->data
= (void*) zeroes
;
3025 shift
= PAGE_OFFSET(part
->memfd_offset
);
3026 psz
= PAGE_ALIGN(part
->size
+ shift
);
3028 if (part
->memfd
>= 0)
3029 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
3030 else if (part
->is_zero
)
3031 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
3035 if (p
== MAP_FAILED
)
3039 part
->mmap_begin
= p
;
3040 part
->data
= (uint8_t*) p
+ shift
;
3041 part
->munmap_this
= true;
3046 void bus_body_part_unmap(struct bus_body_part
*part
) {
3050 if (part
->memfd
< 0)
3053 if (!part
->mmap_begin
)
3056 if (!part
->munmap_this
)
3059 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
3061 part
->mmap_begin
= NULL
;
3064 part
->munmap_this
= false;
3069 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3070 size_t k
, start
, end
;
3075 start
= ALIGN_TO((size_t) *rindex
, align
);
3076 end
= start
+ nbytes
;
3081 /* Verify that padding is 0 */
3082 for (k
= *rindex
; k
< start
; k
++)
3083 if (((const uint8_t*) p
)[k
] != 0)
3087 *r
= (uint8_t*) p
+ start
;
3094 static bool message_end_of_signature(sd_bus_message
*m
) {
3095 struct bus_container
*c
;
3099 c
= message_get_last_container(m
);
3100 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3103 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3104 struct bus_container
*c
;
3108 c
= message_get_last_container(m
);
3109 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3112 if (BUS_MESSAGE_IS_GVARIANT(m
))
3113 return index
>= c
->end
;
3115 assert(c
->array_size
);
3116 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3120 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3121 assert_return(m
, -EINVAL
);
3122 assert_return(m
->sealed
, -EPERM
);
3124 if (complete
&& m
->n_containers
> 0)
3127 if (message_end_of_signature(m
))
3130 if (message_end_of_array(m
, m
->rindex
))
3136 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3137 struct bus_body_part
*part
;
3143 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3144 part
= m
->cached_rindex_part
;
3145 begin
= m
->cached_rindex_part_begin
;
3155 if (index
+ sz
<= begin
+ part
->size
) {
3157 r
= bus_body_part_map(part
);
3162 *p
= part
->data
? (uint8_t*) part
->data
+ index
- begin
3163 : NULL
; /* Avoid dereferencing a NULL pointer. */
3165 m
->cached_rindex_part
= part
;
3166 m
->cached_rindex_part_begin
= begin
;
3171 begin
+= part
->size
;
3178 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3185 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3188 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3191 sz
= bus_gvariant_get_size(c
->signature
);
3195 if (c
->offset_index
+1 >= c
->n_offsets
)
3198 /* Variable-size array */
3200 alignment
= bus_gvariant_get_alignment(c
->signature
);
3201 assert(alignment
> 0);
3203 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3204 assert(c
->offsets
[c
->offset_index
+1] >= *rindex
);
3205 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3208 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3211 /* Fixed-size array */
3212 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3218 } else if (IN_SET(c
->enclosing
, 0, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
3223 if (c
->offset_index
+1 >= c
->n_offsets
)
3226 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3230 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3235 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3238 alignment
= bus_gvariant_get_alignment(t
);
3241 assert(alignment
> 0);
3243 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3244 assert(c
->offsets
[c
->offset_index
+1] >= *rindex
);
3245 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3249 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3252 assert_not_reached("Unknown container type");
3257 /* Reached the end */
3263 static int message_peek_body(
3270 size_t k
, start
, end
, padding
;
3271 struct bus_body_part
*part
;
3278 start
= ALIGN_TO((size_t) *rindex
, align
);
3279 padding
= start
- *rindex
;
3280 end
= start
+ nbytes
;
3282 if (end
> m
->user_body_size
)
3285 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3290 /* Verify padding */
3291 for (k
= 0; k
< padding
; k
++)
3296 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3297 if (!part
|| (nbytes
> 0 && !q
))
3308 static bool validate_nul(const char *s
, size_t l
) {
3310 /* Check for NUL chars in the string */
3311 if (memchr(s
, 0, l
))
3314 /* Check for NUL termination */
3321 static bool validate_string(const char *s
, size_t l
) {
3323 if (!validate_nul(s
, l
))
3326 /* Check if valid UTF8 */
3327 if (!utf8_is_valid(s
))
3333 static bool validate_signature(const char *s
, size_t l
) {
3335 if (!validate_nul(s
, l
))
3338 /* Check if valid signature */
3339 if (!signature_is_valid(s
, true))
3345 static bool validate_object_path(const char *s
, size_t l
) {
3347 if (!validate_nul(s
, l
))
3350 if (!object_path_is_valid(s
))
3356 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3357 struct bus_container
*c
;
3362 assert_return(m
, -EINVAL
);
3363 assert_return(m
->sealed
, -EPERM
);
3364 assert_return(bus_type_is_basic(type
), -EINVAL
);
3366 if (message_end_of_signature(m
))
3369 if (message_end_of_array(m
, m
->rindex
))
3372 c
= message_get_last_container(m
);
3373 if (c
->signature
[c
->index
] != type
)
3378 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3380 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3383 /* D-Bus spec: The marshalling formats for the string-like types all end
3384 * with a single zero (NUL) byte, but that byte is not considered to be part
3386 if (c
->item_size
== 0)
3389 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3393 if (type
== SD_BUS_TYPE_STRING
)
3394 ok
= validate_string(q
, c
->item_size
-1);
3395 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3396 ok
= validate_object_path(q
, c
->item_size
-1);
3398 ok
= validate_signature(q
, c
->item_size
-1);
3404 *(const char**) p
= q
;
3408 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3410 if ((size_t) sz
!= c
->item_size
)
3413 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3416 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3422 case SD_BUS_TYPE_BYTE
:
3424 *(uint8_t*) p
= *(uint8_t*) q
;
3427 case SD_BUS_TYPE_BOOLEAN
:
3429 *(int*) p
= !!*(uint8_t*) q
;
3432 case SD_BUS_TYPE_INT16
:
3433 case SD_BUS_TYPE_UINT16
:
3435 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3438 case SD_BUS_TYPE_INT32
:
3439 case SD_BUS_TYPE_UINT32
:
3441 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3444 case SD_BUS_TYPE_INT64
:
3445 case SD_BUS_TYPE_UINT64
:
3446 case SD_BUS_TYPE_DOUBLE
:
3448 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3451 case SD_BUS_TYPE_UNIX_FD
: {
3454 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3459 *(int*) p
= m
->fds
[j
];
3465 assert_not_reached("unexpected type");
3469 r
= container_next_item(m
, c
, &rindex
);
3474 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3478 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3482 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3483 if (l
== UINT32_MAX
)
3484 /* avoid overflow right below */
3487 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3491 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3492 ok
= validate_object_path(q
, l
);
3494 ok
= validate_string(q
, l
);
3499 *(const char**) p
= q
;
3501 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3504 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3510 /* avoid overflow right below */
3513 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3517 if (!validate_signature(q
, l
))
3521 *(const char**) p
= q
;
3526 align
= bus_type_get_alignment(type
);
3529 sz
= bus_type_get_size(type
);
3532 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3538 case SD_BUS_TYPE_BYTE
:
3540 *(uint8_t*) p
= *(uint8_t*) q
;
3543 case SD_BUS_TYPE_BOOLEAN
:
3545 *(int*) p
= !!*(uint32_t*) q
;
3548 case SD_BUS_TYPE_INT16
:
3549 case SD_BUS_TYPE_UINT16
:
3551 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3554 case SD_BUS_TYPE_INT32
:
3555 case SD_BUS_TYPE_UINT32
:
3557 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3560 case SD_BUS_TYPE_INT64
:
3561 case SD_BUS_TYPE_UINT64
:
3562 case SD_BUS_TYPE_DOUBLE
:
3564 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3567 case SD_BUS_TYPE_UNIX_FD
: {
3570 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3575 *(int*) p
= m
->fds
[j
];
3580 assert_not_reached("Unknown basic type...");
3587 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3593 static int bus_message_enter_array(
3595 struct bus_container
*c
,
3596 const char *contents
,
3597 uint32_t **array_size
,
3600 size_t *n_offsets
) {
3614 if (!signature_is_single(contents
, true))
3617 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3620 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3623 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3628 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3632 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3636 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3639 alignment
= bus_type_get_alignment(contents
[0]);
3643 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3647 *array_size
= (uint32_t*) q
;
3649 } else if (c
->item_size
<= 0) {
3651 /* gvariant: empty array */
3656 } else if (bus_gvariant_is_fixed_size(contents
)) {
3658 /* gvariant: fixed length array */
3659 *item_size
= bus_gvariant_get_size(contents
);
3664 size_t where
, previous
= 0, framing
, sz
;
3668 /* gvariant: variable length array */
3669 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3671 where
= rindex
+ c
->item_size
- sz
;
3672 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3676 framing
= bus_gvariant_read_word_le(q
, sz
);
3677 if (framing
> c
->item_size
- sz
)
3679 if ((c
->item_size
- framing
) % sz
!= 0)
3682 *n_offsets
= (c
->item_size
- framing
) / sz
;
3684 where
= rindex
+ framing
;
3685 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3689 *offsets
= new(size_t, *n_offsets
);
3693 alignment
= bus_gvariant_get_alignment(c
->signature
);
3694 assert(alignment
> 0);
3696 for (i
= 0; i
< *n_offsets
; i
++) {
3699 start
= ALIGN_TO(previous
, alignment
);
3701 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3702 if (x
> c
->item_size
- sz
)
3707 (*offsets
)[i
] = rindex
+ x
;
3711 *item_size
= (*offsets
)[0] - rindex
;
3716 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3717 c
->index
+= 1 + strlen(contents
);
3722 static int bus_message_enter_variant(
3724 struct bus_container
*c
,
3725 const char *contents
,
3726 size_t *item_size
) {
3738 if (!signature_is_single(contents
, false))
3741 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3744 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3747 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3752 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3755 k
= strlen(contents
);
3756 if (1+k
> c
->item_size
)
3759 where
= rindex
+ c
->item_size
- (1+k
);
3760 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3764 if (*(char*) q
!= 0)
3767 if (memcmp((uint8_t*) q
+1, contents
, k
))
3770 *item_size
= c
->item_size
- (1+k
);
3773 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3779 /* avoid overflow right below */
3782 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3786 if (!validate_signature(q
, l
))
3789 if (!streq(q
, contents
))
3795 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3801 static int build_struct_offsets(
3803 const char *signature
,
3807 size_t *n_offsets
) {
3809 unsigned n_variable
= 0, n_total
= 0, v
;
3810 size_t previous
, where
;
3821 if (isempty(signature
)) {
3822 /* Unary type is encoded as *fixed* 1 byte padding */
3823 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3827 if (*(uint8_t *) q
!= 0)
3836 sz
= bus_gvariant_determine_word_size(size
, 0);
3840 /* First, loop over signature and count variable elements and
3841 * elements in general. We use this to know how large the
3842 * offset array is at the end of the structure. Note that
3843 * GVariant only stores offsets for all variable size elements
3844 * that are not the last item. */
3850 r
= signature_element_length(p
, &n
);
3859 r
= bus_gvariant_is_fixed_size(t
);
3864 if (r
== 0 && p
[n
] != 0) /* except the last item */
3871 if (size
< n_variable
* sz
)
3874 where
= m
->rindex
+ size
- (n_variable
* sz
);
3875 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3881 *offsets
= new(size_t, n_total
);
3887 /* Second, loop again and build an offset table */
3889 previous
= m
->rindex
;
3894 r
= signature_element_length(p
, &n
);
3903 size_t align
= bus_gvariant_get_alignment(t
);
3906 /* The possible start of this member after including alignment */
3907 size_t start
= ALIGN_TO(previous
, align
);
3909 k
= bus_gvariant_get_size(t
);
3917 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3921 /* The last item's end is determined
3922 * from the start of the offset array */
3923 x
= size
- (n_variable
* sz
);
3925 offset
= m
->rindex
+ x
;
3927 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG
),
3928 "For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu",
3938 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3943 assert(*n_offsets
== n_total
);
3945 *item_size
= (*offsets
)[0] - m
->rindex
;
3949 static int enter_struct_or_dict_entry(
3951 struct bus_container
*c
,
3952 const char *contents
,
3955 size_t *n_offsets
) {
3966 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3969 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3974 /* gvariant with contents */
3975 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3980 static int bus_message_enter_struct(
3982 struct bus_container
*c
,
3983 const char *contents
,
3986 size_t *n_offsets
) {
3998 if (!signature_is_valid(contents
, false))
4001 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4004 l
= strlen(contents
);
4006 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
4007 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4008 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
4011 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4015 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4016 c
->index
+= 1 + l
+ 1;
4021 static int bus_message_enter_dict_entry(
4023 struct bus_container
*c
,
4024 const char *contents
,
4027 size_t *n_offsets
) {
4036 if (!signature_is_pair(contents
))
4039 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4042 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4045 l
= strlen(contents
);
4047 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
4048 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4049 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
4052 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4056 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4057 c
->index
+= 1 + l
+ 1;
4062 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
4064 const char *contents
) {
4065 struct bus_container
*c
;
4066 uint32_t *array_size
= NULL
;
4067 _cleanup_free_
char *signature
= NULL
;
4069 _cleanup_free_
size_t *offsets
= NULL
;
4070 size_t n_offsets
= 0, item_size
= 0;
4073 assert_return(m
, -EINVAL
);
4074 assert_return(m
->sealed
, -EPERM
);
4075 assert_return(type
!= 0 || !contents
, -EINVAL
);
4077 if (type
== 0 || !contents
) {
4081 /* Allow entering into anonymous containers */
4082 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
4086 if (type
!= 0 && type
!= tt
)
4089 if (contents
&& !streq(contents
, cc
))
4097 * We enforce a global limit on container depth, that is much
4098 * higher than the 32 structs and 32 arrays the specification
4099 * mandates. This is simpler to implement for us, and we need
4100 * this only to ensure our container array doesn't grow
4101 * without bounds. We are happy to return any data from a
4102 * message as long as the data itself is valid, even if the
4103 * overall message might be not.
4105 * Note that the message signature is validated when
4106 * parsing the headers, and that validation does check the
4109 * Note that the specification defines no limits on the depth
4110 * of stacked variants, but we do.
4112 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4115 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4118 if (message_end_of_signature(m
))
4121 if (message_end_of_array(m
, m
->rindex
))
4124 c
= message_get_last_container(m
);
4126 signature
= strdup(contents
);
4130 c
->saved_index
= c
->index
;
4133 if (type
== SD_BUS_TYPE_ARRAY
)
4134 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4135 else if (type
== SD_BUS_TYPE_VARIANT
)
4136 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4137 else if (type
== SD_BUS_TYPE_STRUCT
)
4138 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4139 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4140 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4146 /* OK, let's fill it in */
4147 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4148 type
== SD_BUS_TYPE_STRUCT
&&
4150 end
= m
->rindex
+ 0;
4152 end
= m
->rindex
+ c
->item_size
;
4154 m
->containers
[m
->n_containers
++] = (struct bus_container
) {
4156 .signature
= TAKE_PTR(signature
),
4160 /* Unary type has fixed size of 1, but virtual size of 0 */
4162 .array_size
= array_size
,
4163 .item_size
= item_size
,
4164 .offsets
= TAKE_PTR(offsets
),
4165 .n_offsets
= n_offsets
,
4171 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4172 struct bus_container
*c
;
4176 assert_return(m
, -EINVAL
);
4177 assert_return(m
->sealed
, -EPERM
);
4178 assert_return(m
->n_containers
> 0, -ENXIO
);
4180 c
= message_get_last_container(m
);
4182 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4183 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4187 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4188 if (m
->rindex
< c
->end
)
4191 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4194 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4195 if (c
->begin
+ l
!= m
->rindex
)
4199 message_free_last_container(m
);
4201 c
= message_get_last_container(m
);
4203 c
->index
= c
->saved_index
;
4204 r
= container_next_item(m
, c
, &m
->rindex
);
4212 static void message_quit_container(sd_bus_message
*m
) {
4213 struct bus_container
*c
;
4217 assert(m
->n_containers
> 0);
4220 c
= message_get_last_container(m
);
4221 assert(m
->rindex
>= c
->before
);
4222 m
->rindex
= c
->before
;
4224 /* Free container */
4225 message_free_last_container(m
);
4227 /* Correct index of new top-level container */
4228 c
= message_get_last_container(m
);
4229 c
->index
= c
->saved_index
;
4232 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4233 struct bus_container
*c
;
4236 assert_return(m
, -EINVAL
);
4237 assert_return(m
->sealed
, -EPERM
);
4239 if (message_end_of_signature(m
))
4242 if (message_end_of_array(m
, m
->rindex
))
4245 c
= message_get_last_container(m
);
4247 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4251 *type
= c
->signature
[c
->index
];
4255 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4260 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4264 /* signature_element_length does verification internally */
4266 /* The array element must not be empty */
4268 if (free_and_strndup(&c
->peeked_signature
,
4269 c
->signature
+ c
->index
+ 1, l
) < 0)
4272 *contents
= c
->peeked_signature
;
4276 *type
= SD_BUS_TYPE_ARRAY
;
4281 if (IN_SET(c
->signature
[c
->index
], SD_BUS_TYPE_STRUCT_BEGIN
, SD_BUS_TYPE_DICT_ENTRY_BEGIN
)) {
4286 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4291 if (free_and_strndup(&c
->peeked_signature
,
4292 c
->signature
+ c
->index
+ 1, l
- 2) < 0)
4295 *contents
= c
->peeked_signature
;
4299 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4304 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4308 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4311 if (c
->item_size
< 2)
4314 /* Look for the NUL delimiter that
4315 separates the payload from the
4316 signature. Since the body might be
4317 in a different part that then the
4318 signature we map byte by byte. */
4320 for (k
= 2; k
<= c
->item_size
; k
++) {
4323 where
= m
->rindex
+ c
->item_size
- k
;
4324 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4328 if (*(char*) q
== 0)
4332 if (k
> c
->item_size
)
4335 if (free_and_strndup(&c
->peeked_signature
,
4336 (char*) q
+ 1, k
- 1) < 0)
4339 if (!signature_is_valid(c
->peeked_signature
, true))
4342 *contents
= c
->peeked_signature
;
4347 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4353 /* avoid overflow right below */
4356 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4360 if (!validate_signature(q
, l
))
4368 *type
= SD_BUS_TYPE_VARIANT
;
4383 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4384 struct bus_container
*c
;
4386 assert_return(m
, -EINVAL
);
4387 assert_return(m
->sealed
, -EPERM
);
4390 message_reset_containers(m
);
4393 c
= message_get_last_container(m
);
4395 c
= message_get_last_container(m
);
4398 m
->rindex
= c
->begin
;
4401 c
->offset_index
= 0;
4402 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4404 return !isempty(c
->signature
);
4407 _public_
int sd_bus_message_readv(
4412 unsigned n_array
, n_struct
;
4413 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4414 unsigned stack_ptr
= 0;
4415 unsigned n_loop
= 0;
4418 assert_return(m
, -EINVAL
);
4419 assert_return(m
->sealed
, -EPERM
);
4420 assert_return(types
, -EINVAL
);
4425 /* Ideally, we'd just call ourselves recursively on every
4426 * complex type. However, the state of a va_list that is
4427 * passed to a function is undefined after that function
4428 * returns. This means we need to decode the va_list linearly
4429 * in a single stackframe. We hence implement our own
4430 * home-grown stack in an array. */
4432 n_array
= (unsigned) -1; /* length of current array entries */
4433 n_struct
= strlen(types
); /* length of current struct contents signature */
4440 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4441 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4447 r
= sd_bus_message_exit_container(m
);
4455 if (n_array
!= (unsigned) -1)
4464 case SD_BUS_TYPE_BYTE
:
4465 case SD_BUS_TYPE_BOOLEAN
:
4466 case SD_BUS_TYPE_INT16
:
4467 case SD_BUS_TYPE_UINT16
:
4468 case SD_BUS_TYPE_INT32
:
4469 case SD_BUS_TYPE_UINT32
:
4470 case SD_BUS_TYPE_INT64
:
4471 case SD_BUS_TYPE_UINT64
:
4472 case SD_BUS_TYPE_DOUBLE
:
4473 case SD_BUS_TYPE_STRING
:
4474 case SD_BUS_TYPE_OBJECT_PATH
:
4475 case SD_BUS_TYPE_SIGNATURE
:
4476 case SD_BUS_TYPE_UNIX_FD
: {
4479 p
= va_arg(ap
, void*);
4480 r
= sd_bus_message_read_basic(m
, *t
, p
);
4493 case SD_BUS_TYPE_ARRAY
: {
4496 r
= signature_element_length(t
+ 1, &k
);
4502 memcpy(s
, t
+ 1, k
);
4505 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4516 if (n_array
== (unsigned) -1) {
4521 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4527 n_array
= va_arg(ap
, unsigned);
4532 case SD_BUS_TYPE_VARIANT
: {
4535 s
= va_arg(ap
, const char *);
4539 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4549 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4554 n_struct
= strlen(s
);
4555 n_array
= (unsigned) -1;
4560 case SD_BUS_TYPE_STRUCT_BEGIN
:
4561 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4564 r
= signature_element_length(t
, &k
);
4570 memcpy(s
, t
+ 1, k
- 2);
4573 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4583 if (n_array
== (unsigned) -1) {
4588 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4594 n_array
= (unsigned) -1;
4607 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4611 va_start(ap
, types
);
4612 r
= sd_bus_message_readv(m
, types
, ap
);
4618 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4621 assert_return(m
, -EINVAL
);
4622 assert_return(m
->sealed
, -EPERM
);
4624 /* If types is NULL, read exactly one element */
4626 struct bus_container
*c
;
4629 if (message_end_of_signature(m
))
4632 if (message_end_of_array(m
, m
->rindex
))
4635 c
= message_get_last_container(m
);
4637 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4641 types
= strndupa(c
->signature
+ c
->index
, l
);
4646 case 0: /* Nothing to drop */
4649 case SD_BUS_TYPE_BYTE
:
4650 case SD_BUS_TYPE_BOOLEAN
:
4651 case SD_BUS_TYPE_INT16
:
4652 case SD_BUS_TYPE_UINT16
:
4653 case SD_BUS_TYPE_INT32
:
4654 case SD_BUS_TYPE_UINT32
:
4655 case SD_BUS_TYPE_INT64
:
4656 case SD_BUS_TYPE_UINT64
:
4657 case SD_BUS_TYPE_DOUBLE
:
4658 case SD_BUS_TYPE_STRING
:
4659 case SD_BUS_TYPE_OBJECT_PATH
:
4660 case SD_BUS_TYPE_SIGNATURE
:
4661 case SD_BUS_TYPE_UNIX_FD
:
4663 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4667 r
= sd_bus_message_skip(m
, types
+ 1);
4673 case SD_BUS_TYPE_ARRAY
: {
4676 r
= signature_element_length(types
+ 1, &k
);
4682 memcpy(s
, types
+1, k
);
4685 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4690 r
= sd_bus_message_skip(m
, s
);
4697 r
= sd_bus_message_exit_container(m
);
4702 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4709 case SD_BUS_TYPE_VARIANT
: {
4710 const char *contents
;
4713 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4717 if (x
!= SD_BUS_TYPE_VARIANT
)
4720 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4724 r
= sd_bus_message_skip(m
, contents
);
4729 r
= sd_bus_message_exit_container(m
);
4733 r
= sd_bus_message_skip(m
, types
+ 1);
4740 case SD_BUS_TYPE_STRUCT_BEGIN
:
4741 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4744 r
= signature_element_length(types
, &k
);
4750 memcpy(s
, types
+1, k
-2);
4753 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4757 r
= sd_bus_message_skip(m
, s
);
4761 r
= sd_bus_message_exit_container(m
);
4766 r
= sd_bus_message_skip(m
, types
+ k
);
4778 _public_
int sd_bus_message_read_array(
4784 struct bus_container
*c
;
4790 assert_return(m
, -EINVAL
);
4791 assert_return(m
->sealed
, -EPERM
);
4792 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4793 assert_return(ptr
, -EINVAL
);
4794 assert_return(size
, -EINVAL
);
4795 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4797 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4806 c
= message_get_last_container(m
);
4808 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4809 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4813 sz
= c
->end
- c
->begin
;
4815 align
= bus_type_get_alignment(type
);
4819 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4823 /* Zero length array, let's return some aligned
4824 * pointer that is not NULL */
4825 p
= (uint8_t*) align
;
4827 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4832 r
= sd_bus_message_exit_container(m
);
4836 *ptr
= (const void*) p
;
4842 message_quit_container(m
);
4846 static int message_peek_fields(
4857 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4860 static int message_peek_field_uint32(
4872 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4875 /* identical for gvariant and dbus1 */
4877 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4882 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4887 static int message_peek_field_uint64(
4899 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4902 /* identical for gvariant and dbus1 */
4904 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4909 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4914 static int message_peek_field_string(
4916 bool (*validate
)(const char *p
),
4928 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4933 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4939 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4943 if (l
== UINT32_MAX
)
4944 /* avoid overflow right below */
4947 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4953 if (!validate_nul(q
, l
))
4959 if (!validate_string(q
, l
))
4969 static int message_peek_field_signature(
4982 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4987 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4993 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
4999 /* avoid overflow right below */
5002 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
5007 if (!validate_signature(q
, l
))
5016 static int message_skip_fields(
5019 uint32_t array_size
,
5020 const char **signature
) {
5022 size_t original_index
;
5028 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
5030 original_index
= *ri
;
5036 if (array_size
!= (uint32_t) -1 &&
5037 array_size
<= *ri
- original_index
)
5044 if (t
== SD_BUS_TYPE_STRING
) {
5046 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
5052 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
5054 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
5060 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
5062 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
5068 } else if (bus_type_is_basic(t
)) {
5071 align
= bus_type_get_alignment(t
);
5072 k
= bus_type_get_size(t
);
5073 assert(align
> 0 && k
> 0);
5075 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
5081 } else if (t
== SD_BUS_TYPE_ARRAY
) {
5083 r
= signature_element_length(*signature
+ 1, &l
);
5089 char sig
[l
+ 1], *s
= sig
;
5093 strncpy(sig
, *signature
+ 1, l
);
5096 alignment
= bus_type_get_alignment(sig
[0]);
5100 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5103 if (nas
> BUS_ARRAY_MAX_SIZE
)
5106 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5110 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5115 (*signature
) += 1 + l
;
5117 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5120 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5124 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5130 } else if (IN_SET(t
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
5132 r
= signature_element_length(*signature
, &l
);
5138 char sig
[l
+ 1], *s
= sig
;
5139 strncpy(sig
, *signature
+ 1, l
);
5142 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5153 int bus_message_parse_fields(sd_bus_message
*m
) {
5156 uint32_t unix_fds
= 0;
5157 bool unix_fds_set
= false;
5158 void *offsets
= NULL
;
5159 unsigned n_offsets
= 0;
5165 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5168 /* Read the signature from the end of the body variant first */
5169 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5170 if (m
->footer_accessible
< 1 + sz
)
5173 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5175 if (p
< (char*) m
->footer
)
5179 _cleanup_free_
char *k
= NULL
;
5182 /* We found the beginning of the signature
5183 * string, yay! We require the body to be a
5184 * structure, so verify it and then strip the
5185 * opening/closing brackets. */
5187 l
= (char*) m
->footer
+ m
->footer_accessible
- p
- (1 + sz
);
5189 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5190 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5193 k
= memdup_suffix0(p
+ 1 + 1, l
- 2);
5197 if (!signature_is_valid(k
, true))
5200 free_and_replace(m
->root_container
.signature
, k
);
5207 /* Calculate the actual user body size, by removing
5208 * the trailing variant signature and struct offset
5210 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5212 /* Pull out the offset table for the fields array, if any */
5213 if (m
->fields_size
> 0) {
5214 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5219 if (m
->fields_size
< sz
)
5222 ri
= m
->fields_size
- sz
;
5223 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5227 framing
= bus_gvariant_read_word_le(q
, sz
);
5228 if (framing
>= m
->fields_size
- sz
)
5230 if ((m
->fields_size
- framing
) % sz
!= 0)
5234 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5238 n_offsets
= (m
->fields_size
- framing
) / sz
;
5242 m
->user_body_size
= m
->body_size
;
5245 while (ri
< m
->fields_size
) {
5246 _cleanup_free_
char *sig
= NULL
;
5247 const char *signature
;
5248 uint64_t field_type
;
5249 size_t item_size
= (size_t) -1;
5251 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5260 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5262 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5266 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5270 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5277 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5282 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5287 where
= ri
= ALIGN_TO(ri
, 8);
5288 item_size
= end
- ri
;
5289 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5293 b
= memrchr(q
, 0, item_size
);
5297 sig
= memdup_suffix0(b
+1, item_size
- (b
+1-(char*) q
));
5302 item_size
= b
- (char*) q
;
5304 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5309 switch (field_type
) {
5311 case _BUS_MESSAGE_HEADER_INVALID
:
5314 case BUS_MESSAGE_HEADER_PATH
:
5319 if (!streq(signature
, "o"))
5322 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5325 case BUS_MESSAGE_HEADER_INTERFACE
:
5330 if (!streq(signature
, "s"))
5333 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5336 case BUS_MESSAGE_HEADER_MEMBER
:
5341 if (!streq(signature
, "s"))
5344 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5347 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5352 if (!streq(signature
, "s"))
5355 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5357 m
->error
._need_free
= -1;
5361 case BUS_MESSAGE_HEADER_DESTINATION
:
5366 if (!streq(signature
, "s"))
5369 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5372 case BUS_MESSAGE_HEADER_SENDER
:
5377 if (!streq(signature
, "s"))
5380 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5382 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
) {
5383 m
->creds
.unique_name
= (char*) m
->sender
;
5384 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5389 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5393 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5396 if (m
->root_container
.signature
)
5399 if (!streq(signature
, "g"))
5402 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5410 free_and_replace(m
->root_container
.signature
, c
);
5414 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5416 if (m
->reply_cookie
!= 0)
5419 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5420 /* 64bit on dbus2 */
5422 if (!streq(signature
, "t"))
5425 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5429 /* 32bit on dbus1 */
5432 if (!streq(signature
, "u"))
5435 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5439 m
->reply_cookie
= serial
;
5442 if (m
->reply_cookie
== 0)
5447 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5451 if (!streq(signature
, "u"))
5454 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5458 unix_fds_set
= true;
5462 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5463 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5472 if (m
->n_fds
!= unix_fds
)
5475 switch (m
->header
->type
) {
5477 case SD_BUS_MESSAGE_SIGNAL
:
5478 if (!m
->path
|| !m
->interface
|| !m
->member
)
5481 if (m
->reply_cookie
!= 0)
5486 case SD_BUS_MESSAGE_METHOD_CALL
:
5488 if (!m
->path
|| !m
->member
)
5491 if (m
->reply_cookie
!= 0)
5496 case SD_BUS_MESSAGE_METHOD_RETURN
:
5498 if (m
->reply_cookie
== 0)
5502 case SD_BUS_MESSAGE_METHOD_ERROR
:
5504 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5509 /* Refuse non-local messages that claim they are local */
5510 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5512 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5514 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5517 m
->root_container
.end
= m
->user_body_size
;
5519 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5520 r
= build_struct_offsets(
5522 m
->root_container
.signature
,
5524 &m
->root_container
.item_size
,
5525 &m
->root_container
.offsets
,
5526 &m
->root_container
.n_offsets
);
5533 /* Try to read the error message, but if we can't it's a non-issue */
5534 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5535 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5540 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5541 assert_return(m
, -EINVAL
);
5542 assert_return(destination
, -EINVAL
);
5543 assert_return(service_name_is_valid(destination
), -EINVAL
);
5544 assert_return(!m
->sealed
, -EPERM
);
5545 assert_return(!m
->destination
, -EEXIST
);
5547 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5550 _public_
int sd_bus_message_set_sender(sd_bus_message
*m
, const char *sender
) {
5551 assert_return(m
, -EINVAL
);
5552 assert_return(sender
, -EINVAL
);
5553 assert_return(service_name_is_valid(sender
), -EINVAL
);
5554 assert_return(!m
->sealed
, -EPERM
);
5555 assert_return(!m
->sender
, -EEXIST
);
5557 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5560 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5564 struct bus_body_part
*part
;
5570 total
= BUS_MESSAGE_SIZE(m
);
5576 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5577 MESSAGE_FOREACH_PART(part
, i
, m
)
5578 e
= mempcpy(e
, part
->data
, part
->size
);
5580 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5588 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5595 r
= sd_bus_message_enter_container(m
, 'a', "s");
5599 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5600 r
= strv_extend(l
, s
);
5607 r
= sd_bus_message_exit_container(m
);
5614 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5615 _cleanup_strv_free_
char **strv
= NULL
;
5618 assert_return(m
, -EINVAL
);
5619 assert_return(m
->sealed
, -EPERM
);
5620 assert_return(l
, -EINVAL
);
5622 r
= bus_message_read_strv_extend(m
, &strv
);
5626 *l
= TAKE_PTR(strv
);
5630 static int bus_message_get_arg_skip(
5634 const char **_contents
) {
5639 r
= sd_bus_message_rewind(m
, true);
5644 const char *contents
;
5647 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5653 /* Don't match against arguments after the first one we don't understand */
5654 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5655 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5660 *_contents
= contents
;
5666 r
= sd_bus_message_skip(m
, NULL
);
5673 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5680 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5684 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5687 return sd_bus_message_read_basic(m
, type
, str
);
5690 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5691 const char *contents
;
5698 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5702 if (type
!= SD_BUS_TYPE_ARRAY
)
5704 if (!STR_IN_SET(contents
, "s", "o", "g"))
5707 return sd_bus_message_read_strv(m
, strv
);
5710 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5711 assert_return(m
, EINVAL
);
5713 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5716 return sd_bus_error_get_errno(&m
->error
);
5719 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5720 struct bus_container
*c
;
5722 assert_return(m
, NULL
);
5724 c
= complete
? &m
->root_container
: message_get_last_container(m
);
5725 return strempty(c
->signature
);
5728 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5729 assert_return(m
, -EINVAL
);
5731 return isempty(m
->root_container
.signature
);
5734 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5735 assert_return(m
, -EINVAL
);
5737 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5740 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5741 bool done_something
= false;
5744 assert_return(m
, -EINVAL
);
5745 assert_return(source
, -EINVAL
);
5746 assert_return(!m
->sealed
, -EPERM
);
5747 assert_return(source
->sealed
, -EPERM
);
5750 const char *contents
;
5765 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5771 done_something
= true;
5773 if (bus_type_is_container(type
) > 0) {
5775 r
= sd_bus_message_enter_container(source
, type
, contents
);
5779 r
= sd_bus_message_open_container(m
, type
, contents
);
5783 r
= sd_bus_message_copy(m
, source
, true);
5787 r
= sd_bus_message_close_container(m
);
5791 r
= sd_bus_message_exit_container(source
);
5798 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5804 if (IN_SET(type
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
, SD_BUS_TYPE_STRING
))
5805 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5807 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5814 return done_something
;
5817 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5822 assert_return(m
, -EINVAL
);
5823 assert_return(m
->sealed
, -EPERM
);
5824 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5825 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5826 assert_return(type
|| contents
, -EINVAL
);
5827 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5829 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5833 if (type
!= 0 && type
!= t
)
5836 if (contents
&& !streq_ptr(contents
, c
))
5842 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5843 assert_return(m
, NULL
);
5848 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5849 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
5857 switch ((*m
)->header
->type
) {
5859 case SD_BUS_MESSAGE_SIGNAL
:
5860 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5866 case SD_BUS_MESSAGE_METHOD_CALL
:
5867 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5873 case SD_BUS_MESSAGE_METHOD_RETURN
:
5874 case SD_BUS_MESSAGE_METHOD_ERROR
:
5876 r
= sd_bus_message_new(bus
, &n
, (*m
)->header
->type
);
5882 n
->reply_cookie
= (*m
)->reply_cookie
;
5884 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5888 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5889 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5893 n
->error
._need_free
= -1;
5902 if ((*m
)->destination
&& !n
->destination
) {
5903 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5908 if ((*m
)->sender
&& !n
->sender
) {
5909 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5914 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5916 r
= sd_bus_message_copy(n
, *m
, true);
5920 timeout
= (*m
)->timeout
;
5921 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
)) {
5922 r
= sd_bus_get_method_call_timeout(bus
, &timeout
);
5927 r
= sd_bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5931 sd_bus_message_unref(*m
);
5937 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5938 static bool warned
= false;
5940 assert_return(m
, -EINVAL
);
5941 assert_return(priority
, -EINVAL
);
5944 log_debug("sd_bus_message_get_priority() is deprecated and always returns 0.");
5952 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5953 static bool warned
= false;
5955 assert_return(m
, -EINVAL
);
5956 assert_return(!m
->sealed
, -EPERM
);
5959 log_debug("sd_bus_message_set_priority() is deprecated and does nothing.");
5966 _public_
int sd_bus_message_sensitive(sd_bus_message
*m
) {
5967 assert_return(m
, -EINVAL
);
5969 m
->sensitive
= true;