1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "alloc-util.h"
28 #include "bus-gvariant.h"
29 #include "bus-internal.h"
30 #include "bus-message.h"
31 #include "bus-signature.h"
36 #include "memfd-util.h"
37 #include "string-util.h"
39 #include "time-util.h"
43 static int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
);
45 static void *adjust_pointer(const void *p
, void *old_base
, size_t sz
, void *new_base
) {
50 if (old_base
== new_base
)
53 if ((uint8_t*) p
< (uint8_t*) old_base
)
56 if ((uint8_t*) p
>= (uint8_t*) old_base
+ sz
)
59 return (uint8_t*) new_base
+ ((uint8_t*) p
- (uint8_t*) old_base
);
62 static void message_free_part(sd_bus_message
*m
, struct bus_body_part
*part
) {
67 close_and_munmap(part
->memfd
, part
->mmap_begin
, part
->mapped
);
68 else if (part
->munmap_this
)
69 munmap(part
->mmap_begin
, part
->mapped
);
70 else if (part
->free_this
)
77 static void message_reset_parts(sd_bus_message
*m
) {
78 struct bus_body_part
*part
;
83 while (m
->n_body_parts
> 0) {
84 struct bus_body_part
*next
= part
->next
;
85 message_free_part(m
, part
);
92 m
->cached_rindex_part
= NULL
;
93 m
->cached_rindex_part_begin
= 0;
96 static void message_reset_containers(sd_bus_message
*m
) {
101 for (i
= 0; i
< m
->n_containers
; i
++) {
102 free(m
->containers
[i
].signature
);
103 free(m
->containers
[i
].offsets
);
106 m
->containers
= mfree(m
->containers
);
108 m
->n_containers
= m
->containers_allocated
= 0;
109 m
->root_container
.index
= 0;
112 static void message_free(sd_bus_message
*m
) {
118 message_reset_parts(m
);
120 sd_bus_unref(m
->bus
);
123 close_many(m
->fds
, m
->n_fds
);
127 if (m
->iovec
!= m
->iovec_fixed
)
130 m
->destination_ptr
= mfree(m
->destination_ptr
);
131 message_reset_containers(m
);
132 free(m
->root_container
.signature
);
133 free(m
->root_container
.offsets
);
135 free(m
->root_container
.peeked_signature
);
137 bus_creds_done(&m
->creds
);
141 static void *message_extend_fields(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
143 size_t old_size
, new_size
, start
;
150 old_size
= sizeof(struct bus_header
) + m
->fields_size
;
151 start
= ALIGN_TO(old_size
, align
);
152 new_size
= start
+ sz
;
154 if (new_size
< start
||
155 new_size
> (size_t) ((uint32_t) -1))
158 if (old_size
== new_size
)
159 return (uint8_t*) m
->header
+ old_size
;
161 if (m
->free_header
) {
162 np
= realloc(m
->header
, ALIGN8(new_size
));
166 /* Initially, the header is allocated as part of
167 * the sd_bus_message itself, let's replace it by
170 np
= malloc(ALIGN8(new_size
));
174 memcpy(np
, m
->header
, sizeof(struct bus_header
));
177 /* Zero out padding */
178 if (start
> old_size
)
179 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
183 m
->fields_size
= new_size
- sizeof(struct bus_header
);
185 /* Adjust quick access pointers */
186 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
187 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
188 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
189 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
190 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
191 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
193 m
->free_header
= true;
196 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
199 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
202 return (uint8_t*) np
+ start
;
209 static int message_append_field_string(
221 /* dbus1 only allows 8bit header field ids */
225 /* dbus1 doesn't allow strings over 32bit, let's enforce this
226 * globally, to not risk convertability */
228 if (l
> (size_t) (uint32_t) -1)
231 /* Signature "(yv)" where the variant contains "s" */
233 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
235 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
236 p
= message_extend_fields(m
, 8, 8 + l
+ 1 + 1 + 1, true);
240 *((uint64_t*) p
) = h
;
247 *ret
= (char*) p
+ 8;
250 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
251 p
= message_extend_fields(m
, 8, 4 + 4 + l
+ 1, false);
260 ((uint32_t*) p
)[1] = l
;
261 memcpy(p
+ 8, s
, l
+ 1);
264 *ret
= (char*) p
+ 8;
270 static int message_append_field_signature(
281 /* dbus1 only allows 8bit header field ids */
285 /* dbus1 doesn't allow signatures over 8bit, let's enforce
286 * this globally, to not risk convertability */
291 /* Signature "(yv)" where the variant contains "g" */
293 if (BUS_MESSAGE_IS_GVARIANT(m
))
294 /* For gvariant the serialization is the same as for normal strings */
295 return message_append_field_string(m
, h
, 'g', s
, ret
);
297 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
298 p
= message_extend_fields(m
, 8, 4 + 1 + l
+ 1, false);
304 p
[2] = SD_BUS_TYPE_SIGNATURE
;
307 memcpy(p
+ 5, s
, l
+ 1);
310 *ret
= (const char*) p
+ 5;
316 static int message_append_field_uint32(sd_bus_message
*m
, uint64_t h
, uint32_t x
) {
321 /* dbus1 only allows 8bit header field ids */
325 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
326 /* (field id 64bit + ((value + NUL + signature string 'u') */
328 p
= message_extend_fields(m
, 8, 8 + 4 + 1 + 1, true);
332 *((uint64_t*) p
) = h
;
333 *((uint32_t*) (p
+ 8)) = x
;
337 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
338 p
= message_extend_fields(m
, 8, 4 + 4, false);
347 ((uint32_t*) p
)[1] = x
;
353 static int message_append_field_uint64(sd_bus_message
*m
, uint64_t h
, uint64_t x
) {
358 /* dbus1 only allows 8bit header field ids */
362 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
363 /* (field id 64bit + ((value + NUL + signature string 't') */
365 p
= message_extend_fields(m
, 8, 8 + 8 + 1 + 1, true);
369 *((uint64_t*) p
) = h
;
370 *((uint64_t*) (p
+ 8)) = x
;
374 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
375 p
= message_extend_fields(m
, 8, 4 + 4 + 8, false);
388 ((uint64_t*) p
)[1] = x
;
394 static int message_append_reply_cookie(sd_bus_message
*m
, uint64_t cookie
) {
397 if (BUS_MESSAGE_IS_GVARIANT(m
))
398 return message_append_field_uint64(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, cookie
);
400 /* 64bit cookies are not supported on dbus1 */
401 if (cookie
> 0xffffffffUL
)
404 return message_append_field_uint32(m
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) cookie
);
408 int bus_message_from_header(
411 size_t header_accessible
,
413 size_t footer_accessible
,
419 sd_bus_message
**ret
) {
421 _cleanup_free_ sd_bus_message
*m
= NULL
;
422 struct bus_header
*h
;
426 assert(header
|| header_accessible
<= 0);
427 assert(footer
|| footer_accessible
<= 0);
428 assert(fds
|| n_fds
<= 0);
431 if (header_accessible
< sizeof(struct bus_header
))
434 if (header_accessible
> message_size
)
436 if (footer_accessible
> message_size
)
440 if (!IN_SET(h
->version
, 1, 2))
443 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
446 if (!IN_SET(h
->endian
, BUS_LITTLE_ENDIAN
, BUS_BIG_ENDIAN
))
449 /* Note that we are happy with unknown flags in the flags header! */
451 a
= ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
454 label_sz
= strlen(label
);
465 m
->header_accessible
= header_accessible
;
467 m
->footer_accessible
= footer_accessible
;
469 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
472 if (h
->dbus2
.cookie
== 0)
475 /* dbus2 derives the sizes from the message size and
476 the offset table at the end, since it is formatted as
477 gvariant "yyyyuta{tv}v". Since the message itself is a
478 structure with precisely to variable sized entries,
479 there's only one offset in the table, which marks the
480 end of the fields array. */
482 ws
= bus_gvariant_determine_word_size(message_size
, 0);
483 if (footer_accessible
< ws
)
486 m
->fields_size
= bus_gvariant_read_word_le((uint8_t*) footer
+ footer_accessible
- ws
, ws
);
487 if (ALIGN8(m
->fields_size
) > message_size
- ws
)
489 if (m
->fields_size
< sizeof(struct bus_header
))
492 m
->fields_size
-= sizeof(struct bus_header
);
493 m
->body_size
= message_size
- (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
));
495 if (h
->dbus1
.serial
== 0)
498 /* dbus1 has the sizes in the header */
499 m
->fields_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.fields_size
);
500 m
->body_size
= BUS_MESSAGE_BSWAP32(m
, h
->dbus1
.body_size
);
502 if (sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
!= message_size
)
510 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
511 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
513 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
516 m
->bus
= sd_bus_ref(bus
);
523 int bus_message_from_malloc(
530 sd_bus_message
**ret
) {
536 r
= bus_message_from_header(
538 buffer
, length
, /* in this case the initial bytes and the final bytes are the same */
547 sz
= length
- sizeof(struct bus_header
) - ALIGN8(m
->fields_size
);
550 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(m
->fields_size
);
552 m
->body
.sealed
= true;
557 m
->iovec
= m
->iovec_fixed
;
558 m
->iovec
[0].iov_base
= buffer
;
559 m
->iovec
[0].iov_len
= length
;
561 r
= bus_message_parse_fields(m
);
565 /* We take possession of the memory and fds now */
566 m
->free_header
= true;
577 _public_
int sd_bus_message_new(
584 assert_return(bus
, -ENOTCONN
);
585 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
586 assert_return(m
, -EINVAL
);
588 t
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
593 t
->header
= (struct bus_header
*) ((uint8_t*) t
+ ALIGN(sizeof(struct sd_bus_message
)));
594 t
->header
->endian
= BUS_NATIVE_ENDIAN
;
595 t
->header
->type
= type
;
596 t
->header
->version
= bus
->message_version
;
597 t
->allow_fds
= bus
->can_fds
|| !IN_SET(bus
->state
, BUS_HELLO
, BUS_RUNNING
);
598 t
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(t
);
599 t
->bus
= sd_bus_ref(bus
);
601 if (bus
->allow_interactive_authorization
)
602 t
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
608 _public_
int sd_bus_message_new_signal(
612 const char *interface
,
613 const char *member
) {
618 assert_return(bus
, -ENOTCONN
);
619 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
620 assert_return(object_path_is_valid(path
), -EINVAL
);
621 assert_return(interface_name_is_valid(interface
), -EINVAL
);
622 assert_return(member_name_is_valid(member
), -EINVAL
);
623 assert_return(m
, -EINVAL
);
625 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_SIGNAL
);
631 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
633 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
636 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
639 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
647 sd_bus_message_unref(t
);
651 _public_
int sd_bus_message_new_method_call(
654 const char *destination
,
656 const char *interface
,
657 const char *member
) {
662 assert_return(bus
, -ENOTCONN
);
663 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
664 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
665 assert_return(object_path_is_valid(path
), -EINVAL
);
666 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
667 assert_return(member_name_is_valid(member
), -EINVAL
);
668 assert_return(m
, -EINVAL
);
670 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_CALL
);
676 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
679 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
684 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
690 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
703 static int message_new_reply(
704 sd_bus_message
*call
,
706 sd_bus_message
**m
) {
711 assert_return(call
, -EINVAL
);
712 assert_return(call
->sealed
, -EPERM
);
713 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
714 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
715 assert_return(m
, -EINVAL
);
717 r
= sd_bus_message_new(call
->bus
, &t
, type
);
723 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
724 t
->reply_cookie
= BUS_MESSAGE_COOKIE(call
);
725 if (t
->reply_cookie
== 0)
728 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
733 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
738 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
739 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
749 _public_
int sd_bus_message_new_method_return(
750 sd_bus_message
*call
,
751 sd_bus_message
**m
) {
753 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
756 _public_
int sd_bus_message_new_method_error(
757 sd_bus_message
*call
,
759 const sd_bus_error
*e
) {
764 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
765 assert_return(m
, -EINVAL
);
767 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
771 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
776 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
781 t
->error
._need_free
= -1;
791 _public_
int sd_bus_message_new_method_errorf(
792 sd_bus_message
*call
,
798 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
801 assert_return(name
, -EINVAL
);
802 assert_return(m
, -EINVAL
);
804 va_start(ap
, format
);
805 bus_error_setfv(&error
, name
, format
, ap
);
808 return sd_bus_message_new_method_error(call
, m
, &error
);
811 _public_
int sd_bus_message_new_method_errno(
812 sd_bus_message
*call
,
815 const sd_bus_error
*p
) {
817 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
819 if (sd_bus_error_is_set(p
))
820 return sd_bus_message_new_method_error(call
, m
, p
);
822 sd_bus_error_set_errno(&berror
, error
);
824 return sd_bus_message_new_method_error(call
, m
, &berror
);
827 _public_
int sd_bus_message_new_method_errnof(
828 sd_bus_message
*call
,
834 _cleanup_(sd_bus_error_free
) sd_bus_error berror
= SD_BUS_ERROR_NULL
;
837 va_start(ap
, format
);
838 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
841 return sd_bus_message_new_method_error(call
, m
, &berror
);
844 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
848 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
849 m
->creds
.well_known_names_local
= true;
850 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
853 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
857 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
858 m
->creds
.well_known_names_driver
= true;
859 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
862 int bus_message_new_synthetic_error(
865 const sd_bus_error
*e
,
866 sd_bus_message
**m
) {
872 assert(sd_bus_error_is_set(e
));
875 r
= sd_bus_message_new(bus
, &t
, SD_BUS_MESSAGE_METHOD_ERROR
);
881 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
882 t
->reply_cookie
= cookie
;
884 r
= message_append_reply_cookie(t
, t
->reply_cookie
);
888 if (bus
&& bus
->unique_name
) {
889 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
894 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
899 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
904 t
->error
._need_free
= -1;
906 bus_message_set_sender_driver(bus
, t
);
916 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
921 assert(m
->n_ref
> 0);
927 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
932 assert(m
->n_ref
> 0);
942 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
943 assert_return(m
, -EINVAL
);
944 assert_return(type
, -EINVAL
);
946 *type
= m
->header
->type
;
950 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
953 assert_return(m
, -EINVAL
);
954 assert_return(cookie
, -EINVAL
);
956 c
= BUS_MESSAGE_COOKIE(m
);
960 *cookie
= BUS_MESSAGE_COOKIE(m
);
964 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
965 assert_return(m
, -EINVAL
);
966 assert_return(cookie
, -EINVAL
);
968 if (m
->reply_cookie
== 0)
971 *cookie
= m
->reply_cookie
;
975 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
976 assert_return(m
, -EINVAL
);
978 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
979 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
982 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
983 assert_return(m
, -EINVAL
);
985 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
988 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
989 assert_return(m
, -EINVAL
);
991 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
992 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
995 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
996 assert_return(m
, NULL
);
1001 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
1002 assert_return(m
, NULL
);
1004 return m
->interface
;
1007 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
1008 assert_return(m
, NULL
);
1013 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
1014 assert_return(m
, NULL
);
1016 return m
->destination
;
1019 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
1020 assert_return(m
, NULL
);
1025 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
1026 assert_return(m
, NULL
);
1028 if (!sd_bus_error_is_set(&m
->error
))
1034 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
1035 assert_return(m
, -EINVAL
);
1036 assert_return(usec
, -EINVAL
);
1038 if (m
->monotonic
<= 0)
1041 *usec
= m
->monotonic
;
1045 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
1046 assert_return(m
, -EINVAL
);
1047 assert_return(usec
, -EINVAL
);
1049 if (m
->realtime
<= 0)
1052 *usec
= m
->realtime
;
1056 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
1057 assert_return(m
, -EINVAL
);
1058 assert_return(seqnum
, -EINVAL
);
1063 *seqnum
= m
->seqnum
;
1067 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
1068 assert_return(m
, NULL
);
1070 if (m
->creds
.mask
== 0)
1076 _public_
int sd_bus_message_is_signal(
1078 const char *interface
,
1079 const char *member
) {
1081 assert_return(m
, -EINVAL
);
1083 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
1086 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1089 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1095 _public_
int sd_bus_message_is_method_call(
1097 const char *interface
,
1098 const char *member
) {
1100 assert_return(m
, -EINVAL
);
1102 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
1105 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
1108 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1114 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1115 assert_return(m
, -EINVAL
);
1117 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1120 if (name
&& (!m
->error
.name
|| !streq(m
->error
.name
, name
)))
1126 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1127 assert_return(m
, -EINVAL
);
1128 assert_return(!m
->sealed
, -EPERM
);
1129 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1131 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_REPLY_EXPECTED
, !b
);
1136 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1137 assert_return(m
, -EINVAL
);
1138 assert_return(!m
->sealed
, -EPERM
);
1140 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_NO_AUTO_START
, !b
);
1145 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1146 assert_return(m
, -EINVAL
);
1147 assert_return(!m
->sealed
, -EPERM
);
1149 SET_FLAG(m
->header
->flags
, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
, b
);
1154 static struct bus_container
*message_get_container(sd_bus_message
*m
) {
1157 if (m
->n_containers
== 0)
1158 return &m
->root_container
;
1160 assert(m
->containers
);
1161 return m
->containers
+ m
->n_containers
- 1;
1164 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1165 struct bus_body_part
*part
;
1172 if (m
->n_body_parts
<= 0) {
1176 assert(m
->body_end
);
1178 part
= new0(struct bus_body_part
, 1);
1184 m
->body_end
->next
= part
;
1194 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1199 /* All other fields can be left in their defaults */
1200 assert(!part
->data
);
1201 assert(part
->memfd
< 0);
1204 part
->is_zero
= true;
1205 part
->sealed
= true;
1208 static int part_make_space(
1209 struct sd_bus_message
*m
,
1210 struct bus_body_part
*part
,
1218 assert(!part
->sealed
);
1223 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1224 size_t new_allocated
;
1226 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1227 n
= realloc(part
->data
, new_allocated
);
1234 part
->allocated
= new_allocated
;
1235 part
->free_this
= true;
1239 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1245 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1246 struct bus_container
*c
;
1249 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1251 /* Add offset to current container, unless this is the first
1252 * item in it, which will have the 0 offset, which we can
1254 c
= message_get_container(m
);
1256 if (!c
->need_offsets
)
1259 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1262 c
->offsets
[c
->n_offsets
++] = offset
;
1266 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1267 struct bus_container
*c
;
1274 /* Update counters */
1275 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++) {
1278 *c
->array_size
+= expand
;
1282 static void *message_extend_body(
1287 bool force_inline
) {
1289 size_t start_body
, end_body
, padding
, added
;
1300 start_body
= ALIGN_TO((size_t) m
->body_size
, align
);
1301 end_body
= start_body
+ sz
;
1303 padding
= start_body
- m
->body_size
;
1304 added
= padding
+ sz
;
1306 /* Check for 32bit overflows */
1307 if (end_body
> (size_t) ((uint32_t) -1) ||
1308 end_body
< start_body
) {
1314 struct bus_body_part
*part
= NULL
;
1318 m
->n_body_parts
<= 0 ||
1319 m
->body_end
->sealed
||
1320 (padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
) ||
1321 (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 */
1325 part
= message_append_part(m
);
1329 part_zero(part
, padding
);
1332 part
= message_append_part(m
);
1336 r
= part_make_space(m
, part
, sz
, &p
);
1340 struct bus_container
*c
;
1342 size_t os
, start_part
, end_part
;
1348 start_part
= ALIGN_TO(part
->size
, align
);
1349 end_part
= start_part
+ sz
;
1351 r
= part_make_space(m
, part
, end_part
, &p
);
1356 memzero(p
, padding
);
1357 p
= (uint8_t*) p
+ padding
;
1360 /* Readjust pointers */
1361 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1362 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1364 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1367 /* Return something that is not NULL and is aligned */
1368 p
= (uint8_t *) NULL
+ align
;
1370 m
->body_size
= end_body
;
1371 message_extend_containers(m
, added
);
1374 r
= message_add_offset(m
, end_body
);
1384 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1395 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1399 f
= realloc(m
->fds
, sizeof(int) * (m
->n_fds
+ 1));
1407 m
->fds
[m
->n_fds
] = copy
;
1413 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1414 _cleanup_close_
int fd
= -1;
1415 struct bus_container
*c
;
1419 assert_return(m
, -EINVAL
);
1420 assert_return(!m
->sealed
, -EPERM
);
1421 assert_return(bus_type_is_basic(type
), -EINVAL
);
1422 assert_return(!m
->poisoned
, -ESTALE
);
1424 c
= message_get_container(m
);
1426 if (c
->signature
&& c
->signature
[c
->index
]) {
1427 /* Container signature is already set */
1429 if (c
->signature
[c
->index
] != type
)
1434 /* Maybe we can append to the signature? But only if this is the top-level container */
1435 if (c
->enclosing
!= 0)
1438 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1445 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1451 case SD_BUS_TYPE_SIGNATURE
:
1452 case SD_BUS_TYPE_STRING
:
1455 /* Fall through... */
1456 case SD_BUS_TYPE_OBJECT_PATH
:
1464 case SD_BUS_TYPE_BOOLEAN
:
1466 u8
= p
&& *(int*) p
;
1472 case SD_BUS_TYPE_UNIX_FD
:
1477 fd
= message_push_fd(m
, *(int*) p
);
1488 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1489 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1496 a
= message_extend_body(m
, align
, sz
, true, false);
1503 *stored
= (const uint8_t*) a
;
1510 case SD_BUS_TYPE_STRING
:
1511 /* To make things easy we'll serialize a NULL string
1512 * into the empty string */
1515 /* Fall through... */
1516 case SD_BUS_TYPE_OBJECT_PATH
:
1522 sz
= 4 + strlen(p
) + 1;
1525 case SD_BUS_TYPE_SIGNATURE
:
1530 sz
= 1 + strlen(p
) + 1;
1533 case SD_BUS_TYPE_BOOLEAN
:
1535 u32
= p
&& *(int*) p
;
1541 case SD_BUS_TYPE_UNIX_FD
:
1546 fd
= message_push_fd(m
, *(int*) p
);
1557 align
= bus_type_get_alignment(type
);
1558 sz
= bus_type_get_size(type
);
1565 a
= message_extend_body(m
, align
, sz
, false, false);
1569 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
1570 *(uint32_t*) a
= sz
- 5;
1571 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1574 *stored
= (const uint8_t*) a
+ 4;
1576 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1577 *(uint8_t*) a
= sz
- 2;
1578 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1581 *stored
= (const uint8_t*) a
+ 1;
1590 if (type
== SD_BUS_TYPE_UNIX_FD
)
1593 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1600 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1601 return message_append_basic(m
, type
, p
, NULL
);
1604 _public_
int sd_bus_message_append_string_space(
1609 struct bus_container
*c
;
1612 assert_return(m
, -EINVAL
);
1613 assert_return(s
, -EINVAL
);
1614 assert_return(!m
->sealed
, -EPERM
);
1615 assert_return(!m
->poisoned
, -ESTALE
);
1617 c
= message_get_container(m
);
1619 if (c
->signature
&& c
->signature
[c
->index
]) {
1620 /* Container signature is already set */
1622 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1627 /* Maybe we can append to the signature? But only if this is the top-level container */
1628 if (c
->enclosing
!= 0)
1631 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1638 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1639 a
= message_extend_body(m
, 1, size
+ 1, true, false);
1645 a
= message_extend_body(m
, 4, 4 + size
+ 1, false, false);
1649 *(uint32_t*) a
= size
;
1655 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1661 _public_
int sd_bus_message_append_string_iovec(
1663 const struct iovec
*iov
,
1671 assert_return(m
, -EINVAL
);
1672 assert_return(!m
->sealed
, -EPERM
);
1673 assert_return(iov
|| n
== 0, -EINVAL
);
1674 assert_return(!m
->poisoned
, -ESTALE
);
1676 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1678 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1682 for (i
= 0; i
< n
; i
++) {
1684 if (iov
[i
].iov_base
)
1685 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1687 memset(p
, ' ', iov
[i
].iov_len
);
1689 p
+= iov
[i
].iov_len
;
1695 static int bus_message_open_array(
1697 struct bus_container
*c
,
1698 const char *contents
,
1699 uint32_t **array_size
,
1701 bool *need_offsets
) {
1711 assert(need_offsets
);
1713 if (!signature_is_single(contents
, true))
1716 if (c
->signature
&& c
->signature
[c
->index
]) {
1718 /* Verify the existing signature */
1720 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1723 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1726 nindex
= c
->index
+ 1 + strlen(contents
);
1730 if (c
->enclosing
!= 0)
1733 /* Extend the existing signature */
1735 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1741 nindex
= e
- c
->signature
;
1744 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1745 alignment
= bus_gvariant_get_alignment(contents
);
1749 /* Add alignment padding and add to offset list */
1750 if (!message_extend_body(m
, alignment
, 0, false, false))
1753 r
= bus_gvariant_is_fixed_size(contents
);
1757 *begin
= m
->body_size
;
1758 *need_offsets
= r
== 0;
1762 struct bus_body_part
*o
;
1764 alignment
= bus_type_get_alignment(contents
[0]);
1768 a
= message_extend_body(m
, 4, 4, false, false);
1773 op
= m
->body_end
->data
;
1774 os
= m
->body_end
->size
;
1776 /* Add alignment between size and first element */
1777 if (!message_extend_body(m
, alignment
, 0, false, false))
1780 /* location of array size might have changed so let's readjust a */
1781 if (o
== m
->body_end
)
1782 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1788 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1794 static int bus_message_open_variant(
1796 struct bus_container
*c
,
1797 const char *contents
) {
1803 if (!signature_is_single(contents
, false))
1806 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1809 if (c
->signature
&& c
->signature
[c
->index
]) {
1811 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1817 if (c
->enclosing
!= 0)
1820 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1827 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1828 /* Variants are always aligned to 8 */
1830 if (!message_extend_body(m
, 8, 0, false, false))
1837 l
= strlen(contents
);
1838 a
= message_extend_body(m
, 1, 1 + l
+ 1, false, false);
1843 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1846 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1852 static int bus_message_open_struct(
1854 struct bus_container
*c
,
1855 const char *contents
,
1857 bool *need_offsets
) {
1866 assert(need_offsets
);
1868 if (!signature_is_valid(contents
, false))
1871 if (c
->signature
&& c
->signature
[c
->index
]) {
1874 l
= strlen(contents
);
1876 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1877 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1878 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1881 nindex
= c
->index
+ 1 + l
+ 1;
1885 if (c
->enclosing
!= 0)
1888 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1894 nindex
= e
- c
->signature
;
1897 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1900 alignment
= bus_gvariant_get_alignment(contents
);
1904 if (!message_extend_body(m
, alignment
, 0, false, false))
1907 r
= bus_gvariant_is_fixed_size(contents
);
1911 *begin
= m
->body_size
;
1912 *need_offsets
= r
== 0;
1914 /* Align contents to 8 byte boundary */
1915 if (!message_extend_body(m
, 8, 0, false, false))
1919 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1925 static int bus_message_open_dict_entry(
1927 struct bus_container
*c
,
1928 const char *contents
,
1930 bool *need_offsets
) {
1938 assert(need_offsets
);
1940 if (!signature_is_pair(contents
))
1943 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1946 if (c
->signature
&& c
->signature
[c
->index
]) {
1949 l
= strlen(contents
);
1951 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
1952 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1953 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
1958 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1961 alignment
= bus_gvariant_get_alignment(contents
);
1965 if (!message_extend_body(m
, alignment
, 0, false, false))
1968 r
= bus_gvariant_is_fixed_size(contents
);
1972 *begin
= m
->body_size
;
1973 *need_offsets
= r
== 0;
1975 /* Align contents to 8 byte boundary */
1976 if (!message_extend_body(m
, 8, 0, false, false))
1983 _public_
int sd_bus_message_open_container(
1986 const char *contents
) {
1988 struct bus_container
*c
, *w
;
1989 uint32_t *array_size
= NULL
;
1991 size_t before
, begin
= 0;
1992 bool need_offsets
= false;
1995 assert_return(m
, -EINVAL
);
1996 assert_return(!m
->sealed
, -EPERM
);
1997 assert_return(contents
, -EINVAL
);
1998 assert_return(!m
->poisoned
, -ESTALE
);
2000 /* Make sure we have space for one more container */
2001 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
2006 c
= message_get_container(m
);
2008 signature
= strdup(contents
);
2014 /* Save old index in the parent container, in case we have to
2015 * abort this container */
2016 c
->saved_index
= c
->index
;
2017 before
= m
->body_size
;
2019 if (type
== SD_BUS_TYPE_ARRAY
)
2020 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
2021 else if (type
== SD_BUS_TYPE_VARIANT
)
2022 r
= bus_message_open_variant(m
, c
, contents
);
2023 else if (type
== SD_BUS_TYPE_STRUCT
)
2024 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
2025 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
2026 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
2035 /* OK, let's fill it in */
2036 w
= m
->containers
+ m
->n_containers
++;
2037 w
->enclosing
= type
;
2038 w
->signature
= signature
;
2040 w
->array_size
= array_size
;
2043 w
->n_offsets
= w
->offsets_allocated
= 0;
2045 w
->need_offsets
= need_offsets
;
2050 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2055 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2058 if (c
->need_offsets
) {
2059 size_t payload
, sz
, i
;
2062 /* Variable-width arrays */
2064 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2065 sz
= bus_gvariant_determine_word_size(payload
, c
->n_offsets
);
2067 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true, false);
2071 for (i
= 0; i
< c
->n_offsets
; i
++)
2072 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2076 /* Fixed-width or empty arrays */
2078 a
= message_extend_body(m
, 1, 0, true, false); /* let's add offset to parent */
2086 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2092 assert(c
->signature
);
2094 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2097 l
= strlen(c
->signature
);
2099 a
= message_extend_body(m
, 1, 1 + l
, true, false);
2104 memcpy(a
+1, c
->signature
, l
);
2109 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2110 bool fixed_size
= true;
2111 size_t n_variable
= 0;
2120 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2123 p
= strempty(c
->signature
);
2127 r
= signature_element_length(p
, &n
);
2136 r
= bus_gvariant_is_fixed_size(t
);
2141 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2143 /* We need to add an offset for each item that has a
2144 * variable size and that is not the last one in the
2148 if (r
== 0 && p
[n
] != 0)
2155 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2156 assert(c
->need_offsets
|| n_variable
== 0);
2158 if (isempty(c
->signature
)) {
2159 /* The unary type is encoded as fixed 1 byte padding */
2160 a
= message_extend_body(m
, 1, 1, add_offset
, false);
2165 } else if (n_variable
<= 0) {
2168 /* Structures with fixed-size members only have to be
2169 * fixed-size themselves. But gvariant requires all fixed-size
2170 * elements to be sized a multiple of their alignment. Hence,
2171 * we must *always* add final padding after the last member so
2172 * the overall size of the structure is properly aligned. */
2174 alignment
= bus_gvariant_get_alignment(strempty(c
->signature
));
2176 assert(alignment
> 0);
2178 a
= message_extend_body(m
, alignment
, 0, add_offset
, false);
2185 assert(c
->offsets
[c
->n_offsets
-1] == m
->body_size
);
2187 sz
= bus_gvariant_determine_word_size(m
->body_size
- c
->begin
, n_variable
);
2189 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
, false);
2193 p
= strempty(c
->signature
);
2194 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2198 r
= signature_element_length(p
, &n
);
2209 r
= bus_gvariant_is_fixed_size(t
);
2212 if (r
> 0 || p
[0] == 0)
2216 k
= n_variable
- 1 - j
;
2218 bus_gvariant_write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2227 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2228 struct bus_container
*c
;
2231 assert_return(m
, -EINVAL
);
2232 assert_return(!m
->sealed
, -EPERM
);
2233 assert_return(m
->n_containers
> 0, -EINVAL
);
2234 assert_return(!m
->poisoned
, -ESTALE
);
2236 c
= message_get_container(m
);
2238 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2239 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2244 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2245 r
= bus_message_close_array(m
, c
);
2246 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2247 r
= bus_message_close_variant(m
, c
);
2248 else if (IN_SET(c
->enclosing
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
))
2249 r
= bus_message_close_struct(m
, c
, true);
2251 assert_not_reached("Unknown container type");
2265 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2272 stack
[*i
].types
= types
;
2273 stack
[*i
].n_struct
= n_struct
;
2274 stack
[*i
].n_array
= n_array
;
2280 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2291 *types
= stack
[*i
].types
;
2292 *n_struct
= stack
[*i
].n_struct
;
2293 *n_array
= stack
[*i
].n_array
;
2298 _public_
int sd_bus_message_appendv(
2303 unsigned n_array
, n_struct
;
2304 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2305 unsigned stack_ptr
= 0;
2308 assert_return(m
, -EINVAL
);
2309 assert_return(types
, -EINVAL
);
2310 assert_return(!m
->sealed
, -EPERM
);
2311 assert_return(!m
->poisoned
, -ESTALE
);
2313 n_array
= (unsigned) -1;
2314 n_struct
= strlen(types
);
2319 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2320 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2326 r
= sd_bus_message_close_container(m
);
2334 if (n_array
!= (unsigned) -1)
2343 case SD_BUS_TYPE_BYTE
: {
2346 x
= (uint8_t) va_arg(ap
, int);
2347 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2351 case SD_BUS_TYPE_BOOLEAN
:
2352 case SD_BUS_TYPE_INT32
:
2353 case SD_BUS_TYPE_UINT32
:
2354 case SD_BUS_TYPE_UNIX_FD
: {
2357 /* We assume a boolean is the same as int32_t */
2358 assert_cc(sizeof(int32_t) == sizeof(int));
2360 x
= va_arg(ap
, uint32_t);
2361 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2365 case SD_BUS_TYPE_INT16
:
2366 case SD_BUS_TYPE_UINT16
: {
2369 x
= (uint16_t) va_arg(ap
, int);
2370 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2374 case SD_BUS_TYPE_INT64
:
2375 case SD_BUS_TYPE_UINT64
: {
2378 x
= va_arg(ap
, uint64_t);
2379 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2383 case SD_BUS_TYPE_DOUBLE
: {
2386 x
= va_arg(ap
, double);
2387 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2391 case SD_BUS_TYPE_STRING
:
2392 case SD_BUS_TYPE_OBJECT_PATH
:
2393 case SD_BUS_TYPE_SIGNATURE
: {
2396 x
= va_arg(ap
, const char*);
2397 r
= sd_bus_message_append_basic(m
, *t
, x
);
2401 case SD_BUS_TYPE_ARRAY
: {
2404 r
= signature_element_length(t
+ 1, &k
);
2410 memcpy(s
, t
+ 1, k
);
2413 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2418 if (n_array
== (unsigned) -1) {
2423 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2429 n_array
= va_arg(ap
, unsigned);
2434 case SD_BUS_TYPE_VARIANT
: {
2437 s
= va_arg(ap
, const char*);
2441 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2445 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2450 n_struct
= strlen(s
);
2451 n_array
= (unsigned) -1;
2456 case SD_BUS_TYPE_STRUCT_BEGIN
:
2457 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2460 r
= signature_element_length(t
, &k
);
2467 memcpy(s
, t
+ 1, k
- 2);
2470 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2475 if (n_array
== (unsigned) -1) {
2480 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2486 n_array
= (unsigned) -1;
2502 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2506 assert_return(m
, -EINVAL
);
2507 assert_return(types
, -EINVAL
);
2508 assert_return(!m
->sealed
, -EPERM
);
2509 assert_return(!m
->poisoned
, -ESTALE
);
2511 va_start(ap
, types
);
2512 r
= sd_bus_message_appendv(m
, types
, ap
);
2518 _public_
int sd_bus_message_append_array_space(
2528 assert_return(m
, -EINVAL
);
2529 assert_return(!m
->sealed
, -EPERM
);
2530 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2531 assert_return(ptr
|| size
== 0, -EINVAL
);
2532 assert_return(!m
->poisoned
, -ESTALE
);
2534 /* alignment and size of the trivial types (except bool) is
2535 * identical for gvariant and dbus1 marshalling */
2536 align
= bus_type_get_alignment(type
);
2537 sz
= bus_type_get_size(type
);
2539 assert_se(align
> 0);
2545 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2549 a
= message_extend_body(m
, align
, size
, false, false);
2553 r
= sd_bus_message_close_container(m
);
2561 _public_
int sd_bus_message_append_array(
2569 assert_return(m
, -EINVAL
);
2570 assert_return(!m
->sealed
, -EPERM
);
2571 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2572 assert_return(ptr
|| size
== 0, -EINVAL
);
2573 assert_return(!m
->poisoned
, -ESTALE
);
2575 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2579 memcpy_safe(p
, ptr
, size
);
2584 _public_
int sd_bus_message_append_array_iovec(
2587 const struct iovec
*iov
,
2595 assert_return(m
, -EINVAL
);
2596 assert_return(!m
->sealed
, -EPERM
);
2597 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2598 assert_return(iov
|| n
== 0, -EINVAL
);
2599 assert_return(!m
->poisoned
, -ESTALE
);
2601 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2603 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2607 for (i
= 0; i
< n
; i
++) {
2609 if (iov
[i
].iov_base
)
2610 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2612 memzero(p
, iov
[i
].iov_len
);
2614 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2620 _public_
int sd_bus_message_append_array_memfd(
2627 _cleanup_close_
int copy_fd
= -1;
2628 struct bus_body_part
*part
;
2634 assert_return(m
, -EINVAL
);
2635 assert_return(memfd
>= 0, -EBADF
);
2636 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2637 assert_return(size
> 0, -EINVAL
);
2638 assert_return(!m
->sealed
, -EPERM
);
2639 assert_return(!m
->poisoned
, -ESTALE
);
2641 r
= memfd_set_sealed(memfd
);
2645 copy_fd
= dup(memfd
);
2649 r
= memfd_get_size(memfd
, &real_size
);
2653 if (offset
== 0 && size
== (uint64_t) -1)
2655 else if (offset
+ size
> real_size
)
2658 align
= bus_type_get_alignment(type
);
2659 sz
= bus_type_get_size(type
);
2661 assert_se(align
> 0);
2664 if (offset
% align
!= 0)
2670 if (size
> (uint64_t) (uint32_t) -1)
2673 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2677 a
= message_extend_body(m
, align
, 0, false, false);
2681 part
= message_append_part(m
);
2685 part
->memfd
= copy_fd
;
2686 part
->memfd_offset
= offset
;
2687 part
->sealed
= true;
2691 m
->body_size
+= size
;
2692 message_extend_containers(m
, size
);
2694 return sd_bus_message_close_container(m
);
2697 _public_
int sd_bus_message_append_string_memfd(
2703 _cleanup_close_
int copy_fd
= -1;
2704 struct bus_body_part
*part
;
2705 struct bus_container
*c
;
2710 assert_return(m
, -EINVAL
);
2711 assert_return(memfd
>= 0, -EBADF
);
2712 assert_return(size
> 0, -EINVAL
);
2713 assert_return(!m
->sealed
, -EPERM
);
2714 assert_return(!m
->poisoned
, -ESTALE
);
2716 r
= memfd_set_sealed(memfd
);
2720 copy_fd
= dup(memfd
);
2724 r
= memfd_get_size(memfd
, &real_size
);
2728 if (offset
== 0 && size
== (uint64_t) -1)
2730 else if (offset
+ size
> real_size
)
2733 /* We require this to be NUL terminated */
2737 if (size
> (uint64_t) (uint32_t) -1)
2740 c
= message_get_container(m
);
2741 if (c
->signature
&& c
->signature
[c
->index
]) {
2742 /* Container signature is already set */
2744 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2749 /* Maybe we can append to the signature? But only if this is the top-level container */
2750 if (c
->enclosing
!= 0)
2753 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2760 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2761 a
= message_extend_body(m
, 4, 4, false, false);
2765 *(uint32_t*) a
= size
- 1;
2768 part
= message_append_part(m
);
2772 part
->memfd
= copy_fd
;
2773 part
->memfd_offset
= offset
;
2774 part
->sealed
= true;
2778 m
->body_size
+= size
;
2779 message_extend_containers(m
, size
);
2781 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2782 r
= message_add_offset(m
, m
->body_size
);
2789 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2795 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2799 assert_return(m
, -EINVAL
);
2800 assert_return(!m
->sealed
, -EPERM
);
2801 assert_return(!m
->poisoned
, -ESTALE
);
2803 r
= sd_bus_message_open_container(m
, 'a', "s");
2807 STRV_FOREACH(i
, l
) {
2808 r
= sd_bus_message_append_basic(m
, 's', *i
);
2813 return sd_bus_message_close_container(m
);
2816 static int bus_message_close_header(sd_bus_message
*m
) {
2820 /* The actual user data is finished now, we just complete the
2821 variant and struct now (at least on gvariant). Remember
2822 this position, so that during parsing we know where to
2823 put the outer container end. */
2824 m
->user_body_size
= m
->body_size
;
2826 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2827 const char *signature
;
2831 /* Add offset table to end of fields array */
2832 if (m
->n_header_offsets
>= 1) {
2836 assert(m
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2838 sz
= bus_gvariant_determine_word_size(m
->fields_size
, m
->n_header_offsets
);
2839 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2843 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2844 bus_gvariant_write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2847 /* Add gvariant NUL byte plus signature to the end of
2848 * the body, followed by the final offset pointing to
2849 * the end of the fields array */
2851 signature
= strempty(m
->root_container
.signature
);
2852 l
= strlen(signature
);
2854 sz
= bus_gvariant_determine_word_size(sizeof(struct bus_header
) + ALIGN8(m
->fields_size
) + m
->body_size
+ 1 + l
+ 2, 1);
2855 d
= message_extend_body(m
, 1, 1 + l
+ 2 + sz
, false, true);
2860 *((uint8_t*) d
+ 1) = SD_BUS_TYPE_STRUCT_BEGIN
;
2861 memcpy((uint8_t*) d
+ 2, signature
, l
);
2862 *((uint8_t*) d
+ 1 + l
+ 1) = SD_BUS_TYPE_STRUCT_END
;
2864 bus_gvariant_write_word_le((uint8_t*) d
+ 1 + l
+ 2, sz
, sizeof(struct bus_header
) + m
->fields_size
);
2867 m
->footer_accessible
= 1 + l
+ 2 + sz
;
2869 m
->header
->dbus1
.fields_size
= m
->fields_size
;
2870 m
->header
->dbus1
.body_size
= m
->body_size
;
2876 _public_
int sd_bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, uint64_t timeout_usec
) {
2877 struct bus_body_part
*part
;
2882 assert_return(m
, -EINVAL
);
2887 if (m
->n_containers
> 0)
2893 if (cookie
> 0xffffffffULL
&&
2894 !BUS_MESSAGE_IS_GVARIANT(m
))
2897 /* In vtables the return signature of method calls is listed,
2898 * let's check if they match if this is a response */
2899 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2900 m
->enforced_reply_signature
&&
2901 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2904 /* If gvariant marshalling is used we need to close the body structure */
2905 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2909 /* If there's a non-trivial signature set, then add it in
2910 * here, but only on dbus1 */
2911 if (!isempty(m
->root_container
.signature
) && !BUS_MESSAGE_IS_GVARIANT(m
)) {
2912 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2918 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2923 r
= bus_message_close_header(m
);
2927 if (BUS_MESSAGE_IS_GVARIANT(m
))
2928 m
->header
->dbus2
.cookie
= cookie
;
2930 m
->header
->dbus1
.serial
= (uint32_t) cookie
;
2932 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout_usec
;
2934 /* Add padding at the end of the fields part, since we know
2935 * the body needs to start at an 8 byte alignment. We made
2936 * sure we allocated enough space for this, so all we need to
2937 * do here is to zero it out. */
2938 a
= ALIGN8(m
->fields_size
) - m
->fields_size
;
2940 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + m
->fields_size
, a
);
2942 /* If this is something we can send as memfd, then let's seal
2943 the memfd now. Note that we can send memfds as payload only
2944 for directed messages, and not for broadcasts. */
2945 if (m
->destination
&& m
->bus
->use_memfd
) {
2946 MESSAGE_FOREACH_PART(part
, i
, m
)
2947 if (part
->memfd
>= 0 &&
2949 (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0) &&
2950 part
!= m
->body_end
) { /* The last part may never be sent as memfd */
2953 /* Try to seal it if that makes
2954 * sense. First, unmap our own map to
2955 * make sure we don't keep it busy. */
2956 bus_body_part_unmap(part
);
2958 /* Then, sync up real memfd size */
2960 r
= memfd_set_size(part
->memfd
, sz
);
2964 /* Finally, try to seal */
2965 if (memfd_set_sealed(part
->memfd
) >= 0)
2966 part
->sealed
= true;
2970 m
->root_container
.end
= m
->user_body_size
;
2971 m
->root_container
.index
= 0;
2972 m
->root_container
.offset_index
= 0;
2973 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
2980 int bus_body_part_map(struct bus_body_part
*part
) {
2989 if (part
->size
<= 0)
2992 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2993 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
2994 static const uint8_t zeroes
[7] = { };
2995 part
->data
= (void*) zeroes
;
2999 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
3000 psz
= PAGE_ALIGN(part
->size
+ shift
);
3002 if (part
->memfd
>= 0)
3003 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
3004 else if (part
->is_zero
)
3005 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
3009 if (p
== MAP_FAILED
)
3013 part
->mmap_begin
= p
;
3014 part
->data
= (uint8_t*) p
+ shift
;
3015 part
->munmap_this
= true;
3020 void bus_body_part_unmap(struct bus_body_part
*part
) {
3024 if (part
->memfd
< 0)
3027 if (!part
->mmap_begin
)
3030 if (!part
->munmap_this
)
3033 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
3035 part
->mmap_begin
= NULL
;
3038 part
->munmap_this
= false;
3043 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
3044 size_t k
, start
, end
;
3049 start
= ALIGN_TO((size_t) *rindex
, align
);
3050 end
= start
+ nbytes
;
3055 /* Verify that padding is 0 */
3056 for (k
= *rindex
; k
< start
; k
++)
3057 if (((const uint8_t*) p
)[k
] != 0)
3061 *r
= (uint8_t*) p
+ start
;
3068 static bool message_end_of_signature(sd_bus_message
*m
) {
3069 struct bus_container
*c
;
3073 c
= message_get_container(m
);
3074 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3077 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3078 struct bus_container
*c
;
3082 c
= message_get_container(m
);
3083 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3086 if (BUS_MESSAGE_IS_GVARIANT(m
))
3087 return index
>= c
->end
;
3089 assert(c
->array_size
);
3090 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3094 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3095 assert_return(m
, -EINVAL
);
3096 assert_return(m
->sealed
, -EPERM
);
3098 if (complete
&& m
->n_containers
> 0)
3101 if (message_end_of_signature(m
))
3104 if (message_end_of_array(m
, m
->rindex
))
3110 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3111 struct bus_body_part
*part
;
3117 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3118 part
= m
->cached_rindex_part
;
3119 begin
= m
->cached_rindex_part_begin
;
3129 if (index
+ sz
<= begin
+ part
->size
) {
3131 r
= bus_body_part_map(part
);
3136 *p
= (uint8_t*) part
->data
+ index
- begin
;
3138 m
->cached_rindex_part
= part
;
3139 m
->cached_rindex_part_begin
= begin
;
3144 begin
+= part
->size
;
3151 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3158 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3161 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3164 sz
= bus_gvariant_get_size(c
->signature
);
3168 if (c
->offset_index
+1 >= c
->n_offsets
)
3171 /* Variable-size array */
3173 alignment
= bus_gvariant_get_alignment(c
->signature
);
3174 assert(alignment
> 0);
3176 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3177 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3180 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3183 /* Fixed-size array */
3184 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3190 } else if (IN_SET(c
->enclosing
, 0, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
3195 if (c
->offset_index
+1 >= c
->n_offsets
)
3198 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3202 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3207 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3210 alignment
= bus_gvariant_get_alignment(t
);
3213 assert(alignment
> 0);
3215 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3216 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3220 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3223 assert_not_reached("Unknown container type");
3228 /* Reached the end */
3235 static int message_peek_body(
3242 size_t k
, start
, end
, padding
;
3243 struct bus_body_part
*part
;
3250 start
= ALIGN_TO((size_t) *rindex
, align
);
3251 padding
= start
- *rindex
;
3252 end
= start
+ nbytes
;
3254 if (end
> m
->user_body_size
)
3257 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3262 /* Verify padding */
3263 for (k
= 0; k
< padding
; k
++)
3268 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3269 if (!part
|| (nbytes
> 0 && !q
))
3280 static bool validate_nul(const char *s
, size_t l
) {
3282 /* Check for NUL chars in the string */
3283 if (memchr(s
, 0, l
))
3286 /* Check for NUL termination */
3293 static bool validate_string(const char *s
, size_t l
) {
3295 if (!validate_nul(s
, l
))
3298 /* Check if valid UTF8 */
3299 if (!utf8_is_valid(s
))
3305 static bool validate_signature(const char *s
, size_t l
) {
3307 if (!validate_nul(s
, l
))
3310 /* Check if valid signature */
3311 if (!signature_is_valid(s
, true))
3317 static bool validate_object_path(const char *s
, size_t l
) {
3319 if (!validate_nul(s
, l
))
3322 if (!object_path_is_valid(s
))
3328 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3329 struct bus_container
*c
;
3334 assert_return(m
, -EINVAL
);
3335 assert_return(m
->sealed
, -EPERM
);
3336 assert_return(bus_type_is_basic(type
), -EINVAL
);
3338 if (message_end_of_signature(m
))
3341 if (message_end_of_array(m
, m
->rindex
))
3344 c
= message_get_container(m
);
3345 if (c
->signature
[c
->index
] != type
)
3350 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3352 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3355 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3359 if (type
== SD_BUS_TYPE_STRING
)
3360 ok
= validate_string(q
, c
->item_size
-1);
3361 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3362 ok
= validate_object_path(q
, c
->item_size
-1);
3364 ok
= validate_signature(q
, c
->item_size
-1);
3370 *(const char**) p
= q
;
3374 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3376 if ((size_t) sz
!= c
->item_size
)
3379 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3382 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3388 case SD_BUS_TYPE_BYTE
:
3390 *(uint8_t*) p
= *(uint8_t*) q
;
3393 case SD_BUS_TYPE_BOOLEAN
:
3395 *(int*) p
= !!*(uint8_t*) q
;
3398 case SD_BUS_TYPE_INT16
:
3399 case SD_BUS_TYPE_UINT16
:
3401 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3404 case SD_BUS_TYPE_INT32
:
3405 case SD_BUS_TYPE_UINT32
:
3407 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3410 case SD_BUS_TYPE_INT64
:
3411 case SD_BUS_TYPE_UINT64
:
3412 case SD_BUS_TYPE_DOUBLE
:
3414 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3417 case SD_BUS_TYPE_UNIX_FD
: {
3420 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3425 *(int*) p
= m
->fds
[j
];
3431 assert_not_reached("unexpected type");
3435 r
= container_next_item(m
, c
, &rindex
);
3440 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3444 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3448 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3449 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3453 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3454 ok
= validate_object_path(q
, l
);
3456 ok
= validate_string(q
, l
);
3461 *(const char**) p
= q
;
3463 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3466 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3471 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3475 if (!validate_signature(q
, l
))
3479 *(const char**) p
= q
;
3484 align
= bus_type_get_alignment(type
);
3487 sz
= bus_type_get_size(type
);
3490 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3496 case SD_BUS_TYPE_BYTE
:
3498 *(uint8_t*) p
= *(uint8_t*) q
;
3501 case SD_BUS_TYPE_BOOLEAN
:
3503 *(int*) p
= !!*(uint32_t*) q
;
3506 case SD_BUS_TYPE_INT16
:
3507 case SD_BUS_TYPE_UINT16
:
3509 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3512 case SD_BUS_TYPE_INT32
:
3513 case SD_BUS_TYPE_UINT32
:
3515 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3518 case SD_BUS_TYPE_INT64
:
3519 case SD_BUS_TYPE_UINT64
:
3520 case SD_BUS_TYPE_DOUBLE
:
3522 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3525 case SD_BUS_TYPE_UNIX_FD
: {
3528 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3533 *(int*) p
= m
->fds
[j
];
3538 assert_not_reached("Unknown basic type...");
3545 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3551 static int bus_message_enter_array(
3553 struct bus_container
*c
,
3554 const char *contents
,
3555 uint32_t **array_size
,
3558 size_t *n_offsets
) {
3572 if (!signature_is_single(contents
, true))
3575 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3578 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3581 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3586 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3589 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3593 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3596 alignment
= bus_type_get_alignment(contents
[0]);
3600 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3604 *array_size
= (uint32_t*) q
;
3606 } else if (c
->item_size
<= 0) {
3608 /* gvariant: empty array */
3613 } else if (bus_gvariant_is_fixed_size(contents
)) {
3615 /* gvariant: fixed length array */
3616 *item_size
= bus_gvariant_get_size(contents
);
3621 size_t where
, p
= 0, framing
, sz
;
3624 /* gvariant: variable length array */
3625 sz
= bus_gvariant_determine_word_size(c
->item_size
, 0);
3627 where
= rindex
+ c
->item_size
- sz
;
3628 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3632 framing
= bus_gvariant_read_word_le(q
, sz
);
3633 if (framing
> c
->item_size
- sz
)
3635 if ((c
->item_size
- framing
) % sz
!= 0)
3638 *n_offsets
= (c
->item_size
- framing
) / sz
;
3640 where
= rindex
+ framing
;
3641 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3645 *offsets
= new(size_t, *n_offsets
);
3649 for (i
= 0; i
< *n_offsets
; i
++) {
3652 x
= bus_gvariant_read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3653 if (x
> c
->item_size
- sz
)
3658 (*offsets
)[i
] = rindex
+ x
;
3662 *item_size
= (*offsets
)[0] - rindex
;
3667 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3668 c
->index
+= 1 + strlen(contents
);
3673 static int bus_message_enter_variant(
3675 struct bus_container
*c
,
3676 const char *contents
,
3677 size_t *item_size
) {
3689 if (!signature_is_single(contents
, false))
3692 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3695 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3698 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3703 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3706 k
= strlen(contents
);
3707 if (1+k
> c
->item_size
)
3710 where
= rindex
+ c
->item_size
- (1+k
);
3711 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3715 if (*(char*) q
!= 0)
3718 if (memcmp((uint8_t*) q
+1, contents
, k
))
3721 *item_size
= c
->item_size
- (1+k
);
3724 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3729 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3733 if (!validate_signature(q
, l
))
3736 if (!streq(q
, contents
))
3742 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3748 static int build_struct_offsets(
3750 const char *signature
,
3754 size_t *n_offsets
) {
3756 unsigned n_variable
= 0, n_total
= 0, v
;
3757 size_t previous
= 0, where
;
3768 if (isempty(signature
)) {
3769 /* Unary type is encoded as *fixed* 1 byte padding */
3770 r
= message_peek_body(m
, &m
->rindex
, 1, 1, &q
);
3774 if (*(uint8_t *) q
!= 0)
3783 sz
= bus_gvariant_determine_word_size(size
, 0);
3787 /* First, loop over signature and count variable elements and
3788 * elements in general. We use this to know how large the
3789 * offset array is at the end of the structure. Note that
3790 * GVariant only stores offsets for all variable size elements
3791 * that are not the last item. */
3797 r
= signature_element_length(p
, &n
);
3806 r
= bus_gvariant_is_fixed_size(t
);
3811 if (r
== 0 && p
[n
] != 0) /* except the last item */
3818 if (size
< n_variable
* sz
)
3821 where
= m
->rindex
+ size
- (n_variable
* sz
);
3822 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3828 *offsets
= new(size_t, n_total
);
3834 /* Second, loop again and build an offset table */
3840 r
= signature_element_length(p
, &n
);
3849 k
= bus_gvariant_get_size(t
);
3857 x
= bus_gvariant_read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3860 if (m
->rindex
+ x
< previous
)
3863 /* The last item's end
3864 * is determined from
3867 x
= size
- (n_variable
* sz
);
3869 offset
= m
->rindex
+ x
;
3875 align
= bus_gvariant_get_alignment(t
);
3878 offset
= (*n_offsets
== 0 ? m
->rindex
: ALIGN_TO((*offsets
)[*n_offsets
-1], align
)) + k
;
3882 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3887 assert(*n_offsets
== n_total
);
3889 *item_size
= (*offsets
)[0] - m
->rindex
;
3893 static int enter_struct_or_dict_entry(
3895 struct bus_container
*c
,
3896 const char *contents
,
3899 size_t *n_offsets
) {
3910 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3913 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3918 /* gvariant with contents */
3919 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3924 static int bus_message_enter_struct(
3926 struct bus_container
*c
,
3927 const char *contents
,
3930 size_t *n_offsets
) {
3942 if (!signature_is_valid(contents
, false))
3945 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3948 l
= strlen(contents
);
3950 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
3951 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3952 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
3955 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3959 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3960 c
->index
+= 1 + l
+ 1;
3965 static int bus_message_enter_dict_entry(
3967 struct bus_container
*c
,
3968 const char *contents
,
3971 size_t *n_offsets
) {
3980 if (!signature_is_pair(contents
))
3983 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3986 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3989 l
= strlen(contents
);
3991 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
3992 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3993 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
3996 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
4000 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
4001 c
->index
+= 1 + l
+ 1;
4006 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
4008 const char *contents
) {
4009 struct bus_container
*c
, *w
;
4010 uint32_t *array_size
= NULL
;
4013 size_t *offsets
= NULL
;
4014 size_t n_offsets
= 0, item_size
= 0;
4017 assert_return(m
, -EINVAL
);
4018 assert_return(m
->sealed
, -EPERM
);
4019 assert_return(type
!= 0 || !contents
, -EINVAL
);
4021 if (type
== 0 || !contents
) {
4025 /* Allow entering into anonymous containers */
4026 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
4030 if (type
!= 0 && type
!= tt
)
4033 if (contents
&& !streq(contents
, cc
))
4041 * We enforce a global limit on container depth, that is much
4042 * higher than the 32 structs and 32 arrays the specification
4043 * mandates. This is simpler to implement for us, and we need
4044 * this only to ensure our container array doesn't grow
4045 * without bounds. We are happy to return any data from a
4046 * message as long as the data itself is valid, even if the
4047 * overall message might be not.
4049 * Note that the message signature is validated when
4050 * parsing the headers, and that validation does check the
4053 * Note that the specification defines no limits on the depth
4054 * of stacked variants, but we do.
4056 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
4059 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
4062 if (message_end_of_signature(m
))
4065 if (message_end_of_array(m
, m
->rindex
))
4068 c
= message_get_container(m
);
4070 signature
= strdup(contents
);
4074 c
->saved_index
= c
->index
;
4077 if (type
== SD_BUS_TYPE_ARRAY
)
4078 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4079 else if (type
== SD_BUS_TYPE_VARIANT
)
4080 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4081 else if (type
== SD_BUS_TYPE_STRUCT
)
4082 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4083 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4084 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4094 /* OK, let's fill it in */
4095 w
= m
->containers
+ m
->n_containers
++;
4096 w
->enclosing
= type
;
4097 w
->signature
= signature
;
4098 w
->peeked_signature
= NULL
;
4102 w
->begin
= m
->rindex
;
4104 /* Unary type has fixed size of 1, but virtual size of 0 */
4105 if (BUS_MESSAGE_IS_GVARIANT(m
) &&
4106 type
== SD_BUS_TYPE_STRUCT
&&
4108 w
->end
= m
->rindex
+ 0;
4110 w
->end
= m
->rindex
+ c
->item_size
;
4112 w
->array_size
= array_size
;
4113 w
->item_size
= item_size
;
4114 w
->offsets
= offsets
;
4115 w
->n_offsets
= n_offsets
;
4116 w
->offset_index
= 0;
4121 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4122 struct bus_container
*c
;
4126 assert_return(m
, -EINVAL
);
4127 assert_return(m
->sealed
, -EPERM
);
4128 assert_return(m
->n_containers
> 0, -ENXIO
);
4130 c
= message_get_container(m
);
4132 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4133 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4137 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4138 if (m
->rindex
< c
->end
)
4141 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4144 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4145 if (c
->begin
+ l
!= m
->rindex
)
4150 free(c
->peeked_signature
);
4154 c
= message_get_container(m
);
4157 c
->index
= c
->saved_index
;
4158 r
= container_next_item(m
, c
, &m
->rindex
);
4166 static void message_quit_container(sd_bus_message
*m
) {
4167 struct bus_container
*c
;
4171 assert(m
->n_containers
> 0);
4173 c
= message_get_container(m
);
4176 assert(m
->rindex
>= c
->before
);
4177 m
->rindex
= c
->before
;
4179 /* Free container */
4184 /* Correct index of new top-level container */
4185 c
= message_get_container(m
);
4186 c
->index
= c
->saved_index
;
4189 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4190 struct bus_container
*c
;
4193 assert_return(m
, -EINVAL
);
4194 assert_return(m
->sealed
, -EPERM
);
4196 if (message_end_of_signature(m
))
4199 if (message_end_of_array(m
, m
->rindex
))
4202 c
= message_get_container(m
);
4204 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4208 *type
= c
->signature
[c
->index
];
4212 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4218 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4224 sig
= strndup(c
->signature
+ c
->index
+ 1, l
);
4228 free(c
->peeked_signature
);
4229 *contents
= c
->peeked_signature
= sig
;
4233 *type
= SD_BUS_TYPE_ARRAY
;
4238 if (IN_SET(c
->signature
[c
->index
], SD_BUS_TYPE_STRUCT_BEGIN
, SD_BUS_TYPE_DICT_ENTRY_BEGIN
)) {
4244 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4249 sig
= strndup(c
->signature
+ c
->index
+ 1, l
- 2);
4253 free(c
->peeked_signature
);
4254 *contents
= c
->peeked_signature
= sig
;
4258 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4263 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4267 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4270 if (c
->item_size
< 2)
4273 /* Look for the NUL delimiter that
4274 separates the payload from the
4275 signature. Since the body might be
4276 in a different part that then the
4277 signature we map byte by byte. */
4279 for (k
= 2; k
<= c
->item_size
; k
++) {
4282 where
= m
->rindex
+ c
->item_size
- k
;
4283 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4287 if (*(char*) q
== 0)
4291 if (k
> c
->item_size
)
4294 free(c
->peeked_signature
);
4295 c
->peeked_signature
= strndup((char*) q
+ 1, k
- 1);
4296 if (!c
->peeked_signature
)
4299 if (!signature_is_valid(c
->peeked_signature
, true))
4302 *contents
= c
->peeked_signature
;
4307 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4312 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4316 if (!validate_signature(q
, l
))
4324 *type
= SD_BUS_TYPE_VARIANT
;
4339 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4340 struct bus_container
*c
;
4342 assert_return(m
, -EINVAL
);
4343 assert_return(m
->sealed
, -EPERM
);
4346 message_reset_containers(m
);
4349 c
= message_get_container(m
);
4351 c
= message_get_container(m
);
4353 c
->offset_index
= 0;
4355 m
->rindex
= c
->begin
;
4358 c
->offset_index
= 0;
4359 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4361 return !isempty(c
->signature
);
4364 static int message_read_ap(
4369 unsigned n_array
, n_struct
;
4370 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4371 unsigned stack_ptr
= 0;
4372 unsigned n_loop
= 0;
4380 /* Ideally, we'd just call ourselves recursively on every
4381 * complex type. However, the state of a va_list that is
4382 * passed to a function is undefined after that function
4383 * returns. This means we need to docode the va_list linearly
4384 * in a single stackframe. We hence implement our own
4385 * home-grown stack in an array. */
4387 n_array
= (unsigned) -1; /* length of current array entries */
4388 n_struct
= strlen(types
); /* length of current struct contents signature */
4395 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4396 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4402 r
= sd_bus_message_exit_container(m
);
4410 if (n_array
!= (unsigned) -1)
4419 case SD_BUS_TYPE_BYTE
:
4420 case SD_BUS_TYPE_BOOLEAN
:
4421 case SD_BUS_TYPE_INT16
:
4422 case SD_BUS_TYPE_UINT16
:
4423 case SD_BUS_TYPE_INT32
:
4424 case SD_BUS_TYPE_UINT32
:
4425 case SD_BUS_TYPE_INT64
:
4426 case SD_BUS_TYPE_UINT64
:
4427 case SD_BUS_TYPE_DOUBLE
:
4428 case SD_BUS_TYPE_STRING
:
4429 case SD_BUS_TYPE_OBJECT_PATH
:
4430 case SD_BUS_TYPE_SIGNATURE
:
4431 case SD_BUS_TYPE_UNIX_FD
: {
4434 p
= va_arg(ap
, void*);
4435 r
= sd_bus_message_read_basic(m
, *t
, p
);
4448 case SD_BUS_TYPE_ARRAY
: {
4451 r
= signature_element_length(t
+ 1, &k
);
4457 memcpy(s
, t
+ 1, k
);
4460 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4471 if (n_array
== (unsigned) -1) {
4476 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4482 n_array
= va_arg(ap
, unsigned);
4487 case SD_BUS_TYPE_VARIANT
: {
4490 s
= va_arg(ap
, const char *);
4494 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4504 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4509 n_struct
= strlen(s
);
4510 n_array
= (unsigned) -1;
4515 case SD_BUS_TYPE_STRUCT_BEGIN
:
4516 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4519 r
= signature_element_length(t
, &k
);
4525 memcpy(s
, t
+ 1, k
- 2);
4528 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4538 if (n_array
== (unsigned) -1) {
4543 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4549 n_array
= (unsigned) -1;
4562 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4566 assert_return(m
, -EINVAL
);
4567 assert_return(m
->sealed
, -EPERM
);
4568 assert_return(types
, -EINVAL
);
4570 va_start(ap
, types
);
4571 r
= message_read_ap(m
, types
, ap
);
4577 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4580 assert_return(m
, -EINVAL
);
4581 assert_return(m
->sealed
, -EPERM
);
4583 /* If types is NULL, read exactly one element */
4585 struct bus_container
*c
;
4588 if (message_end_of_signature(m
))
4591 if (message_end_of_array(m
, m
->rindex
))
4594 c
= message_get_container(m
);
4596 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4600 types
= strndupa(c
->signature
+ c
->index
, l
);
4605 case 0: /* Nothing to drop */
4608 case SD_BUS_TYPE_BYTE
:
4609 case SD_BUS_TYPE_BOOLEAN
:
4610 case SD_BUS_TYPE_INT16
:
4611 case SD_BUS_TYPE_UINT16
:
4612 case SD_BUS_TYPE_INT32
:
4613 case SD_BUS_TYPE_UINT32
:
4614 case SD_BUS_TYPE_INT64
:
4615 case SD_BUS_TYPE_UINT64
:
4616 case SD_BUS_TYPE_DOUBLE
:
4617 case SD_BUS_TYPE_STRING
:
4618 case SD_BUS_TYPE_OBJECT_PATH
:
4619 case SD_BUS_TYPE_SIGNATURE
:
4620 case SD_BUS_TYPE_UNIX_FD
:
4622 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4626 r
= sd_bus_message_skip(m
, types
+ 1);
4632 case SD_BUS_TYPE_ARRAY
: {
4635 r
= signature_element_length(types
+ 1, &k
);
4641 memcpy(s
, types
+1, k
);
4644 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4649 r
= sd_bus_message_skip(m
, s
);
4656 r
= sd_bus_message_exit_container(m
);
4661 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4668 case SD_BUS_TYPE_VARIANT
: {
4669 const char *contents
;
4672 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4676 if (x
!= SD_BUS_TYPE_VARIANT
)
4679 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4683 r
= sd_bus_message_skip(m
, contents
);
4688 r
= sd_bus_message_exit_container(m
);
4692 r
= sd_bus_message_skip(m
, types
+ 1);
4699 case SD_BUS_TYPE_STRUCT_BEGIN
:
4700 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4703 r
= signature_element_length(types
, &k
);
4709 memcpy(s
, types
+1, k
-2);
4712 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4716 r
= sd_bus_message_skip(m
, s
);
4720 r
= sd_bus_message_exit_container(m
);
4725 r
= sd_bus_message_skip(m
, types
+ k
);
4737 _public_
int sd_bus_message_read_array(
4743 struct bus_container
*c
;
4749 assert_return(m
, -EINVAL
);
4750 assert_return(m
->sealed
, -EPERM
);
4751 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4752 assert_return(ptr
, -EINVAL
);
4753 assert_return(size
, -EINVAL
);
4754 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -EOPNOTSUPP
);
4756 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4760 c
= message_get_container(m
);
4762 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4763 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4767 sz
= c
->end
- c
->begin
;
4769 align
= bus_type_get_alignment(type
);
4773 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4777 /* Zero length array, let's return some aligned
4778 * pointer that is not NULL */
4779 p
= (uint8_t*) NULL
+ align
;
4781 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4786 r
= sd_bus_message_exit_container(m
);
4790 *ptr
= (const void*) p
;
4796 message_quit_container(m
);
4800 static int message_peek_fields(
4811 return buffer_peek(BUS_MESSAGE_FIELDS(m
), m
->fields_size
, rindex
, align
, nbytes
, ret
);
4814 static int message_peek_field_uint32(
4826 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4829 /* identical for gvariant and dbus1 */
4831 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4836 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4841 static int message_peek_field_uint64(
4853 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 8)
4856 /* identical for gvariant and dbus1 */
4858 r
= message_peek_fields(m
, ri
, 8, 8, &q
);
4863 *ret
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
4868 static int message_peek_field_string(
4870 bool (*validate
)(const char *p
),
4882 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4887 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4893 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4897 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4903 if (!validate_nul(q
, l
))
4909 if (!validate_string(q
, l
))
4919 static int message_peek_field_signature(
4932 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4937 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4943 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
4948 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4953 if (!validate_signature(q
, l
))
4962 static int message_skip_fields(
4965 uint32_t array_size
,
4966 const char **signature
) {
4968 size_t original_index
;
4974 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
4976 original_index
= *ri
;
4982 if (array_size
!= (uint32_t) -1 &&
4983 array_size
<= *ri
- original_index
)
4990 if (t
== SD_BUS_TYPE_STRING
) {
4992 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
4998 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
5000 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
5006 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
5008 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
5014 } else if (bus_type_is_basic(t
)) {
5017 align
= bus_type_get_alignment(t
);
5018 k
= bus_type_get_size(t
);
5019 assert(align
> 0 && k
> 0);
5021 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
5027 } else if (t
== SD_BUS_TYPE_ARRAY
) {
5029 r
= signature_element_length(*signature
+1, &l
);
5039 strncpy(sig
, *signature
+ 1, l
-1);
5042 alignment
= bus_type_get_alignment(sig
[0]);
5046 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
5049 if (nas
> BUS_ARRAY_MAX_SIZE
)
5052 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
5056 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
5061 (*signature
) += 1 + l
;
5063 } else if (t
== SD_BUS_TYPE_VARIANT
) {
5066 r
= message_peek_field_signature(m
, ri
, 0, &s
);
5070 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5076 } else if (IN_SET(t
, SD_BUS_TYPE_STRUCT
, SD_BUS_TYPE_DICT_ENTRY
)) {
5078 r
= signature_element_length(*signature
, &l
);
5085 strncpy(sig
, *signature
+ 1, l
-1);
5088 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
5099 int bus_message_parse_fields(sd_bus_message
*m
) {
5102 uint32_t unix_fds
= 0;
5103 bool unix_fds_set
= false;
5104 void *offsets
= NULL
;
5105 unsigned n_offsets
= 0;
5111 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5114 /* Read the signature from the end of the body variant first */
5115 sz
= bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m
), 0);
5116 if (m
->footer_accessible
< 1 + sz
)
5119 p
= (char*) m
->footer
+ m
->footer_accessible
- (1 + sz
);
5121 if (p
< (char*) m
->footer
)
5128 /* We found the beginning of the signature
5129 * string, yay! We require the body to be a
5130 * structure, so verify it and then strip the
5131 * opening/closing brackets. */
5133 l
= ((char*) m
->footer
+ m
->footer_accessible
) - p
- (1 + sz
);
5135 p
[1] != SD_BUS_TYPE_STRUCT_BEGIN
||
5136 p
[1 + l
- 1] != SD_BUS_TYPE_STRUCT_END
)
5139 c
= strndup(p
+ 1 + 1, l
- 2);
5143 free(m
->root_container
.signature
);
5144 m
->root_container
.signature
= c
;
5151 /* Calculate the actual user body size, by removing
5152 * the trailing variant signature and struct offset
5154 m
->user_body_size
= m
->body_size
- ((char*) m
->footer
+ m
->footer_accessible
- p
);
5156 /* Pull out the offset table for the fields array */
5157 sz
= bus_gvariant_determine_word_size(m
->fields_size
, 0);
5162 ri
= m
->fields_size
- sz
;
5163 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5167 framing
= bus_gvariant_read_word_le(q
, sz
);
5168 if (framing
>= m
->fields_size
- sz
)
5170 if ((m
->fields_size
- framing
) % sz
!= 0)
5174 r
= message_peek_fields(m
, &ri
, 1, m
->fields_size
- framing
, &offsets
);
5178 n_offsets
= (m
->fields_size
- framing
) / sz
;
5181 m
->user_body_size
= m
->body_size
;
5184 while (ri
< m
->fields_size
) {
5185 _cleanup_free_
char *sig
= NULL
;
5186 const char *signature
;
5187 uint64_t field_type
;
5188 size_t item_size
= (size_t) -1;
5190 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5199 ri
= ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5201 r
= message_peek_fields(m
, &ri
, 8, 8, (void**) &u64
);
5205 field_type
= BUS_MESSAGE_BSWAP64(m
, *u64
);
5209 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &u8
);
5216 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5221 end
= bus_gvariant_read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5226 where
= ri
= ALIGN_TO(ri
, 8);
5227 item_size
= end
- ri
;
5228 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5232 b
= memrchr(q
, 0, item_size
);
5236 sig
= strndup(b
+1, item_size
- (b
+1-(char*) q
));
5241 item_size
= b
- (char*) q
;
5243 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5248 switch (field_type
) {
5250 case _BUS_MESSAGE_HEADER_INVALID
:
5253 case BUS_MESSAGE_HEADER_PATH
:
5258 if (!streq(signature
, "o"))
5261 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5264 case BUS_MESSAGE_HEADER_INTERFACE
:
5269 if (!streq(signature
, "s"))
5272 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5275 case BUS_MESSAGE_HEADER_MEMBER
:
5280 if (!streq(signature
, "s"))
5283 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5286 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5291 if (!streq(signature
, "s"))
5294 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5296 m
->error
._need_free
= -1;
5300 case BUS_MESSAGE_HEADER_DESTINATION
:
5305 if (!streq(signature
, "s"))
5308 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5311 case BUS_MESSAGE_HEADER_SENDER
:
5316 if (!streq(signature
, "s"))
5319 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5321 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
) {
5322 m
->creds
.unique_name
= (char*) m
->sender
;
5323 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5329 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5333 if (BUS_MESSAGE_IS_GVARIANT(m
)) /* only applies to dbus1 */
5336 if (m
->root_container
.signature
)
5339 if (!streq(signature
, "g"))
5342 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5350 free(m
->root_container
.signature
);
5351 m
->root_container
.signature
= c
;
5355 case BUS_MESSAGE_HEADER_REPLY_SERIAL
:
5357 if (m
->reply_cookie
!= 0)
5360 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5361 /* 64bit on dbus2 */
5363 if (!streq(signature
, "t"))
5366 r
= message_peek_field_uint64(m
, &ri
, item_size
, &m
->reply_cookie
);
5370 /* 32bit on dbus1 */
5373 if (!streq(signature
, "u"))
5376 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5380 m
->reply_cookie
= serial
;
5383 if (m
->reply_cookie
== 0)
5388 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5392 if (!streq(signature
, "u"))
5395 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5399 unix_fds_set
= true;
5403 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5404 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5413 if (m
->n_fds
!= unix_fds
)
5416 switch (m
->header
->type
) {
5418 case SD_BUS_MESSAGE_SIGNAL
:
5419 if (!m
->path
|| !m
->interface
|| !m
->member
)
5422 if (m
->reply_cookie
!= 0)
5427 case SD_BUS_MESSAGE_METHOD_CALL
:
5429 if (!m
->path
|| !m
->member
)
5432 if (m
->reply_cookie
!= 0)
5437 case SD_BUS_MESSAGE_METHOD_RETURN
:
5439 if (m
->reply_cookie
== 0)
5443 case SD_BUS_MESSAGE_METHOD_ERROR
:
5445 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5450 /* Refuse non-local messages that claim they are local */
5451 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5453 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5455 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5458 m
->root_container
.end
= m
->user_body_size
;
5460 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5461 r
= build_struct_offsets(
5463 m
->root_container
.signature
,
5465 &m
->root_container
.item_size
,
5466 &m
->root_container
.offsets
,
5467 &m
->root_container
.n_offsets
);
5472 /* Try to read the error message, but if we can't it's a non-issue */
5473 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5474 (void) sd_bus_message_read(m
, "s", &m
->error
.message
);
5479 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5480 assert_return(m
, -EINVAL
);
5481 assert_return(destination
, -EINVAL
);
5482 assert_return(!m
->sealed
, -EPERM
);
5483 assert_return(!m
->destination
, -EEXIST
);
5485 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5488 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5492 struct bus_body_part
*part
;
5498 total
= BUS_MESSAGE_SIZE(m
);
5504 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5505 MESSAGE_FOREACH_PART(part
, i
, m
)
5506 e
= mempcpy(e
, part
->data
, part
->size
);
5508 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5516 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5523 r
= sd_bus_message_enter_container(m
, 'a', "s");
5527 while ((r
= sd_bus_message_read_basic(m
, 's', &s
)) > 0) {
5528 r
= strv_extend(l
, s
);
5535 r
= sd_bus_message_exit_container(m
);
5542 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5546 assert_return(m
, -EINVAL
);
5547 assert_return(m
->sealed
, -EPERM
);
5548 assert_return(l
, -EINVAL
);
5550 r
= bus_message_read_strv_extend(m
, &strv
);
5560 static int bus_message_get_arg_skip(
5564 const char **_contents
) {
5569 r
= sd_bus_message_rewind(m
, true);
5574 const char *contents
;
5577 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5583 /* Don't match against arguments after the first one we don't understand */
5584 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5585 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5590 *_contents
= contents
;
5596 r
= sd_bus_message_skip(m
, NULL
);
5603 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
) {
5610 r
= bus_message_get_arg_skip(m
, i
, &type
, NULL
);
5614 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
))
5617 return sd_bus_message_read_basic(m
, type
, str
);
5620 int bus_message_get_arg_strv(sd_bus_message
*m
, unsigned i
, char ***strv
) {
5621 const char *contents
;
5628 r
= bus_message_get_arg_skip(m
, i
, &type
, &contents
);
5632 if (type
!= SD_BUS_TYPE_ARRAY
)
5634 if (!STR_IN_SET(contents
, "s", "o", "g"))
5637 return sd_bus_message_read_strv(m
, strv
);
5640 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5641 assert_return(m
, EINVAL
);
5643 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5646 return sd_bus_error_get_errno(&m
->error
);
5649 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5650 struct bus_container
*c
;
5652 assert_return(m
, NULL
);
5654 c
= complete
? &m
->root_container
: message_get_container(m
);
5655 return strempty(c
->signature
);
5658 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5659 assert_return(m
, -EINVAL
);
5661 return isempty(m
->root_container
.signature
);
5664 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5665 assert_return(m
, -EINVAL
);
5667 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5670 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5671 bool done_something
= false;
5674 assert_return(m
, -EINVAL
);
5675 assert_return(source
, -EINVAL
);
5676 assert_return(!m
->sealed
, -EPERM
);
5677 assert_return(source
->sealed
, -EPERM
);
5680 const char *contents
;
5695 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5701 done_something
= true;
5703 if (bus_type_is_container(type
) > 0) {
5705 r
= sd_bus_message_enter_container(source
, type
, contents
);
5709 r
= sd_bus_message_open_container(m
, type
, contents
);
5713 r
= sd_bus_message_copy(m
, source
, true);
5717 r
= sd_bus_message_close_container(m
);
5721 r
= sd_bus_message_exit_container(source
);
5728 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5734 if (IN_SET(type
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
, SD_BUS_TYPE_STRING
))
5735 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5737 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5744 return done_something
;
5747 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5752 assert_return(m
, -EINVAL
);
5753 assert_return(m
->sealed
, -EPERM
);
5754 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5755 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5756 assert_return(type
|| contents
, -EINVAL
);
5757 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5759 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5763 if (type
!= 0 && type
!= t
)
5766 if (contents
&& !streq_ptr(contents
, c
))
5772 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5773 assert_return(m
, NULL
);
5778 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5779 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*n
= NULL
;
5787 switch ((*m
)->header
->type
) {
5789 case SD_BUS_MESSAGE_SIGNAL
:
5790 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5796 case SD_BUS_MESSAGE_METHOD_CALL
:
5797 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5803 case SD_BUS_MESSAGE_METHOD_RETURN
:
5804 case SD_BUS_MESSAGE_METHOD_ERROR
:
5806 r
= sd_bus_message_new(bus
, &n
, (*m
)->header
->type
);
5812 n
->reply_cookie
= (*m
)->reply_cookie
;
5814 r
= message_append_reply_cookie(n
, n
->reply_cookie
);
5818 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5819 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5823 n
->error
._need_free
= -1;
5832 if ((*m
)->destination
&& !n
->destination
) {
5833 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5838 if ((*m
)->sender
&& !n
->sender
) {
5839 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5844 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5846 r
= sd_bus_message_copy(n
, *m
, true);
5850 timeout
= (*m
)->timeout
;
5851 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
))
5852 timeout
= BUS_DEFAULT_TIMEOUT
;
5854 r
= sd_bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5858 sd_bus_message_unref(*m
);
5865 int bus_message_append_sender(sd_bus_message
*m
, const char *sender
) {
5869 assert_return(!m
->sealed
, -EPERM
);
5870 assert_return(!m
->sender
, -EPERM
);
5872 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5875 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5876 assert_return(m
, -EINVAL
);
5877 assert_return(priority
, -EINVAL
);
5879 *priority
= m
->priority
;
5883 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5884 assert_return(m
, -EINVAL
);
5885 assert_return(!m
->sealed
, -EPERM
);
5887 m
->priority
= priority
;