1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
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
));
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
));
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
);
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
));
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
));
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
));
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
);
3197 if (c
->offset_index
+1 >= c
->n_offsets
)
3200 /* Variable-size array */
3202 alignment
= bus_gvariant_get_alignment(c
->signature
);
3203 assert(alignment
> 0);
3205 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3206 assert(c
->offsets
[c
->offset_index
+1] >= *rindex
);
3207 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3210 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3213 /* Fixed-size array */
3214 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3220 } else if (IN_SET(c
->enclosing
, 0, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
3225 if (c
->offset_index
+1 >= c
->n_offsets
)
3228 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3232 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3237 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3240 alignment
= bus_gvariant_get_alignment(t
);
3243 assert(alignment
> 0);
3245 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3246 assert(c
->offsets
[c
->offset_index
+1] >= *rindex
);
3247 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3251 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3254 assert_not_reached("Unknown container type");
3259 /* Reached the end */
3265 static int message_peek_body(
3272 size_t k
, start
, end
, padding
;
3273 struct bus_body_part
*part
;
3280 start
= ALIGN_TO((size_t) *rindex
, align
);
3281 padding
= start
- *rindex
;
3282 end
= start
+ nbytes
;
3284 if (end
> m
->user_body_size
)
3287 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3292 /* Verify padding */
3293 for (k
= 0; k
< padding
; k
++)
3298 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3299 if (!part
|| (nbytes
> 0 && !q
))
3310 static bool validate_nul(const char *s
, size_t l
) {
3312 /* Check for NUL chars in the string */
3313 if (memchr(s
, 0, l
))
3316 /* Check for NUL termination */
3323 static bool validate_string(const char *s
, size_t l
) {
3325 if (!validate_nul(s
, l
))
3328 /* Check if valid UTF8 */
3329 if (!utf8_is_valid(s
))
3335 static bool validate_signature(const char *s
, size_t l
) {
3337 if (!validate_nul(s
, l
))
3340 /* Check if valid signature */
3341 if (!signature_is_valid(s
, true))
3347 static bool validate_object_path(const char *s
, size_t l
) {
3349 if (!validate_nul(s
, l
))
3352 if (!object_path_is_valid(s
))
3358 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3359 struct bus_container
*c
;
3364 assert_return(m
, -EINVAL
);
3365 assert_return(m
->sealed
, -EPERM
);
3366 assert_return(bus_type_is_basic(type
), -EINVAL
);
3368 if (message_end_of_signature(m
))
3371 if (message_end_of_array(m
, m
->rindex
))
3374 c
= message_get_last_container(m
);
3375 if (c
->signature
[c
->index
] != type
)
3380 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3382 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3385 /* D-Bus spec: The marshalling formats for the string-like types all end
3386 * with a single zero (NUL) byte, but that byte is not considered to be part
3388 if (c
->item_size
== 0)
3391 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3395 if (type
== SD_BUS_TYPE_STRING
)
3396 ok
= validate_string(q
, c
->item_size
-1);
3397 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3398 ok
= validate_object_path(q
, c
->item_size
-1);
3400 ok
= validate_signature(q
, c
->item_size
-1);
3406 *(const char**) p
= q
;
3410 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3412 if ((size_t) sz
!= c
->item_size
)
3415 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3418 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3424 case SD_BUS_TYPE_BYTE
:
3426 *(uint8_t*) p
= *(uint8_t*) q
;
3429 case SD_BUS_TYPE_BOOLEAN
:
3431 *(int*) p
= !!*(uint8_t*) q
;
3434 case SD_BUS_TYPE_INT16
:
3435 case SD_BUS_TYPE_UINT16
:
3437 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3440 case SD_BUS_TYPE_INT32
:
3441 case SD_BUS_TYPE_UINT32
:
3443 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3446 case SD_BUS_TYPE_INT64
:
3447 case SD_BUS_TYPE_UINT64
:
3448 case SD_BUS_TYPE_DOUBLE
:
3450 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3453 case SD_BUS_TYPE_UNIX_FD
: {
3456 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3461 *(int*) p
= m
->fds
[j
];
3467 assert_not_reached("unexpected type");
3471 r
= container_next_item(m
, c
, &rindex
);
3476 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3480 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3484 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3485 if (l
== UINT32_MAX
)
3486 /* avoid overflow right below */
3489 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3493 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3494 ok
= validate_object_path(q
, l
);
3496 ok
= validate_string(q
, l
);
3501 *(const char**) p
= q
;
3503 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3506 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3512 /* avoid overflow right below */
3515 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3519 if (!validate_signature(q
, l
))
3523 *(const char**) p
= q
;
3528 align
= bus_type_get_alignment(type
);
3531 sz
= bus_type_get_size(type
);
3534 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3540 case SD_BUS_TYPE_BYTE
:
3542 *(uint8_t*) p
= *(uint8_t*) q
;
3545 case SD_BUS_TYPE_BOOLEAN
:
3547 *(int*) p
= !!*(uint32_t*) q
;
3550 case SD_BUS_TYPE_INT16
:
3551 case SD_BUS_TYPE_UINT16
:
3553 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3556 case SD_BUS_TYPE_INT32
:
3557 case SD_BUS_TYPE_UINT32
:
3559 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3562 case SD_BUS_TYPE_INT64
:
3563 case SD_BUS_TYPE_UINT64
:
3564 case SD_BUS_TYPE_DOUBLE
:
3566 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3569 case SD_BUS_TYPE_UNIX_FD
: {
3572 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3577 *(int*) p
= m
->fds
[j
];
3582 assert_not_reached("Unknown basic type...");
3589 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3595 static int bus_message_enter_array(
3597 struct bus_container
*c
,
3598 const char *contents
,
3599 uint32_t **array_size
,
3602 size_t *n_offsets
) {
3616 if (!signature_is_single(contents
, true))
3619 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3622 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3625 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3630 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3634 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3638 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3641 alignment
= bus_type_get_alignment(contents
[0]);
3645 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3649 *array_size
= (uint32_t*) q
;
3651 } else if (c
->item_size
<= 0) {
3653 /* gvariant: empty array */
3658 } else if (bus_gvariant_is_fixed_size(contents
)) {
3660 /* gvariant: fixed length array */
3661 *item_size
= bus_gvariant_get_size(contents
);
3666 size_t where
, previous
= 0, framing
, sz
;
3670 /* gvariant: variable length array */
3671 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3673 where
= rindex
+ c
->item_size
- sz
;
3674 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3678 framing
= bus_gvariant_read_word_le(q
, sz
);
3679 if (framing
> c
->item_size
- sz
)
3681 if ((c
->item_size
- framing
) % sz
!= 0)
3684 *n_offsets
= (c
->item_size
- framing
) / sz
;
3686 where
= rindex
+ framing
;
3687 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3691 *offsets
= new(size_t, *n_offsets
);
3695 alignment
= bus_gvariant_get_alignment(c
->signature
);
3696 assert(alignment
> 0);
3698 for (i
= 0; i
< *n_offsets
; i
++) {
3701 start
= ALIGN_TO(previous
, alignment
);
3703 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3704 if (x
> c
->item_size
- sz
)
3709 (*offsets
)[i
] = rindex
+ x
;
3713 *item_size
= (*offsets
)[0] - rindex
;
3718 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3719 c
->index
+= 1 + strlen(contents
);
3724 static int bus_message_enter_variant(
3726 struct bus_container
*c
,
3727 const char *contents
,
3728 size_t *item_size
) {
3740 if (!signature_is_single(contents
, false))
3743 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3746 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3749 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3754 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3757 k
= strlen(contents
);
3758 if (1+k
> c
->item_size
)
3761 where
= rindex
+ c
->item_size
- (1+k
);
3762 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3766 if (*(char*) q
!= 0)
3769 if (memcmp((uint8_t*) q
+1, contents
, k
))
3772 *item_size
= c
->item_size
- (1+k
);
3775 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3781 /* avoid overflow right below */
3784 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3788 if (!validate_signature(q
, l
))
3791 if (!streq(q
, contents
))
3797 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3803 static int build_struct_offsets(
3805 const char *signature
,
3809 size_t *n_offsets
) {
3811 unsigned n_variable
= 0, n_total
= 0, v
;
3812 size_t previous
, where
;
3823 if (isempty(signature
)) {
3824 /* Unary type is encoded as *fixed* 1 byte padding */
3825 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3829 if (*(uint8_t *) q
!= 0)
3838 sz
= bus_gvariant_determine_word_size(size
, 0);
3842 /* First, loop over signature and count variable elements and
3843 * elements in general. We use this to know how large the
3844 * offset array is at the end of the structure. Note that
3845 * GVariant only stores offsets for all variable size elements
3846 * that are not the last item. */
3852 r
= signature_element_length(p
, &n
);
3861 r
= bus_gvariant_is_fixed_size(t
);
3866 if (r
== 0 && p
[n
] != 0) /* except the last item */
3873 if (size
< n_variable
* sz
)
3876 where
= m
->rindex
+ size
- (n_variable
* sz
);
3877 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3883 *offsets
= new(size_t, n_total
);
3889 /* Second, loop again and build an offset table */
3891 previous
= m
->rindex
;
3896 r
= signature_element_length(p
, &n
);
3905 size_t align
= bus_gvariant_get_alignment(t
);
3908 /* The possible start of this member after including alignment */
3909 size_t start
= ALIGN_TO(previous
, align
);
3911 k
= bus_gvariant_get_size(t
);
3919 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3923 /* The last item's end is determined
3924 * from the start of the offset array */
3925 x
= size
- (n_variable
* sz
);
3927 offset
= m
->rindex
+ x
;
3929 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG
),
3930 "For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu",
3940 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3945 assert(*n_offsets
== n_total
);
3947 *item_size
= (*offsets
)[0] - m
->rindex
;
3951 static int enter_struct_or_dict_entry(
3953 struct bus_container
*c
,
3954 const char *contents
,
3957 size_t *n_offsets
) {
3968 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3971 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3976 /* gvariant with contents */
3977 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3982 static int bus_message_enter_struct(
3984 struct bus_container
*c
,
3985 const char *contents
,
3988 size_t *n_offsets
) {
4000 if (!signature_is_valid(contents
, false))
4003 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4006 l
= strlen(contents
);
4008 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
4009 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4010 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
4013 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4017 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4018 c
->index
+= 1 + l
+ 1;
4023 static int bus_message_enter_dict_entry(
4025 struct bus_container
*c
,
4026 const char *contents
,
4029 size_t *n_offsets
) {
4038 if (!signature_is_pair(contents
))
4041 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4044 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4047 l
= strlen(contents
);
4049 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
4050 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4051 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
4054 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4058 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4059 c
->index
+= 1 + l
+ 1;
4064 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
4066 const char *contents
) {
4067 struct bus_container
*c
;
4068 uint32_t *array_size
= NULL
;
4069 _cleanup_free_
char *signature
= NULL
;
4071 _cleanup_free_
size_t *offsets
= NULL
;
4072 size_t n_offsets
= 0, item_size
= 0;
4075 assert_return(m
, -EINVAL
);
4076 assert_return(m
->sealed
, -EPERM
);
4077 assert_return(type
!= 0 || !contents
, -EINVAL
);
4079 if (type
== 0 || !contents
) {
4083 /* Allow entering into anonymous containers */
4084 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
4088 if (type
!= 0 && type
!= tt
)
4091 if (contents
&& !streq(contents
, cc
))
4099 * We enforce a global limit on container depth, that is much
4100 * higher than the 32 structs and 32 arrays the specification
4101 * mandates. This is simpler to implement for us, and we need
4102 * this only to ensure our container array doesn't grow
4103 * without bounds. We are happy to return any data from a
4104 * message as long as the data itself is valid, even if the
4105 * overall message might be not.
4107 * Note that the message signature is validated when
4108 * parsing the headers, and that validation does check the
4111 * Note that the specification defines no limits on the depth
4112 * of stacked variants, but we do.
4114 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4117 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4120 if (message_end_of_signature(m
))
4123 if (message_end_of_array(m
, m
->rindex
))
4126 c
= message_get_last_container(m
);
4128 signature
= strdup(contents
);
4132 c
->saved_index
= c
->index
;
4135 if (type
== SD_BUS_TYPE_ARRAY
)
4136 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4137 else if (type
== SD_BUS_TYPE_VARIANT
)
4138 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4139 else if (type
== SD_BUS_TYPE_STRUCT
)
4140 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4141 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4142 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4148 /* OK, let's fill it in */
4149 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4150 type
== SD_BUS_TYPE_STRUCT
&&
4152 end
= m
->rindex
+ 0;
4154 end
= m
->rindex
+ c
->item_size
;
4156 m
->containers
[m
->n_containers
++] = (struct bus_container
) {
4158 .signature
= TAKE_PTR(signature
),
4162 /* Unary type has fixed size of 1, but virtual size of 0 */
4164 .array_size
= array_size
,
4165 .item_size
= item_size
,
4166 .offsets
= TAKE_PTR(offsets
),
4167 .n_offsets
= n_offsets
,
4173 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4174 struct bus_container
*c
;
4178 assert_return(m
, -EINVAL
);
4179 assert_return(m
->sealed
, -EPERM
);
4180 assert_return(m
->n_containers
> 0, -ENXIO
);
4182 c
= message_get_last_container(m
);
4184 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4185 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4189 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4190 if (m
->rindex
< c
->end
)
4193 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4196 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4197 if (c
->begin
+ l
!= m
->rindex
)
4201 message_free_last_container(m
);
4203 c
= message_get_last_container(m
);
4205 c
->index
= c
->saved_index
;
4206 r
= container_next_item(m
, c
, &m
->rindex
);
4214 static void message_quit_container(sd_bus_message
*m
) {
4215 struct bus_container
*c
;
4219 assert(m
->n_containers
> 0);
4222 c
= message_get_last_container(m
);
4223 assert(m
->rindex
>= c
->before
);
4224 m
->rindex
= c
->before
;
4226 /* Free container */
4227 message_free_last_container(m
);
4229 /* Correct index of new top-level container */
4230 c
= message_get_last_container(m
);
4231 c
->index
= c
->saved_index
;
4234 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4235 struct bus_container
*c
;
4238 assert_return(m
, -EINVAL
);
4239 assert_return(m
->sealed
, -EPERM
);
4241 if (message_end_of_signature(m
))
4244 if (message_end_of_array(m
, m
->rindex
))
4247 c
= message_get_last_container(m
);
4249 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4253 *type
= c
->signature
[c
->index
];
4257 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4262 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4266 /* signature_element_length does verification internally */
4268 /* The array element must not be empty */
4270 if (free_and_strndup(&c
->peeked_signature
,
4271 c
->signature
+ c
->index
+ 1, l
) < 0)
4274 *contents
= c
->peeked_signature
;
4278 *type
= SD_BUS_TYPE_ARRAY
;
4283 if (IN_SET(c
->signature
[c
->index
], SD_BUS_TYPE_STRUCT_BEGIN
, SD_BUS_TYPE_DICT_ENTRY_BEGIN
)) {
4288 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4293 if (free_and_strndup(&c
->peeked_signature
,
4294 c
->signature
+ c
->index
+ 1, l
- 2) < 0)
4297 *contents
= c
->peeked_signature
;
4301 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4306 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4310 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4313 if (c
->item_size
< 2)
4316 /* Look for the NUL delimiter that
4317 separates the payload from the
4318 signature. Since the body might be
4319 in a different part that then the
4320 signature we map byte by byte. */
4322 for (k
= 2; k
<= c
->item_size
; k
++) {
4325 where
= m
->rindex
+ c
->item_size
- k
;
4326 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4330 if (*(char*) q
== 0)
4334 if (k
> c
->item_size
)
4337 if (free_and_strndup(&c
->peeked_signature
,
4338 (char*) q
+ 1, k
- 1) < 0)
4341 if (!signature_is_valid(c
->peeked_signature
, true))
4344 *contents
= c
->peeked_signature
;
4349 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4355 /* avoid overflow right below */
4358 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4362 if (!validate_signature(q
, l
))
4370 *type
= SD_BUS_TYPE_VARIANT
;
4385 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4386 struct bus_container
*c
;
4388 assert_return(m
, -EINVAL
);
4389 assert_return(m
->sealed
, -EPERM
);
4392 message_reset_containers(m
);
4395 c
= message_get_last_container(m
);
4397 c
= message_get_last_container(m
);
4400 m
->rindex
= c
->begin
;
4403 c
->offset_index
= 0;
4404 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4406 return !isempty(c
->signature
);
4409 _public_
int sd_bus_message_readv(
4414 unsigned n_array
, n_struct
;
4415 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4416 unsigned stack_ptr
= 0;
4417 unsigned n_loop
= 0;
4420 assert_return(m
, -EINVAL
);
4421 assert_return(m
->sealed
, -EPERM
);
4422 assert_return(types
, -EINVAL
);
4427 /* Ideally, we'd just call ourselves recursively on every
4428 * complex type. However, the state of a va_list that is
4429 * passed to a function is undefined after that function
4430 * returns. This means we need to decode the va_list linearly
4431 * in a single stackframe. We hence implement our own
4432 * home-grown stack in an array. */
4434 n_array
= (unsigned) -1; /* length of current array entries */
4435 n_struct
= strlen(types
); /* length of current struct contents signature */
4442 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4443 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4449 r
= sd_bus_message_exit_container(m
);
4457 if (n_array
!= (unsigned) -1)
4466 case SD_BUS_TYPE_BYTE
:
4467 case SD_BUS_TYPE_BOOLEAN
:
4468 case SD_BUS_TYPE_INT16
:
4469 case SD_BUS_TYPE_UINT16
:
4470 case SD_BUS_TYPE_INT32
:
4471 case SD_BUS_TYPE_UINT32
:
4472 case SD_BUS_TYPE_INT64
:
4473 case SD_BUS_TYPE_UINT64
:
4474 case SD_BUS_TYPE_DOUBLE
:
4475 case SD_BUS_TYPE_STRING
:
4476 case SD_BUS_TYPE_OBJECT_PATH
:
4477 case SD_BUS_TYPE_SIGNATURE
:
4478 case SD_BUS_TYPE_UNIX_FD
: {
4481 p
= va_arg(ap
, void*);
4482 r
= sd_bus_message_read_basic(m
, *t
, p
);
4495 case SD_BUS_TYPE_ARRAY
: {
4498 r
= signature_element_length(t
+ 1, &k
);
4504 memcpy(s
, t
+ 1, k
);
4507 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4518 if (n_array
== (unsigned) -1) {
4523 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4529 n_array
= va_arg(ap
, unsigned);
4534 case SD_BUS_TYPE_VARIANT
: {
4537 s
= va_arg(ap
, const char *);
4541 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4551 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4556 n_struct
= strlen(s
);
4557 n_array
= (unsigned) -1;
4562 case SD_BUS_TYPE_STRUCT_BEGIN
:
4563 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4566 r
= signature_element_length(t
, &k
);
4572 memcpy(s
, t
+ 1, k
- 2);
4575 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4585 if (n_array
== (unsigned) -1) {
4590 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4596 n_array
= (unsigned) -1;
4609 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4613 va_start(ap
, types
);
4614 r
= sd_bus_message_readv(m
, types
, ap
);
4620 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4623 assert_return(m
, -EINVAL
);
4624 assert_return(m
->sealed
, -EPERM
);
4626 /* If types is NULL, read exactly one element */
4628 struct bus_container
*c
;
4631 if (message_end_of_signature(m
))
4634 if (message_end_of_array(m
, m
->rindex
))
4637 c
= message_get_last_container(m
);
4639 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4643 types
= strndupa(c
->signature
+ c
->index
, l
);
4648 case 0: /* Nothing to drop */
4651 case SD_BUS_TYPE_BYTE
:
4652 case SD_BUS_TYPE_BOOLEAN
:
4653 case SD_BUS_TYPE_INT16
:
4654 case SD_BUS_TYPE_UINT16
:
4655 case SD_BUS_TYPE_INT32
:
4656 case SD_BUS_TYPE_UINT32
:
4657 case SD_BUS_TYPE_INT64
:
4658 case SD_BUS_TYPE_UINT64
:
4659 case SD_BUS_TYPE_DOUBLE
:
4660 case SD_BUS_TYPE_STRING
:
4661 case SD_BUS_TYPE_OBJECT_PATH
:
4662 case SD_BUS_TYPE_SIGNATURE
:
4663 case SD_BUS_TYPE_UNIX_FD
:
4665 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4669 r
= sd_bus_message_skip(m
, types
+ 1);
4675 case SD_BUS_TYPE_ARRAY
: {
4678 r
= signature_element_length(types
+ 1, &k
);
4684 memcpy(s
, types
+1, k
);
4687 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4692 r
= sd_bus_message_skip(m
, s
);
4699 r
= sd_bus_message_exit_container(m
);
4704 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4711 case SD_BUS_TYPE_VARIANT
: {
4712 const char *contents
;
4715 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4719 if (x
!= SD_BUS_TYPE_VARIANT
)
4722 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4726 r
= sd_bus_message_skip(m
, contents
);
4731 r
= sd_bus_message_exit_container(m
);
4735 r
= sd_bus_message_skip(m
, types
+ 1);
4742 case SD_BUS_TYPE_STRUCT_BEGIN
:
4743 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4746 r
= signature_element_length(types
, &k
);
4752 memcpy(s
, types
+1, k
-2);
4755 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4759 r
= sd_bus_message_skip(m
, s
);
4763 r
= sd_bus_message_exit_container(m
);
4768 r
= sd_bus_message_skip(m
, types
+ k
);
4780 _public_
int sd_bus_message_read_array(
4786 struct bus_container
*c
;
4792 assert_return(m
, -EINVAL
);
4793 assert_return(m
->sealed
, -EPERM
);
4794 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4795 assert_return(ptr
, -EINVAL
);
4796 assert_return(size
, -EINVAL
);
4797 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4799 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4808 c
= message_get_last_container(m
);
4810 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4811 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4815 sz
= c
->end
- c
->begin
;
4817 align
= bus_type_get_alignment(type
);
4821 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4825 /* Zero length array, let's return some aligned
4826 * pointer that is not NULL */
4827 p
= (uint8_t*) align
;
4829 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4834 r
= sd_bus_message_exit_container(m
);
4838 *ptr
= (const void*) p
;
4844 message_quit_container(m
);
4848 static int message_peek_fields(
4859 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4862 static int message_peek_field_uint32(
4874 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4877 /* identical for gvariant and dbus1 */
4879 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4884 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4889 static int message_peek_field_uint64(
4901 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4904 /* identical for gvariant and dbus1 */
4906 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4911 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4916 static int message_peek_field_string(
4918 bool (*validate
)(const char *p
),
4930 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4935 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4941 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4945 if (l
== UINT32_MAX
)
4946 /* avoid overflow right below */
4949 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4955 if (!validate_nul(q
, l
))
4961 if (!validate_string(q
, l
))
4971 static int message_peek_field_signature(
4984 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4989 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4995 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
5001 /* avoid overflow right below */
5004 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
5009 if (!validate_signature(q
, l
))
5018 static int message_skip_fields(
5021 uint32_t array_size
,
5022 const char **signature
) {
5024 size_t original_index
;
5030 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
5032 original_index
= *ri
;
5038 if (array_size
!= (uint32_t) -1 &&
5039 array_size
<= *ri
- original_index
)
5046 if (t
== SD_BUS_TYPE_STRING
) {
5048 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
5054 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
5056 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
5062 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
5064 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
5070 } else if (bus_type_is_basic(t
)) {
5073 align
= bus_type_get_alignment(t
);
5074 k
= bus_type_get_size(t
);
5075 assert(align
> 0 && k
> 0);
5077 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
5083 } else if (t
== SD_BUS_TYPE_ARRAY
) {
5085 r
= signature_element_length(*signature
+ 1, &l
);
5091 char sig
[l
+ 1], *s
= sig
;
5095 strncpy(sig
, *signature
+ 1, l
);
5098 alignment
= bus_type_get_alignment(sig
[0]);
5102 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5105 if (nas
> BUS_ARRAY_MAX_SIZE
)
5108 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5112 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5117 (*signature
) += 1 + l
;
5119 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5122 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5126 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5132 } else if (IN_SET(t
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
5134 r
= signature_element_length(*signature
, &l
);
5140 char sig
[l
+ 1], *s
= sig
;
5141 strncpy(sig
, *signature
+ 1, l
);
5144 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5155 int bus_message_parse_fields(sd_bus_message
*m
) {
5158 uint32_t unix_fds
= 0;
5159 bool unix_fds_set
= false;
5160 void *offsets
= NULL
;
5161 unsigned n_offsets
= 0;
5167 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5170 /* Read the signature from the end of the body variant first */
5171 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5172 if (m
->footer_accessible
< 1 + sz
)
5175 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5177 if (p
< (char*) m
->footer
)
5181 _cleanup_free_
char *k
= NULL
;
5184 /* We found the beginning of the signature
5185 * string, yay! We require the body to be a
5186 * structure, so verify it and then strip the
5187 * opening/closing brackets. */
5189 l
= (char*) m
->footer
+ m
->footer_accessible
- p
- (1 + sz
);
5191 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5192 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5195 k
= memdup_suffix0(p
+ 1 + 1, l
- 2);
5199 if (!signature_is_valid(k
, true))
5202 free_and_replace(m
->root_container
.signature
, k
);
5209 /* Calculate the actual user body size, by removing
5210 * the trailing variant signature and struct offset
5212 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5214 /* Pull out the offset table for the fields array, if any */
5215 if (m
->fields_size
> 0) {
5216 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5221 if (m
->fields_size
< sz
)
5224 ri
= m
->fields_size
- sz
;
5225 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5229 framing
= bus_gvariant_read_word_le(q
, sz
);
5230 if (framing
>= m
->fields_size
- sz
)
5232 if ((m
->fields_size
- framing
) % sz
!= 0)
5236 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5240 n_offsets
= (m
->fields_size
- framing
) / sz
;
5244 m
->user_body_size
= m
->body_size
;
5247 while (ri
< m
->fields_size
) {
5248 _cleanup_free_
char *sig
= NULL
;
5249 const char *signature
;
5250 uint64_t field_type
;
5251 size_t item_size
= (size_t) -1;
5253 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5262 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5264 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5268 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5272 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5279 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5284 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5289 where
= ri
= ALIGN_TO(ri
, 8);
5290 item_size
= end
- ri
;
5291 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5295 b
= memrchr(q
, 0, item_size
);
5299 sig
= memdup_suffix0(b
+1, item_size
- (b
+1-(char*) q
));
5304 item_size
= b
- (char*) q
;
5306 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5311 switch (field_type
) {
5313 case _BUS_MESSAGE_HEADER_INVALID
:
5316 case BUS_MESSAGE_HEADER_PATH
:
5321 if (!streq(signature
, "o"))
5324 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5327 case BUS_MESSAGE_HEADER_INTERFACE
:
5332 if (!streq(signature
, "s"))
5335 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5338 case BUS_MESSAGE_HEADER_MEMBER
:
5343 if (!streq(signature
, "s"))
5346 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5349 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5354 if (!streq(signature
, "s"))
5357 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5359 m
->error
._need_free
= -1;
5363 case BUS_MESSAGE_HEADER_DESTINATION
:
5368 if (!streq(signature
, "s"))
5371 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5374 case BUS_MESSAGE_HEADER_SENDER
:
5379 if (!streq(signature
, "s"))
5382 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5384 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
) {
5385 m
->creds
.unique_name
= (char*) m
->sender
;
5386 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5391 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5395 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5398 if (m
->root_container
.signature
)
5401 if (!streq(signature
, "g"))
5404 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5412 free_and_replace(m
->root_container
.signature
, c
);
5416 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5418 if (m
->reply_cookie
!= 0)
5421 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5422 /* 64bit on dbus2 */
5424 if (!streq(signature
, "t"))
5427 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5431 /* 32bit on dbus1 */
5434 if (!streq(signature
, "u"))
5437 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5441 m
->reply_cookie
= serial
;
5444 if (m
->reply_cookie
== 0)
5449 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5453 if (!streq(signature
, "u"))
5456 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5460 unix_fds_set
= true;
5464 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5465 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5474 if (m
->n_fds
!= unix_fds
)
5477 switch (m
->header
->type
) {
5479 case SD_BUS_MESSAGE_SIGNAL
:
5480 if (!m
->path
|| !m
->interface
|| !m
->member
)
5483 if (m
->reply_cookie
!= 0)
5488 case SD_BUS_MESSAGE_METHOD_CALL
:
5490 if (!m
->path
|| !m
->member
)
5493 if (m
->reply_cookie
!= 0)
5498 case SD_BUS_MESSAGE_METHOD_RETURN
:
5500 if (m
->reply_cookie
== 0)
5504 case SD_BUS_MESSAGE_METHOD_ERROR
:
5506 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5511 /* Refuse non-local messages that claim they are local */
5512 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5514 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5516 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5519 m
->root_container
.end
= m
->user_body_size
;
5521 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5522 r
= build_struct_offsets(
5524 m
->root_container
.signature
,
5526 &m
->root_container
.item_size
,
5527 &m
->root_container
.offsets
,
5528 &m
->root_container
.n_offsets
);
5535 /* Try to read the error message, but if we can't it's a non-issue */
5536 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5537 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5542 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5543 assert_return(m
, -EINVAL
);
5544 assert_return(destination
, -EINVAL
);
5545 assert_return(service_name_is_valid(destination
), -EINVAL
);
5546 assert_return(!m
->sealed
, -EPERM
);
5547 assert_return(!m
->destination
, -EEXIST
);
5549 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5552 _public_
int sd_bus_message_set_sender(sd_bus_message
*m
, const char *sender
) {
5553 assert_return(m
, -EINVAL
);
5554 assert_return(sender
, -EINVAL
);
5555 assert_return(service_name_is_valid(sender
), -EINVAL
);
5556 assert_return(!m
->sealed
, -EPERM
);
5557 assert_return(!m
->sender
, -EEXIST
);
5559 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5562 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5566 struct bus_body_part
*part
;
5572 total
= BUS_MESSAGE_SIZE(m
);
5578 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5579 MESSAGE_FOREACH_PART(part
, i
, m
)
5580 e
= mempcpy(e
, part
->data
, part
->size
);
5582 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5590 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5597 r
= sd_bus_message_enter_container(m
, 'a', "s");
5601 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5602 r
= strv_extend(l
, s
);
5609 r
= sd_bus_message_exit_container(m
);
5616 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5617 _cleanup_strv_free_
char **strv
= NULL
;
5620 assert_return(m
, -EINVAL
);
5621 assert_return(m
->sealed
, -EPERM
);
5622 assert_return(l
, -EINVAL
);
5624 r
= bus_message_read_strv_extend(m
, &strv
);
5628 *l
= TAKE_PTR(strv
);
5632 static int bus_message_get_arg_skip(
5636 const char **_contents
) {
5641 r
= sd_bus_message_rewind(m
, true);
5646 const char *contents
;
5649 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5655 /* Don't match against arguments after the first one we don't understand */
5656 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5657 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5662 *_contents
= contents
;
5668 r
= sd_bus_message_skip(m
, NULL
);
5675 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5682 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5686 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5689 return sd_bus_message_read_basic(m
, type
, str
);
5692 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5693 const char *contents
;
5700 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5704 if (type
!= SD_BUS_TYPE_ARRAY
)
5706 if (!STR_IN_SET(contents
, "s", "o", "g"))
5709 return sd_bus_message_read_strv(m
, strv
);
5712 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5713 assert_return(m
, EINVAL
);
5715 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5718 return sd_bus_error_get_errno(&m
->error
);
5721 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5722 struct bus_container
*c
;
5724 assert_return(m
, NULL
);
5726 c
= complete
? &m
->root_container
: message_get_last_container(m
);
5727 return strempty(c
->signature
);
5730 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5731 assert_return(m
, -EINVAL
);
5733 return isempty(m
->root_container
.signature
);
5736 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5737 assert_return(m
, -EINVAL
);
5739 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5742 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5743 bool done_something
= false;
5746 assert_return(m
, -EINVAL
);
5747 assert_return(source
, -EINVAL
);
5748 assert_return(!m
->sealed
, -EPERM
);
5749 assert_return(source
->sealed
, -EPERM
);
5752 const char *contents
;
5767 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5773 done_something
= true;
5775 if (bus_type_is_container(type
) > 0) {
5777 r
= sd_bus_message_enter_container(source
, type
, contents
);
5781 r
= sd_bus_message_open_container(m
, type
, contents
);
5785 r
= sd_bus_message_copy(m
, source
, true);
5789 r
= sd_bus_message_close_container(m
);
5793 r
= sd_bus_message_exit_container(source
);
5800 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5806 if (IN_SET(type
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
, SD_BUS_TYPE_STRING
))
5807 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5809 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5816 return done_something
;
5819 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5824 assert_return(m
, -EINVAL
);
5825 assert_return(m
->sealed
, -EPERM
);
5826 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5827 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5828 assert_return(type
|| contents
, -EINVAL
);
5829 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5831 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5835 if (type
!= 0 && type
!= t
)
5838 if (contents
&& !streq_ptr(contents
, c
))
5844 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5845 assert_return(m
, NULL
);
5850 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5851 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
5859 switch ((*m
)->header
->type
) {
5861 case SD_BUS_MESSAGE_SIGNAL
:
5862 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5868 case SD_BUS_MESSAGE_METHOD_CALL
:
5869 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5875 case SD_BUS_MESSAGE_METHOD_RETURN
:
5876 case SD_BUS_MESSAGE_METHOD_ERROR
:
5878 r
= sd_bus_message_new(bus
, &n
, (*m
)->header
->type
);
5884 n
->reply_cookie
= (*m
)->reply_cookie
;
5886 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5890 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5891 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5895 n
->error
._need_free
= -1;
5904 if ((*m
)->destination
&& !n
->destination
) {
5905 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5910 if ((*m
)->sender
&& !n
->sender
) {
5911 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5916 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5918 r
= sd_bus_message_copy(n
, *m
, true);
5922 timeout
= (*m
)->timeout
;
5923 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
)) {
5924 r
= sd_bus_get_method_call_timeout(bus
, &timeout
);
5929 r
= sd_bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5933 sd_bus_message_unref(*m
);
5939 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5940 static bool warned
= false;
5942 assert_return(m
, -EINVAL
);
5943 assert_return(priority
, -EINVAL
);
5946 log_debug("sd_bus_message_get_priority() is deprecated and always returns 0.");
5954 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5955 static bool warned
= false;
5957 assert_return(m
, -EINVAL
);
5958 assert_return(!m
->sealed
, -EPERM
);
5961 log_debug("sd_bus_message_set_priority() is deprecated and does nothing.");
5968 _public_
int sd_bus_message_sensitive(sd_bus_message
*m
) {
5969 assert_return(m
, -EINVAL
);
5971 m
->sensitive
= true;