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"
17 #include "memfd-util.h"
18 #include "memory-util.h"
19 #include "string-util.h"
21 #include "time-util.h"
24 static int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
);
26 static void *adjust_pointer(const void *p
, void *old_base
, size_t sz
, void *new_base
) {
31 if (old_base
== new_base
)
34 if ((uint8_t*) p
< (uint8_t*) old_base
)
37 if ((uint8_t*) p
>= (uint8_t*) old_base
+ sz
)
40 return (uint8_t*) new_base
+ ((uint8_t*) p
- (uint8_t*) old_base
);
43 static void message_free_part(sd_bus_message
*m
, struct bus_body_part
*part
) {
47 if (part
->memfd
>= 0) {
48 /* erase if requested, but only if the memfd is not sealed yet, i.e. is writable */
49 if (m
->sensitive
&& !m
->sealed
)
50 explicit_bzero_safe(part
->data
, part
->size
);
52 close_and_munmap(part
->memfd
, part
->mmap_begin
, part
->mapped
);
53 } else if (part
->munmap_this
)
54 /* We don't erase sensitive data here, since the data is memory mapped from someone else, and
55 * we just don't know if it's OK to write to it */
56 munmap(part
->mmap_begin
, part
->mapped
);
58 /* Erase this if that is requested. Since this is regular memory we know we can write it. */
60 explicit_bzero_safe(part
->data
, part
->size
);
70 static void message_reset_parts(sd_bus_message
*m
) {
71 struct bus_body_part
*part
;
76 while (m
->n_body_parts
> 0) {
77 struct bus_body_part
*next
= part
->next
;
78 message_free_part(m
, part
);
85 m
->cached_rindex_part
= NULL
;
86 m
->cached_rindex_part_begin
= 0;
89 static struct bus_container
*message_get_last_container(sd_bus_message
*m
) {
92 if (m
->n_containers
== 0)
93 return &m
->root_container
;
95 assert(m
->containers
);
96 return m
->containers
+ m
->n_containers
- 1;
99 static void message_free_last_container(sd_bus_message
*m
) {
100 struct bus_container
*c
;
102 c
= message_get_last_container(m
);
105 free(c
->peeked_signature
);
108 /* Move to previous container, but not if we are on root container */
109 if (m
->n_containers
> 0)
113 static void message_reset_containers(sd_bus_message
*m
) {
116 while (m
->n_containers
> 0)
117 message_free_last_container(m
);
119 m
->containers
= mfree(m
->containers
);
120 m
->root_container
.index
= 0;
123 static sd_bus_message
* message_free(sd_bus_message
*m
) {
126 message_reset_parts(m
);
131 /* Note that we don't unref m->bus here. That's already done by sd_bus_message_unref() as each user
132 * reference to the bus message also is considered a reference to the bus connection itself. */
135 close_many(m
->fds
, m
->n_fds
);
139 if (m
->iovec
!= m
->iovec_fixed
)
142 message_reset_containers(m
);
143 assert(m
->n_containers
== 0);
144 message_free_last_container(m
);
146 bus_creds_done(&m
->creds
);
150 static void *message_extend_fields(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
152 size_t old_size
, new_size
, start
;
159 old_size
= sizeof(struct bus_header
) + m
->fields_size
;
160 start
= ALIGN_TO(old_size
, align
);
161 new_size
= start
+ sz
;
163 if (new_size
< start
|| new_size
> UINT32_MAX
)
166 if (old_size
== new_size
)
167 return (uint8_t*) m
->header
+ old_size
;
169 if (m
->free_header
) {
170 np
= realloc(m
->header
, ALIGN8(new_size
));
174 /* Initially, the header is allocated as part of
175 * the sd_bus_message itself, let's replace it by
178 np
= malloc(ALIGN8(new_size
));
182 memcpy(np
, m
->header
, sizeof(struct bus_header
));
185 /* Zero out padding */
186 if (start
> old_size
)
187 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
191 m
->fields_size
= new_size
- sizeof(struct bus_header
);
193 /* Adjust quick access pointers */
194 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
195 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
196 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
197 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
198 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
199 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
201 m
->free_header
= true;
204 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
207 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
210 return (uint8_t*) np
+ start
;
217 static int message_append_field_string(
229 /* dbus1 only allows 8bit header field ids */
233 /* dbus1 doesn't allow strings over 32bit, let's enforce this
234 * globally, to not risk convertability */
239 /* Signature "(yv)" where the variant contains "s" */
241 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
243 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
244 p
= message_extend_fields(m
, 8, 8 + l
+ 1 + 1 + 1, true);
248 *((uint64_t*) p
) = h
;
255 *ret
= (char*) p
+ 8;
258 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
259 p
= message_extend_fields(m
, 8, 4 + 4 + l
+ 1, false);
268 ((uint32_t*) p
)[1] = l
;
269 memcpy(p
+ 8, s
, l
+ 1);
272 *ret
= (char*) p
+ 8;
278 static int message_append_field_signature(
289 /* dbus1 only allows 8bit header field ids */
293 /* dbus1 doesn't allow signatures over 8bit, let's enforce
294 * this globally, to not risk convertability */
296 if (l
> SD_BUS_MAXIMUM_SIGNATURE_LENGTH
)
299 /* Signature "(yv)" where the variant contains "g" */
301 if (BUS_MESSAGE_IS_GVARIANT(m
))
302 /* For gvariant the serialization is the same as for normal strings */
303 return message_append_field_string(m
, h
, 'g', s
, ret
);
305 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
306 p
= message_extend_fields(m
, 8, 4 + 1 + l
+ 1, false);
312 p
[2] = SD_BUS_TYPE_SIGNATURE
;
315 memcpy(p
+ 5, s
, l
+ 1);
318 *ret
= (const char*) p
+ 5;
324 static int message_append_field_uint32(sd_bus_message
*m
, uint64_t h
, uint32_t x
) {
329 /* dbus1 only allows 8bit header field ids */
333 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
334 /* (field id 64bit + ((value + NUL + signature string 'u') */
336 p
= message_extend_fields(m
, 8, 8 + 4 + 1 + 1, true);
340 *((uint64_t*) p
) = h
;
341 *((uint32_t*) (p
+ 8)) = x
;
345 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
346 p
= message_extend_fields(m
, 8, 4 + 4, false);
355 ((uint32_t*) p
)[1] = x
;
361 static int message_append_field_uint64(sd_bus_message
*m
, uint64_t h
, uint64_t x
) {
366 /* dbus1 only allows 8bit header field ids */
370 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
371 /* (field id 64bit + ((value + NUL + signature string 't') */
373 p
= message_extend_fields(m
, 8, 8 + 8 + 1 + 1, true);
377 *((uint64_t*) p
) = h
;
378 *((uint64_t*) (p
+ 8)) = x
;
382 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
383 p
= message_extend_fields(m
, 8, 4 + 4 + 8, false);
396 ((uint64_t*) p
)[1] = x
;
402 static int message_append_reply_cookie(sd_bus_message
*m
, uint64_t cookie
) {
405 if (BUS_MESSAGE_IS_GVARIANT(m
))
406 return message_append_field_uint64(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, cookie
);
408 /* 64bit cookies are not supported on dbus1 */
409 if (cookie
> 0xffffffffUL
)
412 return message_append_field_uint32(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) cookie
);
416 int bus_message_from_header(
419 size_t header_accessible
,
421 size_t footer_accessible
,
427 sd_bus_message
**ret
) {
429 _cleanup_free_ sd_bus_message
*m
= NULL
;
430 struct bus_header
*h
;
434 assert(header
|| header_accessible
<= 0);
435 assert(footer
|| footer_accessible
<= 0);
436 assert(fds
|| n_fds
<= 0);
439 if (header_accessible
< sizeof(struct bus_header
))
442 if (header_accessible
> message_size
)
444 if (footer_accessible
> message_size
)
448 if (!IN_SET(h
->version
, 1, 2))
451 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
454 if (!IN_SET(h
->endian
, BUS_LITTLE_ENDIAN
, BUS_BIG_ENDIAN
))
457 /* Note that we are happy with unknown flags in the flags header! */
459 a
= ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
462 label_sz
= strlen(label
);
472 m
->header_accessible
= header_accessible
;
474 m
->footer_accessible
= footer_accessible
;
476 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
479 if (h
->dbus2
.cookie
== 0)
482 /* dbus2 derives the sizes from the message size and
483 the offset table at the end, since it is formatted as
484 gvariant "yyyyuta{tv}v". Since the message itself is a
485 structure with precisely to variable sized entries,
486 there's only one offset in the table, which marks the
487 end of the fields array. */
489 ws
= bus_gvariant_determine_word_size(message_size
, 0);
490 if (footer_accessible
< ws
)
493 m
->fields_size
= bus_gvariant_read_word_le((uint8_t*) footer
+ footer_accessible
- ws
, ws
);
494 if (ALIGN8(m
->fields_size
) > message_size
- ws
)
496 if (m
->fields_size
< sizeof(struct bus_header
))
499 m
->fields_size
-= sizeof(struct bus_header
);
500 m
->body_size
= message_size
- (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
));
502 if (h
->dbus1
.serial
== 0)
505 /* dbus1 has the sizes in the header */
506 m
->fields_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.fields_size
);
507 m
->body_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.body_size
);
509 if (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
!= message_size
)
517 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
518 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
520 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
524 m
->bus
= sd_bus_ref(bus
);
531 int bus_message_from_malloc(
538 sd_bus_message
**ret
) {
540 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
544 r
= bus_message_from_header(
546 buffer
, length
, /* in this case the initial bytes and the final bytes are the same */
555 sz
= length
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
);
558 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(m
->fields_size
);
560 m
->body
.sealed
= true;
565 m
->iovec
= m
->iovec_fixed
;
566 m
->iovec
[0] = IOVEC_MAKE(buffer
, length
);
568 r
= bus_message_parse_fields(m
);
572 /* We take possession of the memory and fds now */
573 m
->free_header
= true;
580 _public_
int sd_bus_message_new(
585 assert_return(bus
, -ENOTCONN
);
586 assert_return(bus
= bus_resolve(bus
), -ENOPKG
);
587 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
588 assert_return(m
, -EINVAL
);
589 /* Creation of messages with _SD_BUS_MESSAGE_TYPE_INVALID is allowed. */
590 assert_return(type
< _SD_BUS_MESSAGE_TYPE_MAX
, -EINVAL
);
592 sd_bus_message
*t
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
597 t
->bus
= sd_bus_ref(bus
);
598 t
->header
= (struct bus_header
*) ((uint8_t*) t
+ ALIGN(sizeof(struct sd_bus_message
)));
599 t
->header
->endian
= BUS_NATIVE_ENDIAN
;
600 t
->header
->type
= type
;
601 t
->header
->version
= bus
->message_version
;
602 t
->allow_fds
= bus
->can_fds
|| !IN_SET(bus
->state
, BUS_HELLO
, BUS_RUNNING
);
603 t
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(t
);
605 if (bus
->allow_interactive_authorization
)
606 t
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
612 _public_
int sd_bus_message_new_signal(
616 const char *interface
,
617 const char *member
) {
619 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
622 assert_return(bus
, -ENOTCONN
);
623 assert_return(bus
= bus_resolve(bus
), -ENOPKG
);
624 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
625 assert_return(object_path_is_valid(path
), -EINVAL
);
626 assert_return(interface_name_is_valid(interface
), -EINVAL
);
627 assert_return(member_name_is_valid(member
), -EINVAL
);
628 assert_return(m
, -EINVAL
);
630 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_SIGNAL
);
636 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
638 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
641 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
644 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
652 _public_
int sd_bus_message_new_method_call(
655 const char *destination
,
657 const char *interface
,
658 const char *member
) {
660 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
663 assert_return(bus
, -ENOTCONN
);
664 assert_return(bus
= bus_resolve(bus
), -ENOPKG
);
665 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
666 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
667 assert_return(object_path_is_valid(path
), -EINVAL
);
668 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
669 assert_return(member_name_is_valid(member
), -EINVAL
);
670 assert_return(m
, -EINVAL
);
672 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_CALL
);
678 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
681 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
686 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
692 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
701 static int message_new_reply(
702 sd_bus_message
*call
,
704 sd_bus_message
**m
) {
706 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
710 assert_return(call
, -EINVAL
);
711 assert_return(call
->sealed
, -EPERM
);
712 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
713 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
714 assert_return(m
, -EINVAL
);
716 cookie
= BUS_MESSAGE_COOKIE(call
);
720 r
= sd_bus_message_new(call
->bus
, &t
, type
);
726 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
727 t
->reply_cookie
= cookie
;
728 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
733 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
738 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
739 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
741 /* let's copy the sensitive flag over. Let's do that as a safety precaution to keep a transaction
742 * wholly sensitive if already the incoming message was sensitive. This is particularly useful when a
743 * vtable record sets the SD_BUS_VTABLE_SENSITIVE flag on a method call, since this means it applies
744 * to both the message call and the reply. */
745 t
->sensitive
= call
->sensitive
;
751 _public_
int sd_bus_message_new_method_return(
752 sd_bus_message
*call
,
753 sd_bus_message
**m
) {
755 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
758 _public_
int sd_bus_message_new_method_error(
759 sd_bus_message
*call
,
761 const sd_bus_error
*e
) {
763 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
766 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
767 assert_return(m
, -EINVAL
);
769 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
773 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
778 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
783 t
->error
._need_free
= -1;
789 _public_
int sd_bus_message_new_method_errorf(
790 sd_bus_message
*call
,
796 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
799 assert_return(name
, -EINVAL
);
800 assert_return(m
, -EINVAL
);
802 va_start(ap
, format
);
803 bus_error_setfv(&error
, name
, format
, ap
);
806 return sd_bus_message_new_method_error(call
, m
, &error
);
809 _public_
int sd_bus_message_new_method_errno(
810 sd_bus_message
*call
,
813 const sd_bus_error
*p
) {
815 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
817 if (sd_bus_error_is_set(p
))
818 return sd_bus_message_new_method_error(call
, m
, p
);
820 sd_bus_error_set_errno(&berror
, error
);
822 return sd_bus_message_new_method_error(call
, m
, &berror
);
825 _public_
int sd_bus_message_new_method_errnof(
826 sd_bus_message
*call
,
832 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
835 va_start(ap
, format
);
836 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
839 return sd_bus_message_new_method_error(call
, m
, &berror
);
842 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
846 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
847 m
->creds
.well_known_names_local
= true;
848 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
851 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
855 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
856 m
->creds
.well_known_names_driver
= true;
857 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
860 int bus_message_new_synthetic_error(
863 const sd_bus_error
*e
,
864 sd_bus_message
**m
) {
866 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
870 assert(sd_bus_error_is_set(e
));
873 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_ERROR
);
879 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
880 t
->reply_cookie
= cookie
;
882 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
886 if (bus
&& bus
->unique_name
) {
887 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
892 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
897 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
902 t
->error
._need_free
= -1;
904 bus_message_set_sender_driver(bus
, t
);
910 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
914 /* We are fine if this message so far was either explicitly reffed or not reffed but queued into at
915 * least one bus connection object. */
916 assert(m
->n_ref
> 0 || m
->n_queued
> 0);
920 /* Each user reference to a bus message shall also be considered a ref on the bus */
925 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
929 assert(m
->n_ref
> 0);
931 sd_bus_unref(m
->bus
); /* Each regular ref is also a ref on the bus connection. Let's hence drop it
932 * here. Note we have to do this before decrementing our own n_ref here, since
933 * otherwise, if this message is currently queued sd_bus_unref() might call
934 * bus_message_unref_queued() for this which might then destroy the message
935 * while we are still processing it. */
938 if (m
->n_ref
> 0 || m
->n_queued
> 0)
941 /* Unset the bus field if neither the user has a reference nor this message is queued. We are careful
942 * to reset the field only after the last reference to the bus is dropped, after all we might keep
943 * multiple references to the bus, once for each reference kept on ourselves. */
946 return message_free(m
);
949 sd_bus_message
* bus_message_ref_queued(sd_bus_message
*m
, sd_bus
*bus
) {
953 /* If this is a different bus than the message is associated with, then implicitly turn this into a
954 * regular reference. This means that you can create a memory leak by enqueuing a message generated
955 * on one bus onto another at the same time as enqueueing a message from the second one on the first,
956 * as we'll not detect the cyclic references there. */
958 return sd_bus_message_ref(m
);
960 assert(m
->n_ref
> 0 || m
->n_queued
> 0);
966 sd_bus_message
* bus_message_unref_queued(sd_bus_message
*m
, sd_bus
*bus
) {
971 return sd_bus_message_unref(m
);
973 assert(m
->n_queued
> 0);
976 if (m
->n_ref
> 0 || m
->n_queued
> 0)
981 return message_free(m
);
984 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
985 assert_return(m
, -EINVAL
);
986 assert_return(type
, -EINVAL
);
988 *type
= m
->header
->type
;
992 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
995 assert_return(m
, -EINVAL
);
996 assert_return(cookie
, -EINVAL
);
998 c
= BUS_MESSAGE_COOKIE(m
);
1002 *cookie
= BUS_MESSAGE_COOKIE(m
);
1006 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
1007 assert_return(m
, -EINVAL
);
1008 assert_return(cookie
, -EINVAL
);
1010 if (m
->reply_cookie
== 0)
1013 *cookie
= m
->reply_cookie
;
1017 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
1018 assert_return(m
, -EINVAL
);
1020 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
1021 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
1024 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
1025 assert_return(m
, -EINVAL
);
1027 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
1030 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
1031 assert_return(m
, -EINVAL
);
1033 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
1034 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
1037 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
1038 assert_return(m
, NULL
);
1043 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
1044 assert_return(m
, NULL
);
1046 return m
->interface
;
1049 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
1050 assert_return(m
, NULL
);
1055 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
1056 assert_return(m
, NULL
);
1058 return m
->destination
;
1061 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
1062 assert_return(m
, NULL
);
1067 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
1068 assert_return(m
, NULL
);
1070 if (!sd_bus_error_is_set(&m
->error
))
1076 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
1077 assert_return(m
, -EINVAL
);
1078 assert_return(usec
, -EINVAL
);
1080 if (m
->monotonic
<= 0)
1083 *usec
= m
->monotonic
;
1087 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1088 assert_return(m
, -EINVAL
);
1089 assert_return(usec
, -EINVAL
);
1091 if (m
->realtime
<= 0)
1094 *usec
= m
->realtime
;
1098 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1099 assert_return(m
, -EINVAL
);
1100 assert_return(seqnum
, -EINVAL
);
1105 *seqnum
= m
->seqnum
;
1109 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1110 assert_return(m
, NULL
);
1112 if (m
->creds
.mask
== 0)
1118 _public_
int sd_bus_message_is_signal(
1120 const char *interface
,
1121 const char *member
) {
1123 assert_return(m
, -EINVAL
);
1125 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1128 if (interface
&& !streq_ptr(m
->interface
, interface
))
1131 if (member
&& !streq_ptr(m
->member
, member
))
1137 _public_
int sd_bus_message_is_method_call(
1139 const char *interface
,
1140 const char *member
) {
1142 assert_return(m
, -EINVAL
);
1144 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1147 if (interface
&& !streq_ptr(m
->interface
, interface
))
1150 if (member
&& !streq_ptr(m
->member
, member
))
1156 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1157 assert_return(m
, -EINVAL
);
1159 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1162 if (name
&& !streq_ptr(m
->error
.name
, name
))
1168 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1169 assert_return(m
, -EINVAL
);
1170 assert_return(!m
->sealed
, -EPERM
);
1171 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1173 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_REPLY_EXPECTED
, !b
);
1178 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1179 assert_return(m
, -EINVAL
);
1180 assert_return(!m
->sealed
, -EPERM
);
1182 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_AUTO_START
, !b
);
1187 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1188 assert_return(m
, -EINVAL
);
1189 assert_return(!m
->sealed
, -EPERM
);
1191 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
, b
);
1196 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1197 struct bus_body_part
*part
;
1204 if (m
->n_body_parts
<= 0) {
1208 assert(m
->body_end
);
1210 part
= new0(struct bus_body_part
, 1);
1216 m
->body_end
->next
= part
;
1226 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1231 /* All other fields can be left in their defaults */
1232 assert(!part
->data
);
1233 assert(part
->memfd
< 0);
1236 part
->is_zero
= true;
1237 part
->sealed
= true;
1240 static int part_make_space(
1241 struct sd_bus_message
*m
,
1242 struct bus_body_part
*part
,
1250 assert(!part
->sealed
);
1255 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1256 size_t new_allocated
;
1258 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1259 n
= realloc(part
->data
, new_allocated
);
1266 part
->allocated
= new_allocated
;
1267 part
->free_this
= true;
1271 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1277 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1278 struct bus_container
*c
;
1281 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1283 /* Add offset to current container, unless this is the first
1284 * item in it, which will have the 0 offset, which we can
1286 c
= message_get_last_container(m
);
1288 if (!c
->need_offsets
)
1291 if (!GREEDY_REALLOC(c
->offsets
, c
->n_offsets
+ 1))
1294 c
->offsets
[c
->n_offsets
++] = offset
;
1298 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1304 if (m
->n_containers
<= 0)
1307 /* Update counters */
1308 for (struct bus_container
*c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1310 *c
->array_size
+= expand
;
1313 static void *message_extend_body(
1318 bool force_inline
) {
1320 size_t start_body
, end_body
, padding
, added
;
1331 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1332 end_body
= start_body
+ sz
;
1334 padding
= start_body
- m
->body_size
;
1335 added
= padding
+ sz
;
1337 /* Check for 32bit overflows */
1338 if (end_body
< start_body
|| end_body
> UINT32_MAX
) {
1344 struct bus_body_part
*part
= NULL
;
1348 m
->n_body_parts
<= 0 ||
1349 m
->body_end
->sealed
||
1350 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1351 (force_inline
&& m
->body_end
->size
> MEMFD_MIN_SIZE
);
1352 /* If this must be an inlined extension, let's create a new part if
1353 * the previous part is large enough to be inlined. */
1357 part
= message_append_part(m
);
1361 part_zero(part
, padding
);
1364 part
= message_append_part(m
);
1368 r
= part_make_space(m
, part
, sz
, &p
);
1373 size_t os
, start_part
, end_part
;
1379 start_part
= ALIGN_TO(part
->size
, align
);
1380 end_part
= start_part
+ sz
;
1382 r
= part_make_space(m
, part
, end_part
, &p
);
1387 memzero(p
, padding
);
1388 p
= (uint8_t*) p
+ padding
;
1391 /* Readjust pointers */
1392 if (m
->n_containers
> 0)
1393 for (struct bus_container
*c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1394 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1396 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1399 /* Return something that is not NULL and is aligned */
1400 p
= (uint8_t*) align
;
1402 m
->body_size
= end_body
;
1403 message_extend_containers(m
, added
);
1406 r
= message_add_offset(m
, end_body
);
1416 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1427 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1431 f
= reallocarray(m
->fds
, sizeof(int), m
->n_fds
+ 1);
1439 m
->fds
[m
->n_fds
] = copy
;
1445 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1446 _cleanup_close_
int fd
= -1;
1447 struct bus_container
*c
;
1451 assert_return(m
, -EINVAL
);
1452 assert_return(!m
->sealed
, -EPERM
);
1453 assert_return(bus_type_is_basic(type
), -EINVAL
);
1454 assert_return(!m
->poisoned
, -ESTALE
);
1456 c
= message_get_last_container(m
);
1458 if (c
->signature
&& c
->signature
[c
->index
]) {
1459 /* Container signature is already set */
1461 if (c
->signature
[c
->index
] != type
)
1466 /* Maybe we can append to the signature? But only if this is the top-level container */
1467 if (c
->enclosing
!= 0)
1470 e
= strextend(&c
->signature
, CHAR_TO_STR(type
));
1477 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1483 case SD_BUS_TYPE_SIGNATURE
:
1484 case SD_BUS_TYPE_STRING
:
1488 case SD_BUS_TYPE_OBJECT_PATH
:
1496 case SD_BUS_TYPE_BOOLEAN
:
1498 u8
= p
&& *(int*) p
;
1504 case SD_BUS_TYPE_UNIX_FD
:
1509 fd
= message_push_fd(m
, *(int*) p
);
1520 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1521 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1528 a
= message_extend_body(m
, align
, sz
, true, false);
1535 *stored
= (const uint8_t*) a
;
1542 case SD_BUS_TYPE_STRING
:
1543 /* To make things easy we'll serialize a NULL string
1544 * into the empty string */
1548 case SD_BUS_TYPE_OBJECT_PATH
:
1554 sz
= 4 + strlen(p
) + 1;
1557 case SD_BUS_TYPE_SIGNATURE
:
1562 sz
= 1 + strlen(p
) + 1;
1565 case SD_BUS_TYPE_BOOLEAN
:
1567 u32
= p
&& *(int*) p
;
1573 case SD_BUS_TYPE_UNIX_FD
:
1578 fd
= message_push_fd(m
, *(int*) p
);
1589 align
= bus_type_get_alignment(type
);
1590 sz
= bus_type_get_size(type
);
1597 a
= message_extend_body(m
, align
, sz
, false, false);
1601 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
1602 *(uint32_t*) a
= sz
- 5;
1603 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1606 *stored
= (const uint8_t*) a
+ 4;
1608 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1609 *(uint8_t*) a
= sz
- 2;
1610 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1613 *stored
= (const uint8_t*) a
+ 1;
1622 if (type
== SD_BUS_TYPE_UNIX_FD
)
1625 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1632 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1633 return message_append_basic(m
, type
, p
, NULL
);
1636 _public_
int sd_bus_message_append_string_space(
1641 struct bus_container
*c
;
1644 assert_return(m
, -EINVAL
);
1645 assert_return(s
, -EINVAL
);
1646 assert_return(!m
->sealed
, -EPERM
);
1647 assert_return(!m
->poisoned
, -ESTALE
);
1649 c
= message_get_last_container(m
);
1651 if (c
->signature
&& c
->signature
[c
->index
]) {
1652 /* Container signature is already set */
1654 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1659 /* Maybe we can append to the signature? But only if this is the top-level container */
1660 if (c
->enclosing
!= 0)
1663 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
));
1670 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1671 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1677 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1681 *(uint32_t*) a
= size
;
1687 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1693 _public_
int sd_bus_message_append_string_iovec(
1695 const struct iovec
*iov
,
1696 unsigned n
/* should be size_t, but is API now… 😞 */) {
1703 assert_return(m
, -EINVAL
);
1704 assert_return(!m
->sealed
, -EPERM
);
1705 assert_return(iov
|| n
== 0, -EINVAL
);
1706 assert_return(!m
->poisoned
, -ESTALE
);
1708 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1710 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1714 for (i
= 0; i
< n
; i
++) {
1716 if (iov
[i
].iov_base
)
1717 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1719 memset(p
, ' ', iov
[i
].iov_len
);
1721 p
+= iov
[i
].iov_len
;
1727 static int bus_message_open_array(
1729 struct bus_container
*c
,
1730 const char *contents
,
1731 uint32_t **array_size
,
1733 bool *need_offsets
) {
1743 assert(need_offsets
);
1745 if (!signature_is_single(contents
, true))
1748 if (c
->signature
&& c
->signature
[c
->index
]) {
1750 /* Verify the existing signature */
1752 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1755 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1758 nindex
= c
->index
+ 1 + strlen(contents
);
1762 if (c
->enclosing
!= 0)
1765 /* Extend the existing signature */
1767 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
);
1773 nindex
= e
- c
->signature
;
1776 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1777 alignment
= bus_gvariant_get_alignment(contents
);
1781 /* Add alignment padding and add to offset list */
1782 if (!message_extend_body(m
, alignment
, 0, false, false))
1785 r
= bus_gvariant_is_fixed_size(contents
);
1789 *begin
= m
->body_size
;
1790 *need_offsets
= r
== 0;
1794 struct bus_body_part
*o
;
1796 alignment
= bus_type_get_alignment(contents
[0]);
1800 a
= message_extend_body(m
, 4, 4, false, false);
1805 op
= m
->body_end
->data
;
1806 os
= m
->body_end
->size
;
1808 /* Add alignment between size and first element */
1809 if (!message_extend_body(m
, alignment
, 0, false, false))
1812 /* location of array size might have changed so let's readjust a */
1813 if (o
== m
->body_end
)
1814 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1820 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1826 static int bus_message_open_variant(
1828 struct bus_container
*c
,
1829 const char *contents
) {
1835 if (!signature_is_single(contents
, false))
1838 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1841 if (c
->signature
&& c
->signature
[c
->index
]) {
1843 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1849 if (c
->enclosing
!= 0)
1852 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
));
1859 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1860 /* Variants are always aligned to 8 */
1862 if (!message_extend_body(m
, 8, 0, false, false))
1869 l
= strlen(contents
);
1870 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1875 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1878 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1884 static int bus_message_open_struct(
1886 struct bus_container
*c
,
1887 const char *contents
,
1889 bool *need_offsets
) {
1898 assert(need_offsets
);
1900 if (!signature_is_valid(contents
, false))
1903 if (c
->signature
&& c
->signature
[c
->index
]) {
1906 l
= strlen(contents
);
1908 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1909 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1910 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1913 nindex
= c
->index
+ 1 + l
+ 1;
1917 if (c
->enclosing
!= 0)
1920 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
));
1926 nindex
= e
- c
->signature
;
1929 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1932 alignment
= bus_gvariant_get_alignment(contents
);
1936 if (!message_extend_body(m
, alignment
, 0, false, false))
1939 r
= bus_gvariant_is_fixed_size(contents
);
1943 *begin
= m
->body_size
;
1944 *need_offsets
= r
== 0;
1946 /* Align contents to 8 byte boundary */
1947 if (!message_extend_body(m
, 8, 0, false, false))
1951 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1957 static int bus_message_open_dict_entry(
1959 struct bus_container
*c
,
1960 const char *contents
,
1962 bool *need_offsets
) {
1970 assert(need_offsets
);
1972 if (!signature_is_pair(contents
))
1975 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1978 if (c
->signature
&& c
->signature
[c
->index
]) {
1981 l
= strlen(contents
);
1983 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
1984 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1985 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
1990 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1993 alignment
= bus_gvariant_get_alignment(contents
);
1997 if (!message_extend_body(m
, alignment
, 0, false, false))
2000 r
= bus_gvariant_is_fixed_size(contents
);
2004 *begin
= m
->body_size
;
2005 *need_offsets
= r
== 0;
2007 /* Align contents to 8 byte boundary */
2008 if (!message_extend_body(m
, 8, 0, false, false))
2015 _public_
int sd_bus_message_open_container(
2018 const char *contents
) {
2020 struct bus_container
*c
;
2021 uint32_t *array_size
= NULL
;
2022 _cleanup_free_
char *signature
= NULL
;
2023 size_t before
, begin
= 0;
2024 bool need_offsets
= false;
2027 assert_return(m
, -EINVAL
);
2028 assert_return(!m
->sealed
, -EPERM
);
2029 assert_return(contents
, -EINVAL
);
2030 assert_return(!m
->poisoned
, -ESTALE
);
2032 /* Make sure we have space for one more container */
2033 if (!GREEDY_REALLOC(m
->containers
, m
->n_containers
+ 1)) {
2038 c
= message_get_last_container(m
);
2040 signature
= strdup(contents
);
2046 /* Save old index in the parent container, in case we have to
2047 * abort this container */
2048 c
->saved_index
= c
->index
;
2049 before
= m
->body_size
;
2051 if (type
== SD_BUS_TYPE_ARRAY
)
2052 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
2053 else if (type
== SD_BUS_TYPE_VARIANT
)
2054 r
= bus_message_open_variant(m
, c
, contents
);
2055 else if (type
== SD_BUS_TYPE_STRUCT
)
2056 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
2057 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
2058 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
2064 /* OK, let's fill it in */
2065 m
->containers
[m
->n_containers
++] = (struct bus_container
) {
2067 .signature
= TAKE_PTR(signature
),
2068 .array_size
= array_size
,
2071 .need_offsets
= need_offsets
,
2077 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2082 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2085 if (c
->need_offsets
) {
2086 size_t payload
, sz
, i
;
2089 /* Variable-width arrays */
2091 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2092 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2094 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2098 for (i
= 0; i
< c
->n_offsets
; i
++)
2099 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2103 /* Fixed-width or empty arrays */
2105 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2113 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2119 assert(c
->signature
);
2121 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2124 l
= strlen(c
->signature
);
2126 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2131 memcpy(a
+1, c
->signature
, l
);
2136 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2137 bool fixed_size
= true;
2138 size_t n_variable
= 0;
2147 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2150 p
= strempty(c
->signature
);
2154 r
= signature_element_length(p
, &n
);
2163 r
= bus_gvariant_is_fixed_size(t
);
2168 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2170 /* We need to add an offset for each item that has a
2171 * variable size and that is not the last one in the
2175 if (r
== 0 && p
[n
] != 0)
2182 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2183 assert(c
->need_offsets
|| n_variable
== 0);
2185 if (isempty(c
->signature
)) {
2186 /* The unary type is encoded as fixed 1 byte padding */
2187 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2192 } else if (n_variable
<= 0) {
2195 /* Structures with fixed-size members only have to be
2196 * fixed-size themselves. But gvariant requires all fixed-size
2197 * elements to be sized a multiple of their alignment. Hence,
2198 * we must *always* add final padding after the last member so
2199 * the overall size of the structure is properly aligned. */
2201 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2203 assert(alignment
> 0);
2205 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2212 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2214 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2216 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2220 p
= strempty(c
->signature
);
2221 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2225 r
= signature_element_length(p
, &n
);
2236 r
= bus_gvariant_is_fixed_size(t
);
2239 if (r
> 0 || p
[0] == 0)
2243 k
= n_variable
- 1 - j
;
2245 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2254 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2255 struct bus_container
*c
;
2258 assert_return(m
, -EINVAL
);
2259 assert_return(!m
->sealed
, -EPERM
);
2260 assert_return(m
->n_containers
> 0, -EINVAL
);
2261 assert_return(!m
->poisoned
, -ESTALE
);
2263 c
= message_get_last_container(m
);
2265 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2266 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2271 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2272 r
= bus_message_close_array(m
, c
);
2273 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2274 r
= bus_message_close_variant(m
, c
);
2275 else if (IN_SET(c
->enclosing
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
))
2276 r
= bus_message_close_struct(m
, c
, true);
2278 assert_not_reached();
2292 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2299 stack
[*i
].types
= types
;
2300 stack
[*i
].n_struct
= n_struct
;
2301 stack
[*i
].n_array
= n_array
;
2307 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2318 *types
= stack
[*i
].types
;
2319 *n_struct
= stack
[*i
].n_struct
;
2320 *n_array
= stack
[*i
].n_array
;
2325 _public_
int sd_bus_message_appendv(
2330 unsigned n_array
, n_struct
;
2331 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2332 unsigned stack_ptr
= 0;
2335 assert_return(m
, -EINVAL
);
2336 assert_return(types
, -EINVAL
);
2337 assert_return(!m
->sealed
, -EPERM
);
2338 assert_return(!m
->poisoned
, -ESTALE
);
2341 n_struct
= strlen(types
);
2346 if (n_array
== 0 || (n_array
== UINT_MAX
&& n_struct
== 0)) {
2347 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2353 r
= sd_bus_message_close_container(m
);
2361 if (n_array
!= UINT_MAX
)
2370 case SD_BUS_TYPE_BYTE
: {
2373 x
= (uint8_t) va_arg(ap
, int);
2374 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2378 case SD_BUS_TYPE_BOOLEAN
:
2379 case SD_BUS_TYPE_INT32
:
2380 case SD_BUS_TYPE_UINT32
:
2381 case SD_BUS_TYPE_UNIX_FD
: {
2384 /* We assume a boolean is the same as int32_t */
2385 assert_cc(sizeof(int32_t) == sizeof(int));
2387 x
= va_arg(ap
, uint32_t);
2388 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2392 case SD_BUS_TYPE_INT16
:
2393 case SD_BUS_TYPE_UINT16
: {
2396 x
= (uint16_t) va_arg(ap
, int);
2397 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2401 case SD_BUS_TYPE_INT64
:
2402 case SD_BUS_TYPE_UINT64
: {
2405 x
= va_arg(ap
, uint64_t);
2406 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2410 case SD_BUS_TYPE_DOUBLE
: {
2413 x
= va_arg(ap
, double);
2414 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2418 case SD_BUS_TYPE_STRING
:
2419 case SD_BUS_TYPE_OBJECT_PATH
:
2420 case SD_BUS_TYPE_SIGNATURE
: {
2423 x
= va_arg(ap
, const char*);
2424 r
= sd_bus_message_append_basic(m
, *t
, x
);
2428 case SD_BUS_TYPE_ARRAY
: {
2431 r
= signature_element_length(t
+ 1, &k
);
2437 memcpy(s
, t
+ 1, k
);
2440 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2445 if (n_array
== UINT_MAX
) {
2450 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2456 n_array
= va_arg(ap
, unsigned);
2461 case SD_BUS_TYPE_VARIANT
: {
2464 s
= va_arg(ap
, const char*);
2468 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2472 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2477 n_struct
= strlen(s
);
2483 case SD_BUS_TYPE_STRUCT_BEGIN
:
2484 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2487 r
= signature_element_length(t
, &k
);
2494 memcpy(s
, t
+ 1, k
- 2);
2497 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2502 if (n_array
== UINT_MAX
) {
2507 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2529 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2533 va_start(ap
, types
);
2534 r
= sd_bus_message_appendv(m
, types
, ap
);
2540 _public_
int sd_bus_message_append_array_space(
2550 assert_return(m
, -EINVAL
);
2551 assert_return(!m
->sealed
, -EPERM
);
2552 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2553 assert_return(ptr
|| size
== 0, -EINVAL
);
2554 assert_return(!m
->poisoned
, -ESTALE
);
2556 /* alignment and size of the trivial types (except bool) is
2557 * identical for gvariant and dbus1 marshalling */
2558 align
= bus_type_get_alignment(type
);
2559 sz
= bus_type_get_size(type
);
2561 assert_se(align
> 0);
2567 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2571 a
= message_extend_body(m
, align
, size
, false, false);
2575 r
= sd_bus_message_close_container(m
);
2583 _public_
int sd_bus_message_append_array(
2591 assert_return(m
, -EINVAL
);
2592 assert_return(!m
->sealed
, -EPERM
);
2593 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2594 assert_return(ptr
|| size
== 0, -EINVAL
);
2595 assert_return(!m
->poisoned
, -ESTALE
);
2597 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2601 memcpy_safe(p
, ptr
, size
);
2606 _public_
int sd_bus_message_append_array_iovec(
2609 const struct iovec
*iov
,
2610 unsigned n
/* should be size_t, but is API now… 😞 */) {
2617 assert_return(m
, -EINVAL
);
2618 assert_return(!m
->sealed
, -EPERM
);
2619 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2620 assert_return(iov
|| n
== 0, -EINVAL
);
2621 assert_return(!m
->poisoned
, -ESTALE
);
2623 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2625 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2629 for (i
= 0; i
< n
; i
++) {
2631 if (iov
[i
].iov_base
)
2632 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2634 memzero(p
, iov
[i
].iov_len
);
2636 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2642 _public_
int sd_bus_message_append_array_memfd(
2649 _cleanup_close_
int copy_fd
= -1;
2650 struct bus_body_part
*part
;
2656 assert_return(m
, -EINVAL
);
2657 assert_return(memfd
>= 0, -EBADF
);
2658 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2659 assert_return(size
> 0, -EINVAL
);
2660 assert_return(!m
->sealed
, -EPERM
);
2661 assert_return(!m
->poisoned
, -ESTALE
);
2663 r
= memfd_set_sealed(memfd
);
2667 copy_fd
= fcntl(memfd
, F_DUPFD_CLOEXEC
, 3);
2671 r
= memfd_get_size(memfd
, &real_size
);
2675 if (offset
== 0 && size
== UINT64_MAX
)
2677 else if (offset
+ size
> real_size
)
2680 align
= bus_type_get_alignment(type
);
2681 sz
= bus_type_get_size(type
);
2683 assert_se(align
> 0);
2686 if (offset
% align
!= 0)
2692 if (size
> (uint64_t) UINT32_MAX
)
2695 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2699 a
= message_extend_body(m
, align
, 0, false, false);
2703 part
= message_append_part(m
);
2707 part
->memfd
= copy_fd
;
2708 part
->memfd_offset
= offset
;
2709 part
->sealed
= true;
2713 m
->body_size
+= size
;
2714 message_extend_containers(m
, size
);
2716 return sd_bus_message_close_container(m
);
2719 _public_
int sd_bus_message_append_string_memfd(
2725 _cleanup_close_
int copy_fd
= -1;
2726 struct bus_body_part
*part
;
2727 struct bus_container
*c
;
2732 assert_return(m
, -EINVAL
);
2733 assert_return(memfd
>= 0, -EBADF
);
2734 assert_return(size
> 0, -EINVAL
);
2735 assert_return(!m
->sealed
, -EPERM
);
2736 assert_return(!m
->poisoned
, -ESTALE
);
2738 r
= memfd_set_sealed(memfd
);
2742 copy_fd
= fcntl(memfd
, FD_CLOEXEC
, 3);
2746 r
= memfd_get_size(memfd
, &real_size
);
2750 if (offset
== 0 && size
== UINT64_MAX
)
2752 else if (offset
+ size
> real_size
)
2755 /* We require this to be NUL terminated */
2759 if (size
> (uint64_t) UINT32_MAX
)
2762 c
= message_get_last_container(m
);
2763 if (c
->signature
&& c
->signature
[c
->index
]) {
2764 /* Container signature is already set */
2766 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2771 /* Maybe we can append to the signature? But only if this is the top-level container */
2772 if (c
->enclosing
!= 0)
2775 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
));
2782 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2783 a
= message_extend_body(m
, 4, 4, false, false);
2787 *(uint32_t*) a
= size
- 1;
2790 part
= message_append_part(m
);
2794 part
->memfd
= copy_fd
;
2795 part
->memfd_offset
= offset
;
2796 part
->sealed
= true;
2800 m
->body_size
+= size
;
2801 message_extend_containers(m
, size
);
2803 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2804 r
= message_add_offset(m
, m
->body_size
);
2811 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2817 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2820 assert_return(m
, -EINVAL
);
2821 assert_return(!m
->sealed
, -EPERM
);
2822 assert_return(!m
->poisoned
, -ESTALE
);
2824 r
= sd_bus_message_open_container(m
, 'a', "s");
2828 STRV_FOREACH(i
, l
) {
2829 r
= sd_bus_message_append_basic(m
, 's', *i
);
2834 return sd_bus_message_close_container(m
);
2837 static int bus_message_close_header(sd_bus_message
*m
) {
2841 /* The actual user data is finished now, we just complete the
2842 variant and struct now (at least on gvariant). Remember
2843 this position, so that during parsing we know where to
2844 put the outer container end. */
2845 m
->user_body_size
= m
->body_size
;
2847 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2848 const char *signature
;
2852 /* Add offset table to end of fields array */
2853 if (m
->n_header_offsets
>= 1) {
2857 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2859 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2860 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2864 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2865 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2868 /* Add gvariant NUL byte plus signature to the end of
2869 * the body, followed by the final offset pointing to
2870 * the end of the fields array */
2872 signature
= strempty(m
->root_container
.signature
);
2873 l
= strlen(signature
);
2875 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2876 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2881 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2882 memcpy((uint8_t*) d
+ 2, signature
, l
);
2883 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2885 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2888 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2890 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2891 m
->header
->dbus1
.body_size
= m
->body_size
;
2897 _public_
int sd_bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, uint64_t timeout_usec
) {
2898 struct bus_body_part
*part
;
2903 assert_return(m
, -EINVAL
);
2908 if (m
->n_containers
> 0)
2914 if (cookie
> 0xffffffffULL
&&
2915 !BUS_MESSAGE_IS_GVARIANT(m
))
2918 /* In vtables the return signature of method calls is listed,
2919 * let's check if they match if this is a response */
2920 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2921 m
->enforced_reply_signature
&&
2922 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2925 /* If gvariant marshalling is used we need to close the body structure */
2926 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2930 /* If there's a non-trivial signature set, then add it in
2931 * here, but only on dbus1 */
2932 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2933 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2939 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2944 r
= bus_message_close_header(m
);
2948 if (BUS_MESSAGE_IS_GVARIANT(m
))
2949 m
->header
->dbus2
.cookie
= cookie
;
2951 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2953 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout_usec
;
2955 /* Add padding at the end of the fields part, since we know
2956 * the body needs to start at an 8 byte alignment. We made
2957 * sure we allocated enough space for this, so all we need to
2958 * do here is to zero it out. */
2959 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2961 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2963 /* If this is something we can send as memfd, then let's seal
2964 the memfd now. Note that we can send memfds as payload only
2965 for directed messages, and not for broadcasts. */
2966 if (m
->destination
&& m
->bus
->use_memfd
) {
2967 MESSAGE_FOREACH_PART(part
, i
, m
)
2968 if (part
->memfd
>= 0 &&
2970 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
2971 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
2974 /* Try to seal it if that makes
2975 * sense. First, unmap our own map to
2976 * make sure we don't keep it busy. */
2977 bus_body_part_unmap(part
);
2979 /* Then, sync up real memfd size */
2981 r
= memfd_set_size(part
->memfd
, sz
);
2985 /* Finally, try to seal */
2986 if (memfd_set_sealed(part
->memfd
) >= 0)
2987 part
->sealed
= true;
2991 m
->root_container
.end
= m
->user_body_size
;
2992 m
->root_container
.index
= 0;
2993 m
->root_container
.offset_index
= 0;
2994 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
3001 int bus_body_part_map(struct bus_body_part
*part
) {
3010 if (part
->size
<= 0)
3013 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3014 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
3015 static const uint8_t zeroes
[7] = { };
3016 part
->data
= (void*) zeroes
;
3020 shift
= PAGE_OFFSET(part
->memfd_offset
);
3021 psz
= PAGE_ALIGN(part
->size
+ shift
);
3023 if (part
->memfd
>= 0)
3024 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
3025 else if (part
->is_zero
)
3026 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
3030 if (p
== MAP_FAILED
)
3034 part
->mmap_begin
= p
;
3035 part
->data
= (uint8_t*) p
+ shift
;
3036 part
->munmap_this
= true;
3041 void bus_body_part_unmap(struct bus_body_part
*part
) {
3045 if (part
->memfd
< 0)
3048 if (!part
->mmap_begin
)
3051 if (!part
->munmap_this
)
3054 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
3056 part
->mmap_begin
= NULL
;
3059 part
->munmap_this
= false;
3064 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3065 size_t k
, start
, end
;
3070 start
= ALIGN_TO((size_t) *rindex
, align
);
3071 end
= start
+ nbytes
;
3076 /* Verify that padding is 0 */
3077 for (k
= *rindex
; k
< start
; k
++)
3078 if (((const uint8_t*) p
)[k
] != 0)
3082 *r
= (uint8_t*) p
+ start
;
3089 static bool message_end_of_signature(sd_bus_message
*m
) {
3090 struct bus_container
*c
;
3094 c
= message_get_last_container(m
);
3095 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3098 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3099 struct bus_container
*c
;
3103 c
= message_get_last_container(m
);
3104 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3107 if (BUS_MESSAGE_IS_GVARIANT(m
))
3108 return index
>= c
->end
;
3110 assert(c
->array_size
);
3111 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3115 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3116 assert_return(m
, -EINVAL
);
3117 assert_return(m
->sealed
, -EPERM
);
3119 if (complete
&& m
->n_containers
> 0)
3122 if (message_end_of_signature(m
))
3125 if (message_end_of_array(m
, m
->rindex
))
3131 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3132 struct bus_body_part
*part
;
3138 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3139 part
= m
->cached_rindex_part
;
3140 begin
= m
->cached_rindex_part_begin
;
3150 if (index
+ sz
<= begin
+ part
->size
) {
3152 r
= bus_body_part_map(part
);
3157 *p
= part
->data
? (uint8_t*) part
->data
+ index
- begin
3158 : NULL
; /* Avoid dereferencing a NULL pointer. */
3160 m
->cached_rindex_part
= part
;
3161 m
->cached_rindex_part_begin
= begin
;
3166 begin
+= part
->size
;
3173 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3180 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3183 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3186 sz
= bus_gvariant_get_size(c
->signature
);
3192 if (c
->offset_index
+1 >= c
->n_offsets
)
3195 /* Variable-size array */
3197 alignment
= bus_gvariant_get_alignment(c
->signature
);
3198 assert(alignment
> 0);
3200 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3201 assert(c
->offsets
[c
->offset_index
+1] >= *rindex
);
3202 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3205 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3208 /* Fixed-size array */
3209 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3215 } else if (IN_SET(c
->enclosing
, 0, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
3220 if (c
->offset_index
+1 >= c
->n_offsets
)
3223 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3227 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3232 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3235 alignment
= bus_gvariant_get_alignment(t
);
3238 assert(alignment
> 0);
3240 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3241 assert(c
->offsets
[c
->offset_index
+1] >= *rindex
);
3242 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3246 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3249 assert_not_reached();
3254 /* Reached the end */
3260 static int message_peek_body(
3267 size_t k
, start
, end
, padding
;
3268 struct bus_body_part
*part
;
3275 start
= ALIGN_TO((size_t) *rindex
, align
);
3276 padding
= start
- *rindex
;
3277 end
= start
+ nbytes
;
3279 if (end
> m
->user_body_size
)
3282 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3287 /* Verify padding */
3288 for (k
= 0; k
< padding
; k
++)
3293 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3294 if (!part
|| (nbytes
> 0 && !q
))
3305 static bool validate_nul(const char *s
, size_t l
) {
3307 /* Check for NUL chars in the string */
3308 if (memchr(s
, 0, l
))
3311 /* Check for NUL termination */
3318 static bool validate_string(const char *s
, size_t l
) {
3320 if (!validate_nul(s
, l
))
3323 /* Check if valid UTF8 */
3324 if (!utf8_is_valid(s
))
3330 static bool validate_signature(const char *s
, size_t l
) {
3332 if (!validate_nul(s
, l
))
3335 /* Check if valid signature */
3336 if (!signature_is_valid(s
, true))
3342 static bool validate_object_path(const char *s
, size_t l
) {
3344 if (!validate_nul(s
, l
))
3347 if (!object_path_is_valid(s
))
3353 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3354 struct bus_container
*c
;
3359 assert_return(m
, -EINVAL
);
3360 assert_return(m
->sealed
, -EPERM
);
3361 assert_return(bus_type_is_basic(type
), -EINVAL
);
3363 if (message_end_of_signature(m
))
3366 if (message_end_of_array(m
, m
->rindex
))
3369 c
= message_get_last_container(m
);
3370 if (c
->signature
[c
->index
] != type
)
3375 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3377 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3380 /* D-Bus spec: The marshalling formats for the string-like types all end
3381 * with a single zero (NUL) byte, but that byte is not considered to be part
3383 if (c
->item_size
== 0)
3386 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3390 if (type
== SD_BUS_TYPE_STRING
)
3391 ok
= validate_string(q
, c
->item_size
-1);
3392 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3393 ok
= validate_object_path(q
, c
->item_size
-1);
3395 ok
= validate_signature(q
, c
->item_size
-1);
3401 *(const char**) p
= q
;
3405 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3407 if ((size_t) sz
!= c
->item_size
)
3410 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3413 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3419 case SD_BUS_TYPE_BYTE
:
3421 *(uint8_t*) p
= *(uint8_t*) q
;
3424 case SD_BUS_TYPE_BOOLEAN
:
3426 *(int*) p
= !!*(uint8_t*) q
;
3429 case SD_BUS_TYPE_INT16
:
3430 case SD_BUS_TYPE_UINT16
:
3432 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3435 case SD_BUS_TYPE_INT32
:
3436 case SD_BUS_TYPE_UINT32
:
3438 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3441 case SD_BUS_TYPE_INT64
:
3442 case SD_BUS_TYPE_UINT64
:
3443 case SD_BUS_TYPE_DOUBLE
:
3445 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3448 case SD_BUS_TYPE_UNIX_FD
: {
3451 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3456 *(int*) p
= m
->fds
[j
];
3462 assert_not_reached();
3466 r
= container_next_item(m
, c
, &rindex
);
3471 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3475 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3479 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3480 if (l
== UINT32_MAX
)
3481 /* avoid overflow right below */
3484 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3488 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3489 ok
= validate_object_path(q
, l
);
3491 ok
= validate_string(q
, l
);
3496 *(const char**) p
= q
;
3498 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3501 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3507 /* avoid overflow right below */
3510 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3514 if (!validate_signature(q
, l
))
3518 *(const char**) p
= q
;
3523 align
= bus_type_get_alignment(type
);
3526 sz
= bus_type_get_size(type
);
3529 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3535 case SD_BUS_TYPE_BYTE
:
3537 *(uint8_t*) p
= *(uint8_t*) q
;
3540 case SD_BUS_TYPE_BOOLEAN
:
3542 *(int*) p
= !!*(uint32_t*) q
;
3545 case SD_BUS_TYPE_INT16
:
3546 case SD_BUS_TYPE_UINT16
:
3548 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3551 case SD_BUS_TYPE_INT32
:
3552 case SD_BUS_TYPE_UINT32
:
3554 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3557 case SD_BUS_TYPE_INT64
:
3558 case SD_BUS_TYPE_UINT64
:
3559 case SD_BUS_TYPE_DOUBLE
:
3561 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3564 case SD_BUS_TYPE_UNIX_FD
: {
3567 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3572 *(int*) p
= m
->fds
[j
];
3577 assert_not_reached();
3584 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3590 static int bus_message_enter_array(
3592 struct bus_container
*c
,
3593 const char *contents
,
3594 uint32_t **array_size
,
3597 size_t *n_offsets
) {
3611 if (!signature_is_single(contents
, true))
3614 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3617 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3620 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3625 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3629 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3633 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3636 alignment
= bus_type_get_alignment(contents
[0]);
3640 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3644 *array_size
= (uint32_t*) q
;
3646 } else if (c
->item_size
<= 0) {
3648 /* gvariant: empty array */
3653 } else if (bus_gvariant_is_fixed_size(contents
)) {
3655 /* gvariant: fixed length array */
3656 *item_size
= bus_gvariant_get_size(contents
);
3661 size_t where
, previous
= 0, framing
, sz
;
3665 /* gvariant: variable length array */
3666 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3668 where
= rindex
+ c
->item_size
- sz
;
3669 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3673 framing
= bus_gvariant_read_word_le(q
, sz
);
3674 if (framing
> c
->item_size
- sz
)
3676 if ((c
->item_size
- framing
) % sz
!= 0)
3679 *n_offsets
= (c
->item_size
- framing
) / sz
;
3681 where
= rindex
+ framing
;
3682 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3686 *offsets
= new(size_t, *n_offsets
);
3690 alignment
= bus_gvariant_get_alignment(c
->signature
);
3691 assert(alignment
> 0);
3693 for (i
= 0; i
< *n_offsets
; i
++) {
3696 start
= ALIGN_TO(previous
, alignment
);
3698 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3699 if (x
> c
->item_size
- sz
)
3704 (*offsets
)[i
] = rindex
+ x
;
3708 *item_size
= (*offsets
)[0] - rindex
;
3713 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3714 c
->index
+= 1 + strlen(contents
);
3719 static int bus_message_enter_variant(
3721 struct bus_container
*c
,
3722 const char *contents
,
3723 size_t *item_size
) {
3735 if (!signature_is_single(contents
, false))
3738 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3741 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3744 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3749 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3752 k
= strlen(contents
);
3753 if (1+k
> c
->item_size
)
3756 where
= rindex
+ c
->item_size
- (1+k
);
3757 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3761 if (*(char*) q
!= 0)
3764 if (memcmp((uint8_t*) q
+1, contents
, k
))
3767 *item_size
= c
->item_size
- (1+k
);
3770 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3776 /* avoid overflow right below */
3779 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3783 if (!validate_signature(q
, l
))
3786 if (!streq(q
, contents
))
3792 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3798 static int build_struct_offsets(
3800 const char *signature
,
3804 size_t *n_offsets
) {
3806 unsigned n_variable
= 0, n_total
= 0, v
;
3807 size_t previous
, where
;
3818 if (isempty(signature
)) {
3819 /* Unary type is encoded as *fixed* 1 byte padding */
3820 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3824 if (*(uint8_t *) q
!= 0)
3833 sz
= bus_gvariant_determine_word_size(size
, 0);
3837 /* First, loop over signature and count variable elements and
3838 * elements in general. We use this to know how large the
3839 * offset array is at the end of the structure. Note that
3840 * GVariant only stores offsets for all variable size elements
3841 * that are not the last item. */
3847 r
= signature_element_length(p
, &n
);
3856 r
= bus_gvariant_is_fixed_size(t
);
3861 if (r
== 0 && p
[n
] != 0) /* except the last item */
3868 if (size
< n_variable
* sz
)
3871 where
= m
->rindex
+ size
- (n_variable
* sz
);
3872 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3878 *offsets
= new(size_t, n_total
);
3884 /* Second, loop again and build an offset table */
3886 previous
= m
->rindex
;
3891 r
= signature_element_length(p
, &n
);
3900 size_t align
= bus_gvariant_get_alignment(t
);
3903 /* The possible start of this member after including alignment */
3904 size_t start
= ALIGN_TO(previous
, align
);
3906 k
= bus_gvariant_get_size(t
);
3914 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3918 /* The last item's end is determined
3919 * from the start of the offset array */
3920 x
= size
- (n_variable
* sz
);
3922 offset
= m
->rindex
+ x
;
3924 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG
),
3925 "For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu",
3935 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3940 assert(*n_offsets
== n_total
);
3942 *item_size
= (*offsets
)[0] - m
->rindex
;
3946 static int enter_struct_or_dict_entry(
3948 struct bus_container
*c
,
3949 const char *contents
,
3952 size_t *n_offsets
) {
3963 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3966 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3971 /* gvariant with contents */
3972 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3977 static int bus_message_enter_struct(
3979 struct bus_container
*c
,
3980 const char *contents
,
3983 size_t *n_offsets
) {
3995 if (!signature_is_valid(contents
, false))
3998 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4001 l
= strlen(contents
);
4003 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
4004 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4005 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
4008 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4012 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4013 c
->index
+= 1 + l
+ 1;
4018 static int bus_message_enter_dict_entry(
4020 struct bus_container
*c
,
4021 const char *contents
,
4024 size_t *n_offsets
) {
4033 if (!signature_is_pair(contents
))
4036 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4039 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4042 l
= strlen(contents
);
4044 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
4045 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4046 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
4049 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4053 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4054 c
->index
+= 1 + l
+ 1;
4059 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
4061 const char *contents
) {
4062 struct bus_container
*c
;
4063 uint32_t *array_size
= NULL
;
4064 _cleanup_free_
char *signature
= NULL
;
4066 _cleanup_free_
size_t *offsets
= NULL
;
4067 size_t n_offsets
= 0, item_size
= 0;
4070 assert_return(m
, -EINVAL
);
4071 assert_return(m
->sealed
, -EPERM
);
4072 assert_return(type
!= 0 || !contents
, -EINVAL
);
4074 if (type
== 0 || !contents
) {
4078 /* Allow entering into anonymous containers */
4079 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
4083 if (type
!= 0 && type
!= tt
)
4086 if (contents
&& !streq(contents
, cc
))
4094 * We enforce a global limit on container depth, that is much
4095 * higher than the 32 structs and 32 arrays the specification
4096 * mandates. This is simpler to implement for us, and we need
4097 * this only to ensure our container array doesn't grow
4098 * without bounds. We are happy to return any data from a
4099 * message as long as the data itself is valid, even if the
4100 * overall message might be not.
4102 * Note that the message signature is validated when
4103 * parsing the headers, and that validation does check the
4106 * Note that the specification defines no limits on the depth
4107 * of stacked variants, but we do.
4109 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4112 if (!GREEDY_REALLOC(m
->containers
, m
->n_containers
+ 1))
4115 if (message_end_of_signature(m
))
4118 if (message_end_of_array(m
, m
->rindex
))
4121 c
= message_get_last_container(m
);
4123 signature
= strdup(contents
);
4127 c
->saved_index
= c
->index
;
4130 if (type
== SD_BUS_TYPE_ARRAY
)
4131 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4132 else if (type
== SD_BUS_TYPE_VARIANT
)
4133 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4134 else if (type
== SD_BUS_TYPE_STRUCT
)
4135 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4136 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4137 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4143 /* OK, let's fill it in */
4144 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4145 type
== SD_BUS_TYPE_STRUCT
&&
4147 end
= m
->rindex
+ 0;
4149 end
= m
->rindex
+ c
->item_size
;
4151 m
->containers
[m
->n_containers
++] = (struct bus_container
) {
4153 .signature
= TAKE_PTR(signature
),
4157 /* Unary type has fixed size of 1, but virtual size of 0 */
4159 .array_size
= array_size
,
4160 .item_size
= item_size
,
4161 .offsets
= TAKE_PTR(offsets
),
4162 .n_offsets
= n_offsets
,
4168 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4169 struct bus_container
*c
;
4173 assert_return(m
, -EINVAL
);
4174 assert_return(m
->sealed
, -EPERM
);
4175 assert_return(m
->n_containers
> 0, -ENXIO
);
4177 c
= message_get_last_container(m
);
4179 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4180 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4184 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4185 if (m
->rindex
< c
->end
)
4188 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4191 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4192 if (c
->begin
+ l
!= m
->rindex
)
4196 message_free_last_container(m
);
4198 c
= message_get_last_container(m
);
4200 c
->index
= c
->saved_index
;
4201 r
= container_next_item(m
, c
, &m
->rindex
);
4209 static void message_quit_container(sd_bus_message
*m
) {
4210 struct bus_container
*c
;
4214 assert(m
->n_containers
> 0);
4217 c
= message_get_last_container(m
);
4218 assert(m
->rindex
>= c
->before
);
4219 m
->rindex
= c
->before
;
4221 /* Free container */
4222 message_free_last_container(m
);
4224 /* Correct index of new top-level container */
4225 c
= message_get_last_container(m
);
4226 c
->index
= c
->saved_index
;
4229 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4230 struct bus_container
*c
;
4233 assert_return(m
, -EINVAL
);
4234 assert_return(m
->sealed
, -EPERM
);
4236 if (message_end_of_signature(m
))
4239 if (message_end_of_array(m
, m
->rindex
))
4242 c
= message_get_last_container(m
);
4244 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4248 *type
= c
->signature
[c
->index
];
4252 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4257 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4261 /* signature_element_length does verification internally */
4263 /* The array element must not be empty */
4265 if (free_and_strndup(&c
->peeked_signature
,
4266 c
->signature
+ c
->index
+ 1, l
) < 0)
4269 *contents
= c
->peeked_signature
;
4273 *type
= SD_BUS_TYPE_ARRAY
;
4278 if (IN_SET(c
->signature
[c
->index
], SD_BUS_TYPE_STRUCT_BEGIN
, SD_BUS_TYPE_DICT_ENTRY_BEGIN
)) {
4283 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4288 if (free_and_strndup(&c
->peeked_signature
,
4289 c
->signature
+ c
->index
+ 1, l
- 2) < 0)
4292 *contents
= c
->peeked_signature
;
4296 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4301 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4305 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4308 if (c
->item_size
< 2)
4311 /* Look for the NUL delimiter that
4312 separates the payload from the
4313 signature. Since the body might be
4314 in a different part that then the
4315 signature we map byte by byte. */
4317 for (k
= 2; k
<= c
->item_size
; k
++) {
4320 where
= m
->rindex
+ c
->item_size
- k
;
4321 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4325 if (*(char*) q
== 0)
4329 if (k
> c
->item_size
)
4332 if (free_and_strndup(&c
->peeked_signature
,
4333 (char*) q
+ 1, k
- 1) < 0)
4336 if (!signature_is_valid(c
->peeked_signature
, true))
4339 *contents
= c
->peeked_signature
;
4344 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4350 /* avoid overflow right below */
4353 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4357 if (!validate_signature(q
, l
))
4365 *type
= SD_BUS_TYPE_VARIANT
;
4380 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4381 struct bus_container
*c
;
4383 assert_return(m
, -EINVAL
);
4384 assert_return(m
->sealed
, -EPERM
);
4387 message_reset_containers(m
);
4390 c
= message_get_last_container(m
);
4392 c
= message_get_last_container(m
);
4395 m
->rindex
= c
->begin
;
4398 c
->offset_index
= 0;
4399 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4401 return !isempty(c
->signature
);
4404 _public_
int sd_bus_message_readv(
4409 unsigned n_array
, n_struct
;
4410 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4411 unsigned stack_ptr
= 0;
4412 unsigned n_loop
= 0;
4415 assert_return(m
, -EINVAL
);
4416 assert_return(m
->sealed
, -EPERM
);
4417 assert_return(types
, -EINVAL
);
4422 /* Ideally, we'd just call ourselves recursively on every
4423 * complex type. However, the state of a va_list that is
4424 * passed to a function is undefined after that function
4425 * returns. This means we need to decode the va_list linearly
4426 * in a single stackframe. We hence implement our own
4427 * home-grown stack in an array. */
4429 n_array
= UINT_MAX
; /* length of current array entries */
4430 n_struct
= strlen(types
); /* length of current struct contents signature */
4437 if (n_array
== 0 || (n_array
== UINT_MAX
&& n_struct
== 0)) {
4438 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4444 r
= sd_bus_message_exit_container(m
);
4452 if (n_array
!= UINT_MAX
)
4461 case SD_BUS_TYPE_BYTE
:
4462 case SD_BUS_TYPE_BOOLEAN
:
4463 case SD_BUS_TYPE_INT16
:
4464 case SD_BUS_TYPE_UINT16
:
4465 case SD_BUS_TYPE_INT32
:
4466 case SD_BUS_TYPE_UINT32
:
4467 case SD_BUS_TYPE_INT64
:
4468 case SD_BUS_TYPE_UINT64
:
4469 case SD_BUS_TYPE_DOUBLE
:
4470 case SD_BUS_TYPE_STRING
:
4471 case SD_BUS_TYPE_OBJECT_PATH
:
4472 case SD_BUS_TYPE_SIGNATURE
:
4473 case SD_BUS_TYPE_UNIX_FD
: {
4476 p
= va_arg(ap
, void*);
4477 r
= sd_bus_message_read_basic(m
, *t
, p
);
4490 case SD_BUS_TYPE_ARRAY
: {
4493 r
= signature_element_length(t
+ 1, &k
);
4499 memcpy(s
, t
+ 1, k
);
4502 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4513 if (n_array
== UINT_MAX
) {
4518 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4524 n_array
= va_arg(ap
, unsigned);
4529 case SD_BUS_TYPE_VARIANT
: {
4532 s
= va_arg(ap
, const char *);
4536 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4546 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4551 n_struct
= strlen(s
);
4557 case SD_BUS_TYPE_STRUCT_BEGIN
:
4558 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4561 r
= signature_element_length(t
, &k
);
4567 memcpy(s
, t
+ 1, k
- 2);
4570 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4580 if (n_array
== UINT_MAX
) {
4585 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4604 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4608 va_start(ap
, types
);
4609 r
= sd_bus_message_readv(m
, types
, ap
);
4615 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4618 assert_return(m
, -EINVAL
);
4619 assert_return(m
->sealed
, -EPERM
);
4621 /* If types is NULL, read exactly one element */
4623 struct bus_container
*c
;
4626 if (message_end_of_signature(m
))
4629 if (message_end_of_array(m
, m
->rindex
))
4632 c
= message_get_last_container(m
);
4634 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4638 types
= strndupa_safe(c
->signature
+ c
->index
, l
);
4643 case 0: /* Nothing to drop */
4646 case SD_BUS_TYPE_BYTE
:
4647 case SD_BUS_TYPE_BOOLEAN
:
4648 case SD_BUS_TYPE_INT16
:
4649 case SD_BUS_TYPE_UINT16
:
4650 case SD_BUS_TYPE_INT32
:
4651 case SD_BUS_TYPE_UINT32
:
4652 case SD_BUS_TYPE_INT64
:
4653 case SD_BUS_TYPE_UINT64
:
4654 case SD_BUS_TYPE_DOUBLE
:
4655 case SD_BUS_TYPE_STRING
:
4656 case SD_BUS_TYPE_OBJECT_PATH
:
4657 case SD_BUS_TYPE_SIGNATURE
:
4658 case SD_BUS_TYPE_UNIX_FD
:
4660 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4664 r
= sd_bus_message_skip(m
, types
+ 1);
4670 case SD_BUS_TYPE_ARRAY
: {
4673 r
= signature_element_length(types
+ 1, &k
);
4679 memcpy(s
, types
+1, k
);
4682 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4687 r
= sd_bus_message_skip(m
, s
);
4694 r
= sd_bus_message_exit_container(m
);
4699 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4706 case SD_BUS_TYPE_VARIANT
: {
4707 const char *contents
;
4710 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4714 if (x
!= SD_BUS_TYPE_VARIANT
)
4717 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4721 r
= sd_bus_message_skip(m
, contents
);
4726 r
= sd_bus_message_exit_container(m
);
4730 r
= sd_bus_message_skip(m
, types
+ 1);
4737 case SD_BUS_TYPE_STRUCT_BEGIN
:
4738 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4741 r
= signature_element_length(types
, &k
);
4747 memcpy(s
, types
+1, k
-2);
4750 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4754 r
= sd_bus_message_skip(m
, s
);
4758 r
= sd_bus_message_exit_container(m
);
4763 r
= sd_bus_message_skip(m
, types
+ k
);
4775 _public_
int sd_bus_message_read_array(
4781 struct bus_container
*c
;
4787 assert_return(m
, -EINVAL
);
4788 assert_return(m
->sealed
, -EPERM
);
4789 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4790 assert_return(ptr
, -EINVAL
);
4791 assert_return(size
, -EINVAL
);
4792 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4794 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4803 c
= message_get_last_container(m
);
4805 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4806 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4810 sz
= c
->end
- c
->begin
;
4812 align
= bus_type_get_alignment(type
);
4816 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4820 /* Zero length array, let's return some aligned
4821 * pointer that is not NULL */
4822 p
= (uint8_t*) align
;
4824 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4829 r
= sd_bus_message_exit_container(m
);
4833 *ptr
= (const void*) p
;
4839 message_quit_container(m
);
4843 static int message_peek_fields(
4854 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4857 static int message_peek_field_uint32(
4869 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4872 /* identical for gvariant and dbus1 */
4874 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4879 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4884 static int message_peek_field_uint64(
4896 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4899 /* identical for gvariant and dbus1 */
4901 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4906 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4911 static int message_peek_field_string(
4913 bool (*validate
)(const char *p
),
4925 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4930 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4936 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4940 if (l
== UINT32_MAX
)
4941 /* avoid overflow right below */
4944 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4950 if (!validate_nul(q
, l
))
4956 if (!validate_string(q
, l
))
4966 static int message_peek_field_signature(
4979 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4984 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4990 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
4996 /* avoid overflow right below */
4999 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
5004 if (!validate_signature(q
, l
))
5013 static int message_skip_fields(
5016 uint32_t array_size
,
5017 const char **signature
) {
5019 size_t original_index
;
5025 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
5027 original_index
= *ri
;
5033 if (array_size
!= UINT32_MAX
&&
5034 array_size
<= *ri
- original_index
)
5041 if (t
== SD_BUS_TYPE_STRING
) {
5043 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
5049 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
5051 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
5057 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
5059 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
5065 } else if (bus_type_is_basic(t
)) {
5068 align
= bus_type_get_alignment(t
);
5069 k
= bus_type_get_size(t
);
5070 assert(align
> 0 && k
> 0);
5072 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
5078 } else if (t
== SD_BUS_TYPE_ARRAY
) {
5080 r
= signature_element_length(*signature
+ 1, &l
);
5086 char sig
[l
+ 1], *s
= sig
;
5090 strncpy(sig
, *signature
+ 1, l
);
5093 alignment
= bus_type_get_alignment(sig
[0]);
5097 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5100 if (nas
> BUS_ARRAY_MAX_SIZE
)
5103 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5107 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5112 (*signature
) += 1 + l
;
5114 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5117 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5121 r
= message_skip_fields(m
, ri
, UINT32_MAX
, (const char**) &s
);
5127 } else if (IN_SET(t
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
5129 r
= signature_element_length(*signature
, &l
);
5135 char sig
[l
+ 1], *s
= sig
;
5136 strncpy(sig
, *signature
+ 1, l
);
5139 r
= message_skip_fields(m
, ri
, UINT32_MAX
, (const char**) &s
);
5150 int bus_message_parse_fields(sd_bus_message
*m
) {
5153 uint32_t unix_fds
= 0;
5154 bool unix_fds_set
= false;
5155 void *offsets
= NULL
;
5156 unsigned n_offsets
= 0;
5162 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5165 /* Read the signature from the end of the body variant first */
5166 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5167 if (m
->footer_accessible
< 1 + sz
)
5170 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5172 if (p
< (char*) m
->footer
)
5176 _cleanup_free_
char *k
= NULL
;
5179 /* We found the beginning of the signature
5180 * string, yay! We require the body to be a
5181 * structure, so verify it and then strip the
5182 * opening/closing brackets. */
5184 l
= (char*) m
->footer
+ m
->footer_accessible
- p
- (1 + sz
);
5186 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5187 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5190 k
= memdup_suffix0(p
+ 1 + 1, l
- 2);
5194 if (!signature_is_valid(k
, true))
5197 free_and_replace(m
->root_container
.signature
, k
);
5204 /* Calculate the actual user body size, by removing
5205 * the trailing variant signature and struct offset
5207 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5209 /* Pull out the offset table for the fields array, if any */
5210 if (m
->fields_size
> 0) {
5211 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5216 if (m
->fields_size
< sz
)
5219 ri
= m
->fields_size
- sz
;
5220 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5224 framing
= bus_gvariant_read_word_le(q
, sz
);
5225 if (framing
>= m
->fields_size
- sz
)
5227 if ((m
->fields_size
- framing
) % sz
!= 0)
5231 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5235 n_offsets
= (m
->fields_size
- framing
) / sz
;
5239 m
->user_body_size
= m
->body_size
;
5242 while (ri
< m
->fields_size
) {
5243 _cleanup_free_
char *sig
= NULL
;
5244 const char *signature
;
5245 uint64_t field_type
;
5246 size_t item_size
= SIZE_MAX
;
5248 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5257 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5259 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5263 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5267 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5274 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5279 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5284 where
= ri
= ALIGN_TO(ri
, 8);
5285 item_size
= end
- ri
;
5286 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5290 b
= memrchr(q
, 0, item_size
);
5294 sig
= memdup_suffix0(b
+1, item_size
- (b
+1-(char*) q
));
5299 item_size
= b
- (char*) q
;
5301 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5306 switch (field_type
) {
5308 case _BUS_MESSAGE_HEADER_INVALID
:
5311 case BUS_MESSAGE_HEADER_PATH
:
5316 if (!streq(signature
, "o"))
5319 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5322 case BUS_MESSAGE_HEADER_INTERFACE
:
5327 if (!streq(signature
, "s"))
5330 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5333 case BUS_MESSAGE_HEADER_MEMBER
:
5338 if (!streq(signature
, "s"))
5341 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5344 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5349 if (!streq(signature
, "s"))
5352 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5354 m
->error
._need_free
= -1;
5358 case BUS_MESSAGE_HEADER_DESTINATION
:
5363 if (!streq(signature
, "s"))
5366 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5369 case BUS_MESSAGE_HEADER_SENDER
:
5374 if (!streq(signature
, "s"))
5377 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5379 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
) {
5380 m
->creds
.unique_name
= (char*) m
->sender
;
5381 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5386 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5390 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5393 if (m
->root_container
.signature
)
5396 if (!streq(signature
, "g"))
5399 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5407 free_and_replace(m
->root_container
.signature
, c
);
5411 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5413 if (m
->reply_cookie
!= 0)
5416 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5417 /* 64bit on dbus2 */
5419 if (!streq(signature
, "t"))
5422 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5426 /* 32bit on dbus1 */
5429 if (!streq(signature
, "u"))
5432 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5436 m
->reply_cookie
= serial
;
5439 if (m
->reply_cookie
== 0)
5444 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5448 if (!streq(signature
, "u"))
5451 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5455 unix_fds_set
= true;
5459 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5460 r
= message_skip_fields(m
, &ri
, UINT32_MAX
, (const char **) &signature
);
5469 if (m
->n_fds
!= unix_fds
)
5472 switch (m
->header
->type
) {
5474 case SD_BUS_MESSAGE_SIGNAL
:
5475 if (!m
->path
|| !m
->interface
|| !m
->member
)
5478 if (m
->reply_cookie
!= 0)
5483 case SD_BUS_MESSAGE_METHOD_CALL
:
5485 if (!m
->path
|| !m
->member
)
5488 if (m
->reply_cookie
!= 0)
5493 case SD_BUS_MESSAGE_METHOD_RETURN
:
5495 if (m
->reply_cookie
== 0)
5499 case SD_BUS_MESSAGE_METHOD_ERROR
:
5501 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5506 /* Refuse non-local messages that claim they are local */
5507 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5509 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5511 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5514 m
->root_container
.end
= m
->user_body_size
;
5516 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5517 r
= build_struct_offsets(
5519 m
->root_container
.signature
,
5521 &m
->root_container
.item_size
,
5522 &m
->root_container
.offsets
,
5523 &m
->root_container
.n_offsets
);
5530 /* Try to read the error message, but if we can't it's a non-issue */
5531 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5532 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5537 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5538 assert_return(m
, -EINVAL
);
5539 assert_return(destination
, -EINVAL
);
5540 assert_return(service_name_is_valid(destination
), -EINVAL
);
5541 assert_return(!m
->sealed
, -EPERM
);
5542 assert_return(!m
->destination
, -EEXIST
);
5544 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5547 _public_
int sd_bus_message_set_sender(sd_bus_message
*m
, const char *sender
) {
5548 assert_return(m
, -EINVAL
);
5549 assert_return(sender
, -EINVAL
);
5550 assert_return(service_name_is_valid(sender
), -EINVAL
);
5551 assert_return(!m
->sealed
, -EPERM
);
5552 assert_return(!m
->sender
, -EEXIST
);
5554 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5557 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5561 struct bus_body_part
*part
;
5567 total
= BUS_MESSAGE_SIZE(m
);
5573 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5574 MESSAGE_FOREACH_PART(part
, i
, m
)
5575 e
= mempcpy(e
, part
->data
, part
->size
);
5577 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5585 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5587 const char *contents
, *s
;
5593 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5597 if (type
!= SD_BUS_TYPE_ARRAY
|| !STR_IN_SET(contents
, "s", "o", "g"))
5600 r
= sd_bus_message_enter_container(m
, 'a', NULL
);
5604 /* sd_bus_message_read_basic() does content validation for us. */
5605 while ((r
= sd_bus_message_read_basic(m
, *contents
, &s
)) > 0) {
5606 r
= strv_extend(l
, s
);
5613 r
= sd_bus_message_exit_container(m
);
5620 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5621 _cleanup_strv_free_
char **strv
= NULL
;
5624 assert_return(m
, -EINVAL
);
5625 assert_return(m
->sealed
, -EPERM
);
5626 assert_return(l
, -EINVAL
);
5628 r
= bus_message_read_strv_extend(m
, &strv
);
5632 *l
= TAKE_PTR(strv
);
5636 static int bus_message_get_arg_skip(
5640 const char **_contents
) {
5645 r
= sd_bus_message_rewind(m
, true);
5650 const char *contents
;
5653 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5659 /* Don't match against arguments after the first one we don't understand */
5660 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5661 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5666 *_contents
= contents
;
5672 r
= sd_bus_message_skip(m
, NULL
);
5679 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5686 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5690 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5693 return sd_bus_message_read_basic(m
, type
, str
);
5696 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5697 const char *contents
;
5704 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5708 if (type
!= SD_BUS_TYPE_ARRAY
)
5710 if (!STR_IN_SET(contents
, "s", "o", "g"))
5713 return sd_bus_message_read_strv(m
, strv
);
5716 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5717 assert_return(m
, EINVAL
);
5719 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5722 return sd_bus_error_get_errno(&m
->error
);
5725 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5726 struct bus_container
*c
;
5728 assert_return(m
, NULL
);
5730 c
= complete
? &m
->root_container
: message_get_last_container(m
);
5731 return strempty(c
->signature
);
5734 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5735 assert_return(m
, -EINVAL
);
5737 return isempty(m
->root_container
.signature
);
5740 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5741 assert_return(m
, -EINVAL
);
5743 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5746 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5747 bool done_something
= false;
5750 assert_return(m
, -EINVAL
);
5751 assert_return(source
, -EINVAL
);
5752 assert_return(!m
->sealed
, -EPERM
);
5753 assert_return(source
->sealed
, -EPERM
);
5756 const char *contents
;
5771 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5777 done_something
= true;
5779 if (bus_type_is_container(type
) > 0) {
5781 r
= sd_bus_message_enter_container(source
, type
, contents
);
5785 r
= sd_bus_message_open_container(m
, type
, contents
);
5789 r
= sd_bus_message_copy(m
, source
, true);
5793 r
= sd_bus_message_close_container(m
);
5797 r
= sd_bus_message_exit_container(source
);
5804 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5810 if (IN_SET(type
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
, SD_BUS_TYPE_STRING
))
5811 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5813 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5820 return done_something
;
5823 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5828 assert_return(m
, -EINVAL
);
5829 assert_return(m
->sealed
, -EPERM
);
5830 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5831 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5832 assert_return(type
|| contents
, -EINVAL
);
5833 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5835 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5839 if (type
!= 0 && type
!= t
)
5842 if (contents
&& !streq_ptr(contents
, c
))
5848 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5849 assert_return(m
, NULL
);
5854 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5855 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
5863 switch ((*m
)->header
->type
) {
5865 case SD_BUS_MESSAGE_SIGNAL
:
5866 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5872 case SD_BUS_MESSAGE_METHOD_CALL
:
5873 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5879 case SD_BUS_MESSAGE_METHOD_RETURN
:
5880 case SD_BUS_MESSAGE_METHOD_ERROR
:
5882 r
= sd_bus_message_new(bus
, &n
, (*m
)->header
->type
);
5888 n
->reply_cookie
= (*m
)->reply_cookie
;
5890 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5894 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5895 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5899 n
->error
._need_free
= -1;
5908 if ((*m
)->destination
&& !n
->destination
) {
5909 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5914 if ((*m
)->sender
&& !n
->sender
) {
5915 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5920 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5922 r
= sd_bus_message_copy(n
, *m
, true);
5926 timeout
= (*m
)->timeout
;
5927 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
)) {
5928 r
= sd_bus_get_method_call_timeout(bus
, &timeout
);
5933 r
= sd_bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5937 sd_bus_message_unref(*m
);
5943 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5944 static bool warned
= false;
5946 assert_return(m
, -EINVAL
);
5947 assert_return(priority
, -EINVAL
);
5950 log_debug("sd_bus_message_get_priority() is deprecated and always returns 0.");
5958 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5959 static bool warned
= false;
5961 assert_return(m
, -EINVAL
);
5962 assert_return(!m
->sealed
, -EPERM
);
5965 log_debug("sd_bus_message_set_priority() is deprecated and does nothing.");
5972 _public_
int sd_bus_message_sensitive(sd_bus_message
*m
) {
5973 assert_return(m
, -EINVAL
);
5975 m
->sensitive
= true;