2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "alloc-util.h"
27 #include "bus-gvariant.h"
28 #include "bus-internal.h"
29 #include "bus-message.h"
30 #include "bus-signature.h"
35 #include "memfd-util.h"
36 #include "string-util.h"
38 #include "time-util.h"
42 static int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
);
44 static void *adjust_pointer(const void *p
, void *old_base
, size_t sz
, void *new_base
) {
49 if (old_base
== new_base
)
52 if ((uint8_t*) p
< (uint8_t*) old_base
)
55 if ((uint8_t*) p
>= (uint8_t*) old_base
+ sz
)
58 return (uint8_t*) new_base
+ ((uint8_t*) p
- (uint8_t*) old_base
);
61 static void message_free_part(sd_bus_message
*m
, struct bus_body_part
*part
) {
66 close_and_munmap(part
->memfd
, part
->mmap_begin
, part
->mapped
);
67 else if (part
->munmap_this
)
68 munmap(part
->mmap_begin
, part
->mapped
);
69 else if (part
->free_this
)
76 static void message_reset_parts(sd_bus_message
*m
) {
77 struct bus_body_part
*part
;
82 while (m
->n_body_parts
> 0) {
83 struct bus_body_part
*next
= part
->next
;
84 message_free_part(m
, part
);
91 m
->cached_rindex_part
= NULL
;
92 m
->cached_rindex_part_begin
= 0;
95 static void message_reset_containers(sd_bus_message
*m
) {
100 for (i
= 0; i
< m
->n_containers
; i
++) {
101 free(m
->containers
[i
].signature
);
102 free(m
->containers
[i
].offsets
);
105 m
->containers
= mfree(m
->containers
);
107 m
->n_containers
= m
->containers_allocated
= 0;
108 m
->root_container
.index
= 0;
111 static void message_free(sd_bus_message
*m
) {
117 message_reset_parts(m
);
119 sd_bus_unref(m
->bus
);
122 close_many(m
->fds
, m
->n_fds
);
126 if (m
->iovec
!= m
->iovec_fixed
)
129 m
->destination_ptr
= mfree(m
->destination_ptr
);
130 message_reset_containers(m
);
131 free(m
->root_container
.signature
);
132 free(m
->root_container
.offsets
);
134 free(m
->root_container
.peeked_signature
);
136 bus_creds_done(&m
->creds
);
140 static void *message_extend_fields(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
142 size_t old_size
, new_size
, start
;
149 old_size
= sizeof(struct bus_header
) + m
->fields_size
;
150 start
= ALIGN_TO(old_size
, align
);
151 new_size
= start
+ sz
;
153 if (new_size
< start
||
154 new_size
> (size_t) ((uint32_t) -1))
157 if (old_size
== new_size
)
158 return (uint8_t*) m
->header
+ old_size
;
160 if (m
->free_header
) {
161 np
= realloc(m
->header
, ALIGN8(new_size
));
165 /* Initially, the header is allocated as part of
166 * the sd_bus_message itself, let's replace it by
169 np
= malloc(ALIGN8(new_size
));
173 memcpy(np
, m
->header
, sizeof(struct bus_header
));
176 /* Zero out padding */
177 if (start
> old_size
)
178 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
182 m
->fields_size
= new_size
- sizeof(struct bus_header
);
184 /* Adjust quick access pointers */
185 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
186 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
187 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
188 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
189 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
190 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
192 m
->free_header
= true;
195 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
198 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
201 return (uint8_t*) np
+ start
;
208 static int message_append_field_string(
220 /* dbus1 only allows 8bit header field ids */
224 /* dbus1 doesn't allow strings over 32bit, let's enforce this
225 * globally, to not risk convertability */
227 if (l
> (size_t) (uint32_t) -1)
230 /* Signature "(yv)" where the variant contains "s" */
232 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
234 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
235 p
= message_extend_fields(m
, 8, 8 + l
+ 1 + 1 + 1, true);
239 *((uint64_t*) p
) = h
;
246 *ret
= (char*) p
+ 8;
249 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
250 p
= message_extend_fields(m
, 8, 4 + 4 + l
+ 1, false);
259 ((uint32_t*) p
)[1] = l
;
260 memcpy(p
+ 8, s
, l
+ 1);
263 *ret
= (char*) p
+ 8;
269 static int message_append_field_signature(
280 /* dbus1 only allows 8bit header field ids */
284 /* dbus1 doesn't allow signatures over 8bit, let's enforce
285 * this globally, to not risk convertability */
290 /* Signature "(yv)" where the variant contains "g" */
292 if (BUS_MESSAGE_IS_GVARIANT(m
))
293 /* For gvariant the serialization is the same as for normal strings */
294 return message_append_field_string(m
, h
, 'g', s
, ret
);
296 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
297 p
= message_extend_fields(m
, 8, 4 + 1 + l
+ 1, false);
303 p
[2] = SD_BUS_TYPE_SIGNATURE
;
306 memcpy(p
+ 5, s
, l
+ 1);
309 *ret
= (const char*) p
+ 5;
315 static int message_append_field_uint32(sd_bus_message
*m
, uint64_t h
, uint32_t x
) {
320 /* dbus1 only allows 8bit header field ids */
324 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
325 /* (field id 64bit + ((value + NUL + signature string 'u') */
327 p
= message_extend_fields(m
, 8, 8 + 4 + 1 + 1, true);
331 *((uint64_t*) p
) = h
;
332 *((uint32_t*) (p
+ 8)) = x
;
336 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
337 p
= message_extend_fields(m
, 8, 4 + 4, false);
346 ((uint32_t*) p
)[1] = x
;
352 static int message_append_field_uint64(sd_bus_message
*m
, uint64_t h
, uint64_t x
) {
357 /* dbus1 only allows 8bit header field ids */
361 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
362 /* (field id 64bit + ((value + NUL + signature string 't') */
364 p
= message_extend_fields(m
, 8, 8 + 8 + 1 + 1, true);
368 *((uint64_t*) p
) = h
;
369 *((uint64_t*) (p
+ 8)) = x
;
373 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
374 p
= message_extend_fields(m
, 8, 4 + 4 + 8, false);
387 ((uint64_t*) p
)[1] = x
;
393 static int message_append_reply_cookie(sd_bus_message
*m
, uint64_t cookie
) {
396 if (BUS_MESSAGE_IS_GVARIANT(m
))
397 return message_append_field_uint64(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, cookie
);
399 /* 64bit cookies are not supported on dbus1 */
400 if (cookie
> 0xffffffffUL
)
403 return message_append_field_uint32(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) cookie
);
407 int bus_message_from_header(
410 size_t header_accessible
,
412 size_t footer_accessible
,
418 sd_bus_message
**ret
) {
420 _cleanup_free_ sd_bus_message
*m
= NULL
;
421 struct bus_header
*h
;
425 assert(header
|| header_accessible
<= 0);
426 assert(footer
|| footer_accessible
<= 0);
427 assert(fds
|| n_fds
<= 0);
430 if (header_accessible
< sizeof(struct bus_header
))
433 if (header_accessible
> message_size
)
435 if (footer_accessible
> message_size
)
439 if (!IN_SET(h
->version
, 1, 2))
442 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
445 if (!IN_SET(h
->endian
, BUS_LITTLE_ENDIAN
, BUS_BIG_ENDIAN
))
448 /* Note that we are happy with unknown flags in the flags header! */
450 a
= ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
453 label_sz
= strlen(label
);
464 m
->header_accessible
= header_accessible
;
466 m
->footer_accessible
= footer_accessible
;
468 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
471 if (h
->dbus2
.cookie
== 0)
474 /* dbus2 derives the sizes from the message size and
475 the offset table at the end, since it is formatted as
476 gvariant "yyyyuta{tv}v". Since the message itself is a
477 structure with precisely to variable sized entries,
478 there's only one offset in the table, which marks the
479 end of the fields array. */
481 ws
= bus_gvariant_determine_word_size(message_size
, 0);
482 if (footer_accessible
< ws
)
485 m
->fields_size
= bus_gvariant_read_word_le((uint8_t*) footer
+ footer_accessible
- ws
, ws
);
486 if (ALIGN8(m
->fields_size
) > message_size
- ws
)
488 if (m
->fields_size
< sizeof(struct bus_header
))
491 m
->fields_size
-= sizeof(struct bus_header
);
492 m
->body_size
= message_size
- (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
));
494 if (h
->dbus1
.serial
== 0)
497 /* dbus1 has the sizes in the header */
498 m
->fields_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.fields_size
);
499 m
->body_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.body_size
);
501 if (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
!= message_size
)
509 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
510 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
512 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
515 m
->bus
= sd_bus_ref(bus
);
522 int bus_message_from_malloc(
529 sd_bus_message
**ret
) {
535 r
= bus_message_from_header(
537 buffer
, length
, /* in this case the initial bytes and the final bytes are the same */
546 sz
= length
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
);
549 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(m
->fields_size
);
551 m
->body
.sealed
= true;
556 m
->iovec
= m
->iovec_fixed
;
557 m
->iovec
[0].iov_base
= buffer
;
558 m
->iovec
[0].iov_len
= length
;
560 r
= bus_message_parse_fields(m
);
564 /* We take possession of the memory and fds now */
565 m
->free_header
= true;
576 _public_
int sd_bus_message_new(
583 assert_return(bus
, -ENOTCONN
);
584 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
585 assert_return(m
, -EINVAL
);
587 t
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
592 t
->header
= (struct bus_header
*) ((uint8_t*) t
+ ALIGN(sizeof(struct sd_bus_message
)));
593 t
->header
->endian
= BUS_NATIVE_ENDIAN
;
594 t
->header
->type
= type
;
595 t
->header
->version
= bus
->message_version
;
596 t
->allow_fds
= bus
->can_fds
|| !IN_SET(bus
->state
, BUS_HELLO
, BUS_RUNNING
);
597 t
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(t
);
598 t
->bus
= sd_bus_ref(bus
);
600 if (bus
->allow_interactive_authorization
)
601 t
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
607 _public_
int sd_bus_message_new_signal(
611 const char *interface
,
612 const char *member
) {
617 assert_return(bus
, -ENOTCONN
);
618 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
619 assert_return(object_path_is_valid(path
), -EINVAL
);
620 assert_return(interface_name_is_valid(interface
), -EINVAL
);
621 assert_return(member_name_is_valid(member
), -EINVAL
);
622 assert_return(m
, -EINVAL
);
624 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_SIGNAL
);
630 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
632 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
635 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
638 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
646 sd_bus_message_unref(t
);
650 _public_
int sd_bus_message_new_method_call(
653 const char *destination
,
655 const char *interface
,
656 const char *member
) {
661 assert_return(bus
, -ENOTCONN
);
662 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
663 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
664 assert_return(object_path_is_valid(path
), -EINVAL
);
665 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
666 assert_return(member_name_is_valid(member
), -EINVAL
);
667 assert_return(m
, -EINVAL
);
669 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_CALL
);
675 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
678 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
683 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
689 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
702 static int message_new_reply(
703 sd_bus_message
*call
,
705 sd_bus_message
**m
) {
710 assert_return(call
, -EINVAL
);
711 assert_return(call
->sealed
, -EPERM
);
712 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
713 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
714 assert_return(m
, -EINVAL
);
716 r
= sd_bus_message_new(call
->bus
, &t
, type
);
722 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
723 t
->reply_cookie
= BUS_MESSAGE_COOKIE(call
);
724 if (t
->reply_cookie
== 0)
727 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
732 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
737 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
738 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
748 _public_
int sd_bus_message_new_method_return(
749 sd_bus_message
*call
,
750 sd_bus_message
**m
) {
752 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
755 _public_
int sd_bus_message_new_method_error(
756 sd_bus_message
*call
,
758 const sd_bus_error
*e
) {
763 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
764 assert_return(m
, -EINVAL
);
766 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
770 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
775 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
780 t
->error
._need_free
= -1;
790 _public_
int sd_bus_message_new_method_errorf(
791 sd_bus_message
*call
,
797 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
800 assert_return(name
, -EINVAL
);
801 assert_return(m
, -EINVAL
);
803 va_start(ap
, format
);
804 bus_error_setfv(&error
, name
, format
, ap
);
807 return sd_bus_message_new_method_error(call
, m
, &error
);
810 _public_
int sd_bus_message_new_method_errno(
811 sd_bus_message
*call
,
814 const sd_bus_error
*p
) {
816 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
818 if (sd_bus_error_is_set(p
))
819 return sd_bus_message_new_method_error(call
, m
, p
);
821 sd_bus_error_set_errno(&berror
, error
);
823 return sd_bus_message_new_method_error(call
, m
, &berror
);
826 _public_
int sd_bus_message_new_method_errnof(
827 sd_bus_message
*call
,
833 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
836 va_start(ap
, format
);
837 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
840 return sd_bus_message_new_method_error(call
, m
, &berror
);
843 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
847 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
848 m
->creds
.well_known_names_local
= true;
849 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
852 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
856 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
857 m
->creds
.well_known_names_driver
= true;
858 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
861 int bus_message_new_synthetic_error(
864 const sd_bus_error
*e
,
865 sd_bus_message
**m
) {
871 assert(sd_bus_error_is_set(e
));
874 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_ERROR
);
880 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
881 t
->reply_cookie
= cookie
;
883 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
887 if (bus
&& bus
->unique_name
) {
888 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
893 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
898 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
903 t
->error
._need_free
= -1;
905 bus_message_set_sender_driver(bus
, t
);
915 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
920 assert(m
->n_ref
> 0);
926 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
931 assert(m
->n_ref
> 0);
941 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
942 assert_return(m
, -EINVAL
);
943 assert_return(type
, -EINVAL
);
945 *type
= m
->header
->type
;
949 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
952 assert_return(m
, -EINVAL
);
953 assert_return(cookie
, -EINVAL
);
955 c
= BUS_MESSAGE_COOKIE(m
);
959 *cookie
= BUS_MESSAGE_COOKIE(m
);
963 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
964 assert_return(m
, -EINVAL
);
965 assert_return(cookie
, -EINVAL
);
967 if (m
->reply_cookie
== 0)
970 *cookie
= m
->reply_cookie
;
974 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
975 assert_return(m
, -EINVAL
);
977 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
978 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
981 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
982 assert_return(m
, -EINVAL
);
984 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
987 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
988 assert_return(m
, -EINVAL
);
990 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
991 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
994 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
995 assert_return(m
, NULL
);
1000 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
1001 assert_return(m
, NULL
);
1003 return m
->interface
;
1006 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
1007 assert_return(m
, NULL
);
1012 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
1013 assert_return(m
, NULL
);
1015 return m
->destination
;
1018 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
1019 assert_return(m
, NULL
);
1024 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
1025 assert_return(m
, NULL
);
1027 if (!sd_bus_error_is_set(&m
->error
))
1033 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
1034 assert_return(m
, -EINVAL
);
1035 assert_return(usec
, -EINVAL
);
1037 if (m
->monotonic
<= 0)
1040 *usec
= m
->monotonic
;
1044 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1045 assert_return(m
, -EINVAL
);
1046 assert_return(usec
, -EINVAL
);
1048 if (m
->realtime
<= 0)
1051 *usec
= m
->realtime
;
1055 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1056 assert_return(m
, -EINVAL
);
1057 assert_return(seqnum
, -EINVAL
);
1062 *seqnum
= m
->seqnum
;
1066 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1067 assert_return(m
, NULL
);
1069 if (m
->creds
.mask
== 0)
1075 _public_
int sd_bus_message_is_signal(
1077 const char *interface
,
1078 const char *member
) {
1080 assert_return(m
, -EINVAL
);
1082 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1085 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1088 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1094 _public_
int sd_bus_message_is_method_call(
1096 const char *interface
,
1097 const char *member
) {
1099 assert_return(m
, -EINVAL
);
1101 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1104 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1107 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1113 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1114 assert_return(m
, -EINVAL
);
1116 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1119 if (name
&& (!m
->error
.name
|| !streq(m
->error
.name
, name
)))
1125 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1126 assert_return(m
, -EINVAL
);
1127 assert_return(!m
->sealed
, -EPERM
);
1128 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1130 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_REPLY_EXPECTED
, !b
);
1135 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1136 assert_return(m
, -EINVAL
);
1137 assert_return(!m
->sealed
, -EPERM
);
1139 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_AUTO_START
, !b
);
1144 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1145 assert_return(m
, -EINVAL
);
1146 assert_return(!m
->sealed
, -EPERM
);
1148 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
, b
);
1153 static struct bus_container
*message_get_container(sd_bus_message
*m
) {
1156 if (m
->n_containers
== 0)
1157 return &m
->root_container
;
1159 assert(m
->containers
);
1160 return m
->containers
+ m
->n_containers
- 1;
1163 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1164 struct bus_body_part
*part
;
1171 if (m
->n_body_parts
<= 0) {
1175 assert(m
->body_end
);
1177 part
= new0(struct bus_body_part
, 1);
1183 m
->body_end
->next
= part
;
1193 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1198 /* All other fields can be left in their defaults */
1199 assert(!part
->data
);
1200 assert(part
->memfd
< 0);
1203 part
->is_zero
= true;
1204 part
->sealed
= true;
1207 static int part_make_space(
1208 struct sd_bus_message
*m
,
1209 struct bus_body_part
*part
,
1217 assert(!part
->sealed
);
1222 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1223 size_t new_allocated
;
1225 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1226 n
= realloc(part
->data
, new_allocated
);
1233 part
->allocated
= new_allocated
;
1234 part
->free_this
= true;
1238 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1244 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1245 struct bus_container
*c
;
1248 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1250 /* Add offset to current container, unless this is the first
1251 * item in it, which will have the 0 offset, which we can
1253 c
= message_get_container(m
);
1255 if (!c
->need_offsets
)
1258 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1261 c
->offsets
[c
->n_offsets
++] = offset
;
1265 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1266 struct bus_container
*c
;
1273 /* Update counters */
1274 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++) {
1277 *c
->array_size
+= expand
;
1281 static void *message_extend_body(
1286 bool force_inline
) {
1288 size_t start_body
, end_body
, padding
, added
;
1299 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1300 end_body
= start_body
+ sz
;
1302 padding
= start_body
- m
->body_size
;
1303 added
= padding
+ sz
;
1305 /* Check for 32bit overflows */
1306 if (end_body
> (size_t) ((uint32_t) -1) ||
1307 end_body
< start_body
) {
1313 struct bus_body_part
*part
= NULL
;
1317 m
->n_body_parts
<= 0 ||
1318 m
->body_end
->sealed
||
1319 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1320 (force_inline
&& m
->body_end
->size
> MEMFD_MIN_SIZE
); /* if this must be an inlined extension, let's create a new part if the previous part is large enough to be inlined */
1324 part
= message_append_part(m
);
1328 part_zero(part
, padding
);
1331 part
= message_append_part(m
);
1335 r
= part_make_space(m
, part
, sz
, &p
);
1339 struct bus_container
*c
;
1341 size_t os
, start_part
, end_part
;
1347 start_part
= ALIGN_TO(part
->size
, align
);
1348 end_part
= start_part
+ sz
;
1350 r
= part_make_space(m
, part
, end_part
, &p
);
1355 memzero(p
, padding
);
1356 p
= (uint8_t*) p
+ padding
;
1359 /* Readjust pointers */
1360 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1361 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1363 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1366 /* Return something that is not NULL and is aligned */
1367 p
= (uint8_t *) NULL
+ align
;
1369 m
->body_size
= end_body
;
1370 message_extend_containers(m
, added
);
1373 r
= message_add_offset(m
, end_body
);
1383 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1394 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1398 f
= realloc(m
->fds
, sizeof(int) * (m
->n_fds
+ 1));
1406 m
->fds
[m
->n_fds
] = copy
;
1412 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1413 _cleanup_close_
int fd
= -1;
1414 struct bus_container
*c
;
1418 assert_return(m
, -EINVAL
);
1419 assert_return(!m
->sealed
, -EPERM
);
1420 assert_return(bus_type_is_basic(type
), -EINVAL
);
1421 assert_return(!m
->poisoned
, -ESTALE
);
1423 c
= message_get_container(m
);
1425 if (c
->signature
&& c
->signature
[c
->index
]) {
1426 /* Container signature is already set */
1428 if (c
->signature
[c
->index
] != type
)
1433 /* Maybe we can append to the signature? But only if this is the top-level container */
1434 if (c
->enclosing
!= 0)
1437 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1444 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1450 case SD_BUS_TYPE_SIGNATURE
:
1451 case SD_BUS_TYPE_STRING
:
1454 /* Fall through... */
1455 case SD_BUS_TYPE_OBJECT_PATH
:
1463 case SD_BUS_TYPE_BOOLEAN
:
1465 u8
= p
&& *(int*) p
;
1471 case SD_BUS_TYPE_UNIX_FD
:
1476 fd
= message_push_fd(m
, *(int*) p
);
1487 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1488 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1495 a
= message_extend_body(m
, align
, sz
, true, false);
1502 *stored
= (const uint8_t*) a
;
1509 case SD_BUS_TYPE_STRING
:
1510 /* To make things easy we'll serialize a NULL string
1511 * into the empty string */
1514 /* Fall through... */
1515 case SD_BUS_TYPE_OBJECT_PATH
:
1521 sz
= 4 + strlen(p
) + 1;
1524 case SD_BUS_TYPE_SIGNATURE
:
1529 sz
= 1 + strlen(p
) + 1;
1532 case SD_BUS_TYPE_BOOLEAN
:
1534 u32
= p
&& *(int*) p
;
1540 case SD_BUS_TYPE_UNIX_FD
:
1545 fd
= message_push_fd(m
, *(int*) p
);
1556 align
= bus_type_get_alignment(type
);
1557 sz
= bus_type_get_size(type
);
1564 a
= message_extend_body(m
, align
, sz
, false, false);
1568 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
1569 *(uint32_t*) a
= sz
- 5;
1570 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1573 *stored
= (const uint8_t*) a
+ 4;
1575 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1576 *(uint8_t*) a
= sz
- 2;
1577 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1580 *stored
= (const uint8_t*) a
+ 1;
1589 if (type
== SD_BUS_TYPE_UNIX_FD
)
1592 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1599 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1600 return message_append_basic(m
, type
, p
, NULL
);
1603 _public_
int sd_bus_message_append_string_space(
1608 struct bus_container
*c
;
1611 assert_return(m
, -EINVAL
);
1612 assert_return(s
, -EINVAL
);
1613 assert_return(!m
->sealed
, -EPERM
);
1614 assert_return(!m
->poisoned
, -ESTALE
);
1616 c
= message_get_container(m
);
1618 if (c
->signature
&& c
->signature
[c
->index
]) {
1619 /* Container signature is already set */
1621 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1626 /* Maybe we can append to the signature? But only if this is the top-level container */
1627 if (c
->enclosing
!= 0)
1630 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1637 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1638 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1644 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1648 *(uint32_t*) a
= size
;
1654 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1660 _public_
int sd_bus_message_append_string_iovec(
1662 const struct iovec
*iov
,
1670 assert_return(m
, -EINVAL
);
1671 assert_return(!m
->sealed
, -EPERM
);
1672 assert_return(iov
|| n
== 0, -EINVAL
);
1673 assert_return(!m
->poisoned
, -ESTALE
);
1675 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1677 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1681 for (i
= 0; i
< n
; i
++) {
1683 if (iov
[i
].iov_base
)
1684 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1686 memset(p
, ' ', iov
[i
].iov_len
);
1688 p
+= iov
[i
].iov_len
;
1694 static int bus_message_open_array(
1696 struct bus_container
*c
,
1697 const char *contents
,
1698 uint32_t **array_size
,
1700 bool *need_offsets
) {
1710 assert(need_offsets
);
1712 if (!signature_is_single(contents
, true))
1715 if (c
->signature
&& c
->signature
[c
->index
]) {
1717 /* Verify the existing signature */
1719 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1722 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1725 nindex
= c
->index
+ 1 + strlen(contents
);
1729 if (c
->enclosing
!= 0)
1732 /* Extend the existing signature */
1734 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1740 nindex
= e
- c
->signature
;
1743 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1744 alignment
= bus_gvariant_get_alignment(contents
);
1748 /* Add alignment padding and add to offset list */
1749 if (!message_extend_body(m
, alignment
, 0, false, false))
1752 r
= bus_gvariant_is_fixed_size(contents
);
1756 *begin
= m
->body_size
;
1757 *need_offsets
= r
== 0;
1761 struct bus_body_part
*o
;
1763 alignment
= bus_type_get_alignment(contents
[0]);
1767 a
= message_extend_body(m
, 4, 4, false, false);
1772 op
= m
->body_end
->data
;
1773 os
= m
->body_end
->size
;
1775 /* Add alignment between size and first element */
1776 if (!message_extend_body(m
, alignment
, 0, false, false))
1779 /* location of array size might have changed so let's readjust a */
1780 if (o
== m
->body_end
)
1781 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1787 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1793 static int bus_message_open_variant(
1795 struct bus_container
*c
,
1796 const char *contents
) {
1802 if (!signature_is_single(contents
, false))
1805 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1808 if (c
->signature
&& c
->signature
[c
->index
]) {
1810 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1816 if (c
->enclosing
!= 0)
1819 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1826 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1827 /* Variants are always aligned to 8 */
1829 if (!message_extend_body(m
, 8, 0, false, false))
1836 l
= strlen(contents
);
1837 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1842 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1845 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1851 static int bus_message_open_struct(
1853 struct bus_container
*c
,
1854 const char *contents
,
1856 bool *need_offsets
) {
1865 assert(need_offsets
);
1867 if (!signature_is_valid(contents
, false))
1870 if (c
->signature
&& c
->signature
[c
->index
]) {
1873 l
= strlen(contents
);
1875 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1876 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1877 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1880 nindex
= c
->index
+ 1 + l
+ 1;
1884 if (c
->enclosing
!= 0)
1887 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1893 nindex
= e
- c
->signature
;
1896 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1899 alignment
= bus_gvariant_get_alignment(contents
);
1903 if (!message_extend_body(m
, alignment
, 0, false, false))
1906 r
= bus_gvariant_is_fixed_size(contents
);
1910 *begin
= m
->body_size
;
1911 *need_offsets
= r
== 0;
1913 /* Align contents to 8 byte boundary */
1914 if (!message_extend_body(m
, 8, 0, false, false))
1918 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1924 static int bus_message_open_dict_entry(
1926 struct bus_container
*c
,
1927 const char *contents
,
1929 bool *need_offsets
) {
1937 assert(need_offsets
);
1939 if (!signature_is_pair(contents
))
1942 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1945 if (c
->signature
&& c
->signature
[c
->index
]) {
1948 l
= strlen(contents
);
1950 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
1951 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1952 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
1957 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1960 alignment
= bus_gvariant_get_alignment(contents
);
1964 if (!message_extend_body(m
, alignment
, 0, false, false))
1967 r
= bus_gvariant_is_fixed_size(contents
);
1971 *begin
= m
->body_size
;
1972 *need_offsets
= r
== 0;
1974 /* Align contents to 8 byte boundary */
1975 if (!message_extend_body(m
, 8, 0, false, false))
1982 _public_
int sd_bus_message_open_container(
1985 const char *contents
) {
1987 struct bus_container
*c
, *w
;
1988 uint32_t *array_size
= NULL
;
1990 size_t before
, begin
= 0;
1991 bool need_offsets
= false;
1994 assert_return(m
, -EINVAL
);
1995 assert_return(!m
->sealed
, -EPERM
);
1996 assert_return(contents
, -EINVAL
);
1997 assert_return(!m
->poisoned
, -ESTALE
);
1999 /* Make sure we have space for one more container */
2000 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
2005 c
= message_get_container(m
);
2007 signature
= strdup(contents
);
2013 /* Save old index in the parent container, in case we have to
2014 * abort this container */
2015 c
->saved_index
= c
->index
;
2016 before
= m
->body_size
;
2018 if (type
== SD_BUS_TYPE_ARRAY
)
2019 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
2020 else if (type
== SD_BUS_TYPE_VARIANT
)
2021 r
= bus_message_open_variant(m
, c
, contents
);
2022 else if (type
== SD_BUS_TYPE_STRUCT
)
2023 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
2024 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
2025 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
2034 /* OK, let's fill it in */
2035 w
= m
->containers
+ m
->n_containers
++;
2036 w
->enclosing
= type
;
2037 w
->signature
= signature
;
2039 w
->array_size
= array_size
;
2042 w
->n_offsets
= w
->offsets_allocated
= 0;
2044 w
->need_offsets
= need_offsets
;
2049 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2054 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2057 if (c
->need_offsets
) {
2058 size_t payload
, sz
, i
;
2061 /* Variable-width arrays */
2063 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2064 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2066 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2070 for (i
= 0; i
< c
->n_offsets
; i
++)
2071 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2075 /* Fixed-width or empty arrays */
2077 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2085 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2091 assert(c
->signature
);
2093 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2096 l
= strlen(c
->signature
);
2098 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2103 memcpy(a
+1, c
->signature
, l
);
2108 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2109 bool fixed_size
= true;
2110 size_t n_variable
= 0;
2119 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2122 p
= strempty(c
->signature
);
2126 r
= signature_element_length(p
, &n
);
2135 r
= bus_gvariant_is_fixed_size(t
);
2140 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2142 /* We need to add an offset for each item that has a
2143 * variable size and that is not the last one in the
2147 if (r
== 0 && p
[n
] != 0)
2154 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2155 assert(c
->need_offsets
|| n_variable
== 0);
2157 if (isempty(c
->signature
)) {
2158 /* The unary type is encoded as fixed 1 byte padding */
2159 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2164 } else if (n_variable
<= 0) {
2167 /* Structures with fixed-size members only have to be
2168 * fixed-size themselves. But gvariant requires all fixed-size
2169 * elements to be sized a multiple of their alignment. Hence,
2170 * we must *always* add final padding after the last member so
2171 * the overall size of the structure is properly aligned. */
2173 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2175 assert(alignment
> 0);
2177 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2184 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2186 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2188 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2192 p
= strempty(c
->signature
);
2193 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2197 r
= signature_element_length(p
, &n
);
2208 r
= bus_gvariant_is_fixed_size(t
);
2211 if (r
> 0 || p
[0] == 0)
2215 k
= n_variable
- 1 - j
;
2217 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2226 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2227 struct bus_container
*c
;
2230 assert_return(m
, -EINVAL
);
2231 assert_return(!m
->sealed
, -EPERM
);
2232 assert_return(m
->n_containers
> 0, -EINVAL
);
2233 assert_return(!m
->poisoned
, -ESTALE
);
2235 c
= message_get_container(m
);
2237 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2238 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2243 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2244 r
= bus_message_close_array(m
, c
);
2245 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2246 r
= bus_message_close_variant(m
, c
);
2247 else if (IN_SET(c
->enclosing
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
))
2248 r
= bus_message_close_struct(m
, c
, true);
2250 assert_not_reached("Unknown container type");
2264 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2271 stack
[*i
].types
= types
;
2272 stack
[*i
].n_struct
= n_struct
;
2273 stack
[*i
].n_array
= n_array
;
2279 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2290 *types
= stack
[*i
].types
;
2291 *n_struct
= stack
[*i
].n_struct
;
2292 *n_array
= stack
[*i
].n_array
;
2297 _public_
int sd_bus_message_appendv(
2302 unsigned n_array
, n_struct
;
2303 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2304 unsigned stack_ptr
= 0;
2307 assert_return(m
, -EINVAL
);
2308 assert_return(types
, -EINVAL
);
2309 assert_return(!m
->sealed
, -EPERM
);
2310 assert_return(!m
->poisoned
, -ESTALE
);
2312 n_array
= (unsigned) -1;
2313 n_struct
= strlen(types
);
2318 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2319 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2325 r
= sd_bus_message_close_container(m
);
2333 if (n_array
!= (unsigned) -1)
2342 case SD_BUS_TYPE_BYTE
: {
2345 x
= (uint8_t) va_arg(ap
, int);
2346 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2350 case SD_BUS_TYPE_BOOLEAN
:
2351 case SD_BUS_TYPE_INT32
:
2352 case SD_BUS_TYPE_UINT32
:
2353 case SD_BUS_TYPE_UNIX_FD
: {
2356 /* We assume a boolean is the same as int32_t */
2357 assert_cc(sizeof(int32_t) == sizeof(int));
2359 x
= va_arg(ap
, uint32_t);
2360 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2364 case SD_BUS_TYPE_INT16
:
2365 case SD_BUS_TYPE_UINT16
: {
2368 x
= (uint16_t) va_arg(ap
, int);
2369 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2373 case SD_BUS_TYPE_INT64
:
2374 case SD_BUS_TYPE_UINT64
: {
2377 x
= va_arg(ap
, uint64_t);
2378 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2382 case SD_BUS_TYPE_DOUBLE
: {
2385 x
= va_arg(ap
, double);
2386 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2390 case SD_BUS_TYPE_STRING
:
2391 case SD_BUS_TYPE_OBJECT_PATH
:
2392 case SD_BUS_TYPE_SIGNATURE
: {
2395 x
= va_arg(ap
, const char*);
2396 r
= sd_bus_message_append_basic(m
, *t
, x
);
2400 case SD_BUS_TYPE_ARRAY
: {
2403 r
= signature_element_length(t
+ 1, &k
);
2409 memcpy(s
, t
+ 1, k
);
2412 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2417 if (n_array
== (unsigned) -1) {
2422 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2428 n_array
= va_arg(ap
, unsigned);
2433 case SD_BUS_TYPE_VARIANT
: {
2436 s
= va_arg(ap
, const char*);
2440 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2444 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2449 n_struct
= strlen(s
);
2450 n_array
= (unsigned) -1;
2455 case SD_BUS_TYPE_STRUCT_BEGIN
:
2456 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2459 r
= signature_element_length(t
, &k
);
2466 memcpy(s
, t
+ 1, k
- 2);
2469 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2474 if (n_array
== (unsigned) -1) {
2479 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2485 n_array
= (unsigned) -1;
2501 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2505 assert_return(m
, -EINVAL
);
2506 assert_return(types
, -EINVAL
);
2507 assert_return(!m
->sealed
, -EPERM
);
2508 assert_return(!m
->poisoned
, -ESTALE
);
2510 va_start(ap
, types
);
2511 r
= sd_bus_message_appendv(m
, types
, ap
);
2517 _public_
int sd_bus_message_append_array_space(
2527 assert_return(m
, -EINVAL
);
2528 assert_return(!m
->sealed
, -EPERM
);
2529 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2530 assert_return(ptr
|| size
== 0, -EINVAL
);
2531 assert_return(!m
->poisoned
, -ESTALE
);
2533 /* alignment and size of the trivial types (except bool) is
2534 * identical for gvariant and dbus1 marshalling */
2535 align
= bus_type_get_alignment(type
);
2536 sz
= bus_type_get_size(type
);
2538 assert_se(align
> 0);
2544 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2548 a
= message_extend_body(m
, align
, size
, false, false);
2552 r
= sd_bus_message_close_container(m
);
2560 _public_
int sd_bus_message_append_array(
2568 assert_return(m
, -EINVAL
);
2569 assert_return(!m
->sealed
, -EPERM
);
2570 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2571 assert_return(ptr
|| size
== 0, -EINVAL
);
2572 assert_return(!m
->poisoned
, -ESTALE
);
2574 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2578 memcpy_safe(p
, ptr
, size
);
2583 _public_
int sd_bus_message_append_array_iovec(
2586 const struct iovec
*iov
,
2594 assert_return(m
, -EINVAL
);
2595 assert_return(!m
->sealed
, -EPERM
);
2596 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2597 assert_return(iov
|| n
== 0, -EINVAL
);
2598 assert_return(!m
->poisoned
, -ESTALE
);
2600 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2602 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2606 for (i
= 0; i
< n
; i
++) {
2608 if (iov
[i
].iov_base
)
2609 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2611 memzero(p
, iov
[i
].iov_len
);
2613 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2619 _public_
int sd_bus_message_append_array_memfd(
2626 _cleanup_close_
int copy_fd
= -1;
2627 struct bus_body_part
*part
;
2633 assert_return(m
, -EINVAL
);
2634 assert_return(memfd
>= 0, -EBADF
);
2635 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2636 assert_return(size
> 0, -EINVAL
);
2637 assert_return(!m
->sealed
, -EPERM
);
2638 assert_return(!m
->poisoned
, -ESTALE
);
2640 r
= memfd_set_sealed(memfd
);
2644 copy_fd
= dup(memfd
);
2648 r
= memfd_get_size(memfd
, &real_size
);
2652 if (offset
== 0 && size
== (uint64_t) -1)
2654 else if (offset
+ size
> real_size
)
2657 align
= bus_type_get_alignment(type
);
2658 sz
= bus_type_get_size(type
);
2660 assert_se(align
> 0);
2663 if (offset
% align
!= 0)
2669 if (size
> (uint64_t) (uint32_t) -1)
2672 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2676 a
= message_extend_body(m
, align
, 0, false, false);
2680 part
= message_append_part(m
);
2684 part
->memfd
= copy_fd
;
2685 part
->memfd_offset
= offset
;
2686 part
->sealed
= true;
2690 m
->body_size
+= size
;
2691 message_extend_containers(m
, size
);
2693 return sd_bus_message_close_container(m
);
2696 _public_
int sd_bus_message_append_string_memfd(
2702 _cleanup_close_
int copy_fd
= -1;
2703 struct bus_body_part
*part
;
2704 struct bus_container
*c
;
2709 assert_return(m
, -EINVAL
);
2710 assert_return(memfd
>= 0, -EBADF
);
2711 assert_return(size
> 0, -EINVAL
);
2712 assert_return(!m
->sealed
, -EPERM
);
2713 assert_return(!m
->poisoned
, -ESTALE
);
2715 r
= memfd_set_sealed(memfd
);
2719 copy_fd
= dup(memfd
);
2723 r
= memfd_get_size(memfd
, &real_size
);
2727 if (offset
== 0 && size
== (uint64_t) -1)
2729 else if (offset
+ size
> real_size
)
2732 /* We require this to be NUL terminated */
2736 if (size
> (uint64_t) (uint32_t) -1)
2739 c
= message_get_container(m
);
2740 if (c
->signature
&& c
->signature
[c
->index
]) {
2741 /* Container signature is already set */
2743 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2748 /* Maybe we can append to the signature? But only if this is the top-level container */
2749 if (c
->enclosing
!= 0)
2752 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2759 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2760 a
= message_extend_body(m
, 4, 4, false, false);
2764 *(uint32_t*) a
= size
- 1;
2767 part
= message_append_part(m
);
2771 part
->memfd
= copy_fd
;
2772 part
->memfd_offset
= offset
;
2773 part
->sealed
= true;
2777 m
->body_size
+= size
;
2778 message_extend_containers(m
, size
);
2780 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2781 r
= message_add_offset(m
, m
->body_size
);
2788 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2794 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2798 assert_return(m
, -EINVAL
);
2799 assert_return(!m
->sealed
, -EPERM
);
2800 assert_return(!m
->poisoned
, -ESTALE
);
2802 r
= sd_bus_message_open_container(m
, 'a', "s");
2806 STRV_FOREACH(i
, l
) {
2807 r
= sd_bus_message_append_basic(m
, 's', *i
);
2812 return sd_bus_message_close_container(m
);
2815 static int bus_message_close_header(sd_bus_message
*m
) {
2819 /* The actual user data is finished now, we just complete the
2820 variant and struct now (at least on gvariant). Remember
2821 this position, so that during parsing we know where to
2822 put the outer container end. */
2823 m
->user_body_size
= m
->body_size
;
2825 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2826 const char *signature
;
2830 /* Add offset table to end of fields array */
2831 if (m
->n_header_offsets
>= 1) {
2835 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2837 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2838 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2842 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2843 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2846 /* Add gvariant NUL byte plus signature to the end of
2847 * the body, followed by the final offset pointing to
2848 * the end of the fields array */
2850 signature
= strempty(m
->root_container
.signature
);
2851 l
= strlen(signature
);
2853 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2854 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2859 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2860 memcpy((uint8_t*) d
+ 2, signature
, l
);
2861 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2863 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2866 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2868 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2869 m
->header
->dbus1
.body_size
= m
->body_size
;
2875 _public_
int sd_bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, uint64_t timeout_usec
) {
2876 struct bus_body_part
*part
;
2881 assert_return(m
, -EINVAL
);
2886 if (m
->n_containers
> 0)
2892 if (cookie
> 0xffffffffULL
&&
2893 !BUS_MESSAGE_IS_GVARIANT(m
))
2896 /* In vtables the return signature of method calls is listed,
2897 * let's check if they match if this is a response */
2898 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2899 m
->enforced_reply_signature
&&
2900 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2903 /* If gvariant marshalling is used we need to close the body structure */
2904 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2908 /* If there's a non-trivial signature set, then add it in
2909 * here, but only on dbus1 */
2910 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2911 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2917 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2922 r
= bus_message_close_header(m
);
2926 if (BUS_MESSAGE_IS_GVARIANT(m
))
2927 m
->header
->dbus2
.cookie
= cookie
;
2929 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2931 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout_usec
;
2933 /* Add padding at the end of the fields part, since we know
2934 * the body needs to start at an 8 byte alignment. We made
2935 * sure we allocated enough space for this, so all we need to
2936 * do here is to zero it out. */
2937 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2939 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2941 /* If this is something we can send as memfd, then let's seal
2942 the memfd now. Note that we can send memfds as payload only
2943 for directed messages, and not for broadcasts. */
2944 if (m
->destination
&& m
->bus
->use_memfd
) {
2945 MESSAGE_FOREACH_PART(part
, i
, m
)
2946 if (part
->memfd
>= 0 &&
2948 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
2949 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
2952 /* Try to seal it if that makes
2953 * sense. First, unmap our own map to
2954 * make sure we don't keep it busy. */
2955 bus_body_part_unmap(part
);
2957 /* Then, sync up real memfd size */
2959 r
= memfd_set_size(part
->memfd
, sz
);
2963 /* Finally, try to seal */
2964 if (memfd_set_sealed(part
->memfd
) >= 0)
2965 part
->sealed
= true;
2969 m
->root_container
.end
= m
->user_body_size
;
2970 m
->root_container
.index
= 0;
2971 m
->root_container
.offset_index
= 0;
2972 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
2979 int bus_body_part_map(struct bus_body_part
*part
) {
2988 if (part
->size
<= 0)
2991 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2992 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
2993 static const uint8_t zeroes
[7] = { };
2994 part
->data
= (void*) zeroes
;
2998 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
2999 psz
= PAGE_ALIGN(part
->size
+ shift
);
3001 if (part
->memfd
>= 0)
3002 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
3003 else if (part
->is_zero
)
3004 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
3008 if (p
== MAP_FAILED
)
3012 part
->mmap_begin
= p
;
3013 part
->data
= (uint8_t*) p
+ shift
;
3014 part
->munmap_this
= true;
3019 void bus_body_part_unmap(struct bus_body_part
*part
) {
3023 if (part
->memfd
< 0)
3026 if (!part
->mmap_begin
)
3029 if (!part
->munmap_this
)
3032 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
3034 part
->mmap_begin
= NULL
;
3037 part
->munmap_this
= false;
3042 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3043 size_t k
, start
, end
;
3048 start
= ALIGN_TO((size_t) *rindex
, align
);
3049 end
= start
+ nbytes
;
3054 /* Verify that padding is 0 */
3055 for (k
= *rindex
; k
< start
; k
++)
3056 if (((const uint8_t*) p
)[k
] != 0)
3060 *r
= (uint8_t*) p
+ start
;
3067 static bool message_end_of_signature(sd_bus_message
*m
) {
3068 struct bus_container
*c
;
3072 c
= message_get_container(m
);
3073 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3076 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3077 struct bus_container
*c
;
3081 c
= message_get_container(m
);
3082 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3085 if (BUS_MESSAGE_IS_GVARIANT(m
))
3086 return index
>= c
->end
;
3088 assert(c
->array_size
);
3089 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3093 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3094 assert_return(m
, -EINVAL
);
3095 assert_return(m
->sealed
, -EPERM
);
3097 if (complete
&& m
->n_containers
> 0)
3100 if (message_end_of_signature(m
))
3103 if (message_end_of_array(m
, m
->rindex
))
3109 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3110 struct bus_body_part
*part
;
3116 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3117 part
= m
->cached_rindex_part
;
3118 begin
= m
->cached_rindex_part_begin
;
3128 if (index
+ sz
<= begin
+ part
->size
) {
3130 r
= bus_body_part_map(part
);
3135 *p
= (uint8_t*) part
->data
+ index
- begin
;
3137 m
->cached_rindex_part
= part
;
3138 m
->cached_rindex_part_begin
= begin
;
3143 begin
+= part
->size
;
3150 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3157 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3160 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3163 sz
= bus_gvariant_get_size(c
->signature
);
3167 if (c
->offset_index
+1 >= c
->n_offsets
)
3170 /* Variable-size array */
3172 alignment
= bus_gvariant_get_alignment(c
->signature
);
3173 assert(alignment
> 0);
3175 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3176 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3179 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3182 /* Fixed-size array */
3183 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3189 } else if (IN_SET(c
->enclosing
, 0, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
3194 if (c
->offset_index
+1 >= c
->n_offsets
)
3197 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3201 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3206 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3209 alignment
= bus_gvariant_get_alignment(t
);
3212 assert(alignment
> 0);
3214 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3215 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3219 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3222 assert_not_reached("Unknown container type");
3227 /* Reached the end */
3234 static int message_peek_body(
3241 size_t k
, start
, end
, padding
;
3242 struct bus_body_part
*part
;
3249 start
= ALIGN_TO((size_t) *rindex
, align
);
3250 padding
= start
- *rindex
;
3251 end
= start
+ nbytes
;
3253 if (end
> m
->user_body_size
)
3256 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3261 /* Verify padding */
3262 for (k
= 0; k
< padding
; k
++)
3267 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3268 if (!part
|| (nbytes
> 0 && !q
))
3279 static bool validate_nul(const char *s
, size_t l
) {
3281 /* Check for NUL chars in the string */
3282 if (memchr(s
, 0, l
))
3285 /* Check for NUL termination */
3292 static bool validate_string(const char *s
, size_t l
) {
3294 if (!validate_nul(s
, l
))
3297 /* Check if valid UTF8 */
3298 if (!utf8_is_valid(s
))
3304 static bool validate_signature(const char *s
, size_t l
) {
3306 if (!validate_nul(s
, l
))
3309 /* Check if valid signature */
3310 if (!signature_is_valid(s
, true))
3316 static bool validate_object_path(const char *s
, size_t l
) {
3318 if (!validate_nul(s
, l
))
3321 if (!object_path_is_valid(s
))
3327 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3328 struct bus_container
*c
;
3333 assert_return(m
, -EINVAL
);
3334 assert_return(m
->sealed
, -EPERM
);
3335 assert_return(bus_type_is_basic(type
), -EINVAL
);
3337 if (message_end_of_signature(m
))
3340 if (message_end_of_array(m
, m
->rindex
))
3343 c
= message_get_container(m
);
3344 if (c
->signature
[c
->index
] != type
)
3349 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3351 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3354 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3358 if (type
== SD_BUS_TYPE_STRING
)
3359 ok
= validate_string(q
, c
->item_size
-1);
3360 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3361 ok
= validate_object_path(q
, c
->item_size
-1);
3363 ok
= validate_signature(q
, c
->item_size
-1);
3369 *(const char**) p
= q
;
3373 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3375 if ((size_t) sz
!= c
->item_size
)
3378 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3381 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3387 case SD_BUS_TYPE_BYTE
:
3389 *(uint8_t*) p
= *(uint8_t*) q
;
3392 case SD_BUS_TYPE_BOOLEAN
:
3394 *(int*) p
= !!*(uint8_t*) q
;
3397 case SD_BUS_TYPE_INT16
:
3398 case SD_BUS_TYPE_UINT16
:
3400 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3403 case SD_BUS_TYPE_INT32
:
3404 case SD_BUS_TYPE_UINT32
:
3406 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3409 case SD_BUS_TYPE_INT64
:
3410 case SD_BUS_TYPE_UINT64
:
3411 case SD_BUS_TYPE_DOUBLE
:
3413 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3416 case SD_BUS_TYPE_UNIX_FD
: {
3419 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3424 *(int*) p
= m
->fds
[j
];
3430 assert_not_reached("unexpected type");
3434 r
= container_next_item(m
, c
, &rindex
);
3439 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3443 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3447 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3448 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3452 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3453 ok
= validate_object_path(q
, l
);
3455 ok
= validate_string(q
, l
);
3460 *(const char**) p
= q
;
3462 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3465 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3470 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3474 if (!validate_signature(q
, l
))
3478 *(const char**) p
= q
;
3483 align
= bus_type_get_alignment(type
);
3486 sz
= bus_type_get_size(type
);
3489 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3495 case SD_BUS_TYPE_BYTE
:
3497 *(uint8_t*) p
= *(uint8_t*) q
;
3500 case SD_BUS_TYPE_BOOLEAN
:
3502 *(int*) p
= !!*(uint32_t*) q
;
3505 case SD_BUS_TYPE_INT16
:
3506 case SD_BUS_TYPE_UINT16
:
3508 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3511 case SD_BUS_TYPE_INT32
:
3512 case SD_BUS_TYPE_UINT32
:
3514 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3517 case SD_BUS_TYPE_INT64
:
3518 case SD_BUS_TYPE_UINT64
:
3519 case SD_BUS_TYPE_DOUBLE
:
3521 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3524 case SD_BUS_TYPE_UNIX_FD
: {
3527 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3532 *(int*) p
= m
->fds
[j
];
3537 assert_not_reached("Unknown basic type...");
3544 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3550 static int bus_message_enter_array(
3552 struct bus_container
*c
,
3553 const char *contents
,
3554 uint32_t **array_size
,
3557 size_t *n_offsets
) {
3571 if (!signature_is_single(contents
, true))
3574 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3577 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3580 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3585 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3588 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3592 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3595 alignment
= bus_type_get_alignment(contents
[0]);
3599 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3603 *array_size
= (uint32_t*) q
;
3605 } else if (c
->item_size
<= 0) {
3607 /* gvariant: empty array */
3612 } else if (bus_gvariant_is_fixed_size(contents
)) {
3614 /* gvariant: fixed length array */
3615 *item_size
= bus_gvariant_get_size(contents
);
3620 size_t where
, p
= 0, framing
, sz
;
3623 /* gvariant: variable length array */
3624 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3626 where
= rindex
+ c
->item_size
- sz
;
3627 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3631 framing
= bus_gvariant_read_word_le(q
, sz
);
3632 if (framing
> c
->item_size
- sz
)
3634 if ((c
->item_size
- framing
) % sz
!= 0)
3637 *n_offsets
= (c
->item_size
- framing
) / sz
;
3639 where
= rindex
+ framing
;
3640 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3644 *offsets
= new(size_t, *n_offsets
);
3648 for (i
= 0; i
< *n_offsets
; i
++) {
3651 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3652 if (x
> c
->item_size
- sz
)
3657 (*offsets
)[i
] = rindex
+ x
;
3661 *item_size
= (*offsets
)[0] - rindex
;
3666 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3667 c
->index
+= 1 + strlen(contents
);
3672 static int bus_message_enter_variant(
3674 struct bus_container
*c
,
3675 const char *contents
,
3676 size_t *item_size
) {
3688 if (!signature_is_single(contents
, false))
3691 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3694 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3697 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3702 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3705 k
= strlen(contents
);
3706 if (1+k
> c
->item_size
)
3709 where
= rindex
+ c
->item_size
- (1+k
);
3710 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3714 if (*(char*) q
!= 0)
3717 if (memcmp((uint8_t*) q
+1, contents
, k
))
3720 *item_size
= c
->item_size
- (1+k
);
3723 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3728 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3732 if (!validate_signature(q
, l
))
3735 if (!streq(q
, contents
))
3741 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3747 static int build_struct_offsets(
3749 const char *signature
,
3753 size_t *n_offsets
) {
3755 unsigned n_variable
= 0, n_total
= 0, v
;
3756 size_t previous
= 0, where
;
3767 if (isempty(signature
)) {
3768 /* Unary type is encoded as *fixed* 1 byte padding */
3769 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3773 if (*(uint8_t *) q
!= 0)
3782 sz
= bus_gvariant_determine_word_size(size
, 0);
3786 /* First, loop over signature and count variable elements and
3787 * elements in general. We use this to know how large the
3788 * offset array is at the end of the structure. Note that
3789 * GVariant only stores offsets for all variable size elements
3790 * that are not the last item. */
3796 r
= signature_element_length(p
, &n
);
3805 r
= bus_gvariant_is_fixed_size(t
);
3810 if (r
== 0 && p
[n
] != 0) /* except the last item */
3817 if (size
< n_variable
* sz
)
3820 where
= m
->rindex
+ size
- (n_variable
* sz
);
3821 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3827 *offsets
= new(size_t, n_total
);
3833 /* Second, loop again and build an offset table */
3839 r
= signature_element_length(p
, &n
);
3848 k
= bus_gvariant_get_size(t
);
3856 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3859 if (m
->rindex
+ x
< previous
)
3862 /* The last item's end
3863 * is determined from
3866 x
= size
- (n_variable
* sz
);
3868 offset
= m
->rindex
+ x
;
3874 align
= bus_gvariant_get_alignment(t
);
3877 offset
= (*n_offsets
== 0 ? m
->rindex
: ALIGN_TO((*offsets
)[*n_offsets
-1], align
)) + k
;
3881 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3886 assert(*n_offsets
== n_total
);
3888 *item_size
= (*offsets
)[0] - m
->rindex
;
3892 static int enter_struct_or_dict_entry(
3894 struct bus_container
*c
,
3895 const char *contents
,
3898 size_t *n_offsets
) {
3909 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3912 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3917 /* gvariant with contents */
3918 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3923 static int bus_message_enter_struct(
3925 struct bus_container
*c
,
3926 const char *contents
,
3929 size_t *n_offsets
) {
3941 if (!signature_is_valid(contents
, false))
3944 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3947 l
= strlen(contents
);
3949 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
3950 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3951 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
3954 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3958 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3959 c
->index
+= 1 + l
+ 1;
3964 static int bus_message_enter_dict_entry(
3966 struct bus_container
*c
,
3967 const char *contents
,
3970 size_t *n_offsets
) {
3979 if (!signature_is_pair(contents
))
3982 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3985 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3988 l
= strlen(contents
);
3990 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
3991 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3992 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
3995 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3999 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4000 c
->index
+= 1 + l
+ 1;
4005 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
4007 const char *contents
) {
4008 struct bus_container
*c
, *w
;
4009 uint32_t *array_size
= NULL
;
4012 size_t *offsets
= NULL
;
4013 size_t n_offsets
= 0, item_size
= 0;
4016 assert_return(m
, -EINVAL
);
4017 assert_return(m
->sealed
, -EPERM
);
4018 assert_return(type
!= 0 || !contents
, -EINVAL
);
4020 if (type
== 0 || !contents
) {
4024 /* Allow entering into anonymous containers */
4025 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
4029 if (type
!= 0 && type
!= tt
)
4032 if (contents
&& !streq(contents
, cc
))
4040 * We enforce a global limit on container depth, that is much
4041 * higher than the 32 structs and 32 arrays the specification
4042 * mandates. This is simpler to implement for us, and we need
4043 * this only to ensure our container array doesn't grow
4044 * without bounds. We are happy to return any data from a
4045 * message as long as the data itself is valid, even if the
4046 * overall message might be not.
4048 * Note that the message signature is validated when
4049 * parsing the headers, and that validation does check the
4052 * Note that the specification defines no limits on the depth
4053 * of stacked variants, but we do.
4055 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4058 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4061 if (message_end_of_signature(m
))
4064 if (message_end_of_array(m
, m
->rindex
))
4067 c
= message_get_container(m
);
4069 signature
= strdup(contents
);
4073 c
->saved_index
= c
->index
;
4076 if (type
== SD_BUS_TYPE_ARRAY
)
4077 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4078 else if (type
== SD_BUS_TYPE_VARIANT
)
4079 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4080 else if (type
== SD_BUS_TYPE_STRUCT
)
4081 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4082 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4083 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4093 /* OK, let's fill it in */
4094 w
= m
->containers
+ m
->n_containers
++;
4095 w
->enclosing
= type
;
4096 w
->signature
= signature
;
4097 w
->peeked_signature
= NULL
;
4101 w
->begin
= m
->rindex
;
4103 /* Unary type has fixed size of 1, but virtual size of 0 */
4104 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4105 type
== SD_BUS_TYPE_STRUCT
&&
4107 w
->end
= m
->rindex
+ 0;
4109 w
->end
= m
->rindex
+ c
->item_size
;
4111 w
->array_size
= array_size
;
4112 w
->item_size
= item_size
;
4113 w
->offsets
= offsets
;
4114 w
->n_offsets
= n_offsets
;
4115 w
->offset_index
= 0;
4120 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4121 struct bus_container
*c
;
4125 assert_return(m
, -EINVAL
);
4126 assert_return(m
->sealed
, -EPERM
);
4127 assert_return(m
->n_containers
> 0, -ENXIO
);
4129 c
= message_get_container(m
);
4131 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4132 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4136 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4137 if (m
->rindex
< c
->end
)
4140 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4143 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4144 if (c
->begin
+ l
!= m
->rindex
)
4149 free(c
->peeked_signature
);
4153 c
= message_get_container(m
);
4156 c
->index
= c
->saved_index
;
4157 r
= container_next_item(m
, c
, &m
->rindex
);
4165 static void message_quit_container(sd_bus_message
*m
) {
4166 struct bus_container
*c
;
4170 assert(m
->n_containers
> 0);
4172 c
= message_get_container(m
);
4175 assert(m
->rindex
>= c
->before
);
4176 m
->rindex
= c
->before
;
4178 /* Free container */
4183 /* Correct index of new top-level container */
4184 c
= message_get_container(m
);
4185 c
->index
= c
->saved_index
;
4188 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4189 struct bus_container
*c
;
4192 assert_return(m
, -EINVAL
);
4193 assert_return(m
->sealed
, -EPERM
);
4195 if (message_end_of_signature(m
))
4198 if (message_end_of_array(m
, m
->rindex
))
4201 c
= message_get_container(m
);
4203 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4207 *type
= c
->signature
[c
->index
];
4211 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4217 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4223 sig
= strndup(c
->signature
+ c
->index
+ 1, l
);
4227 free(c
->peeked_signature
);
4228 *contents
= c
->peeked_signature
= sig
;
4232 *type
= SD_BUS_TYPE_ARRAY
;
4237 if (IN_SET(c
->signature
[c
->index
], SD_BUS_TYPE_STRUCT_BEGIN
, SD_BUS_TYPE_DICT_ENTRY_BEGIN
)) {
4243 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4248 sig
= strndup(c
->signature
+ c
->index
+ 1, l
- 2);
4252 free(c
->peeked_signature
);
4253 *contents
= c
->peeked_signature
= sig
;
4257 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4262 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4266 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4269 if (c
->item_size
< 2)
4272 /* Look for the NUL delimiter that
4273 separates the payload from the
4274 signature. Since the body might be
4275 in a different part that then the
4276 signature we map byte by byte. */
4278 for (k
= 2; k
<= c
->item_size
; k
++) {
4281 where
= m
->rindex
+ c
->item_size
- k
;
4282 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4286 if (*(char*) q
== 0)
4290 if (k
> c
->item_size
)
4293 free(c
->peeked_signature
);
4294 c
->peeked_signature
= strndup((char*) q
+ 1, k
- 1);
4295 if (!c
->peeked_signature
)
4298 if (!signature_is_valid(c
->peeked_signature
, true))
4301 *contents
= c
->peeked_signature
;
4306 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4311 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4315 if (!validate_signature(q
, l
))
4323 *type
= SD_BUS_TYPE_VARIANT
;
4338 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4339 struct bus_container
*c
;
4341 assert_return(m
, -EINVAL
);
4342 assert_return(m
->sealed
, -EPERM
);
4345 message_reset_containers(m
);
4348 c
= message_get_container(m
);
4350 c
= message_get_container(m
);
4352 c
->offset_index
= 0;
4354 m
->rindex
= c
->begin
;
4357 c
->offset_index
= 0;
4358 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4360 return !isempty(c
->signature
);
4363 static int message_read_ap(
4368 unsigned n_array
, n_struct
;
4369 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4370 unsigned stack_ptr
= 0;
4371 unsigned n_loop
= 0;
4379 /* Ideally, we'd just call ourselves recursively on every
4380 * complex type. However, the state of a va_list that is
4381 * passed to a function is undefined after that function
4382 * returns. This means we need to docode the va_list linearly
4383 * in a single stackframe. We hence implement our own
4384 * home-grown stack in an array. */
4386 n_array
= (unsigned) -1; /* length of current array entries */
4387 n_struct
= strlen(types
); /* length of current struct contents signature */
4394 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4395 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4401 r
= sd_bus_message_exit_container(m
);
4409 if (n_array
!= (unsigned) -1)
4418 case SD_BUS_TYPE_BYTE
:
4419 case SD_BUS_TYPE_BOOLEAN
:
4420 case SD_BUS_TYPE_INT16
:
4421 case SD_BUS_TYPE_UINT16
:
4422 case SD_BUS_TYPE_INT32
:
4423 case SD_BUS_TYPE_UINT32
:
4424 case SD_BUS_TYPE_INT64
:
4425 case SD_BUS_TYPE_UINT64
:
4426 case SD_BUS_TYPE_DOUBLE
:
4427 case SD_BUS_TYPE_STRING
:
4428 case SD_BUS_TYPE_OBJECT_PATH
:
4429 case SD_BUS_TYPE_SIGNATURE
:
4430 case SD_BUS_TYPE_UNIX_FD
: {
4433 p
= va_arg(ap
, void*);
4434 r
= sd_bus_message_read_basic(m
, *t
, p
);
4447 case SD_BUS_TYPE_ARRAY
: {
4450 r
= signature_element_length(t
+ 1, &k
);
4456 memcpy(s
, t
+ 1, k
);
4459 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4470 if (n_array
== (unsigned) -1) {
4475 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4481 n_array
= va_arg(ap
, unsigned);
4486 case SD_BUS_TYPE_VARIANT
: {
4489 s
= va_arg(ap
, const char *);
4493 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4503 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4508 n_struct
= strlen(s
);
4509 n_array
= (unsigned) -1;
4514 case SD_BUS_TYPE_STRUCT_BEGIN
:
4515 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4518 r
= signature_element_length(t
, &k
);
4524 memcpy(s
, t
+ 1, k
- 2);
4527 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4537 if (n_array
== (unsigned) -1) {
4542 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4548 n_array
= (unsigned) -1;
4561 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4565 assert_return(m
, -EINVAL
);
4566 assert_return(m
->sealed
, -EPERM
);
4567 assert_return(types
, -EINVAL
);
4569 va_start(ap
, types
);
4570 r
= message_read_ap(m
, types
, ap
);
4576 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4579 assert_return(m
, -EINVAL
);
4580 assert_return(m
->sealed
, -EPERM
);
4582 /* If types is NULL, read exactly one element */
4584 struct bus_container
*c
;
4587 if (message_end_of_signature(m
))
4590 if (message_end_of_array(m
, m
->rindex
))
4593 c
= message_get_container(m
);
4595 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4599 types
= strndupa(c
->signature
+ c
->index
, l
);
4604 case 0: /* Nothing to drop */
4607 case SD_BUS_TYPE_BYTE
:
4608 case SD_BUS_TYPE_BOOLEAN
:
4609 case SD_BUS_TYPE_INT16
:
4610 case SD_BUS_TYPE_UINT16
:
4611 case SD_BUS_TYPE_INT32
:
4612 case SD_BUS_TYPE_UINT32
:
4613 case SD_BUS_TYPE_INT64
:
4614 case SD_BUS_TYPE_UINT64
:
4615 case SD_BUS_TYPE_DOUBLE
:
4616 case SD_BUS_TYPE_STRING
:
4617 case SD_BUS_TYPE_OBJECT_PATH
:
4618 case SD_BUS_TYPE_SIGNATURE
:
4619 case SD_BUS_TYPE_UNIX_FD
:
4621 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4625 r
= sd_bus_message_skip(m
, types
+ 1);
4631 case SD_BUS_TYPE_ARRAY
: {
4634 r
= signature_element_length(types
+ 1, &k
);
4640 memcpy(s
, types
+1, k
);
4643 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4648 r
= sd_bus_message_skip(m
, s
);
4655 r
= sd_bus_message_exit_container(m
);
4660 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4667 case SD_BUS_TYPE_VARIANT
: {
4668 const char *contents
;
4671 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4675 if (x
!= SD_BUS_TYPE_VARIANT
)
4678 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4682 r
= sd_bus_message_skip(m
, contents
);
4687 r
= sd_bus_message_exit_container(m
);
4691 r
= sd_bus_message_skip(m
, types
+ 1);
4698 case SD_BUS_TYPE_STRUCT_BEGIN
:
4699 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4702 r
= signature_element_length(types
, &k
);
4708 memcpy(s
, types
+1, k
-2);
4711 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4715 r
= sd_bus_message_skip(m
, s
);
4719 r
= sd_bus_message_exit_container(m
);
4724 r
= sd_bus_message_skip(m
, types
+ k
);
4736 _public_
int sd_bus_message_read_array(
4742 struct bus_container
*c
;
4748 assert_return(m
, -EINVAL
);
4749 assert_return(m
->sealed
, -EPERM
);
4750 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4751 assert_return(ptr
, -EINVAL
);
4752 assert_return(size
, -EINVAL
);
4753 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4755 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4759 c
= message_get_container(m
);
4761 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4762 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4766 sz
= c
->end
- c
->begin
;
4768 align
= bus_type_get_alignment(type
);
4772 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4776 /* Zero length array, let's return some aligned
4777 * pointer that is not NULL */
4778 p
= (uint8_t*) NULL
+ align
;
4780 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4785 r
= sd_bus_message_exit_container(m
);
4789 *ptr
= (const void*) p
;
4795 message_quit_container(m
);
4799 static int message_peek_fields(
4810 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4813 static int message_peek_field_uint32(
4825 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4828 /* identical for gvariant and dbus1 */
4830 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4835 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4840 static int message_peek_field_uint64(
4852 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4855 /* identical for gvariant and dbus1 */
4857 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4862 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4867 static int message_peek_field_string(
4869 bool (*validate
)(const char *p
),
4881 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4886 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4892 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4896 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4902 if (!validate_nul(q
, l
))
4908 if (!validate_string(q
, l
))
4918 static int message_peek_field_signature(
4931 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4936 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4942 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
4947 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4952 if (!validate_signature(q
, l
))
4961 static int message_skip_fields(
4964 uint32_t array_size
,
4965 const char **signature
) {
4967 size_t original_index
;
4973 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
4975 original_index
= *ri
;
4981 if (array_size
!= (uint32_t) -1 &&
4982 array_size
<= *ri
- original_index
)
4989 if (t
== SD_BUS_TYPE_STRING
) {
4991 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
4997 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
4999 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
5005 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
5007 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
5013 } else if (bus_type_is_basic(t
)) {
5016 align
= bus_type_get_alignment(t
);
5017 k
= bus_type_get_size(t
);
5018 assert(align
> 0 && k
> 0);
5020 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
5026 } else if (t
== SD_BUS_TYPE_ARRAY
) {
5028 r
= signature_element_length(*signature
+1, &l
);
5038 strncpy(sig
, *signature
+ 1, l
-1);
5041 alignment
= bus_type_get_alignment(sig
[0]);
5045 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5048 if (nas
> BUS_ARRAY_MAX_SIZE
)
5051 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5055 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5060 (*signature
) += 1 + l
;
5062 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5065 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5069 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5075 } else if (IN_SET(t
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
5077 r
= signature_element_length(*signature
, &l
);
5084 strncpy(sig
, *signature
+ 1, l
-1);
5087 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5098 int bus_message_parse_fields(sd_bus_message
*m
) {
5101 uint32_t unix_fds
= 0;
5102 bool unix_fds_set
= false;
5103 void *offsets
= NULL
;
5104 unsigned n_offsets
= 0;
5110 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5113 /* Read the signature from the end of the body variant first */
5114 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5115 if (m
->footer_accessible
< 1 + sz
)
5118 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5120 if (p
< (char*) m
->footer
)
5127 /* We found the beginning of the signature
5128 * string, yay! We require the body to be a
5129 * structure, so verify it and then strip the
5130 * opening/closing brackets. */
5132 l
= ((char*) m
->footer
+ m
->footer_accessible
) - p
- (1 + sz
);
5134 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5135 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5138 c
= strndup(p
+ 1 + 1, l
- 2);
5142 free(m
->root_container
.signature
);
5143 m
->root_container
.signature
= c
;
5150 /* Calculate the actual user body size, by removing
5151 * the trailing variant signature and struct offset
5153 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5155 /* Pull out the offset table for the fields array */
5156 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5161 ri
= m
->fields_size
- sz
;
5162 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5166 framing
= bus_gvariant_read_word_le(q
, sz
);
5167 if (framing
>= m
->fields_size
- sz
)
5169 if ((m
->fields_size
- framing
) % sz
!= 0)
5173 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5177 n_offsets
= (m
->fields_size
- framing
) / sz
;
5180 m
->user_body_size
= m
->body_size
;
5183 while (ri
< m
->fields_size
) {
5184 _cleanup_free_
char *sig
= NULL
;
5185 const char *signature
;
5186 uint64_t field_type
;
5187 size_t item_size
= (size_t) -1;
5189 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5198 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5200 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5204 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5208 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5215 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5220 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5225 where
= ri
= ALIGN_TO(ri
, 8);
5226 item_size
= end
- ri
;
5227 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5231 b
= memrchr(q
, 0, item_size
);
5235 sig
= strndup(b
+1, item_size
- (b
+1-(char*) q
));
5240 item_size
= b
- (char*) q
;
5242 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5247 switch (field_type
) {
5249 case _BUS_MESSAGE_HEADER_INVALID
:
5252 case BUS_MESSAGE_HEADER_PATH
:
5257 if (!streq(signature
, "o"))
5260 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5263 case BUS_MESSAGE_HEADER_INTERFACE
:
5268 if (!streq(signature
, "s"))
5271 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5274 case BUS_MESSAGE_HEADER_MEMBER
:
5279 if (!streq(signature
, "s"))
5282 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5285 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5290 if (!streq(signature
, "s"))
5293 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5295 m
->error
._need_free
= -1;
5299 case BUS_MESSAGE_HEADER_DESTINATION
:
5304 if (!streq(signature
, "s"))
5307 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5310 case BUS_MESSAGE_HEADER_SENDER
:
5315 if (!streq(signature
, "s"))
5318 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5320 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
) {
5321 m
->creds
.unique_name
= (char*) m
->sender
;
5322 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5328 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5332 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5335 if (m
->root_container
.signature
)
5338 if (!streq(signature
, "g"))
5341 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5349 free(m
->root_container
.signature
);
5350 m
->root_container
.signature
= c
;
5354 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5356 if (m
->reply_cookie
!= 0)
5359 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5360 /* 64bit on dbus2 */
5362 if (!streq(signature
, "t"))
5365 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5369 /* 32bit on dbus1 */
5372 if (!streq(signature
, "u"))
5375 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5379 m
->reply_cookie
= serial
;
5382 if (m
->reply_cookie
== 0)
5387 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5391 if (!streq(signature
, "u"))
5394 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5398 unix_fds_set
= true;
5402 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5403 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5412 if (m
->n_fds
!= unix_fds
)
5415 switch (m
->header
->type
) {
5417 case SD_BUS_MESSAGE_SIGNAL
:
5418 if (!m
->path
|| !m
->interface
|| !m
->member
)
5421 if (m
->reply_cookie
!= 0)
5426 case SD_BUS_MESSAGE_METHOD_CALL
:
5428 if (!m
->path
|| !m
->member
)
5431 if (m
->reply_cookie
!= 0)
5436 case SD_BUS_MESSAGE_METHOD_RETURN
:
5438 if (m
->reply_cookie
== 0)
5442 case SD_BUS_MESSAGE_METHOD_ERROR
:
5444 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5449 /* Refuse non-local messages that claim they are local */
5450 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5452 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5454 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5457 m
->root_container
.end
= m
->user_body_size
;
5459 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5460 r
= build_struct_offsets(
5462 m
->root_container
.signature
,
5464 &m
->root_container
.item_size
,
5465 &m
->root_container
.offsets
,
5466 &m
->root_container
.n_offsets
);
5471 /* Try to read the error message, but if we can't it's a non-issue */
5472 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5473 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5478 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5479 assert_return(m
, -EINVAL
);
5480 assert_return(destination
, -EINVAL
);
5481 assert_return(!m
->sealed
, -EPERM
);
5482 assert_return(!m
->destination
, -EEXIST
);
5484 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5487 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5491 struct bus_body_part
*part
;
5497 total
= BUS_MESSAGE_SIZE(m
);
5503 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5504 MESSAGE_FOREACH_PART(part
, i
, m
)
5505 e
= mempcpy(e
, part
->data
, part
->size
);
5507 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5515 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5522 r
= sd_bus_message_enter_container(m
, 'a', "s");
5526 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5527 r
= strv_extend(l
, s
);
5534 r
= sd_bus_message_exit_container(m
);
5541 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5545 assert_return(m
, -EINVAL
);
5546 assert_return(m
->sealed
, -EPERM
);
5547 assert_return(l
, -EINVAL
);
5549 r
= bus_message_read_strv_extend(m
, &strv
);
5559 static int bus_message_get_arg_skip(
5563 const char **_contents
) {
5568 r
= sd_bus_message_rewind(m
, true);
5573 const char *contents
;
5576 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5582 /* Don't match against arguments after the first one we don't understand */
5583 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5584 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5589 *_contents
= contents
;
5595 r
= sd_bus_message_skip(m
, NULL
);
5602 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5609 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5613 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5616 return sd_bus_message_read_basic(m
, type
, str
);
5619 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5620 const char *contents
;
5627 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5631 if (type
!= SD_BUS_TYPE_ARRAY
)
5633 if (!STR_IN_SET(contents
, "s", "o", "g"))
5636 return sd_bus_message_read_strv(m
, strv
);
5639 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5640 assert_return(m
, EINVAL
);
5642 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5645 return sd_bus_error_get_errno(&m
->error
);
5648 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5649 struct bus_container
*c
;
5651 assert_return(m
, NULL
);
5653 c
= complete
? &m
->root_container
: message_get_container(m
);
5654 return strempty(c
->signature
);
5657 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5658 assert_return(m
, -EINVAL
);
5660 return isempty(m
->root_container
.signature
);
5663 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5664 assert_return(m
, -EINVAL
);
5666 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5669 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5670 bool done_something
= false;
5673 assert_return(m
, -EINVAL
);
5674 assert_return(source
, -EINVAL
);
5675 assert_return(!m
->sealed
, -EPERM
);
5676 assert_return(source
->sealed
, -EPERM
);
5679 const char *contents
;
5694 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5700 done_something
= true;
5702 if (bus_type_is_container(type
) > 0) {
5704 r
= sd_bus_message_enter_container(source
, type
, contents
);
5708 r
= sd_bus_message_open_container(m
, type
, contents
);
5712 r
= sd_bus_message_copy(m
, source
, true);
5716 r
= sd_bus_message_close_container(m
);
5720 r
= sd_bus_message_exit_container(source
);
5727 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5733 if (IN_SET(type
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
, SD_BUS_TYPE_STRING
))
5734 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5736 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5743 return done_something
;
5746 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5751 assert_return(m
, -EINVAL
);
5752 assert_return(m
->sealed
, -EPERM
);
5753 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5754 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5755 assert_return(type
|| contents
, -EINVAL
);
5756 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5758 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5762 if (type
!= 0 && type
!= t
)
5765 if (contents
&& !streq_ptr(contents
, c
))
5771 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5772 assert_return(m
, NULL
);
5777 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5778 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
5786 switch ((*m
)->header
->type
) {
5788 case SD_BUS_MESSAGE_SIGNAL
:
5789 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5795 case SD_BUS_MESSAGE_METHOD_CALL
:
5796 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5802 case SD_BUS_MESSAGE_METHOD_RETURN
:
5803 case SD_BUS_MESSAGE_METHOD_ERROR
:
5805 r
= sd_bus_message_new(bus
, &n
, (*m
)->header
->type
);
5811 n
->reply_cookie
= (*m
)->reply_cookie
;
5813 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5817 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5818 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5822 n
->error
._need_free
= -1;
5831 if ((*m
)->destination
&& !n
->destination
) {
5832 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5837 if ((*m
)->sender
&& !n
->sender
) {
5838 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5843 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5845 r
= sd_bus_message_copy(n
, *m
, true);
5849 timeout
= (*m
)->timeout
;
5850 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
))
5851 timeout
= BUS_DEFAULT_TIMEOUT
;
5853 r
= sd_bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5857 sd_bus_message_unref(*m
);
5864 int bus_message_append_sender(sd_bus_message
*m
, const char *sender
) {
5868 assert_return(!m
->sealed
, -EPERM
);
5869 assert_return(!m
->sender
, -EPERM
);
5871 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5874 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5875 assert_return(m
, -EINVAL
);
5876 assert_return(priority
, -EINVAL
);
5878 *priority
= m
->priority
;
5882 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5883 assert_return(m
, -EINVAL
);
5884 assert_return(!m
->sealed
, -EPERM
);
5886 m
->priority
= priority
;