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
->containers_allocated
= 0;
121 m
->root_container
.index
= 0;
124 static sd_bus_message
* message_free(sd_bus_message
*m
) {
127 message_reset_parts(m
);
132 /* Note that we don't unref m->bus here. That's already done by sd_bus_message_unref() as each user
133 * reference to the bus message also is considered a reference to the bus connection itself. */
136 close_many(m
->fds
, m
->n_fds
);
140 if (m
->iovec
!= m
->iovec_fixed
)
143 message_reset_containers(m
);
144 assert(m
->n_containers
== 0);
145 message_free_last_container(m
);
147 bus_creds_done(&m
->creds
);
151 static void *message_extend_fields(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
153 size_t old_size
, new_size
, start
;
160 old_size
= sizeof(struct bus_header
) + m
->fields_size
;
161 start
= ALIGN_TO(old_size
, align
);
162 new_size
= start
+ sz
;
164 if (new_size
< start
||
165 new_size
> (size_t) ((uint32_t) -1))
168 if (old_size
== new_size
)
169 return (uint8_t*) m
->header
+ old_size
;
171 if (m
->free_header
) {
172 np
= realloc(m
->header
, ALIGN8(new_size
));
176 /* Initially, the header is allocated as part of
177 * the sd_bus_message itself, let's replace it by
180 np
= malloc(ALIGN8(new_size
));
184 memcpy(np
, m
->header
, sizeof(struct bus_header
));
187 /* Zero out padding */
188 if (start
> old_size
)
189 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
193 m
->fields_size
= new_size
- sizeof(struct bus_header
);
195 /* Adjust quick access pointers */
196 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
197 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
198 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
199 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
200 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
201 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
203 m
->free_header
= true;
206 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
209 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
212 return (uint8_t*) np
+ start
;
219 static int message_append_field_string(
231 /* dbus1 only allows 8bit header field ids */
235 /* dbus1 doesn't allow strings over 32bit, let's enforce this
236 * globally, to not risk convertability */
241 /* Signature "(yv)" where the variant contains "s" */
243 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
245 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
246 p
= message_extend_fields(m
, 8, 8 + l
+ 1 + 1 + 1, true);
250 *((uint64_t*) p
) = h
;
257 *ret
= (char*) p
+ 8;
260 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
261 p
= message_extend_fields(m
, 8, 4 + 4 + l
+ 1, false);
270 ((uint32_t*) p
)[1] = l
;
271 memcpy(p
+ 8, s
, l
+ 1);
274 *ret
= (char*) p
+ 8;
280 static int message_append_field_signature(
291 /* dbus1 only allows 8bit header field ids */
295 /* dbus1 doesn't allow signatures over 8bit, let's enforce
296 * this globally, to not risk convertability */
298 if (l
> SD_BUS_MAXIMUM_SIGNATURE_LENGTH
)
301 /* Signature "(yv)" where the variant contains "g" */
303 if (BUS_MESSAGE_IS_GVARIANT(m
))
304 /* For gvariant the serialization is the same as for normal strings */
305 return message_append_field_string(m
, h
, 'g', s
, ret
);
307 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
308 p
= message_extend_fields(m
, 8, 4 + 1 + l
+ 1, false);
314 p
[2] = SD_BUS_TYPE_SIGNATURE
;
317 memcpy(p
+ 5, s
, l
+ 1);
320 *ret
= (const char*) p
+ 5;
326 static int message_append_field_uint32(sd_bus_message
*m
, uint64_t h
, uint32_t x
) {
331 /* dbus1 only allows 8bit header field ids */
335 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
336 /* (field id 64bit + ((value + NUL + signature string 'u') */
338 p
= message_extend_fields(m
, 8, 8 + 4 + 1 + 1, true);
342 *((uint64_t*) p
) = h
;
343 *((uint32_t*) (p
+ 8)) = x
;
347 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
348 p
= message_extend_fields(m
, 8, 4 + 4, false);
357 ((uint32_t*) p
)[1] = x
;
363 static int message_append_field_uint64(sd_bus_message
*m
, uint64_t h
, uint64_t x
) {
368 /* dbus1 only allows 8bit header field ids */
372 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
373 /* (field id 64bit + ((value + NUL + signature string 't') */
375 p
= message_extend_fields(m
, 8, 8 + 8 + 1 + 1, true);
379 *((uint64_t*) p
) = h
;
380 *((uint64_t*) (p
+ 8)) = x
;
384 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
385 p
= message_extend_fields(m
, 8, 4 + 4 + 8, false);
398 ((uint64_t*) p
)[1] = x
;
404 static int message_append_reply_cookie(sd_bus_message
*m
, uint64_t cookie
) {
407 if (BUS_MESSAGE_IS_GVARIANT(m
))
408 return message_append_field_uint64(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, cookie
);
410 /* 64bit cookies are not supported on dbus1 */
411 if (cookie
> 0xffffffffUL
)
414 return message_append_field_uint32(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) cookie
);
418 int bus_message_from_header(
421 size_t header_accessible
,
423 size_t footer_accessible
,
429 sd_bus_message
**ret
) {
431 _cleanup_free_ sd_bus_message
*m
= NULL
;
432 struct bus_header
*h
;
436 assert(header
|| header_accessible
<= 0);
437 assert(footer
|| footer_accessible
<= 0);
438 assert(fds
|| n_fds
<= 0);
441 if (header_accessible
< sizeof(struct bus_header
))
444 if (header_accessible
> message_size
)
446 if (footer_accessible
> message_size
)
450 if (!IN_SET(h
->version
, 1, 2))
453 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
456 if (!IN_SET(h
->endian
, BUS_LITTLE_ENDIAN
, BUS_BIG_ENDIAN
))
459 /* Note that we are happy with unknown flags in the flags header! */
461 a
= ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
464 label_sz
= strlen(label
);
474 m
->header_accessible
= header_accessible
;
476 m
->footer_accessible
= footer_accessible
;
478 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
481 if (h
->dbus2
.cookie
== 0)
484 /* dbus2 derives the sizes from the message size and
485 the offset table at the end, since it is formatted as
486 gvariant "yyyyuta{tv}v". Since the message itself is a
487 structure with precisely to variable sized entries,
488 there's only one offset in the table, which marks the
489 end of the fields array. */
491 ws
= bus_gvariant_determine_word_size(message_size
, 0);
492 if (footer_accessible
< ws
)
495 m
->fields_size
= bus_gvariant_read_word_le((uint8_t*) footer
+ footer_accessible
- ws
, ws
);
496 if (ALIGN8(m
->fields_size
) > message_size
- ws
)
498 if (m
->fields_size
< sizeof(struct bus_header
))
501 m
->fields_size
-= sizeof(struct bus_header
);
502 m
->body_size
= message_size
- (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
));
504 if (h
->dbus1
.serial
== 0)
507 /* dbus1 has the sizes in the header */
508 m
->fields_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.fields_size
);
509 m
->body_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.body_size
);
511 if (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
!= message_size
)
519 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
520 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
522 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
526 m
->bus
= sd_bus_ref(bus
);
533 int bus_message_from_malloc(
540 sd_bus_message
**ret
) {
542 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
546 r
= bus_message_from_header(
548 buffer
, length
, /* in this case the initial bytes and the final bytes are the same */
557 sz
= length
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
);
560 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(m
->fields_size
);
562 m
->body
.sealed
= true;
567 m
->iovec
= m
->iovec_fixed
;
568 m
->iovec
[0] = IOVEC_MAKE(buffer
, length
);
570 r
= bus_message_parse_fields(m
);
574 /* We take possession of the memory and fds now */
575 m
->free_header
= true;
582 _public_
int sd_bus_message_new(
587 assert_return(bus
, -ENOTCONN
);
588 assert_return(bus
= bus_resolve(bus
), -ENOPKG
);
589 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
590 assert_return(m
, -EINVAL
);
591 /* Creation of messages with _SD_BUS_MESSAGE_TYPE_INVALID is allowed. */
592 assert_return(type
< _SD_BUS_MESSAGE_TYPE_MAX
, -EINVAL
);
594 sd_bus_message
*t
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
599 t
->bus
= sd_bus_ref(bus
);
600 t
->header
= (struct bus_header
*) ((uint8_t*) t
+ ALIGN(sizeof(struct sd_bus_message
)));
601 t
->header
->endian
= BUS_NATIVE_ENDIAN
;
602 t
->header
->type
= type
;
603 t
->header
->version
= bus
->message_version
;
604 t
->allow_fds
= bus
->can_fds
|| !IN_SET(bus
->state
, BUS_HELLO
, BUS_RUNNING
);
605 t
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(t
);
607 if (bus
->allow_interactive_authorization
)
608 t
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
614 _public_
int sd_bus_message_new_signal(
618 const char *interface
,
619 const char *member
) {
621 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
624 assert_return(bus
, -ENOTCONN
);
625 assert_return(bus
= bus_resolve(bus
), -ENOPKG
);
626 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
627 assert_return(object_path_is_valid(path
), -EINVAL
);
628 assert_return(interface_name_is_valid(interface
), -EINVAL
);
629 assert_return(member_name_is_valid(member
), -EINVAL
);
630 assert_return(m
, -EINVAL
);
632 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_SIGNAL
);
638 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
640 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
643 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
646 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
654 _public_
int sd_bus_message_new_method_call(
657 const char *destination
,
659 const char *interface
,
660 const char *member
) {
662 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
665 assert_return(bus
, -ENOTCONN
);
666 assert_return(bus
= bus_resolve(bus
), -ENOPKG
);
667 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
668 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
669 assert_return(object_path_is_valid(path
), -EINVAL
);
670 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
671 assert_return(member_name_is_valid(member
), -EINVAL
);
672 assert_return(m
, -EINVAL
);
674 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_CALL
);
680 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
683 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
688 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
694 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
703 static int message_new_reply(
704 sd_bus_message
*call
,
706 sd_bus_message
**m
) {
708 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
712 assert_return(call
, -EINVAL
);
713 assert_return(call
->sealed
, -EPERM
);
714 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
715 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
716 assert_return(m
, -EINVAL
);
718 cookie
= BUS_MESSAGE_COOKIE(call
);
722 r
= sd_bus_message_new(call
->bus
, &t
, type
);
728 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
729 t
->reply_cookie
= cookie
;
730 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
735 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
740 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
741 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
743 /* let's copy the sensitive flag over. Let's do that as a safety precaution to keep a transaction
744 * wholly sensitive if already the incoming message was sensitive. This is particularly useful when a
745 * vtable record sets the SD_BUS_VTABLE_SENSITIVE flag on a method call, since this means it applies
746 * to both the message call and the reply. */
747 t
->sensitive
= call
->sensitive
;
753 _public_
int sd_bus_message_new_method_return(
754 sd_bus_message
*call
,
755 sd_bus_message
**m
) {
757 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
760 _public_
int sd_bus_message_new_method_error(
761 sd_bus_message
*call
,
763 const sd_bus_error
*e
) {
765 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
768 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
769 assert_return(m
, -EINVAL
);
771 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
775 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
780 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
785 t
->error
._need_free
= -1;
791 _public_
int sd_bus_message_new_method_errorf(
792 sd_bus_message
*call
,
798 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
801 assert_return(name
, -EINVAL
);
802 assert_return(m
, -EINVAL
);
804 va_start(ap
, format
);
805 bus_error_setfv(&error
, name
, format
, ap
);
808 return sd_bus_message_new_method_error(call
, m
, &error
);
811 _public_
int sd_bus_message_new_method_errno(
812 sd_bus_message
*call
,
815 const sd_bus_error
*p
) {
817 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
819 if (sd_bus_error_is_set(p
))
820 return sd_bus_message_new_method_error(call
, m
, p
);
822 sd_bus_error_set_errno(&berror
, error
);
824 return sd_bus_message_new_method_error(call
, m
, &berror
);
827 _public_
int sd_bus_message_new_method_errnof(
828 sd_bus_message
*call
,
834 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
837 va_start(ap
, format
);
838 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
841 return sd_bus_message_new_method_error(call
, m
, &berror
);
844 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
848 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
849 m
->creds
.well_known_names_local
= true;
850 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
853 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
857 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
858 m
->creds
.well_known_names_driver
= true;
859 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
862 int bus_message_new_synthetic_error(
865 const sd_bus_error
*e
,
866 sd_bus_message
**m
) {
868 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*t
= NULL
;
872 assert(sd_bus_error_is_set(e
));
875 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_ERROR
);
881 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
882 t
->reply_cookie
= cookie
;
884 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
888 if (bus
&& bus
->unique_name
) {
889 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
894 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
899 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
904 t
->error
._need_free
= -1;
906 bus_message_set_sender_driver(bus
, t
);
912 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
916 /* We are fine if this message so far was either explicitly reffed or not reffed but queued into at
917 * least one bus connection object. */
918 assert(m
->n_ref
> 0 || m
->n_queued
> 0);
922 /* Each user reference to a bus message shall also be considered a ref on the bus */
927 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
931 assert(m
->n_ref
> 0);
933 sd_bus_unref(m
->bus
); /* Each regular ref is also a ref on the bus connection. Let's hence drop it
934 * here. Note we have to do this before decrementing our own n_ref here, since
935 * otherwise, if this message is currently queued sd_bus_unref() might call
936 * bus_message_unref_queued() for this which might then destroy the message
937 * while we are still processing it. */
940 if (m
->n_ref
> 0 || m
->n_queued
> 0)
943 /* Unset the bus field if neither the user has a reference nor this message is queued. We are careful
944 * to reset the field only after the last reference to the bus is dropped, after all we might keep
945 * multiple references to the bus, once for each reference kept on ourselves. */
948 return message_free(m
);
951 sd_bus_message
* bus_message_ref_queued(sd_bus_message
*m
, sd_bus
*bus
) {
955 /* If this is a different bus than the message is associated with, then implicitly turn this into a
956 * regular reference. This means that you can create a memory leak by enqueuing a message generated
957 * on one bus onto another at the same time as enqueueing a message from the second one on the first,
958 * as we'll not detect the cyclic references there. */
960 return sd_bus_message_ref(m
);
962 assert(m
->n_ref
> 0 || m
->n_queued
> 0);
968 sd_bus_message
* bus_message_unref_queued(sd_bus_message
*m
, sd_bus
*bus
) {
973 return sd_bus_message_unref(m
);
975 assert(m
->n_queued
> 0);
978 if (m
->n_ref
> 0 || m
->n_queued
> 0)
983 return message_free(m
);
986 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
987 assert_return(m
, -EINVAL
);
988 assert_return(type
, -EINVAL
);
990 *type
= m
->header
->type
;
994 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
997 assert_return(m
, -EINVAL
);
998 assert_return(cookie
, -EINVAL
);
1000 c
= BUS_MESSAGE_COOKIE(m
);
1004 *cookie
= BUS_MESSAGE_COOKIE(m
);
1008 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
1009 assert_return(m
, -EINVAL
);
1010 assert_return(cookie
, -EINVAL
);
1012 if (m
->reply_cookie
== 0)
1015 *cookie
= m
->reply_cookie
;
1019 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
1020 assert_return(m
, -EINVAL
);
1022 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
1023 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
1026 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
1027 assert_return(m
, -EINVAL
);
1029 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
1032 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
1033 assert_return(m
, -EINVAL
);
1035 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
1036 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
1039 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
1040 assert_return(m
, NULL
);
1045 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
1046 assert_return(m
, NULL
);
1048 return m
->interface
;
1051 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
1052 assert_return(m
, NULL
);
1057 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
1058 assert_return(m
, NULL
);
1060 return m
->destination
;
1063 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
1064 assert_return(m
, NULL
);
1069 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
1070 assert_return(m
, NULL
);
1072 if (!sd_bus_error_is_set(&m
->error
))
1078 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
1079 assert_return(m
, -EINVAL
);
1080 assert_return(usec
, -EINVAL
);
1082 if (m
->monotonic
<= 0)
1085 *usec
= m
->monotonic
;
1089 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1090 assert_return(m
, -EINVAL
);
1091 assert_return(usec
, -EINVAL
);
1093 if (m
->realtime
<= 0)
1096 *usec
= m
->realtime
;
1100 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1101 assert_return(m
, -EINVAL
);
1102 assert_return(seqnum
, -EINVAL
);
1107 *seqnum
= m
->seqnum
;
1111 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1112 assert_return(m
, NULL
);
1114 if (m
->creds
.mask
== 0)
1120 _public_
int sd_bus_message_is_signal(
1122 const char *interface
,
1123 const char *member
) {
1125 assert_return(m
, -EINVAL
);
1127 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1130 if (interface
&& !streq_ptr(m
->interface
, interface
))
1133 if (member
&& !streq_ptr(m
->member
, member
))
1139 _public_
int sd_bus_message_is_method_call(
1141 const char *interface
,
1142 const char *member
) {
1144 assert_return(m
, -EINVAL
);
1146 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1149 if (interface
&& !streq_ptr(m
->interface
, interface
))
1152 if (member
&& !streq_ptr(m
->member
, member
))
1158 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1159 assert_return(m
, -EINVAL
);
1161 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1164 if (name
&& !streq_ptr(m
->error
.name
, name
))
1170 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1171 assert_return(m
, -EINVAL
);
1172 assert_return(!m
->sealed
, -EPERM
);
1173 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1175 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_REPLY_EXPECTED
, !b
);
1180 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1181 assert_return(m
, -EINVAL
);
1182 assert_return(!m
->sealed
, -EPERM
);
1184 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_AUTO_START
, !b
);
1189 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1190 assert_return(m
, -EINVAL
);
1191 assert_return(!m
->sealed
, -EPERM
);
1193 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
, b
);
1198 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1199 struct bus_body_part
*part
;
1206 if (m
->n_body_parts
<= 0) {
1210 assert(m
->body_end
);
1212 part
= new0(struct bus_body_part
, 1);
1218 m
->body_end
->next
= part
;
1228 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1233 /* All other fields can be left in their defaults */
1234 assert(!part
->data
);
1235 assert(part
->memfd
< 0);
1238 part
->is_zero
= true;
1239 part
->sealed
= true;
1242 static int part_make_space(
1243 struct sd_bus_message
*m
,
1244 struct bus_body_part
*part
,
1252 assert(!part
->sealed
);
1257 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1258 size_t new_allocated
;
1260 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1261 n
= realloc(part
->data
, new_allocated
);
1268 part
->allocated
= new_allocated
;
1269 part
->free_this
= true;
1273 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1279 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1280 struct bus_container
*c
;
1283 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1285 /* Add offset to current container, unless this is the first
1286 * item in it, which will have the 0 offset, which we can
1288 c
= message_get_last_container(m
);
1290 if (!c
->need_offsets
)
1293 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1296 c
->offsets
[c
->n_offsets
++] = offset
;
1300 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1306 if (m
->n_containers
<= 0)
1309 /* Update counters */
1310 for (struct bus_container
*c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1312 *c
->array_size
+= expand
;
1315 static void *message_extend_body(
1320 bool force_inline
) {
1322 size_t start_body
, end_body
, padding
, added
;
1333 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1334 end_body
= start_body
+ sz
;
1336 padding
= start_body
- m
->body_size
;
1337 added
= padding
+ sz
;
1339 /* Check for 32bit overflows */
1340 if (end_body
> (size_t) ((uint32_t) -1) ||
1341 end_body
< start_body
) {
1347 struct bus_body_part
*part
= NULL
;
1351 m
->n_body_parts
<= 0 ||
1352 m
->body_end
->sealed
||
1353 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1354 (force_inline
&& m
->body_end
->size
> MEMFD_MIN_SIZE
);
1355 /* If this must be an inlined extension, let's create a new part if
1356 * the previous part is large enough to be inlined. */
1360 part
= message_append_part(m
);
1364 part_zero(part
, padding
);
1367 part
= message_append_part(m
);
1371 r
= part_make_space(m
, part
, sz
, &p
);
1376 size_t os
, start_part
, end_part
;
1382 start_part
= ALIGN_TO(part
->size
, align
);
1383 end_part
= start_part
+ sz
;
1385 r
= part_make_space(m
, part
, end_part
, &p
);
1390 memzero(p
, padding
);
1391 p
= (uint8_t*) p
+ padding
;
1394 /* Readjust pointers */
1395 if (m
->n_containers
> 0)
1396 for (struct bus_container
*c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1397 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1399 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1402 /* Return something that is not NULL and is aligned */
1403 p
= (uint8_t*) align
;
1405 m
->body_size
= end_body
;
1406 message_extend_containers(m
, added
);
1409 r
= message_add_offset(m
, end_body
);
1419 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1430 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1434 f
= reallocarray(m
->fds
, sizeof(int), m
->n_fds
+ 1);
1442 m
->fds
[m
->n_fds
] = copy
;
1448 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1449 _cleanup_close_
int fd
= -1;
1450 struct bus_container
*c
;
1454 assert_return(m
, -EINVAL
);
1455 assert_return(!m
->sealed
, -EPERM
);
1456 assert_return(bus_type_is_basic(type
), -EINVAL
);
1457 assert_return(!m
->poisoned
, -ESTALE
);
1459 c
= message_get_last_container(m
);
1461 if (c
->signature
&& c
->signature
[c
->index
]) {
1462 /* Container signature is already set */
1464 if (c
->signature
[c
->index
] != type
)
1469 /* Maybe we can append to the signature? But only if this is the top-level container */
1470 if (c
->enclosing
!= 0)
1473 e
= strextend(&c
->signature
, CHAR_TO_STR(type
));
1480 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1486 case SD_BUS_TYPE_SIGNATURE
:
1487 case SD_BUS_TYPE_STRING
:
1491 case SD_BUS_TYPE_OBJECT_PATH
:
1499 case SD_BUS_TYPE_BOOLEAN
:
1501 u8
= p
&& *(int*) p
;
1507 case SD_BUS_TYPE_UNIX_FD
:
1512 fd
= message_push_fd(m
, *(int*) p
);
1523 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1524 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1531 a
= message_extend_body(m
, align
, sz
, true, false);
1538 *stored
= (const uint8_t*) a
;
1545 case SD_BUS_TYPE_STRING
:
1546 /* To make things easy we'll serialize a NULL string
1547 * into the empty string */
1551 case SD_BUS_TYPE_OBJECT_PATH
:
1557 sz
= 4 + strlen(p
) + 1;
1560 case SD_BUS_TYPE_SIGNATURE
:
1565 sz
= 1 + strlen(p
) + 1;
1568 case SD_BUS_TYPE_BOOLEAN
:
1570 u32
= p
&& *(int*) p
;
1576 case SD_BUS_TYPE_UNIX_FD
:
1581 fd
= message_push_fd(m
, *(int*) p
);
1592 align
= bus_type_get_alignment(type
);
1593 sz
= bus_type_get_size(type
);
1600 a
= message_extend_body(m
, align
, sz
, false, false);
1604 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
1605 *(uint32_t*) a
= sz
- 5;
1606 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1609 *stored
= (const uint8_t*) a
+ 4;
1611 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1612 *(uint8_t*) a
= sz
- 2;
1613 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1616 *stored
= (const uint8_t*) a
+ 1;
1625 if (type
== SD_BUS_TYPE_UNIX_FD
)
1628 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1635 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1636 return message_append_basic(m
, type
, p
, NULL
);
1639 _public_
int sd_bus_message_append_string_space(
1644 struct bus_container
*c
;
1647 assert_return(m
, -EINVAL
);
1648 assert_return(s
, -EINVAL
);
1649 assert_return(!m
->sealed
, -EPERM
);
1650 assert_return(!m
->poisoned
, -ESTALE
);
1652 c
= message_get_last_container(m
);
1654 if (c
->signature
&& c
->signature
[c
->index
]) {
1655 /* Container signature is already set */
1657 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1662 /* Maybe we can append to the signature? But only if this is the top-level container */
1663 if (c
->enclosing
!= 0)
1666 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
));
1673 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1674 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1680 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1684 *(uint32_t*) a
= size
;
1690 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1696 _public_
int sd_bus_message_append_string_iovec(
1698 const struct iovec
*iov
,
1699 unsigned n
/* should be size_t, but is API now… 😞 */) {
1706 assert_return(m
, -EINVAL
);
1707 assert_return(!m
->sealed
, -EPERM
);
1708 assert_return(iov
|| n
== 0, -EINVAL
);
1709 assert_return(!m
->poisoned
, -ESTALE
);
1711 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1713 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1717 for (i
= 0; i
< n
; i
++) {
1719 if (iov
[i
].iov_base
)
1720 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1722 memset(p
, ' ', iov
[i
].iov_len
);
1724 p
+= iov
[i
].iov_len
;
1730 static int bus_message_open_array(
1732 struct bus_container
*c
,
1733 const char *contents
,
1734 uint32_t **array_size
,
1736 bool *need_offsets
) {
1746 assert(need_offsets
);
1748 if (!signature_is_single(contents
, true))
1751 if (c
->signature
&& c
->signature
[c
->index
]) {
1753 /* Verify the existing signature */
1755 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1758 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1761 nindex
= c
->index
+ 1 + strlen(contents
);
1765 if (c
->enclosing
!= 0)
1768 /* Extend the existing signature */
1770 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
);
1776 nindex
= e
- c
->signature
;
1779 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1780 alignment
= bus_gvariant_get_alignment(contents
);
1784 /* Add alignment padding and add to offset list */
1785 if (!message_extend_body(m
, alignment
, 0, false, false))
1788 r
= bus_gvariant_is_fixed_size(contents
);
1792 *begin
= m
->body_size
;
1793 *need_offsets
= r
== 0;
1797 struct bus_body_part
*o
;
1799 alignment
= bus_type_get_alignment(contents
[0]);
1803 a
= message_extend_body(m
, 4, 4, false, false);
1808 op
= m
->body_end
->data
;
1809 os
= m
->body_end
->size
;
1811 /* Add alignment between size and first element */
1812 if (!message_extend_body(m
, alignment
, 0, false, false))
1815 /* location of array size might have changed so let's readjust a */
1816 if (o
== m
->body_end
)
1817 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1823 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1829 static int bus_message_open_variant(
1831 struct bus_container
*c
,
1832 const char *contents
) {
1838 if (!signature_is_single(contents
, false))
1841 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1844 if (c
->signature
&& c
->signature
[c
->index
]) {
1846 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1852 if (c
->enclosing
!= 0)
1855 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
));
1862 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1863 /* Variants are always aligned to 8 */
1865 if (!message_extend_body(m
, 8, 0, false, false))
1872 l
= strlen(contents
);
1873 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1878 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1881 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1887 static int bus_message_open_struct(
1889 struct bus_container
*c
,
1890 const char *contents
,
1892 bool *need_offsets
) {
1901 assert(need_offsets
);
1903 if (!signature_is_valid(contents
, false))
1906 if (c
->signature
&& c
->signature
[c
->index
]) {
1909 l
= strlen(contents
);
1911 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1912 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1913 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1916 nindex
= c
->index
+ 1 + l
+ 1;
1920 if (c
->enclosing
!= 0)
1923 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
));
1929 nindex
= e
- c
->signature
;
1932 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1935 alignment
= bus_gvariant_get_alignment(contents
);
1939 if (!message_extend_body(m
, alignment
, 0, false, false))
1942 r
= bus_gvariant_is_fixed_size(contents
);
1946 *begin
= m
->body_size
;
1947 *need_offsets
= r
== 0;
1949 /* Align contents to 8 byte boundary */
1950 if (!message_extend_body(m
, 8, 0, false, false))
1954 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1960 static int bus_message_open_dict_entry(
1962 struct bus_container
*c
,
1963 const char *contents
,
1965 bool *need_offsets
) {
1973 assert(need_offsets
);
1975 if (!signature_is_pair(contents
))
1978 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1981 if (c
->signature
&& c
->signature
[c
->index
]) {
1984 l
= strlen(contents
);
1986 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
1987 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1988 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
1993 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1996 alignment
= bus_gvariant_get_alignment(contents
);
2000 if (!message_extend_body(m
, alignment
, 0, false, false))
2003 r
= bus_gvariant_is_fixed_size(contents
);
2007 *begin
= m
->body_size
;
2008 *need_offsets
= r
== 0;
2010 /* Align contents to 8 byte boundary */
2011 if (!message_extend_body(m
, 8, 0, false, false))
2018 _public_
int sd_bus_message_open_container(
2021 const char *contents
) {
2023 struct bus_container
*c
;
2024 uint32_t *array_size
= NULL
;
2025 _cleanup_free_
char *signature
= NULL
;
2026 size_t before
, begin
= 0;
2027 bool need_offsets
= false;
2030 assert_return(m
, -EINVAL
);
2031 assert_return(!m
->sealed
, -EPERM
);
2032 assert_return(contents
, -EINVAL
);
2033 assert_return(!m
->poisoned
, -ESTALE
);
2035 /* Make sure we have space for one more container */
2036 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
2041 c
= message_get_last_container(m
);
2043 signature
= strdup(contents
);
2049 /* Save old index in the parent container, in case we have to
2050 * abort this container */
2051 c
->saved_index
= c
->index
;
2052 before
= m
->body_size
;
2054 if (type
== SD_BUS_TYPE_ARRAY
)
2055 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
2056 else if (type
== SD_BUS_TYPE_VARIANT
)
2057 r
= bus_message_open_variant(m
, c
, contents
);
2058 else if (type
== SD_BUS_TYPE_STRUCT
)
2059 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
2060 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
2061 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
2067 /* OK, let's fill it in */
2068 m
->containers
[m
->n_containers
++] = (struct bus_container
) {
2070 .signature
= TAKE_PTR(signature
),
2071 .array_size
= array_size
,
2074 .need_offsets
= need_offsets
,
2080 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2085 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2088 if (c
->need_offsets
) {
2089 size_t payload
, sz
, i
;
2092 /* Variable-width arrays */
2094 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2095 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2097 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2101 for (i
= 0; i
< c
->n_offsets
; i
++)
2102 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2106 /* Fixed-width or empty arrays */
2108 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2116 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2122 assert(c
->signature
);
2124 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2127 l
= strlen(c
->signature
);
2129 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2134 memcpy(a
+1, c
->signature
, l
);
2139 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2140 bool fixed_size
= true;
2141 size_t n_variable
= 0;
2150 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2153 p
= strempty(c
->signature
);
2157 r
= signature_element_length(p
, &n
);
2166 r
= bus_gvariant_is_fixed_size(t
);
2171 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2173 /* We need to add an offset for each item that has a
2174 * variable size and that is not the last one in the
2178 if (r
== 0 && p
[n
] != 0)
2185 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2186 assert(c
->need_offsets
|| n_variable
== 0);
2188 if (isempty(c
->signature
)) {
2189 /* The unary type is encoded as fixed 1 byte padding */
2190 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2195 } else if (n_variable
<= 0) {
2198 /* Structures with fixed-size members only have to be
2199 * fixed-size themselves. But gvariant requires all fixed-size
2200 * elements to be sized a multiple of their alignment. Hence,
2201 * we must *always* add final padding after the last member so
2202 * the overall size of the structure is properly aligned. */
2204 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2206 assert(alignment
> 0);
2208 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2215 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2217 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2219 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2223 p
= strempty(c
->signature
);
2224 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2228 r
= signature_element_length(p
, &n
);
2239 r
= bus_gvariant_is_fixed_size(t
);
2242 if (r
> 0 || p
[0] == 0)
2246 k
= n_variable
- 1 - j
;
2248 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2257 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2258 struct bus_container
*c
;
2261 assert_return(m
, -EINVAL
);
2262 assert_return(!m
->sealed
, -EPERM
);
2263 assert_return(m
->n_containers
> 0, -EINVAL
);
2264 assert_return(!m
->poisoned
, -ESTALE
);
2266 c
= message_get_last_container(m
);
2268 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2269 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2274 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2275 r
= bus_message_close_array(m
, c
);
2276 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2277 r
= bus_message_close_variant(m
, c
);
2278 else if (IN_SET(c
->enclosing
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
))
2279 r
= bus_message_close_struct(m
, c
, true);
2281 assert_not_reached("Unknown container type");
2295 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2302 stack
[*i
].types
= types
;
2303 stack
[*i
].n_struct
= n_struct
;
2304 stack
[*i
].n_array
= n_array
;
2310 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2321 *types
= stack
[*i
].types
;
2322 *n_struct
= stack
[*i
].n_struct
;
2323 *n_array
= stack
[*i
].n_array
;
2328 _public_
int sd_bus_message_appendv(
2333 unsigned n_array
, n_struct
;
2334 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2335 unsigned stack_ptr
= 0;
2338 assert_return(m
, -EINVAL
);
2339 assert_return(types
, -EINVAL
);
2340 assert_return(!m
->sealed
, -EPERM
);
2341 assert_return(!m
->poisoned
, -ESTALE
);
2343 n_array
= (unsigned) -1;
2344 n_struct
= strlen(types
);
2349 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2350 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2356 r
= sd_bus_message_close_container(m
);
2364 if (n_array
!= (unsigned) -1)
2373 case SD_BUS_TYPE_BYTE
: {
2376 x
= (uint8_t) va_arg(ap
, int);
2377 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2381 case SD_BUS_TYPE_BOOLEAN
:
2382 case SD_BUS_TYPE_INT32
:
2383 case SD_BUS_TYPE_UINT32
:
2384 case SD_BUS_TYPE_UNIX_FD
: {
2387 /* We assume a boolean is the same as int32_t */
2388 assert_cc(sizeof(int32_t) == sizeof(int));
2390 x
= va_arg(ap
, uint32_t);
2391 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2395 case SD_BUS_TYPE_INT16
:
2396 case SD_BUS_TYPE_UINT16
: {
2399 x
= (uint16_t) va_arg(ap
, int);
2400 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2404 case SD_BUS_TYPE_INT64
:
2405 case SD_BUS_TYPE_UINT64
: {
2408 x
= va_arg(ap
, uint64_t);
2409 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2413 case SD_BUS_TYPE_DOUBLE
: {
2416 x
= va_arg(ap
, double);
2417 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2421 case SD_BUS_TYPE_STRING
:
2422 case SD_BUS_TYPE_OBJECT_PATH
:
2423 case SD_BUS_TYPE_SIGNATURE
: {
2426 x
= va_arg(ap
, const char*);
2427 r
= sd_bus_message_append_basic(m
, *t
, x
);
2431 case SD_BUS_TYPE_ARRAY
: {
2434 r
= signature_element_length(t
+ 1, &k
);
2440 memcpy(s
, t
+ 1, k
);
2443 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2448 if (n_array
== (unsigned) -1) {
2453 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2459 n_array
= va_arg(ap
, unsigned);
2464 case SD_BUS_TYPE_VARIANT
: {
2467 s
= va_arg(ap
, const char*);
2471 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2475 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2480 n_struct
= strlen(s
);
2481 n_array
= (unsigned) -1;
2486 case SD_BUS_TYPE_STRUCT_BEGIN
:
2487 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2490 r
= signature_element_length(t
, &k
);
2497 memcpy(s
, t
+ 1, k
- 2);
2500 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2505 if (n_array
== (unsigned) -1) {
2510 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2516 n_array
= (unsigned) -1;
2532 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2536 va_start(ap
, types
);
2537 r
= sd_bus_message_appendv(m
, types
, ap
);
2543 _public_
int sd_bus_message_append_array_space(
2553 assert_return(m
, -EINVAL
);
2554 assert_return(!m
->sealed
, -EPERM
);
2555 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2556 assert_return(ptr
|| size
== 0, -EINVAL
);
2557 assert_return(!m
->poisoned
, -ESTALE
);
2559 /* alignment and size of the trivial types (except bool) is
2560 * identical for gvariant and dbus1 marshalling */
2561 align
= bus_type_get_alignment(type
);
2562 sz
= bus_type_get_size(type
);
2564 assert_se(align
> 0);
2570 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2574 a
= message_extend_body(m
, align
, size
, false, false);
2578 r
= sd_bus_message_close_container(m
);
2586 _public_
int sd_bus_message_append_array(
2594 assert_return(m
, -EINVAL
);
2595 assert_return(!m
->sealed
, -EPERM
);
2596 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2597 assert_return(ptr
|| size
== 0, -EINVAL
);
2598 assert_return(!m
->poisoned
, -ESTALE
);
2600 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2604 memcpy_safe(p
, ptr
, size
);
2609 _public_
int sd_bus_message_append_array_iovec(
2612 const struct iovec
*iov
,
2613 unsigned n
/* should be size_t, but is API now… 😞 */) {
2620 assert_return(m
, -EINVAL
);
2621 assert_return(!m
->sealed
, -EPERM
);
2622 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2623 assert_return(iov
|| n
== 0, -EINVAL
);
2624 assert_return(!m
->poisoned
, -ESTALE
);
2626 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2628 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2632 for (i
= 0; i
< n
; i
++) {
2634 if (iov
[i
].iov_base
)
2635 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2637 memzero(p
, iov
[i
].iov_len
);
2639 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2645 _public_
int sd_bus_message_append_array_memfd(
2652 _cleanup_close_
int copy_fd
= -1;
2653 struct bus_body_part
*part
;
2659 assert_return(m
, -EINVAL
);
2660 assert_return(memfd
>= 0, -EBADF
);
2661 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2662 assert_return(size
> 0, -EINVAL
);
2663 assert_return(!m
->sealed
, -EPERM
);
2664 assert_return(!m
->poisoned
, -ESTALE
);
2666 r
= memfd_set_sealed(memfd
);
2670 copy_fd
= fcntl(memfd
, F_DUPFD_CLOEXEC
, 3);
2674 r
= memfd_get_size(memfd
, &real_size
);
2678 if (offset
== 0 && size
== (uint64_t) -1)
2680 else if (offset
+ size
> real_size
)
2683 align
= bus_type_get_alignment(type
);
2684 sz
= bus_type_get_size(type
);
2686 assert_se(align
> 0);
2689 if (offset
% align
!= 0)
2695 if (size
> (uint64_t) (uint32_t) -1)
2698 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2702 a
= message_extend_body(m
, align
, 0, false, false);
2706 part
= message_append_part(m
);
2710 part
->memfd
= copy_fd
;
2711 part
->memfd_offset
= offset
;
2712 part
->sealed
= true;
2716 m
->body_size
+= size
;
2717 message_extend_containers(m
, size
);
2719 return sd_bus_message_close_container(m
);
2722 _public_
int sd_bus_message_append_string_memfd(
2728 _cleanup_close_
int copy_fd
= -1;
2729 struct bus_body_part
*part
;
2730 struct bus_container
*c
;
2735 assert_return(m
, -EINVAL
);
2736 assert_return(memfd
>= 0, -EBADF
);
2737 assert_return(size
> 0, -EINVAL
);
2738 assert_return(!m
->sealed
, -EPERM
);
2739 assert_return(!m
->poisoned
, -ESTALE
);
2741 r
= memfd_set_sealed(memfd
);
2745 copy_fd
= fcntl(memfd
, FD_CLOEXEC
, 3);
2749 r
= memfd_get_size(memfd
, &real_size
);
2753 if (offset
== 0 && size
== (uint64_t) -1)
2755 else if (offset
+ size
> real_size
)
2758 /* We require this to be NUL terminated */
2762 if (size
> (uint64_t) (uint32_t) -1)
2765 c
= message_get_last_container(m
);
2766 if (c
->signature
&& c
->signature
[c
->index
]) {
2767 /* Container signature is already set */
2769 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2774 /* Maybe we can append to the signature? But only if this is the top-level container */
2775 if (c
->enclosing
!= 0)
2778 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
));
2785 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2786 a
= message_extend_body(m
, 4, 4, false, false);
2790 *(uint32_t*) a
= size
- 1;
2793 part
= message_append_part(m
);
2797 part
->memfd
= copy_fd
;
2798 part
->memfd_offset
= offset
;
2799 part
->sealed
= true;
2803 m
->body_size
+= size
;
2804 message_extend_containers(m
, size
);
2806 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2807 r
= message_add_offset(m
, m
->body_size
);
2814 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2820 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2824 assert_return(m
, -EINVAL
);
2825 assert_return(!m
->sealed
, -EPERM
);
2826 assert_return(!m
->poisoned
, -ESTALE
);
2828 r
= sd_bus_message_open_container(m
, 'a', "s");
2832 STRV_FOREACH(i
, l
) {
2833 r
= sd_bus_message_append_basic(m
, 's', *i
);
2838 return sd_bus_message_close_container(m
);
2841 static int bus_message_close_header(sd_bus_message
*m
) {
2845 /* The actual user data is finished now, we just complete the
2846 variant and struct now (at least on gvariant). Remember
2847 this position, so that during parsing we know where to
2848 put the outer container end. */
2849 m
->user_body_size
= m
->body_size
;
2851 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2852 const char *signature
;
2856 /* Add offset table to end of fields array */
2857 if (m
->n_header_offsets
>= 1) {
2861 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2863 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2864 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2868 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2869 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2872 /* Add gvariant NUL byte plus signature to the end of
2873 * the body, followed by the final offset pointing to
2874 * the end of the fields array */
2876 signature
= strempty(m
->root_container
.signature
);
2877 l
= strlen(signature
);
2879 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2880 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2885 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2886 memcpy((uint8_t*) d
+ 2, signature
, l
);
2887 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2889 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2892 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2894 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2895 m
->header
->dbus1
.body_size
= m
->body_size
;
2901 _public_
int sd_bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, uint64_t timeout_usec
) {
2902 struct bus_body_part
*part
;
2907 assert_return(m
, -EINVAL
);
2912 if (m
->n_containers
> 0)
2918 if (cookie
> 0xffffffffULL
&&
2919 !BUS_MESSAGE_IS_GVARIANT(m
))
2922 /* In vtables the return signature of method calls is listed,
2923 * let's check if they match if this is a response */
2924 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2925 m
->enforced_reply_signature
&&
2926 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2929 /* If gvariant marshalling is used we need to close the body structure */
2930 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2934 /* If there's a non-trivial signature set, then add it in
2935 * here, but only on dbus1 */
2936 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2937 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2943 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2948 r
= bus_message_close_header(m
);
2952 if (BUS_MESSAGE_IS_GVARIANT(m
))
2953 m
->header
->dbus2
.cookie
= cookie
;
2955 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2957 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout_usec
;
2959 /* Add padding at the end of the fields part, since we know
2960 * the body needs to start at an 8 byte alignment. We made
2961 * sure we allocated enough space for this, so all we need to
2962 * do here is to zero it out. */
2963 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2965 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2967 /* If this is something we can send as memfd, then let's seal
2968 the memfd now. Note that we can send memfds as payload only
2969 for directed messages, and not for broadcasts. */
2970 if (m
->destination
&& m
->bus
->use_memfd
) {
2971 MESSAGE_FOREACH_PART(part
, i
, m
)
2972 if (part
->memfd
>= 0 &&
2974 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
2975 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
2978 /* Try to seal it if that makes
2979 * sense. First, unmap our own map to
2980 * make sure we don't keep it busy. */
2981 bus_body_part_unmap(part
);
2983 /* Then, sync up real memfd size */
2985 r
= memfd_set_size(part
->memfd
, sz
);
2989 /* Finally, try to seal */
2990 if (memfd_set_sealed(part
->memfd
) >= 0)
2991 part
->sealed
= true;
2995 m
->root_container
.end
= m
->user_body_size
;
2996 m
->root_container
.index
= 0;
2997 m
->root_container
.offset_index
= 0;
2998 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
3005 int bus_body_part_map(struct bus_body_part
*part
) {
3014 if (part
->size
<= 0)
3017 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3018 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
3019 static const uint8_t zeroes
[7] = { };
3020 part
->data
= (void*) zeroes
;
3024 shift
= PAGE_OFFSET(part
->memfd_offset
);
3025 psz
= PAGE_ALIGN(part
->size
+ shift
);
3027 if (part
->memfd
>= 0)
3028 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
3029 else if (part
->is_zero
)
3030 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
3034 if (p
== MAP_FAILED
)
3038 part
->mmap_begin
= p
;
3039 part
->data
= (uint8_t*) p
+ shift
;
3040 part
->munmap_this
= true;
3045 void bus_body_part_unmap(struct bus_body_part
*part
) {
3049 if (part
->memfd
< 0)
3052 if (!part
->mmap_begin
)
3055 if (!part
->munmap_this
)
3058 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
3060 part
->mmap_begin
= NULL
;
3063 part
->munmap_this
= false;
3068 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3069 size_t k
, start
, end
;
3074 start
= ALIGN_TO((size_t) *rindex
, align
);
3075 end
= start
+ nbytes
;
3080 /* Verify that padding is 0 */
3081 for (k
= *rindex
; k
< start
; k
++)
3082 if (((const uint8_t*) p
)[k
] != 0)
3086 *r
= (uint8_t*) p
+ start
;
3093 static bool message_end_of_signature(sd_bus_message
*m
) {
3094 struct bus_container
*c
;
3098 c
= message_get_last_container(m
);
3099 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3102 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3103 struct bus_container
*c
;
3107 c
= message_get_last_container(m
);
3108 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3111 if (BUS_MESSAGE_IS_GVARIANT(m
))
3112 return index
>= c
->end
;
3114 assert(c
->array_size
);
3115 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3119 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3120 assert_return(m
, -EINVAL
);
3121 assert_return(m
->sealed
, -EPERM
);
3123 if (complete
&& m
->n_containers
> 0)
3126 if (message_end_of_signature(m
))
3129 if (message_end_of_array(m
, m
->rindex
))
3135 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3136 struct bus_body_part
*part
;
3142 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3143 part
= m
->cached_rindex_part
;
3144 begin
= m
->cached_rindex_part_begin
;
3154 if (index
+ sz
<= begin
+ part
->size
) {
3156 r
= bus_body_part_map(part
);
3161 *p
= part
->data
? (uint8_t*) part
->data
+ index
- begin
3162 : NULL
; /* Avoid dereferencing a NULL pointer. */
3164 m
->cached_rindex_part
= part
;
3165 m
->cached_rindex_part_begin
= begin
;
3170 begin
+= part
->size
;
3177 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3184 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3187 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3190 sz
= bus_gvariant_get_size(c
->signature
);
3196 if (c
->offset_index
+1 >= c
->n_offsets
)
3199 /* Variable-size array */
3201 alignment
= bus_gvariant_get_alignment(c
->signature
);
3202 assert(alignment
> 0);
3204 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3205 assert(c
->offsets
[c
->offset_index
+1] >= *rindex
);
3206 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3209 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3212 /* Fixed-size array */
3213 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3219 } else if (IN_SET(c
->enclosing
, 0, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
3224 if (c
->offset_index
+1 >= c
->n_offsets
)
3227 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3231 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3236 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3239 alignment
= bus_gvariant_get_alignment(t
);
3242 assert(alignment
> 0);
3244 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3245 assert(c
->offsets
[c
->offset_index
+1] >= *rindex
);
3246 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3250 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3253 assert_not_reached("Unknown container type");
3258 /* Reached the end */
3264 static int message_peek_body(
3271 size_t k
, start
, end
, padding
;
3272 struct bus_body_part
*part
;
3279 start
= ALIGN_TO((size_t) *rindex
, align
);
3280 padding
= start
- *rindex
;
3281 end
= start
+ nbytes
;
3283 if (end
> m
->user_body_size
)
3286 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3291 /* Verify padding */
3292 for (k
= 0; k
< padding
; k
++)
3297 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3298 if (!part
|| (nbytes
> 0 && !q
))
3309 static bool validate_nul(const char *s
, size_t l
) {
3311 /* Check for NUL chars in the string */
3312 if (memchr(s
, 0, l
))
3315 /* Check for NUL termination */
3322 static bool validate_string(const char *s
, size_t l
) {
3324 if (!validate_nul(s
, l
))
3327 /* Check if valid UTF8 */
3328 if (!utf8_is_valid(s
))
3334 static bool validate_signature(const char *s
, size_t l
) {
3336 if (!validate_nul(s
, l
))
3339 /* Check if valid signature */
3340 if (!signature_is_valid(s
, true))
3346 static bool validate_object_path(const char *s
, size_t l
) {
3348 if (!validate_nul(s
, l
))
3351 if (!object_path_is_valid(s
))
3357 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3358 struct bus_container
*c
;
3363 assert_return(m
, -EINVAL
);
3364 assert_return(m
->sealed
, -EPERM
);
3365 assert_return(bus_type_is_basic(type
), -EINVAL
);
3367 if (message_end_of_signature(m
))
3370 if (message_end_of_array(m
, m
->rindex
))
3373 c
= message_get_last_container(m
);
3374 if (c
->signature
[c
->index
] != type
)
3379 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3381 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3384 /* D-Bus spec: The marshalling formats for the string-like types all end
3385 * with a single zero (NUL) byte, but that byte is not considered to be part
3387 if (c
->item_size
== 0)
3390 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3394 if (type
== SD_BUS_TYPE_STRING
)
3395 ok
= validate_string(q
, c
->item_size
-1);
3396 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3397 ok
= validate_object_path(q
, c
->item_size
-1);
3399 ok
= validate_signature(q
, c
->item_size
-1);
3405 *(const char**) p
= q
;
3409 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3411 if ((size_t) sz
!= c
->item_size
)
3414 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3417 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3423 case SD_BUS_TYPE_BYTE
:
3425 *(uint8_t*) p
= *(uint8_t*) q
;
3428 case SD_BUS_TYPE_BOOLEAN
:
3430 *(int*) p
= !!*(uint8_t*) q
;
3433 case SD_BUS_TYPE_INT16
:
3434 case SD_BUS_TYPE_UINT16
:
3436 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3439 case SD_BUS_TYPE_INT32
:
3440 case SD_BUS_TYPE_UINT32
:
3442 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3445 case SD_BUS_TYPE_INT64
:
3446 case SD_BUS_TYPE_UINT64
:
3447 case SD_BUS_TYPE_DOUBLE
:
3449 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3452 case SD_BUS_TYPE_UNIX_FD
: {
3455 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3460 *(int*) p
= m
->fds
[j
];
3466 assert_not_reached("unexpected type");
3470 r
= container_next_item(m
, c
, &rindex
);
3475 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3479 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3483 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3484 if (l
== UINT32_MAX
)
3485 /* avoid overflow right below */
3488 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3492 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3493 ok
= validate_object_path(q
, l
);
3495 ok
= validate_string(q
, l
);
3500 *(const char**) p
= q
;
3502 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3505 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3511 /* avoid overflow right below */
3514 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3518 if (!validate_signature(q
, l
))
3522 *(const char**) p
= q
;
3527 align
= bus_type_get_alignment(type
);
3530 sz
= bus_type_get_size(type
);
3533 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3539 case SD_BUS_TYPE_BYTE
:
3541 *(uint8_t*) p
= *(uint8_t*) q
;
3544 case SD_BUS_TYPE_BOOLEAN
:
3546 *(int*) p
= !!*(uint32_t*) q
;
3549 case SD_BUS_TYPE_INT16
:
3550 case SD_BUS_TYPE_UINT16
:
3552 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3555 case SD_BUS_TYPE_INT32
:
3556 case SD_BUS_TYPE_UINT32
:
3558 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3561 case SD_BUS_TYPE_INT64
:
3562 case SD_BUS_TYPE_UINT64
:
3563 case SD_BUS_TYPE_DOUBLE
:
3565 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3568 case SD_BUS_TYPE_UNIX_FD
: {
3571 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3576 *(int*) p
= m
->fds
[j
];
3581 assert_not_reached("Unknown basic type...");
3588 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3594 static int bus_message_enter_array(
3596 struct bus_container
*c
,
3597 const char *contents
,
3598 uint32_t **array_size
,
3601 size_t *n_offsets
) {
3615 if (!signature_is_single(contents
, true))
3618 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3621 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3624 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3629 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3633 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3637 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3640 alignment
= bus_type_get_alignment(contents
[0]);
3644 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3648 *array_size
= (uint32_t*) q
;
3650 } else if (c
->item_size
<= 0) {
3652 /* gvariant: empty array */
3657 } else if (bus_gvariant_is_fixed_size(contents
)) {
3659 /* gvariant: fixed length array */
3660 *item_size
= bus_gvariant_get_size(contents
);
3665 size_t where
, previous
= 0, framing
, sz
;
3669 /* gvariant: variable length array */
3670 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3672 where
= rindex
+ c
->item_size
- sz
;
3673 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3677 framing
= bus_gvariant_read_word_le(q
, sz
);
3678 if (framing
> c
->item_size
- sz
)
3680 if ((c
->item_size
- framing
) % sz
!= 0)
3683 *n_offsets
= (c
->item_size
- framing
) / sz
;
3685 where
= rindex
+ framing
;
3686 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3690 *offsets
= new(size_t, *n_offsets
);
3694 alignment
= bus_gvariant_get_alignment(c
->signature
);
3695 assert(alignment
> 0);
3697 for (i
= 0; i
< *n_offsets
; i
++) {
3700 start
= ALIGN_TO(previous
, alignment
);
3702 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3703 if (x
> c
->item_size
- sz
)
3708 (*offsets
)[i
] = rindex
+ x
;
3712 *item_size
= (*offsets
)[0] - rindex
;
3717 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3718 c
->index
+= 1 + strlen(contents
);
3723 static int bus_message_enter_variant(
3725 struct bus_container
*c
,
3726 const char *contents
,
3727 size_t *item_size
) {
3739 if (!signature_is_single(contents
, false))
3742 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3745 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3748 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3753 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3756 k
= strlen(contents
);
3757 if (1+k
> c
->item_size
)
3760 where
= rindex
+ c
->item_size
- (1+k
);
3761 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3765 if (*(char*) q
!= 0)
3768 if (memcmp((uint8_t*) q
+1, contents
, k
))
3771 *item_size
= c
->item_size
- (1+k
);
3774 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3780 /* avoid overflow right below */
3783 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3787 if (!validate_signature(q
, l
))
3790 if (!streq(q
, contents
))
3796 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3802 static int build_struct_offsets(
3804 const char *signature
,
3808 size_t *n_offsets
) {
3810 unsigned n_variable
= 0, n_total
= 0, v
;
3811 size_t previous
, where
;
3822 if (isempty(signature
)) {
3823 /* Unary type is encoded as *fixed* 1 byte padding */
3824 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3828 if (*(uint8_t *) q
!= 0)
3837 sz
= bus_gvariant_determine_word_size(size
, 0);
3841 /* First, loop over signature and count variable elements and
3842 * elements in general. We use this to know how large the
3843 * offset array is at the end of the structure. Note that
3844 * GVariant only stores offsets for all variable size elements
3845 * that are not the last item. */
3851 r
= signature_element_length(p
, &n
);
3860 r
= bus_gvariant_is_fixed_size(t
);
3865 if (r
== 0 && p
[n
] != 0) /* except the last item */
3872 if (size
< n_variable
* sz
)
3875 where
= m
->rindex
+ size
- (n_variable
* sz
);
3876 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3882 *offsets
= new(size_t, n_total
);
3888 /* Second, loop again and build an offset table */
3890 previous
= m
->rindex
;
3895 r
= signature_element_length(p
, &n
);
3904 size_t align
= bus_gvariant_get_alignment(t
);
3907 /* The possible start of this member after including alignment */
3908 size_t start
= ALIGN_TO(previous
, align
);
3910 k
= bus_gvariant_get_size(t
);
3918 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3922 /* The last item's end is determined
3923 * from the start of the offset array */
3924 x
= size
- (n_variable
* sz
);
3926 offset
= m
->rindex
+ x
;
3928 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG
),
3929 "For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu",
3939 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3944 assert(*n_offsets
== n_total
);
3946 *item_size
= (*offsets
)[0] - m
->rindex
;
3950 static int enter_struct_or_dict_entry(
3952 struct bus_container
*c
,
3953 const char *contents
,
3956 size_t *n_offsets
) {
3967 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3970 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3975 /* gvariant with contents */
3976 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3981 static int bus_message_enter_struct(
3983 struct bus_container
*c
,
3984 const char *contents
,
3987 size_t *n_offsets
) {
3999 if (!signature_is_valid(contents
, false))
4002 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4005 l
= strlen(contents
);
4007 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
4008 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4009 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
4012 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4016 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4017 c
->index
+= 1 + l
+ 1;
4022 static int bus_message_enter_dict_entry(
4024 struct bus_container
*c
,
4025 const char *contents
,
4028 size_t *n_offsets
) {
4037 if (!signature_is_pair(contents
))
4040 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4043 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
4046 l
= strlen(contents
);
4048 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
4049 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
4050 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
4053 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4057 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4058 c
->index
+= 1 + l
+ 1;
4063 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
4065 const char *contents
) {
4066 struct bus_container
*c
;
4067 uint32_t *array_size
= NULL
;
4068 _cleanup_free_
char *signature
= NULL
;
4070 _cleanup_free_
size_t *offsets
= NULL
;
4071 size_t n_offsets
= 0, item_size
= 0;
4074 assert_return(m
, -EINVAL
);
4075 assert_return(m
->sealed
, -EPERM
);
4076 assert_return(type
!= 0 || !contents
, -EINVAL
);
4078 if (type
== 0 || !contents
) {
4082 /* Allow entering into anonymous containers */
4083 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
4087 if (type
!= 0 && type
!= tt
)
4090 if (contents
&& !streq(contents
, cc
))
4098 * We enforce a global limit on container depth, that is much
4099 * higher than the 32 structs and 32 arrays the specification
4100 * mandates. This is simpler to implement for us, and we need
4101 * this only to ensure our container array doesn't grow
4102 * without bounds. We are happy to return any data from a
4103 * message as long as the data itself is valid, even if the
4104 * overall message might be not.
4106 * Note that the message signature is validated when
4107 * parsing the headers, and that validation does check the
4110 * Note that the specification defines no limits on the depth
4111 * of stacked variants, but we do.
4113 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4116 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4119 if (message_end_of_signature(m
))
4122 if (message_end_of_array(m
, m
->rindex
))
4125 c
= message_get_last_container(m
);
4127 signature
= strdup(contents
);
4131 c
->saved_index
= c
->index
;
4134 if (type
== SD_BUS_TYPE_ARRAY
)
4135 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4136 else if (type
== SD_BUS_TYPE_VARIANT
)
4137 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4138 else if (type
== SD_BUS_TYPE_STRUCT
)
4139 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4140 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4141 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4147 /* OK, let's fill it in */
4148 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4149 type
== SD_BUS_TYPE_STRUCT
&&
4151 end
= m
->rindex
+ 0;
4153 end
= m
->rindex
+ c
->item_size
;
4155 m
->containers
[m
->n_containers
++] = (struct bus_container
) {
4157 .signature
= TAKE_PTR(signature
),
4161 /* Unary type has fixed size of 1, but virtual size of 0 */
4163 .array_size
= array_size
,
4164 .item_size
= item_size
,
4165 .offsets
= TAKE_PTR(offsets
),
4166 .n_offsets
= n_offsets
,
4172 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4173 struct bus_container
*c
;
4177 assert_return(m
, -EINVAL
);
4178 assert_return(m
->sealed
, -EPERM
);
4179 assert_return(m
->n_containers
> 0, -ENXIO
);
4181 c
= message_get_last_container(m
);
4183 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4184 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4188 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4189 if (m
->rindex
< c
->end
)
4192 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4195 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4196 if (c
->begin
+ l
!= m
->rindex
)
4200 message_free_last_container(m
);
4202 c
= message_get_last_container(m
);
4204 c
->index
= c
->saved_index
;
4205 r
= container_next_item(m
, c
, &m
->rindex
);
4213 static void message_quit_container(sd_bus_message
*m
) {
4214 struct bus_container
*c
;
4218 assert(m
->n_containers
> 0);
4221 c
= message_get_last_container(m
);
4222 assert(m
->rindex
>= c
->before
);
4223 m
->rindex
= c
->before
;
4225 /* Free container */
4226 message_free_last_container(m
);
4228 /* Correct index of new top-level container */
4229 c
= message_get_last_container(m
);
4230 c
->index
= c
->saved_index
;
4233 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4234 struct bus_container
*c
;
4237 assert_return(m
, -EINVAL
);
4238 assert_return(m
->sealed
, -EPERM
);
4240 if (message_end_of_signature(m
))
4243 if (message_end_of_array(m
, m
->rindex
))
4246 c
= message_get_last_container(m
);
4248 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4252 *type
= c
->signature
[c
->index
];
4256 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4261 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4265 /* signature_element_length does verification internally */
4267 /* The array element must not be empty */
4269 if (free_and_strndup(&c
->peeked_signature
,
4270 c
->signature
+ c
->index
+ 1, l
) < 0)
4273 *contents
= c
->peeked_signature
;
4277 *type
= SD_BUS_TYPE_ARRAY
;
4282 if (IN_SET(c
->signature
[c
->index
], SD_BUS_TYPE_STRUCT_BEGIN
, SD_BUS_TYPE_DICT_ENTRY_BEGIN
)) {
4287 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4292 if (free_and_strndup(&c
->peeked_signature
,
4293 c
->signature
+ c
->index
+ 1, l
- 2) < 0)
4296 *contents
= c
->peeked_signature
;
4300 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4305 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4309 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4312 if (c
->item_size
< 2)
4315 /* Look for the NUL delimiter that
4316 separates the payload from the
4317 signature. Since the body might be
4318 in a different part that then the
4319 signature we map byte by byte. */
4321 for (k
= 2; k
<= c
->item_size
; k
++) {
4324 where
= m
->rindex
+ c
->item_size
- k
;
4325 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4329 if (*(char*) q
== 0)
4333 if (k
> c
->item_size
)
4336 if (free_and_strndup(&c
->peeked_signature
,
4337 (char*) q
+ 1, k
- 1) < 0)
4340 if (!signature_is_valid(c
->peeked_signature
, true))
4343 *contents
= c
->peeked_signature
;
4348 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4354 /* avoid overflow right below */
4357 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4361 if (!validate_signature(q
, l
))
4369 *type
= SD_BUS_TYPE_VARIANT
;
4384 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4385 struct bus_container
*c
;
4387 assert_return(m
, -EINVAL
);
4388 assert_return(m
->sealed
, -EPERM
);
4391 message_reset_containers(m
);
4394 c
= message_get_last_container(m
);
4396 c
= message_get_last_container(m
);
4399 m
->rindex
= c
->begin
;
4402 c
->offset_index
= 0;
4403 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4405 return !isempty(c
->signature
);
4408 _public_
int sd_bus_message_readv(
4413 unsigned n_array
, n_struct
;
4414 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4415 unsigned stack_ptr
= 0;
4416 unsigned n_loop
= 0;
4419 assert_return(m
, -EINVAL
);
4420 assert_return(m
->sealed
, -EPERM
);
4421 assert_return(types
, -EINVAL
);
4426 /* Ideally, we'd just call ourselves recursively on every
4427 * complex type. However, the state of a va_list that is
4428 * passed to a function is undefined after that function
4429 * returns. This means we need to decode the va_list linearly
4430 * in a single stackframe. We hence implement our own
4431 * home-grown stack in an array. */
4433 n_array
= (unsigned) -1; /* length of current array entries */
4434 n_struct
= strlen(types
); /* length of current struct contents signature */
4441 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4442 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4448 r
= sd_bus_message_exit_container(m
);
4456 if (n_array
!= (unsigned) -1)
4465 case SD_BUS_TYPE_BYTE
:
4466 case SD_BUS_TYPE_BOOLEAN
:
4467 case SD_BUS_TYPE_INT16
:
4468 case SD_BUS_TYPE_UINT16
:
4469 case SD_BUS_TYPE_INT32
:
4470 case SD_BUS_TYPE_UINT32
:
4471 case SD_BUS_TYPE_INT64
:
4472 case SD_BUS_TYPE_UINT64
:
4473 case SD_BUS_TYPE_DOUBLE
:
4474 case SD_BUS_TYPE_STRING
:
4475 case SD_BUS_TYPE_OBJECT_PATH
:
4476 case SD_BUS_TYPE_SIGNATURE
:
4477 case SD_BUS_TYPE_UNIX_FD
: {
4480 p
= va_arg(ap
, void*);
4481 r
= sd_bus_message_read_basic(m
, *t
, p
);
4494 case SD_BUS_TYPE_ARRAY
: {
4497 r
= signature_element_length(t
+ 1, &k
);
4503 memcpy(s
, t
+ 1, k
);
4506 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4517 if (n_array
== (unsigned) -1) {
4522 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4528 n_array
= va_arg(ap
, unsigned);
4533 case SD_BUS_TYPE_VARIANT
: {
4536 s
= va_arg(ap
, const char *);
4540 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4550 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4555 n_struct
= strlen(s
);
4556 n_array
= (unsigned) -1;
4561 case SD_BUS_TYPE_STRUCT_BEGIN
:
4562 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4565 r
= signature_element_length(t
, &k
);
4571 memcpy(s
, t
+ 1, k
- 2);
4574 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4584 if (n_array
== (unsigned) -1) {
4589 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4595 n_array
= (unsigned) -1;
4608 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4612 va_start(ap
, types
);
4613 r
= sd_bus_message_readv(m
, types
, ap
);
4619 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4622 assert_return(m
, -EINVAL
);
4623 assert_return(m
->sealed
, -EPERM
);
4625 /* If types is NULL, read exactly one element */
4627 struct bus_container
*c
;
4630 if (message_end_of_signature(m
))
4633 if (message_end_of_array(m
, m
->rindex
))
4636 c
= message_get_last_container(m
);
4638 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4642 types
= strndupa(c
->signature
+ c
->index
, l
);
4647 case 0: /* Nothing to drop */
4650 case SD_BUS_TYPE_BYTE
:
4651 case SD_BUS_TYPE_BOOLEAN
:
4652 case SD_BUS_TYPE_INT16
:
4653 case SD_BUS_TYPE_UINT16
:
4654 case SD_BUS_TYPE_INT32
:
4655 case SD_BUS_TYPE_UINT32
:
4656 case SD_BUS_TYPE_INT64
:
4657 case SD_BUS_TYPE_UINT64
:
4658 case SD_BUS_TYPE_DOUBLE
:
4659 case SD_BUS_TYPE_STRING
:
4660 case SD_BUS_TYPE_OBJECT_PATH
:
4661 case SD_BUS_TYPE_SIGNATURE
:
4662 case SD_BUS_TYPE_UNIX_FD
:
4664 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4668 r
= sd_bus_message_skip(m
, types
+ 1);
4674 case SD_BUS_TYPE_ARRAY
: {
4677 r
= signature_element_length(types
+ 1, &k
);
4683 memcpy(s
, types
+1, k
);
4686 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4691 r
= sd_bus_message_skip(m
, s
);
4698 r
= sd_bus_message_exit_container(m
);
4703 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4710 case SD_BUS_TYPE_VARIANT
: {
4711 const char *contents
;
4714 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4718 if (x
!= SD_BUS_TYPE_VARIANT
)
4721 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4725 r
= sd_bus_message_skip(m
, contents
);
4730 r
= sd_bus_message_exit_container(m
);
4734 r
= sd_bus_message_skip(m
, types
+ 1);
4741 case SD_BUS_TYPE_STRUCT_BEGIN
:
4742 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4745 r
= signature_element_length(types
, &k
);
4751 memcpy(s
, types
+1, k
-2);
4754 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4758 r
= sd_bus_message_skip(m
, s
);
4762 r
= sd_bus_message_exit_container(m
);
4767 r
= sd_bus_message_skip(m
, types
+ k
);
4779 _public_
int sd_bus_message_read_array(
4785 struct bus_container
*c
;
4791 assert_return(m
, -EINVAL
);
4792 assert_return(m
->sealed
, -EPERM
);
4793 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4794 assert_return(ptr
, -EINVAL
);
4795 assert_return(size
, -EINVAL
);
4796 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4798 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4807 c
= message_get_last_container(m
);
4809 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4810 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4814 sz
= c
->end
- c
->begin
;
4816 align
= bus_type_get_alignment(type
);
4820 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4824 /* Zero length array, let's return some aligned
4825 * pointer that is not NULL */
4826 p
= (uint8_t*) align
;
4828 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4833 r
= sd_bus_message_exit_container(m
);
4837 *ptr
= (const void*) p
;
4843 message_quit_container(m
);
4847 static int message_peek_fields(
4858 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4861 static int message_peek_field_uint32(
4873 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4876 /* identical for gvariant and dbus1 */
4878 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4883 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4888 static int message_peek_field_uint64(
4900 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4903 /* identical for gvariant and dbus1 */
4905 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4910 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4915 static int message_peek_field_string(
4917 bool (*validate
)(const char *p
),
4929 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4934 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4940 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4944 if (l
== UINT32_MAX
)
4945 /* avoid overflow right below */
4948 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4954 if (!validate_nul(q
, l
))
4960 if (!validate_string(q
, l
))
4970 static int message_peek_field_signature(
4983 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4988 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4994 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
5000 /* avoid overflow right below */
5003 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
5008 if (!validate_signature(q
, l
))
5017 static int message_skip_fields(
5020 uint32_t array_size
,
5021 const char **signature
) {
5023 size_t original_index
;
5029 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
5031 original_index
= *ri
;
5037 if (array_size
!= (uint32_t) -1 &&
5038 array_size
<= *ri
- original_index
)
5045 if (t
== SD_BUS_TYPE_STRING
) {
5047 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
5053 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
5055 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
5061 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
5063 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
5069 } else if (bus_type_is_basic(t
)) {
5072 align
= bus_type_get_alignment(t
);
5073 k
= bus_type_get_size(t
);
5074 assert(align
> 0 && k
> 0);
5076 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
5082 } else if (t
== SD_BUS_TYPE_ARRAY
) {
5084 r
= signature_element_length(*signature
+ 1, &l
);
5090 char sig
[l
+ 1], *s
= sig
;
5094 strncpy(sig
, *signature
+ 1, l
);
5097 alignment
= bus_type_get_alignment(sig
[0]);
5101 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5104 if (nas
> BUS_ARRAY_MAX_SIZE
)
5107 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5111 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5116 (*signature
) += 1 + l
;
5118 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5121 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5125 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5131 } else if (IN_SET(t
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
5133 r
= signature_element_length(*signature
, &l
);
5139 char sig
[l
+ 1], *s
= sig
;
5140 strncpy(sig
, *signature
+ 1, l
);
5143 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5154 int bus_message_parse_fields(sd_bus_message
*m
) {
5157 uint32_t unix_fds
= 0;
5158 bool unix_fds_set
= false;
5159 void *offsets
= NULL
;
5160 unsigned n_offsets
= 0;
5166 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5169 /* Read the signature from the end of the body variant first */
5170 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5171 if (m
->footer_accessible
< 1 + sz
)
5174 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5176 if (p
< (char*) m
->footer
)
5180 _cleanup_free_
char *k
= NULL
;
5183 /* We found the beginning of the signature
5184 * string, yay! We require the body to be a
5185 * structure, so verify it and then strip the
5186 * opening/closing brackets. */
5188 l
= (char*) m
->footer
+ m
->footer_accessible
- p
- (1 + sz
);
5190 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5191 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5194 k
= memdup_suffix0(p
+ 1 + 1, l
- 2);
5198 if (!signature_is_valid(k
, true))
5201 free_and_replace(m
->root_container
.signature
, k
);
5208 /* Calculate the actual user body size, by removing
5209 * the trailing variant signature and struct offset
5211 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5213 /* Pull out the offset table for the fields array, if any */
5214 if (m
->fields_size
> 0) {
5215 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5220 if (m
->fields_size
< sz
)
5223 ri
= m
->fields_size
- sz
;
5224 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5228 framing
= bus_gvariant_read_word_le(q
, sz
);
5229 if (framing
>= m
->fields_size
- sz
)
5231 if ((m
->fields_size
- framing
) % sz
!= 0)
5235 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5239 n_offsets
= (m
->fields_size
- framing
) / sz
;
5243 m
->user_body_size
= m
->body_size
;
5246 while (ri
< m
->fields_size
) {
5247 _cleanup_free_
char *sig
= NULL
;
5248 const char *signature
;
5249 uint64_t field_type
;
5250 size_t item_size
= (size_t) -1;
5252 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5261 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5263 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5267 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5271 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5278 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5283 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5288 where
= ri
= ALIGN_TO(ri
, 8);
5289 item_size
= end
- ri
;
5290 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5294 b
= memrchr(q
, 0, item_size
);
5298 sig
= memdup_suffix0(b
+1, item_size
- (b
+1-(char*) q
));
5303 item_size
= b
- (char*) q
;
5305 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5310 switch (field_type
) {
5312 case _BUS_MESSAGE_HEADER_INVALID
:
5315 case BUS_MESSAGE_HEADER_PATH
:
5320 if (!streq(signature
, "o"))
5323 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5326 case BUS_MESSAGE_HEADER_INTERFACE
:
5331 if (!streq(signature
, "s"))
5334 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5337 case BUS_MESSAGE_HEADER_MEMBER
:
5342 if (!streq(signature
, "s"))
5345 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5348 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5353 if (!streq(signature
, "s"))
5356 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5358 m
->error
._need_free
= -1;
5362 case BUS_MESSAGE_HEADER_DESTINATION
:
5367 if (!streq(signature
, "s"))
5370 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5373 case BUS_MESSAGE_HEADER_SENDER
:
5378 if (!streq(signature
, "s"))
5381 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5383 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
) {
5384 m
->creds
.unique_name
= (char*) m
->sender
;
5385 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5390 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5394 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5397 if (m
->root_container
.signature
)
5400 if (!streq(signature
, "g"))
5403 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5411 free_and_replace(m
->root_container
.signature
, c
);
5415 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5417 if (m
->reply_cookie
!= 0)
5420 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5421 /* 64bit on dbus2 */
5423 if (!streq(signature
, "t"))
5426 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5430 /* 32bit on dbus1 */
5433 if (!streq(signature
, "u"))
5436 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5440 m
->reply_cookie
= serial
;
5443 if (m
->reply_cookie
== 0)
5448 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5452 if (!streq(signature
, "u"))
5455 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5459 unix_fds_set
= true;
5463 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5464 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5473 if (m
->n_fds
!= unix_fds
)
5476 switch (m
->header
->type
) {
5478 case SD_BUS_MESSAGE_SIGNAL
:
5479 if (!m
->path
|| !m
->interface
|| !m
->member
)
5482 if (m
->reply_cookie
!= 0)
5487 case SD_BUS_MESSAGE_METHOD_CALL
:
5489 if (!m
->path
|| !m
->member
)
5492 if (m
->reply_cookie
!= 0)
5497 case SD_BUS_MESSAGE_METHOD_RETURN
:
5499 if (m
->reply_cookie
== 0)
5503 case SD_BUS_MESSAGE_METHOD_ERROR
:
5505 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5510 /* Refuse non-local messages that claim they are local */
5511 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5513 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5515 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5518 m
->root_container
.end
= m
->user_body_size
;
5520 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5521 r
= build_struct_offsets(
5523 m
->root_container
.signature
,
5525 &m
->root_container
.item_size
,
5526 &m
->root_container
.offsets
,
5527 &m
->root_container
.n_offsets
);
5534 /* Try to read the error message, but if we can't it's a non-issue */
5535 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5536 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5541 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5542 assert_return(m
, -EINVAL
);
5543 assert_return(destination
, -EINVAL
);
5544 assert_return(service_name_is_valid(destination
), -EINVAL
);
5545 assert_return(!m
->sealed
, -EPERM
);
5546 assert_return(!m
->destination
, -EEXIST
);
5548 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5551 _public_
int sd_bus_message_set_sender(sd_bus_message
*m
, const char *sender
) {
5552 assert_return(m
, -EINVAL
);
5553 assert_return(sender
, -EINVAL
);
5554 assert_return(service_name_is_valid(sender
), -EINVAL
);
5555 assert_return(!m
->sealed
, -EPERM
);
5556 assert_return(!m
->sender
, -EEXIST
);
5558 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5561 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5565 struct bus_body_part
*part
;
5571 total
= BUS_MESSAGE_SIZE(m
);
5577 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5578 MESSAGE_FOREACH_PART(part
, i
, m
)
5579 e
= mempcpy(e
, part
->data
, part
->size
);
5581 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5589 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5591 const char *contents
, *s
;
5597 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5601 if (type
!= SD_BUS_TYPE_ARRAY
|| !STR_IN_SET(contents
, "s", "o", "g"))
5604 r
= sd_bus_message_enter_container(m
, 'a', NULL
);
5608 /* sd_bus_message_read_basic() does content validation for us. */
5609 while ((r
= sd_bus_message_read_basic(m
, *contents
, &s
)) > 0) {
5610 r
= strv_extend(l
, s
);
5617 r
= sd_bus_message_exit_container(m
);
5624 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5625 _cleanup_strv_free_
char **strv
= NULL
;
5628 assert_return(m
, -EINVAL
);
5629 assert_return(m
->sealed
, -EPERM
);
5630 assert_return(l
, -EINVAL
);
5632 r
= bus_message_read_strv_extend(m
, &strv
);
5636 *l
= TAKE_PTR(strv
);
5640 static int bus_message_get_arg_skip(
5644 const char **_contents
) {
5649 r
= sd_bus_message_rewind(m
, true);
5654 const char *contents
;
5657 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5663 /* Don't match against arguments after the first one we don't understand */
5664 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5665 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5670 *_contents
= contents
;
5676 r
= sd_bus_message_skip(m
, NULL
);
5683 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5690 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5694 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5697 return sd_bus_message_read_basic(m
, type
, str
);
5700 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5701 const char *contents
;
5708 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5712 if (type
!= SD_BUS_TYPE_ARRAY
)
5714 if (!STR_IN_SET(contents
, "s", "o", "g"))
5717 return sd_bus_message_read_strv(m
, strv
);
5720 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5721 assert_return(m
, EINVAL
);
5723 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5726 return sd_bus_error_get_errno(&m
->error
);
5729 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5730 struct bus_container
*c
;
5732 assert_return(m
, NULL
);
5734 c
= complete
? &m
->root_container
: message_get_last_container(m
);
5735 return strempty(c
->signature
);
5738 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5739 assert_return(m
, -EINVAL
);
5741 return isempty(m
->root_container
.signature
);
5744 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5745 assert_return(m
, -EINVAL
);
5747 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5750 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5751 bool done_something
= false;
5754 assert_return(m
, -EINVAL
);
5755 assert_return(source
, -EINVAL
);
5756 assert_return(!m
->sealed
, -EPERM
);
5757 assert_return(source
->sealed
, -EPERM
);
5760 const char *contents
;
5775 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5781 done_something
= true;
5783 if (bus_type_is_container(type
) > 0) {
5785 r
= sd_bus_message_enter_container(source
, type
, contents
);
5789 r
= sd_bus_message_open_container(m
, type
, contents
);
5793 r
= sd_bus_message_copy(m
, source
, true);
5797 r
= sd_bus_message_close_container(m
);
5801 r
= sd_bus_message_exit_container(source
);
5808 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5814 if (IN_SET(type
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
, SD_BUS_TYPE_STRING
))
5815 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5817 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5824 return done_something
;
5827 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5832 assert_return(m
, -EINVAL
);
5833 assert_return(m
->sealed
, -EPERM
);
5834 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5835 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5836 assert_return(type
|| contents
, -EINVAL
);
5837 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5839 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5843 if (type
!= 0 && type
!= t
)
5846 if (contents
&& !streq_ptr(contents
, c
))
5852 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5853 assert_return(m
, NULL
);
5858 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5859 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
5867 switch ((*m
)->header
->type
) {
5869 case SD_BUS_MESSAGE_SIGNAL
:
5870 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5876 case SD_BUS_MESSAGE_METHOD_CALL
:
5877 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5883 case SD_BUS_MESSAGE_METHOD_RETURN
:
5884 case SD_BUS_MESSAGE_METHOD_ERROR
:
5886 r
= sd_bus_message_new(bus
, &n
, (*m
)->header
->type
);
5892 n
->reply_cookie
= (*m
)->reply_cookie
;
5894 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5898 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5899 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5903 n
->error
._need_free
= -1;
5912 if ((*m
)->destination
&& !n
->destination
) {
5913 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5918 if ((*m
)->sender
&& !n
->sender
) {
5919 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5924 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5926 r
= sd_bus_message_copy(n
, *m
, true);
5930 timeout
= (*m
)->timeout
;
5931 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
)) {
5932 r
= sd_bus_get_method_call_timeout(bus
, &timeout
);
5937 r
= sd_bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5941 sd_bus_message_unref(*m
);
5947 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5948 static bool warned
= false;
5950 assert_return(m
, -EINVAL
);
5951 assert_return(priority
, -EINVAL
);
5954 log_debug("sd_bus_message_get_priority() is deprecated and always returns 0.");
5962 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5963 static bool warned
= false;
5965 assert_return(m
, -EINVAL
);
5966 assert_return(!m
->sealed
, -EPERM
);
5969 log_debug("sd_bus_message_set_priority() is deprecated and does nothing.");
5976 _public_
int sd_bus_message_sensitive(sd_bus_message
*m
) {
5977 assert_return(m
, -EINVAL
);
5979 m
->sensitive
= true;