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 static sd_bus_message
*message_new(sd_bus
*bus
, uint8_t type
) {
581 m
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
586 m
->header
= (struct bus_header
*) ((uint8_t*) m
+ ALIGN(sizeof(struct sd_bus_message
)));
587 m
->header
->endian
= BUS_NATIVE_ENDIAN
;
588 m
->header
->type
= type
;
589 m
->header
->version
= bus
->message_version
;
590 m
->allow_fds
= bus
->can_fds
|| !IN_SET(bus
->state
, BUS_HELLO
, BUS_RUNNING
);
591 m
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(m
);
592 m
->bus
= sd_bus_ref(bus
);
594 if (bus
->allow_interactive_authorization
)
595 m
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
600 _public_
int sd_bus_message_new_signal(
604 const char *interface
,
605 const char *member
) {
610 assert_return(bus
, -ENOTCONN
);
611 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
612 assert_return(object_path_is_valid(path
), -EINVAL
);
613 assert_return(interface_name_is_valid(interface
), -EINVAL
);
614 assert_return(member_name_is_valid(member
), -EINVAL
);
615 assert_return(m
, -EINVAL
);
617 t
= message_new(bus
, SD_BUS_MESSAGE_SIGNAL
);
621 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
623 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
626 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
629 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
637 sd_bus_message_unref(t
);
641 _public_
int sd_bus_message_new_method_call(
644 const char *destination
,
646 const char *interface
,
647 const char *member
) {
652 assert_return(bus
, -ENOTCONN
);
653 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
654 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
655 assert_return(object_path_is_valid(path
), -EINVAL
);
656 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
657 assert_return(member_name_is_valid(member
), -EINVAL
);
658 assert_return(m
, -EINVAL
);
660 t
= message_new(bus
, SD_BUS_MESSAGE_METHOD_CALL
);
664 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
667 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
672 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
678 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
691 static int message_new_reply(
692 sd_bus_message
*call
,
694 sd_bus_message
**m
) {
699 assert_return(call
, -EINVAL
);
700 assert_return(call
->sealed
, -EPERM
);
701 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
702 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
703 assert_return(m
, -EINVAL
);
705 t
= message_new(call
->bus
, type
);
709 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
710 t
->reply_cookie
= BUS_MESSAGE_COOKIE(call
);
711 if (t
->reply_cookie
== 0)
714 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
719 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
724 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
725 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
735 _public_
int sd_bus_message_new_method_return(
736 sd_bus_message
*call
,
737 sd_bus_message
**m
) {
739 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
742 _public_
int sd_bus_message_new_method_error(
743 sd_bus_message
*call
,
745 const sd_bus_error
*e
) {
750 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
751 assert_return(m
, -EINVAL
);
753 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
757 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
762 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
767 t
->error
._need_free
= -1;
777 _public_
int sd_bus_message_new_method_errorf(
778 sd_bus_message
*call
,
784 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
787 assert_return(name
, -EINVAL
);
788 assert_return(m
, -EINVAL
);
790 va_start(ap
, format
);
791 bus_error_setfv(&error
, name
, format
, ap
);
794 return sd_bus_message_new_method_error(call
, m
, &error
);
797 _public_
int sd_bus_message_new_method_errno(
798 sd_bus_message
*call
,
801 const sd_bus_error
*p
) {
803 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
805 if (sd_bus_error_is_set(p
))
806 return sd_bus_message_new_method_error(call
, m
, p
);
808 sd_bus_error_set_errno(&berror
, error
);
810 return sd_bus_message_new_method_error(call
, m
, &berror
);
813 _public_
int sd_bus_message_new_method_errnof(
814 sd_bus_message
*call
,
820 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
823 va_start(ap
, format
);
824 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
827 return sd_bus_message_new_method_error(call
, m
, &berror
);
830 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
834 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
835 m
->creds
.well_known_names_local
= true;
836 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
839 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
843 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
844 m
->creds
.well_known_names_driver
= true;
845 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
848 int bus_message_new_synthetic_error(
851 const sd_bus_error
*e
,
852 sd_bus_message
**m
) {
858 assert(sd_bus_error_is_set(e
));
861 t
= message_new(bus
, SD_BUS_MESSAGE_METHOD_ERROR
);
865 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
866 t
->reply_cookie
= cookie
;
868 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
872 if (bus
&& bus
->unique_name
) {
873 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
878 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
883 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
888 t
->error
._need_free
= -1;
890 bus_message_set_sender_driver(bus
, t
);
900 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
905 assert(m
->n_ref
> 0);
911 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
916 assert(m
->n_ref
> 0);
926 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
927 assert_return(m
, -EINVAL
);
928 assert_return(type
, -EINVAL
);
930 *type
= m
->header
->type
;
934 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
937 assert_return(m
, -EINVAL
);
938 assert_return(cookie
, -EINVAL
);
940 c
= BUS_MESSAGE_COOKIE(m
);
944 *cookie
= BUS_MESSAGE_COOKIE(m
);
948 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
949 assert_return(m
, -EINVAL
);
950 assert_return(cookie
, -EINVAL
);
952 if (m
->reply_cookie
== 0)
955 *cookie
= m
->reply_cookie
;
959 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
960 assert_return(m
, -EINVAL
);
962 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
963 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
966 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
967 assert_return(m
, -EINVAL
);
969 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
972 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
973 assert_return(m
, -EINVAL
);
975 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
976 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
979 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
980 assert_return(m
, NULL
);
985 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
986 assert_return(m
, NULL
);
991 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
992 assert_return(m
, NULL
);
997 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
998 assert_return(m
, NULL
);
1000 return m
->destination
;
1003 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
1004 assert_return(m
, NULL
);
1009 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
1010 assert_return(m
, NULL
);
1012 if (!sd_bus_error_is_set(&m
->error
))
1018 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
1019 assert_return(m
, -EINVAL
);
1020 assert_return(usec
, -EINVAL
);
1022 if (m
->monotonic
<= 0)
1025 *usec
= m
->monotonic
;
1029 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1030 assert_return(m
, -EINVAL
);
1031 assert_return(usec
, -EINVAL
);
1033 if (m
->realtime
<= 0)
1036 *usec
= m
->realtime
;
1040 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1041 assert_return(m
, -EINVAL
);
1042 assert_return(seqnum
, -EINVAL
);
1047 *seqnum
= m
->seqnum
;
1051 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1052 assert_return(m
, NULL
);
1054 if (m
->creds
.mask
== 0)
1060 _public_
int sd_bus_message_is_signal(
1062 const char *interface
,
1063 const char *member
) {
1065 assert_return(m
, -EINVAL
);
1067 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1070 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1073 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1079 _public_
int sd_bus_message_is_method_call(
1081 const char *interface
,
1082 const char *member
) {
1084 assert_return(m
, -EINVAL
);
1086 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1089 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1092 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1098 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1099 assert_return(m
, -EINVAL
);
1101 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1104 if (name
&& (!m
->error
.name
|| !streq(m
->error
.name
, name
)))
1110 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1111 assert_return(m
, -EINVAL
);
1112 assert_return(!m
->sealed
, -EPERM
);
1113 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1115 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_REPLY_EXPECTED
, !b
);
1120 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1121 assert_return(m
, -EINVAL
);
1122 assert_return(!m
->sealed
, -EPERM
);
1124 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_AUTO_START
, !b
);
1129 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1130 assert_return(m
, -EINVAL
);
1131 assert_return(!m
->sealed
, -EPERM
);
1133 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
, b
);
1138 static struct bus_container
*message_get_container(sd_bus_message
*m
) {
1141 if (m
->n_containers
== 0)
1142 return &m
->root_container
;
1144 assert(m
->containers
);
1145 return m
->containers
+ m
->n_containers
- 1;
1148 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1149 struct bus_body_part
*part
;
1156 if (m
->n_body_parts
<= 0) {
1160 assert(m
->body_end
);
1162 part
= new0(struct bus_body_part
, 1);
1168 m
->body_end
->next
= part
;
1178 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1183 /* All other fields can be left in their defaults */
1184 assert(!part
->data
);
1185 assert(part
->memfd
< 0);
1188 part
->is_zero
= true;
1189 part
->sealed
= true;
1192 static int part_make_space(
1193 struct sd_bus_message
*m
,
1194 struct bus_body_part
*part
,
1202 assert(!part
->sealed
);
1207 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1208 size_t new_allocated
;
1210 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1211 n
= realloc(part
->data
, new_allocated
);
1218 part
->allocated
= new_allocated
;
1219 part
->free_this
= true;
1223 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1229 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1230 struct bus_container
*c
;
1233 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1235 /* Add offset to current container, unless this is the first
1236 * item in it, which will have the 0 offset, which we can
1238 c
= message_get_container(m
);
1240 if (!c
->need_offsets
)
1243 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1246 c
->offsets
[c
->n_offsets
++] = offset
;
1250 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1251 struct bus_container
*c
;
1258 /* Update counters */
1259 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++) {
1262 *c
->array_size
+= expand
;
1266 static void *message_extend_body(
1271 bool force_inline
) {
1273 size_t start_body
, end_body
, padding
, added
;
1284 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1285 end_body
= start_body
+ sz
;
1287 padding
= start_body
- m
->body_size
;
1288 added
= padding
+ sz
;
1290 /* Check for 32bit overflows */
1291 if (end_body
> (size_t) ((uint32_t) -1) ||
1292 end_body
< start_body
) {
1298 struct bus_body_part
*part
= NULL
;
1302 m
->n_body_parts
<= 0 ||
1303 m
->body_end
->sealed
||
1304 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1305 (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 */
1309 part
= message_append_part(m
);
1313 part_zero(part
, padding
);
1316 part
= message_append_part(m
);
1320 r
= part_make_space(m
, part
, sz
, &p
);
1324 struct bus_container
*c
;
1326 size_t os
, start_part
, end_part
;
1332 start_part
= ALIGN_TO(part
->size
, align
);
1333 end_part
= start_part
+ sz
;
1335 r
= part_make_space(m
, part
, end_part
, &p
);
1340 memzero(p
, padding
);
1341 p
= (uint8_t*) p
+ padding
;
1344 /* Readjust pointers */
1345 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1346 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1348 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1351 /* Return something that is not NULL and is aligned */
1352 p
= (uint8_t *) NULL
+ align
;
1354 m
->body_size
= end_body
;
1355 message_extend_containers(m
, added
);
1358 r
= message_add_offset(m
, end_body
);
1368 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1379 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1383 f
= realloc(m
->fds
, sizeof(int) * (m
->n_fds
+ 1));
1391 m
->fds
[m
->n_fds
] = copy
;
1397 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1398 _cleanup_close_
int fd
= -1;
1399 struct bus_container
*c
;
1403 assert_return(m
, -EINVAL
);
1404 assert_return(!m
->sealed
, -EPERM
);
1405 assert_return(bus_type_is_basic(type
), -EINVAL
);
1406 assert_return(!m
->poisoned
, -ESTALE
);
1408 c
= message_get_container(m
);
1410 if (c
->signature
&& c
->signature
[c
->index
]) {
1411 /* Container signature is already set */
1413 if (c
->signature
[c
->index
] != type
)
1418 /* Maybe we can append to the signature? But only if this is the top-level container */
1419 if (c
->enclosing
!= 0)
1422 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1429 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1435 case SD_BUS_TYPE_SIGNATURE
:
1436 case SD_BUS_TYPE_STRING
:
1439 /* Fall through... */
1440 case SD_BUS_TYPE_OBJECT_PATH
:
1448 case SD_BUS_TYPE_BOOLEAN
:
1450 u8
= p
&& *(int*) p
;
1456 case SD_BUS_TYPE_UNIX_FD
:
1461 fd
= message_push_fd(m
, *(int*) p
);
1472 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1473 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1480 a
= message_extend_body(m
, align
, sz
, true, false);
1487 *stored
= (const uint8_t*) a
;
1494 case SD_BUS_TYPE_STRING
:
1495 /* To make things easy we'll serialize a NULL string
1496 * into the empty string */
1499 /* Fall through... */
1500 case SD_BUS_TYPE_OBJECT_PATH
:
1506 sz
= 4 + strlen(p
) + 1;
1509 case SD_BUS_TYPE_SIGNATURE
:
1514 sz
= 1 + strlen(p
) + 1;
1517 case SD_BUS_TYPE_BOOLEAN
:
1519 u32
= p
&& *(int*) p
;
1525 case SD_BUS_TYPE_UNIX_FD
:
1530 fd
= message_push_fd(m
, *(int*) p
);
1541 align
= bus_type_get_alignment(type
);
1542 sz
= bus_type_get_size(type
);
1549 a
= message_extend_body(m
, align
, sz
, false, false);
1553 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
1554 *(uint32_t*) a
= sz
- 5;
1555 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1558 *stored
= (const uint8_t*) a
+ 4;
1560 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1561 *(uint8_t*) a
= sz
- 2;
1562 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1565 *stored
= (const uint8_t*) a
+ 1;
1574 if (type
== SD_BUS_TYPE_UNIX_FD
)
1577 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1584 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1585 return message_append_basic(m
, type
, p
, NULL
);
1588 _public_
int sd_bus_message_append_string_space(
1593 struct bus_container
*c
;
1596 assert_return(m
, -EINVAL
);
1597 assert_return(s
, -EINVAL
);
1598 assert_return(!m
->sealed
, -EPERM
);
1599 assert_return(!m
->poisoned
, -ESTALE
);
1601 c
= message_get_container(m
);
1603 if (c
->signature
&& c
->signature
[c
->index
]) {
1604 /* Container signature is already set */
1606 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1611 /* Maybe we can append to the signature? But only if this is the top-level container */
1612 if (c
->enclosing
!= 0)
1615 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1622 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1623 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1629 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1633 *(uint32_t*) a
= size
;
1639 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1645 _public_
int sd_bus_message_append_string_iovec(
1647 const struct iovec
*iov
,
1655 assert_return(m
, -EINVAL
);
1656 assert_return(!m
->sealed
, -EPERM
);
1657 assert_return(iov
|| n
== 0, -EINVAL
);
1658 assert_return(!m
->poisoned
, -ESTALE
);
1660 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1662 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1666 for (i
= 0; i
< n
; i
++) {
1668 if (iov
[i
].iov_base
)
1669 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1671 memset(p
, ' ', iov
[i
].iov_len
);
1673 p
+= iov
[i
].iov_len
;
1679 static int bus_message_open_array(
1681 struct bus_container
*c
,
1682 const char *contents
,
1683 uint32_t **array_size
,
1685 bool *need_offsets
) {
1695 assert(need_offsets
);
1697 if (!signature_is_single(contents
, true))
1700 if (c
->signature
&& c
->signature
[c
->index
]) {
1702 /* Verify the existing signature */
1704 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1707 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1710 nindex
= c
->index
+ 1 + strlen(contents
);
1714 if (c
->enclosing
!= 0)
1717 /* Extend the existing signature */
1719 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1725 nindex
= e
- c
->signature
;
1728 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1729 alignment
= bus_gvariant_get_alignment(contents
);
1733 /* Add alignment padding and add to offset list */
1734 if (!message_extend_body(m
, alignment
, 0, false, false))
1737 r
= bus_gvariant_is_fixed_size(contents
);
1741 *begin
= m
->body_size
;
1742 *need_offsets
= r
== 0;
1746 struct bus_body_part
*o
;
1748 alignment
= bus_type_get_alignment(contents
[0]);
1752 a
= message_extend_body(m
, 4, 4, false, false);
1757 op
= m
->body_end
->data
;
1758 os
= m
->body_end
->size
;
1760 /* Add alignment between size and first element */
1761 if (!message_extend_body(m
, alignment
, 0, false, false))
1764 /* location of array size might have changed so let's readjust a */
1765 if (o
== m
->body_end
)
1766 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1772 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1778 static int bus_message_open_variant(
1780 struct bus_container
*c
,
1781 const char *contents
) {
1787 if (!signature_is_single(contents
, false))
1790 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1793 if (c
->signature
&& c
->signature
[c
->index
]) {
1795 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1801 if (c
->enclosing
!= 0)
1804 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1811 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1812 /* Variants are always aligned to 8 */
1814 if (!message_extend_body(m
, 8, 0, false, false))
1821 l
= strlen(contents
);
1822 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1827 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1830 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1836 static int bus_message_open_struct(
1838 struct bus_container
*c
,
1839 const char *contents
,
1841 bool *need_offsets
) {
1850 assert(need_offsets
);
1852 if (!signature_is_valid(contents
, false))
1855 if (c
->signature
&& c
->signature
[c
->index
]) {
1858 l
= strlen(contents
);
1860 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1861 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1862 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1865 nindex
= c
->index
+ 1 + l
+ 1;
1869 if (c
->enclosing
!= 0)
1872 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1878 nindex
= e
- c
->signature
;
1881 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1884 alignment
= bus_gvariant_get_alignment(contents
);
1888 if (!message_extend_body(m
, alignment
, 0, false, false))
1891 r
= bus_gvariant_is_fixed_size(contents
);
1895 *begin
= m
->body_size
;
1896 *need_offsets
= r
== 0;
1898 /* Align contents to 8 byte boundary */
1899 if (!message_extend_body(m
, 8, 0, false, false))
1903 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1909 static int bus_message_open_dict_entry(
1911 struct bus_container
*c
,
1912 const char *contents
,
1914 bool *need_offsets
) {
1922 assert(need_offsets
);
1924 if (!signature_is_pair(contents
))
1927 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1930 if (c
->signature
&& c
->signature
[c
->index
]) {
1933 l
= strlen(contents
);
1935 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
1936 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1937 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
1942 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1945 alignment
= bus_gvariant_get_alignment(contents
);
1949 if (!message_extend_body(m
, alignment
, 0, false, false))
1952 r
= bus_gvariant_is_fixed_size(contents
);
1956 *begin
= m
->body_size
;
1957 *need_offsets
= r
== 0;
1959 /* Align contents to 8 byte boundary */
1960 if (!message_extend_body(m
, 8, 0, false, false))
1967 _public_
int sd_bus_message_open_container(
1970 const char *contents
) {
1972 struct bus_container
*c
, *w
;
1973 uint32_t *array_size
= NULL
;
1975 size_t before
, begin
= 0;
1976 bool need_offsets
= false;
1979 assert_return(m
, -EINVAL
);
1980 assert_return(!m
->sealed
, -EPERM
);
1981 assert_return(contents
, -EINVAL
);
1982 assert_return(!m
->poisoned
, -ESTALE
);
1984 /* Make sure we have space for one more container */
1985 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
1990 c
= message_get_container(m
);
1992 signature
= strdup(contents
);
1998 /* Save old index in the parent container, in case we have to
1999 * abort this container */
2000 c
->saved_index
= c
->index
;
2001 before
= m
->body_size
;
2003 if (type
== SD_BUS_TYPE_ARRAY
)
2004 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
2005 else if (type
== SD_BUS_TYPE_VARIANT
)
2006 r
= bus_message_open_variant(m
, c
, contents
);
2007 else if (type
== SD_BUS_TYPE_STRUCT
)
2008 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
2009 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
2010 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
2019 /* OK, let's fill it in */
2020 w
= m
->containers
+ m
->n_containers
++;
2021 w
->enclosing
= type
;
2022 w
->signature
= signature
;
2024 w
->array_size
= array_size
;
2027 w
->n_offsets
= w
->offsets_allocated
= 0;
2029 w
->need_offsets
= need_offsets
;
2034 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2039 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2042 if (c
->need_offsets
) {
2043 size_t payload
, sz
, i
;
2046 /* Variable-width arrays */
2048 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2049 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2051 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2055 for (i
= 0; i
< c
->n_offsets
; i
++)
2056 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2060 /* Fixed-width or empty arrays */
2062 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2070 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2076 assert(c
->signature
);
2078 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2081 l
= strlen(c
->signature
);
2083 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2088 memcpy(a
+1, c
->signature
, l
);
2093 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2094 bool fixed_size
= true;
2095 size_t n_variable
= 0;
2104 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2107 p
= strempty(c
->signature
);
2111 r
= signature_element_length(p
, &n
);
2120 r
= bus_gvariant_is_fixed_size(t
);
2125 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2127 /* We need to add an offset for each item that has a
2128 * variable size and that is not the last one in the
2132 if (r
== 0 && p
[n
] != 0)
2139 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2140 assert(c
->need_offsets
|| n_variable
== 0);
2142 if (isempty(c
->signature
)) {
2143 /* The unary type is encoded as fixed 1 byte padding */
2144 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2149 } else if (n_variable
<= 0) {
2152 /* Structures with fixed-size members only have to be
2153 * fixed-size themselves. But gvariant requires all fixed-size
2154 * elements to be sized a multiple of their alignment. Hence,
2155 * we must *always* add final padding after the last member so
2156 * the overall size of the structure is properly aligned. */
2158 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2160 assert(alignment
> 0);
2162 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2169 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2171 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2173 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2177 p
= strempty(c
->signature
);
2178 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2182 r
= signature_element_length(p
, &n
);
2193 r
= bus_gvariant_is_fixed_size(t
);
2196 if (r
> 0 || p
[0] == 0)
2200 k
= n_variable
- 1 - j
;
2202 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2211 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2212 struct bus_container
*c
;
2215 assert_return(m
, -EINVAL
);
2216 assert_return(!m
->sealed
, -EPERM
);
2217 assert_return(m
->n_containers
> 0, -EINVAL
);
2218 assert_return(!m
->poisoned
, -ESTALE
);
2220 c
= message_get_container(m
);
2222 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2223 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2228 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2229 r
= bus_message_close_array(m
, c
);
2230 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2231 r
= bus_message_close_variant(m
, c
);
2232 else if (IN_SET(c
->enclosing
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
))
2233 r
= bus_message_close_struct(m
, c
, true);
2235 assert_not_reached("Unknown container type");
2249 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2256 stack
[*i
].types
= types
;
2257 stack
[*i
].n_struct
= n_struct
;
2258 stack
[*i
].n_array
= n_array
;
2264 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2275 *types
= stack
[*i
].types
;
2276 *n_struct
= stack
[*i
].n_struct
;
2277 *n_array
= stack
[*i
].n_array
;
2282 _public_
int sd_bus_message_appendv(
2287 unsigned n_array
, n_struct
;
2288 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2289 unsigned stack_ptr
= 0;
2292 assert_return(m
, -EINVAL
);
2293 assert_return(types
, -EINVAL
);
2294 assert_return(!m
->sealed
, -EPERM
);
2295 assert_return(!m
->poisoned
, -ESTALE
);
2297 n_array
= (unsigned) -1;
2298 n_struct
= strlen(types
);
2303 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2304 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2310 r
= sd_bus_message_close_container(m
);
2318 if (n_array
!= (unsigned) -1)
2327 case SD_BUS_TYPE_BYTE
: {
2330 x
= (uint8_t) va_arg(ap
, int);
2331 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2335 case SD_BUS_TYPE_BOOLEAN
:
2336 case SD_BUS_TYPE_INT32
:
2337 case SD_BUS_TYPE_UINT32
:
2338 case SD_BUS_TYPE_UNIX_FD
: {
2341 /* We assume a boolean is the same as int32_t */
2342 assert_cc(sizeof(int32_t) == sizeof(int));
2344 x
= va_arg(ap
, uint32_t);
2345 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2349 case SD_BUS_TYPE_INT16
:
2350 case SD_BUS_TYPE_UINT16
: {
2353 x
= (uint16_t) va_arg(ap
, int);
2354 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2358 case SD_BUS_TYPE_INT64
:
2359 case SD_BUS_TYPE_UINT64
: {
2362 x
= va_arg(ap
, uint64_t);
2363 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2367 case SD_BUS_TYPE_DOUBLE
: {
2370 x
= va_arg(ap
, double);
2371 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2375 case SD_BUS_TYPE_STRING
:
2376 case SD_BUS_TYPE_OBJECT_PATH
:
2377 case SD_BUS_TYPE_SIGNATURE
: {
2380 x
= va_arg(ap
, const char*);
2381 r
= sd_bus_message_append_basic(m
, *t
, x
);
2385 case SD_BUS_TYPE_ARRAY
: {
2388 r
= signature_element_length(t
+ 1, &k
);
2394 memcpy(s
, t
+ 1, k
);
2397 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2402 if (n_array
== (unsigned) -1) {
2407 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2413 n_array
= va_arg(ap
, unsigned);
2418 case SD_BUS_TYPE_VARIANT
: {
2421 s
= va_arg(ap
, const char*);
2425 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2429 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2434 n_struct
= strlen(s
);
2435 n_array
= (unsigned) -1;
2440 case SD_BUS_TYPE_STRUCT_BEGIN
:
2441 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2444 r
= signature_element_length(t
, &k
);
2451 memcpy(s
, t
+ 1, k
- 2);
2454 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2459 if (n_array
== (unsigned) -1) {
2464 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2470 n_array
= (unsigned) -1;
2486 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2490 assert_return(m
, -EINVAL
);
2491 assert_return(types
, -EINVAL
);
2492 assert_return(!m
->sealed
, -EPERM
);
2493 assert_return(!m
->poisoned
, -ESTALE
);
2495 va_start(ap
, types
);
2496 r
= sd_bus_message_appendv(m
, types
, ap
);
2502 _public_
int sd_bus_message_append_array_space(
2512 assert_return(m
, -EINVAL
);
2513 assert_return(!m
->sealed
, -EPERM
);
2514 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2515 assert_return(ptr
|| size
== 0, -EINVAL
);
2516 assert_return(!m
->poisoned
, -ESTALE
);
2518 /* alignment and size of the trivial types (except bool) is
2519 * identical for gvariant and dbus1 marshalling */
2520 align
= bus_type_get_alignment(type
);
2521 sz
= bus_type_get_size(type
);
2523 assert_se(align
> 0);
2529 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2533 a
= message_extend_body(m
, align
, size
, false, false);
2537 r
= sd_bus_message_close_container(m
);
2545 _public_
int sd_bus_message_append_array(
2553 assert_return(m
, -EINVAL
);
2554 assert_return(!m
->sealed
, -EPERM
);
2555 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2556 assert_return(ptr
|| size
== 0, -EINVAL
);
2557 assert_return(!m
->poisoned
, -ESTALE
);
2559 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2563 memcpy_safe(p
, ptr
, size
);
2568 _public_
int sd_bus_message_append_array_iovec(
2571 const struct iovec
*iov
,
2579 assert_return(m
, -EINVAL
);
2580 assert_return(!m
->sealed
, -EPERM
);
2581 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2582 assert_return(iov
|| n
== 0, -EINVAL
);
2583 assert_return(!m
->poisoned
, -ESTALE
);
2585 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2587 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2591 for (i
= 0; i
< n
; i
++) {
2593 if (iov
[i
].iov_base
)
2594 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2596 memzero(p
, iov
[i
].iov_len
);
2598 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2604 _public_
int sd_bus_message_append_array_memfd(
2611 _cleanup_close_
int copy_fd
= -1;
2612 struct bus_body_part
*part
;
2618 assert_return(m
, -EINVAL
);
2619 assert_return(memfd
>= 0, -EBADF
);
2620 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2621 assert_return(size
> 0, -EINVAL
);
2622 assert_return(!m
->sealed
, -EPERM
);
2623 assert_return(!m
->poisoned
, -ESTALE
);
2625 r
= memfd_set_sealed(memfd
);
2629 copy_fd
= dup(memfd
);
2633 r
= memfd_get_size(memfd
, &real_size
);
2637 if (offset
== 0 && size
== (uint64_t) -1)
2639 else if (offset
+ size
> real_size
)
2642 align
= bus_type_get_alignment(type
);
2643 sz
= bus_type_get_size(type
);
2645 assert_se(align
> 0);
2648 if (offset
% align
!= 0)
2654 if (size
> (uint64_t) (uint32_t) -1)
2657 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2661 a
= message_extend_body(m
, align
, 0, false, false);
2665 part
= message_append_part(m
);
2669 part
->memfd
= copy_fd
;
2670 part
->memfd_offset
= offset
;
2671 part
->sealed
= true;
2675 m
->body_size
+= size
;
2676 message_extend_containers(m
, size
);
2678 return sd_bus_message_close_container(m
);
2681 _public_
int sd_bus_message_append_string_memfd(
2687 _cleanup_close_
int copy_fd
= -1;
2688 struct bus_body_part
*part
;
2689 struct bus_container
*c
;
2694 assert_return(m
, -EINVAL
);
2695 assert_return(memfd
>= 0, -EBADF
);
2696 assert_return(size
> 0, -EINVAL
);
2697 assert_return(!m
->sealed
, -EPERM
);
2698 assert_return(!m
->poisoned
, -ESTALE
);
2700 r
= memfd_set_sealed(memfd
);
2704 copy_fd
= dup(memfd
);
2708 r
= memfd_get_size(memfd
, &real_size
);
2712 if (offset
== 0 && size
== (uint64_t) -1)
2714 else if (offset
+ size
> real_size
)
2717 /* We require this to be NUL terminated */
2721 if (size
> (uint64_t) (uint32_t) -1)
2724 c
= message_get_container(m
);
2725 if (c
->signature
&& c
->signature
[c
->index
]) {
2726 /* Container signature is already set */
2728 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2733 /* Maybe we can append to the signature? But only if this is the top-level container */
2734 if (c
->enclosing
!= 0)
2737 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2744 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2745 a
= message_extend_body(m
, 4, 4, false, false);
2749 *(uint32_t*) a
= size
- 1;
2752 part
= message_append_part(m
);
2756 part
->memfd
= copy_fd
;
2757 part
->memfd_offset
= offset
;
2758 part
->sealed
= true;
2762 m
->body_size
+= size
;
2763 message_extend_containers(m
, size
);
2765 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2766 r
= message_add_offset(m
, m
->body_size
);
2773 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2779 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2783 assert_return(m
, -EINVAL
);
2784 assert_return(!m
->sealed
, -EPERM
);
2785 assert_return(!m
->poisoned
, -ESTALE
);
2787 r
= sd_bus_message_open_container(m
, 'a', "s");
2791 STRV_FOREACH(i
, l
) {
2792 r
= sd_bus_message_append_basic(m
, 's', *i
);
2797 return sd_bus_message_close_container(m
);
2800 static int bus_message_close_header(sd_bus_message
*m
) {
2804 /* The actual user data is finished now, we just complete the
2805 variant and struct now (at least on gvariant). Remember
2806 this position, so that during parsing we know where to
2807 put the outer container end. */
2808 m
->user_body_size
= m
->body_size
;
2810 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2811 const char *signature
;
2815 /* Add offset table to end of fields array */
2816 if (m
->n_header_offsets
>= 1) {
2820 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2822 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2823 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2827 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2828 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2831 /* Add gvariant NUL byte plus signature to the end of
2832 * the body, followed by the final offset pointing to
2833 * the end of the fields array */
2835 signature
= strempty(m
->root_container
.signature
);
2836 l
= strlen(signature
);
2838 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2839 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2844 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2845 memcpy((uint8_t*) d
+ 2, signature
, l
);
2846 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2848 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2851 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2853 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2854 m
->header
->dbus1
.body_size
= m
->body_size
;
2860 int bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, usec_t timeout
) {
2861 struct bus_body_part
*part
;
2871 if (m
->n_containers
> 0)
2877 if (cookie
> 0xffffffffULL
&&
2878 !BUS_MESSAGE_IS_GVARIANT(m
))
2881 /* In vtables the return signature of method calls is listed,
2882 * let's check if they match if this is a response */
2883 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2884 m
->enforced_reply_signature
&&
2885 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2888 /* If gvariant marshalling is used we need to close the body structure */
2889 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2893 /* If there's a non-trivial signature set, then add it in
2894 * here, but only on dbus1 */
2895 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2896 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2902 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2907 r
= bus_message_close_header(m
);
2911 if (BUS_MESSAGE_IS_GVARIANT(m
))
2912 m
->header
->dbus2
.cookie
= cookie
;
2914 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2916 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout
;
2918 /* Add padding at the end of the fields part, since we know
2919 * the body needs to start at an 8 byte alignment. We made
2920 * sure we allocated enough space for this, so all we need to
2921 * do here is to zero it out. */
2922 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2924 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2926 /* If this is something we can send as memfd, then let's seal
2927 the memfd now. Note that we can send memfds as payload only
2928 for directed messages, and not for broadcasts. */
2929 if (m
->destination
&& m
->bus
->use_memfd
) {
2930 MESSAGE_FOREACH_PART(part
, i
, m
)
2931 if (part
->memfd
>= 0 &&
2933 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
2934 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
2937 /* Try to seal it if that makes
2938 * sense. First, unmap our own map to
2939 * make sure we don't keep it busy. */
2940 bus_body_part_unmap(part
);
2942 /* Then, sync up real memfd size */
2944 r
= memfd_set_size(part
->memfd
, sz
);
2948 /* Finally, try to seal */
2949 if (memfd_set_sealed(part
->memfd
) >= 0)
2950 part
->sealed
= true;
2954 m
->root_container
.end
= m
->user_body_size
;
2955 m
->root_container
.index
= 0;
2956 m
->root_container
.offset_index
= 0;
2957 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
2964 int bus_body_part_map(struct bus_body_part
*part
) {
2973 if (part
->size
<= 0)
2976 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2977 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
2978 static const uint8_t zeroes
[7] = { };
2979 part
->data
= (void*) zeroes
;
2983 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
2984 psz
= PAGE_ALIGN(part
->size
+ shift
);
2986 if (part
->memfd
>= 0)
2987 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
2988 else if (part
->is_zero
)
2989 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
2993 if (p
== MAP_FAILED
)
2997 part
->mmap_begin
= p
;
2998 part
->data
= (uint8_t*) p
+ shift
;
2999 part
->munmap_this
= true;
3004 void bus_body_part_unmap(struct bus_body_part
*part
) {
3008 if (part
->memfd
< 0)
3011 if (!part
->mmap_begin
)
3014 if (!part
->munmap_this
)
3017 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
3019 part
->mmap_begin
= NULL
;
3022 part
->munmap_this
= false;
3027 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3028 size_t k
, start
, end
;
3033 start
= ALIGN_TO((size_t) *rindex
, align
);
3034 end
= start
+ nbytes
;
3039 /* Verify that padding is 0 */
3040 for (k
= *rindex
; k
< start
; k
++)
3041 if (((const uint8_t*) p
)[k
] != 0)
3045 *r
= (uint8_t*) p
+ start
;
3052 static bool message_end_of_signature(sd_bus_message
*m
) {
3053 struct bus_container
*c
;
3057 c
= message_get_container(m
);
3058 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3061 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3062 struct bus_container
*c
;
3066 c
= message_get_container(m
);
3067 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3070 if (BUS_MESSAGE_IS_GVARIANT(m
))
3071 return index
>= c
->end
;
3073 assert(c
->array_size
);
3074 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3078 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3079 assert_return(m
, -EINVAL
);
3080 assert_return(m
->sealed
, -EPERM
);
3082 if (complete
&& m
->n_containers
> 0)
3085 if (message_end_of_signature(m
))
3088 if (message_end_of_array(m
, m
->rindex
))
3094 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3095 struct bus_body_part
*part
;
3101 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3102 part
= m
->cached_rindex_part
;
3103 begin
= m
->cached_rindex_part_begin
;
3113 if (index
+ sz
<= begin
+ part
->size
) {
3115 r
= bus_body_part_map(part
);
3120 *p
= (uint8_t*) part
->data
+ index
- begin
;
3122 m
->cached_rindex_part
= part
;
3123 m
->cached_rindex_part_begin
= begin
;
3128 begin
+= part
->size
;
3135 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3142 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3145 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3148 sz
= bus_gvariant_get_size(c
->signature
);
3152 if (c
->offset_index
+1 >= c
->n_offsets
)
3155 /* Variable-size array */
3157 alignment
= bus_gvariant_get_alignment(c
->signature
);
3158 assert(alignment
> 0);
3160 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3161 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3164 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3167 /* Fixed-size array */
3168 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3174 } else if (IN_SET(c
->enclosing
, 0, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
3179 if (c
->offset_index
+1 >= c
->n_offsets
)
3182 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3186 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3191 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3194 alignment
= bus_gvariant_get_alignment(t
);
3197 assert(alignment
> 0);
3199 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3200 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3204 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3207 assert_not_reached("Unknown container type");
3212 /* Reached the end */
3219 static int message_peek_body(
3226 size_t k
, start
, end
, padding
;
3227 struct bus_body_part
*part
;
3234 start
= ALIGN_TO((size_t) *rindex
, align
);
3235 padding
= start
- *rindex
;
3236 end
= start
+ nbytes
;
3238 if (end
> m
->user_body_size
)
3241 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3246 /* Verify padding */
3247 for (k
= 0; k
< padding
; k
++)
3252 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3253 if (!part
|| (nbytes
> 0 && !q
))
3264 static bool validate_nul(const char *s
, size_t l
) {
3266 /* Check for NUL chars in the string */
3267 if (memchr(s
, 0, l
))
3270 /* Check for NUL termination */
3277 static bool validate_string(const char *s
, size_t l
) {
3279 if (!validate_nul(s
, l
))
3282 /* Check if valid UTF8 */
3283 if (!utf8_is_valid(s
))
3289 static bool validate_signature(const char *s
, size_t l
) {
3291 if (!validate_nul(s
, l
))
3294 /* Check if valid signature */
3295 if (!signature_is_valid(s
, true))
3301 static bool validate_object_path(const char *s
, size_t l
) {
3303 if (!validate_nul(s
, l
))
3306 if (!object_path_is_valid(s
))
3312 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3313 struct bus_container
*c
;
3318 assert_return(m
, -EINVAL
);
3319 assert_return(m
->sealed
, -EPERM
);
3320 assert_return(bus_type_is_basic(type
), -EINVAL
);
3322 if (message_end_of_signature(m
))
3325 if (message_end_of_array(m
, m
->rindex
))
3328 c
= message_get_container(m
);
3329 if (c
->signature
[c
->index
] != type
)
3334 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3336 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3339 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3343 if (type
== SD_BUS_TYPE_STRING
)
3344 ok
= validate_string(q
, c
->item_size
-1);
3345 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3346 ok
= validate_object_path(q
, c
->item_size
-1);
3348 ok
= validate_signature(q
, c
->item_size
-1);
3354 *(const char**) p
= q
;
3358 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3360 if ((size_t) sz
!= c
->item_size
)
3363 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3366 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3372 case SD_BUS_TYPE_BYTE
:
3374 *(uint8_t*) p
= *(uint8_t*) q
;
3377 case SD_BUS_TYPE_BOOLEAN
:
3379 *(int*) p
= !!*(uint8_t*) q
;
3382 case SD_BUS_TYPE_INT16
:
3383 case SD_BUS_TYPE_UINT16
:
3385 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3388 case SD_BUS_TYPE_INT32
:
3389 case SD_BUS_TYPE_UINT32
:
3391 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3394 case SD_BUS_TYPE_INT64
:
3395 case SD_BUS_TYPE_UINT64
:
3396 case SD_BUS_TYPE_DOUBLE
:
3398 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3401 case SD_BUS_TYPE_UNIX_FD
: {
3404 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3409 *(int*) p
= m
->fds
[j
];
3415 assert_not_reached("unexpected type");
3419 r
= container_next_item(m
, c
, &rindex
);
3424 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3428 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3432 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3433 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3437 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3438 ok
= validate_object_path(q
, l
);
3440 ok
= validate_string(q
, l
);
3445 *(const char**) p
= q
;
3447 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3450 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3455 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3459 if (!validate_signature(q
, l
))
3463 *(const char**) p
= q
;
3468 align
= bus_type_get_alignment(type
);
3471 sz
= bus_type_get_size(type
);
3474 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3480 case SD_BUS_TYPE_BYTE
:
3482 *(uint8_t*) p
= *(uint8_t*) q
;
3485 case SD_BUS_TYPE_BOOLEAN
:
3487 *(int*) p
= !!*(uint32_t*) q
;
3490 case SD_BUS_TYPE_INT16
:
3491 case SD_BUS_TYPE_UINT16
:
3493 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3496 case SD_BUS_TYPE_INT32
:
3497 case SD_BUS_TYPE_UINT32
:
3499 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3502 case SD_BUS_TYPE_INT64
:
3503 case SD_BUS_TYPE_UINT64
:
3504 case SD_BUS_TYPE_DOUBLE
:
3506 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3509 case SD_BUS_TYPE_UNIX_FD
: {
3512 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3517 *(int*) p
= m
->fds
[j
];
3522 assert_not_reached("Unknown basic type...");
3529 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3535 static int bus_message_enter_array(
3537 struct bus_container
*c
,
3538 const char *contents
,
3539 uint32_t **array_size
,
3542 size_t *n_offsets
) {
3556 if (!signature_is_single(contents
, true))
3559 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3562 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3565 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3570 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3573 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3577 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3580 alignment
= bus_type_get_alignment(contents
[0]);
3584 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3588 *array_size
= (uint32_t*) q
;
3590 } else if (c
->item_size
<= 0) {
3592 /* gvariant: empty array */
3597 } else if (bus_gvariant_is_fixed_size(contents
)) {
3599 /* gvariant: fixed length array */
3600 *item_size
= bus_gvariant_get_size(contents
);
3605 size_t where
, p
= 0, framing
, sz
;
3608 /* gvariant: variable length array */
3609 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3611 where
= rindex
+ c
->item_size
- sz
;
3612 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3616 framing
= bus_gvariant_read_word_le(q
, sz
);
3617 if (framing
> c
->item_size
- sz
)
3619 if ((c
->item_size
- framing
) % sz
!= 0)
3622 *n_offsets
= (c
->item_size
- framing
) / sz
;
3624 where
= rindex
+ framing
;
3625 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3629 *offsets
= new(size_t, *n_offsets
);
3633 for (i
= 0; i
< *n_offsets
; i
++) {
3636 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3637 if (x
> c
->item_size
- sz
)
3642 (*offsets
)[i
] = rindex
+ x
;
3646 *item_size
= (*offsets
)[0] - rindex
;
3651 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3652 c
->index
+= 1 + strlen(contents
);
3657 static int bus_message_enter_variant(
3659 struct bus_container
*c
,
3660 const char *contents
,
3661 size_t *item_size
) {
3673 if (!signature_is_single(contents
, false))
3676 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3679 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3682 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3687 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3690 k
= strlen(contents
);
3691 if (1+k
> c
->item_size
)
3694 where
= rindex
+ c
->item_size
- (1+k
);
3695 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3699 if (*(char*) q
!= 0)
3702 if (memcmp((uint8_t*) q
+1, contents
, k
))
3705 *item_size
= c
->item_size
- (1+k
);
3708 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3713 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3717 if (!validate_signature(q
, l
))
3720 if (!streq(q
, contents
))
3726 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3732 static int build_struct_offsets(
3734 const char *signature
,
3738 size_t *n_offsets
) {
3740 unsigned n_variable
= 0, n_total
= 0, v
;
3741 size_t previous
= 0, where
;
3752 if (isempty(signature
)) {
3753 /* Unary type is encoded as *fixed* 1 byte padding */
3754 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3758 if (*(uint8_t *) q
!= 0)
3767 sz
= bus_gvariant_determine_word_size(size
, 0);
3771 /* First, loop over signature and count variable elements and
3772 * elements in general. We use this to know how large the
3773 * offset array is at the end of the structure. Note that
3774 * GVariant only stores offsets for all variable size elements
3775 * that are not the last item. */
3781 r
= signature_element_length(p
, &n
);
3790 r
= bus_gvariant_is_fixed_size(t
);
3795 if (r
== 0 && p
[n
] != 0) /* except the last item */
3802 if (size
< n_variable
* sz
)
3805 where
= m
->rindex
+ size
- (n_variable
* sz
);
3806 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3812 *offsets
= new(size_t, n_total
);
3818 /* Second, loop again and build an offset table */
3824 r
= signature_element_length(p
, &n
);
3833 k
= bus_gvariant_get_size(t
);
3841 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3844 if (m
->rindex
+ x
< previous
)
3847 /* The last item's end
3848 * is determined from
3851 x
= size
- (n_variable
* sz
);
3853 offset
= m
->rindex
+ x
;
3859 align
= bus_gvariant_get_alignment(t
);
3862 offset
= (*n_offsets
== 0 ? m
->rindex
: ALIGN_TO((*offsets
)[*n_offsets
-1], align
)) + k
;
3866 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3871 assert(*n_offsets
== n_total
);
3873 *item_size
= (*offsets
)[0] - m
->rindex
;
3877 static int enter_struct_or_dict_entry(
3879 struct bus_container
*c
,
3880 const char *contents
,
3883 size_t *n_offsets
) {
3894 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3897 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3902 /* gvariant with contents */
3903 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3908 static int bus_message_enter_struct(
3910 struct bus_container
*c
,
3911 const char *contents
,
3914 size_t *n_offsets
) {
3926 if (!signature_is_valid(contents
, false))
3929 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3932 l
= strlen(contents
);
3934 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
3935 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3936 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
3939 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3943 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3944 c
->index
+= 1 + l
+ 1;
3949 static int bus_message_enter_dict_entry(
3951 struct bus_container
*c
,
3952 const char *contents
,
3955 size_t *n_offsets
) {
3964 if (!signature_is_pair(contents
))
3967 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3970 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3973 l
= strlen(contents
);
3975 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
3976 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3977 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
3980 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3984 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3985 c
->index
+= 1 + l
+ 1;
3990 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
3992 const char *contents
) {
3993 struct bus_container
*c
, *w
;
3994 uint32_t *array_size
= NULL
;
3997 size_t *offsets
= NULL
;
3998 size_t n_offsets
= 0, item_size
= 0;
4001 assert_return(m
, -EINVAL
);
4002 assert_return(m
->sealed
, -EPERM
);
4003 assert_return(type
!= 0 || !contents
, -EINVAL
);
4005 if (type
== 0 || !contents
) {
4009 /* Allow entering into anonymous containers */
4010 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
4014 if (type
!= 0 && type
!= tt
)
4017 if (contents
&& !streq(contents
, cc
))
4025 * We enforce a global limit on container depth, that is much
4026 * higher than the 32 structs and 32 arrays the specification
4027 * mandates. This is simpler to implement for us, and we need
4028 * this only to ensure our container array doesn't grow
4029 * without bounds. We are happy to return any data from a
4030 * message as long as the data itself is valid, even if the
4031 * overall message might be not.
4033 * Note that the message signature is validated when
4034 * parsing the headers, and that validation does check the
4037 * Note that the specification defines no limits on the depth
4038 * of stacked variants, but we do.
4040 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4043 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4046 if (message_end_of_signature(m
))
4049 if (message_end_of_array(m
, m
->rindex
))
4052 c
= message_get_container(m
);
4054 signature
= strdup(contents
);
4058 c
->saved_index
= c
->index
;
4061 if (type
== SD_BUS_TYPE_ARRAY
)
4062 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4063 else if (type
== SD_BUS_TYPE_VARIANT
)
4064 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4065 else if (type
== SD_BUS_TYPE_STRUCT
)
4066 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4067 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4068 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4078 /* OK, let's fill it in */
4079 w
= m
->containers
+ m
->n_containers
++;
4080 w
->enclosing
= type
;
4081 w
->signature
= signature
;
4082 w
->peeked_signature
= NULL
;
4086 w
->begin
= m
->rindex
;
4088 /* Unary type has fixed size of 1, but virtual size of 0 */
4089 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4090 type
== SD_BUS_TYPE_STRUCT
&&
4092 w
->end
= m
->rindex
+ 0;
4094 w
->end
= m
->rindex
+ c
->item_size
;
4096 w
->array_size
= array_size
;
4097 w
->item_size
= item_size
;
4098 w
->offsets
= offsets
;
4099 w
->n_offsets
= n_offsets
;
4100 w
->offset_index
= 0;
4105 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4106 struct bus_container
*c
;
4110 assert_return(m
, -EINVAL
);
4111 assert_return(m
->sealed
, -EPERM
);
4112 assert_return(m
->n_containers
> 0, -ENXIO
);
4114 c
= message_get_container(m
);
4116 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4117 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4121 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4122 if (m
->rindex
< c
->end
)
4125 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4128 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4129 if (c
->begin
+ l
!= m
->rindex
)
4134 free(c
->peeked_signature
);
4138 c
= message_get_container(m
);
4141 c
->index
= c
->saved_index
;
4142 r
= container_next_item(m
, c
, &m
->rindex
);
4150 static void message_quit_container(sd_bus_message
*m
) {
4151 struct bus_container
*c
;
4155 assert(m
->n_containers
> 0);
4157 c
= message_get_container(m
);
4160 assert(m
->rindex
>= c
->before
);
4161 m
->rindex
= c
->before
;
4163 /* Free container */
4168 /* Correct index of new top-level container */
4169 c
= message_get_container(m
);
4170 c
->index
= c
->saved_index
;
4173 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4174 struct bus_container
*c
;
4177 assert_return(m
, -EINVAL
);
4178 assert_return(m
->sealed
, -EPERM
);
4180 if (message_end_of_signature(m
))
4183 if (message_end_of_array(m
, m
->rindex
))
4186 c
= message_get_container(m
);
4188 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4192 *type
= c
->signature
[c
->index
];
4196 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4202 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4208 sig
= strndup(c
->signature
+ c
->index
+ 1, l
);
4212 free(c
->peeked_signature
);
4213 *contents
= c
->peeked_signature
= sig
;
4217 *type
= SD_BUS_TYPE_ARRAY
;
4222 if (c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
||
4223 c
->signature
[c
->index
] == SD_BUS_TYPE_DICT_ENTRY_BEGIN
) {
4229 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4234 sig
= strndup(c
->signature
+ c
->index
+ 1, l
- 2);
4238 free(c
->peeked_signature
);
4239 *contents
= c
->peeked_signature
= sig
;
4243 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4248 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4252 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4255 if (c
->item_size
< 2)
4258 /* Look for the NUL delimiter that
4259 separates the payload from the
4260 signature. Since the body might be
4261 in a different part that then the
4262 signature we map byte by byte. */
4264 for (k
= 2; k
<= c
->item_size
; k
++) {
4267 where
= m
->rindex
+ c
->item_size
- k
;
4268 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4272 if (*(char*) q
== 0)
4276 if (k
> c
->item_size
)
4279 free(c
->peeked_signature
);
4280 c
->peeked_signature
= strndup((char*) q
+ 1, k
- 1);
4281 if (!c
->peeked_signature
)
4284 if (!signature_is_valid(c
->peeked_signature
, true))
4287 *contents
= c
->peeked_signature
;
4292 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4297 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4301 if (!validate_signature(q
, l
))
4309 *type
= SD_BUS_TYPE_VARIANT
;
4324 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4325 struct bus_container
*c
;
4327 assert_return(m
, -EINVAL
);
4328 assert_return(m
->sealed
, -EPERM
);
4331 message_reset_containers(m
);
4334 c
= message_get_container(m
);
4336 c
= message_get_container(m
);
4338 c
->offset_index
= 0;
4340 m
->rindex
= c
->begin
;
4343 c
->offset_index
= 0;
4344 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4346 return !isempty(c
->signature
);
4349 static int message_read_ap(
4354 unsigned n_array
, n_struct
;
4355 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4356 unsigned stack_ptr
= 0;
4357 unsigned n_loop
= 0;
4365 /* Ideally, we'd just call ourselves recursively on every
4366 * complex type. However, the state of a va_list that is
4367 * passed to a function is undefined after that function
4368 * returns. This means we need to docode the va_list linearly
4369 * in a single stackframe. We hence implement our own
4370 * home-grown stack in an array. */
4372 n_array
= (unsigned) -1; /* length of current array entries */
4373 n_struct
= strlen(types
); /* length of current struct contents signature */
4380 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4381 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4387 r
= sd_bus_message_exit_container(m
);
4395 if (n_array
!= (unsigned) -1)
4404 case SD_BUS_TYPE_BYTE
:
4405 case SD_BUS_TYPE_BOOLEAN
:
4406 case SD_BUS_TYPE_INT16
:
4407 case SD_BUS_TYPE_UINT16
:
4408 case SD_BUS_TYPE_INT32
:
4409 case SD_BUS_TYPE_UINT32
:
4410 case SD_BUS_TYPE_INT64
:
4411 case SD_BUS_TYPE_UINT64
:
4412 case SD_BUS_TYPE_DOUBLE
:
4413 case SD_BUS_TYPE_STRING
:
4414 case SD_BUS_TYPE_OBJECT_PATH
:
4415 case SD_BUS_TYPE_SIGNATURE
:
4416 case SD_BUS_TYPE_UNIX_FD
: {
4419 p
= va_arg(ap
, void*);
4420 r
= sd_bus_message_read_basic(m
, *t
, p
);
4433 case SD_BUS_TYPE_ARRAY
: {
4436 r
= signature_element_length(t
+ 1, &k
);
4442 memcpy(s
, t
+ 1, k
);
4445 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4456 if (n_array
== (unsigned) -1) {
4461 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4467 n_array
= va_arg(ap
, unsigned);
4472 case SD_BUS_TYPE_VARIANT
: {
4475 s
= va_arg(ap
, const char *);
4479 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4489 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4494 n_struct
= strlen(s
);
4495 n_array
= (unsigned) -1;
4500 case SD_BUS_TYPE_STRUCT_BEGIN
:
4501 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4504 r
= signature_element_length(t
, &k
);
4510 memcpy(s
, t
+ 1, k
- 2);
4513 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4523 if (n_array
== (unsigned) -1) {
4528 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4534 n_array
= (unsigned) -1;
4547 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4551 assert_return(m
, -EINVAL
);
4552 assert_return(m
->sealed
, -EPERM
);
4553 assert_return(types
, -EINVAL
);
4555 va_start(ap
, types
);
4556 r
= message_read_ap(m
, types
, ap
);
4562 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4565 assert_return(m
, -EINVAL
);
4566 assert_return(m
->sealed
, -EPERM
);
4568 /* If types is NULL, read exactly one element */
4570 struct bus_container
*c
;
4573 if (message_end_of_signature(m
))
4576 if (message_end_of_array(m
, m
->rindex
))
4579 c
= message_get_container(m
);
4581 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4585 types
= strndupa(c
->signature
+ c
->index
, l
);
4590 case 0: /* Nothing to drop */
4593 case SD_BUS_TYPE_BYTE
:
4594 case SD_BUS_TYPE_BOOLEAN
:
4595 case SD_BUS_TYPE_INT16
:
4596 case SD_BUS_TYPE_UINT16
:
4597 case SD_BUS_TYPE_INT32
:
4598 case SD_BUS_TYPE_UINT32
:
4599 case SD_BUS_TYPE_INT64
:
4600 case SD_BUS_TYPE_UINT64
:
4601 case SD_BUS_TYPE_DOUBLE
:
4602 case SD_BUS_TYPE_STRING
:
4603 case SD_BUS_TYPE_OBJECT_PATH
:
4604 case SD_BUS_TYPE_SIGNATURE
:
4605 case SD_BUS_TYPE_UNIX_FD
:
4607 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4611 r
= sd_bus_message_skip(m
, types
+ 1);
4617 case SD_BUS_TYPE_ARRAY
: {
4620 r
= signature_element_length(types
+ 1, &k
);
4626 memcpy(s
, types
+1, k
);
4629 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4634 r
= sd_bus_message_skip(m
, s
);
4641 r
= sd_bus_message_exit_container(m
);
4646 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4653 case SD_BUS_TYPE_VARIANT
: {
4654 const char *contents
;
4657 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4661 if (x
!= SD_BUS_TYPE_VARIANT
)
4664 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4668 r
= sd_bus_message_skip(m
, contents
);
4673 r
= sd_bus_message_exit_container(m
);
4677 r
= sd_bus_message_skip(m
, types
+ 1);
4684 case SD_BUS_TYPE_STRUCT_BEGIN
:
4685 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4688 r
= signature_element_length(types
, &k
);
4694 memcpy(s
, types
+1, k
-2);
4697 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4701 r
= sd_bus_message_skip(m
, s
);
4705 r
= sd_bus_message_exit_container(m
);
4710 r
= sd_bus_message_skip(m
, types
+ k
);
4722 _public_
int sd_bus_message_read_array(
4728 struct bus_container
*c
;
4734 assert_return(m
, -EINVAL
);
4735 assert_return(m
->sealed
, -EPERM
);
4736 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4737 assert_return(ptr
, -EINVAL
);
4738 assert_return(size
, -EINVAL
);
4739 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4741 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4745 c
= message_get_container(m
);
4747 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4748 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4752 sz
= c
->end
- c
->begin
;
4754 align
= bus_type_get_alignment(type
);
4758 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4762 /* Zero length array, let's return some aligned
4763 * pointer that is not NULL */
4764 p
= (uint8_t*) NULL
+ align
;
4766 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4771 r
= sd_bus_message_exit_container(m
);
4775 *ptr
= (const void*) p
;
4781 message_quit_container(m
);
4785 static int message_peek_fields(
4796 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4799 static int message_peek_field_uint32(
4811 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4814 /* identical for gvariant and dbus1 */
4816 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4821 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4826 static int message_peek_field_uint64(
4838 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4841 /* identical for gvariant and dbus1 */
4843 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4848 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4853 static int message_peek_field_string(
4855 bool (*validate
)(const char *p
),
4867 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4872 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4878 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4882 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4888 if (!validate_nul(q
, l
))
4894 if (!validate_string(q
, l
))
4904 static int message_peek_field_signature(
4917 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4922 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4928 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
4933 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4938 if (!validate_signature(q
, l
))
4947 static int message_skip_fields(
4950 uint32_t array_size
,
4951 const char **signature
) {
4953 size_t original_index
;
4959 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
4961 original_index
= *ri
;
4967 if (array_size
!= (uint32_t) -1 &&
4968 array_size
<= *ri
- original_index
)
4975 if (t
== SD_BUS_TYPE_STRING
) {
4977 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
4983 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
4985 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
4991 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
4993 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
4999 } else if (bus_type_is_basic(t
)) {
5002 align
= bus_type_get_alignment(t
);
5003 k
= bus_type_get_size(t
);
5004 assert(align
> 0 && k
> 0);
5006 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
5012 } else if (t
== SD_BUS_TYPE_ARRAY
) {
5014 r
= signature_element_length(*signature
+1, &l
);
5024 strncpy(sig
, *signature
+ 1, l
-1);
5027 alignment
= bus_type_get_alignment(sig
[0]);
5031 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5034 if (nas
> BUS_ARRAY_MAX_SIZE
)
5037 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5041 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5046 (*signature
) += 1 + l
;
5048 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5051 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5055 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5061 } else if (IN_SET(t
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
5063 r
= signature_element_length(*signature
, &l
);
5070 strncpy(sig
, *signature
+ 1, l
-1);
5073 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5084 int bus_message_parse_fields(sd_bus_message
*m
) {
5087 uint32_t unix_fds
= 0;
5088 bool unix_fds_set
= false;
5089 void *offsets
= NULL
;
5090 unsigned n_offsets
= 0;
5096 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5099 /* Read the signature from the end of the body variant first */
5100 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5101 if (m
->footer_accessible
< 1 + sz
)
5104 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5106 if (p
< (char*) m
->footer
)
5113 /* We found the beginning of the signature
5114 * string, yay! We require the body to be a
5115 * structure, so verify it and then strip the
5116 * opening/closing brackets. */
5118 l
= ((char*) m
->footer
+ m
->footer_accessible
) - p
- (1 + sz
);
5120 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5121 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5124 c
= strndup(p
+ 1 + 1, l
- 2);
5128 free(m
->root_container
.signature
);
5129 m
->root_container
.signature
= c
;
5136 /* Calculate the actual user body size, by removing
5137 * the trailing variant signature and struct offset
5139 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5141 /* Pull out the offset table for the fields array */
5142 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5147 ri
= m
->fields_size
- sz
;
5148 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5152 framing
= bus_gvariant_read_word_le(q
, sz
);
5153 if (framing
>= m
->fields_size
- sz
)
5155 if ((m
->fields_size
- framing
) % sz
!= 0)
5159 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5163 n_offsets
= (m
->fields_size
- framing
) / sz
;
5166 m
->user_body_size
= m
->body_size
;
5169 while (ri
< m
->fields_size
) {
5170 _cleanup_free_
char *sig
= NULL
;
5171 const char *signature
;
5172 uint64_t field_type
;
5173 size_t item_size
= (size_t) -1;
5175 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5184 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5186 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5190 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5194 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5201 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5206 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5211 where
= ri
= ALIGN_TO(ri
, 8);
5212 item_size
= end
- ri
;
5213 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5217 b
= memrchr(q
, 0, item_size
);
5221 sig
= strndup(b
+1, item_size
- (b
+1-(char*) q
));
5226 item_size
= b
- (char*) q
;
5228 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5233 switch (field_type
) {
5235 case _BUS_MESSAGE_HEADER_INVALID
:
5238 case BUS_MESSAGE_HEADER_PATH
:
5243 if (!streq(signature
, "o"))
5246 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5249 case BUS_MESSAGE_HEADER_INTERFACE
:
5254 if (!streq(signature
, "s"))
5257 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5260 case BUS_MESSAGE_HEADER_MEMBER
:
5265 if (!streq(signature
, "s"))
5268 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5271 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5276 if (!streq(signature
, "s"))
5279 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5281 m
->error
._need_free
= -1;
5285 case BUS_MESSAGE_HEADER_DESTINATION
:
5290 if (!streq(signature
, "s"))
5293 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5296 case BUS_MESSAGE_HEADER_SENDER
:
5301 if (!streq(signature
, "s"))
5304 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5306 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
) {
5307 m
->creds
.unique_name
= (char*) m
->sender
;
5308 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5314 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5318 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5321 if (m
->root_container
.signature
)
5324 if (!streq(signature
, "g"))
5327 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5335 free(m
->root_container
.signature
);
5336 m
->root_container
.signature
= c
;
5340 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5342 if (m
->reply_cookie
!= 0)
5345 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5346 /* 64bit on dbus2 */
5348 if (!streq(signature
, "t"))
5351 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5355 /* 32bit on dbus1 */
5358 if (!streq(signature
, "u"))
5361 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5365 m
->reply_cookie
= serial
;
5368 if (m
->reply_cookie
== 0)
5373 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5377 if (!streq(signature
, "u"))
5380 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5384 unix_fds_set
= true;
5388 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5389 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5398 if (m
->n_fds
!= unix_fds
)
5401 switch (m
->header
->type
) {
5403 case SD_BUS_MESSAGE_SIGNAL
:
5404 if (!m
->path
|| !m
->interface
|| !m
->member
)
5407 if (m
->reply_cookie
!= 0)
5412 case SD_BUS_MESSAGE_METHOD_CALL
:
5414 if (!m
->path
|| !m
->member
)
5417 if (m
->reply_cookie
!= 0)
5422 case SD_BUS_MESSAGE_METHOD_RETURN
:
5424 if (m
->reply_cookie
== 0)
5428 case SD_BUS_MESSAGE_METHOD_ERROR
:
5430 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5435 /* Refuse non-local messages that claim they are local */
5436 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5438 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5440 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5443 m
->root_container
.end
= m
->user_body_size
;
5445 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5446 r
= build_struct_offsets(
5448 m
->root_container
.signature
,
5450 &m
->root_container
.item_size
,
5451 &m
->root_container
.offsets
,
5452 &m
->root_container
.n_offsets
);
5457 /* Try to read the error message, but if we can't it's a non-issue */
5458 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5459 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5464 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5465 assert_return(m
, -EINVAL
);
5466 assert_return(destination
, -EINVAL
);
5467 assert_return(!m
->sealed
, -EPERM
);
5468 assert_return(!m
->destination
, -EEXIST
);
5470 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5473 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5477 struct bus_body_part
*part
;
5483 total
= BUS_MESSAGE_SIZE(m
);
5489 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5490 MESSAGE_FOREACH_PART(part
, i
, m
)
5491 e
= mempcpy(e
, part
->data
, part
->size
);
5493 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5501 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5508 r
= sd_bus_message_enter_container(m
, 'a', "s");
5512 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5513 r
= strv_extend(l
, s
);
5520 r
= sd_bus_message_exit_container(m
);
5527 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5531 assert_return(m
, -EINVAL
);
5532 assert_return(m
->sealed
, -EPERM
);
5533 assert_return(l
, -EINVAL
);
5535 r
= bus_message_read_strv_extend(m
, &strv
);
5545 static int bus_message_get_arg_skip(
5549 const char **_contents
) {
5554 r
= sd_bus_message_rewind(m
, true);
5559 const char *contents
;
5562 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5568 /* Don't match against arguments after the first one we don't understand */
5569 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5570 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5575 *_contents
= contents
;
5581 r
= sd_bus_message_skip(m
, NULL
);
5588 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5595 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5599 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5602 return sd_bus_message_read_basic(m
, type
, str
);
5605 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5606 const char *contents
;
5613 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5617 if (type
!= SD_BUS_TYPE_ARRAY
)
5619 if (!STR_IN_SET(contents
, "s", "o", "g"))
5622 return sd_bus_message_read_strv(m
, strv
);
5625 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5626 assert_return(m
, EINVAL
);
5628 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5631 return sd_bus_error_get_errno(&m
->error
);
5634 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5635 struct bus_container
*c
;
5637 assert_return(m
, NULL
);
5639 c
= complete
? &m
->root_container
: message_get_container(m
);
5640 return strempty(c
->signature
);
5643 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5644 assert_return(m
, -EINVAL
);
5646 return isempty(m
->root_container
.signature
);
5649 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5650 assert_return(m
, -EINVAL
);
5652 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5655 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5656 bool done_something
= false;
5659 assert_return(m
, -EINVAL
);
5660 assert_return(source
, -EINVAL
);
5661 assert_return(!m
->sealed
, -EPERM
);
5662 assert_return(source
->sealed
, -EPERM
);
5665 const char *contents
;
5680 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5686 done_something
= true;
5688 if (bus_type_is_container(type
) > 0) {
5690 r
= sd_bus_message_enter_container(source
, type
, contents
);
5694 r
= sd_bus_message_open_container(m
, type
, contents
);
5698 r
= sd_bus_message_copy(m
, source
, true);
5702 r
= sd_bus_message_close_container(m
);
5706 r
= sd_bus_message_exit_container(source
);
5713 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5719 if (IN_SET(type
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
, SD_BUS_TYPE_STRING
))
5720 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5722 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5729 return done_something
;
5732 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5737 assert_return(m
, -EINVAL
);
5738 assert_return(m
->sealed
, -EPERM
);
5739 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5740 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5741 assert_return(type
|| contents
, -EINVAL
);
5742 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5744 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5748 if (type
!= 0 && type
!= t
)
5751 if (contents
&& !streq_ptr(contents
, c
))
5757 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5758 assert_return(m
, NULL
);
5763 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5764 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
5772 switch ((*m
)->header
->type
) {
5774 case SD_BUS_MESSAGE_SIGNAL
:
5775 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5781 case SD_BUS_MESSAGE_METHOD_CALL
:
5782 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5788 case SD_BUS_MESSAGE_METHOD_RETURN
:
5789 case SD_BUS_MESSAGE_METHOD_ERROR
:
5791 n
= message_new(bus
, (*m
)->header
->type
);
5795 n
->reply_cookie
= (*m
)->reply_cookie
;
5797 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5801 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5802 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5806 n
->error
._need_free
= -1;
5815 if ((*m
)->destination
&& !n
->destination
) {
5816 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5821 if ((*m
)->sender
&& !n
->sender
) {
5822 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5827 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5829 r
= sd_bus_message_copy(n
, *m
, true);
5833 timeout
= (*m
)->timeout
;
5834 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
))
5835 timeout
= BUS_DEFAULT_TIMEOUT
;
5837 r
= bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5841 sd_bus_message_unref(*m
);
5848 int bus_message_append_sender(sd_bus_message
*m
, const char *sender
) {
5852 assert_return(!m
->sealed
, -EPERM
);
5853 assert_return(!m
->sender
, -EPERM
);
5855 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5858 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5859 assert_return(m
, -EINVAL
);
5860 assert_return(priority
, -EINVAL
);
5862 *priority
= m
->priority
;
5866 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5867 assert_return(m
, -EINVAL
);
5868 assert_return(!m
->sealed
, -EPERM
);
5870 m
->priority
= priority
;