1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include "time-util.h"
30 #include "cgroup-util.h"
31 #include "memfd-util.h"
34 #include "bus-message.h"
35 #include "bus-internal.h"
37 #include "bus-signature.h"
38 #include "bus-gvariant.h"
41 static int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
);
43 static void *adjust_pointer(const void *p
, void *old_base
, size_t sz
, void *new_base
) {
48 if (old_base
== new_base
)
51 if ((uint8_t*) p
< (uint8_t*) old_base
)
54 if ((uint8_t*) p
>= (uint8_t*) old_base
+ sz
)
57 return (uint8_t*) new_base
+ ((uint8_t*) p
- (uint8_t*) old_base
);
60 static void message_free_part(sd_bus_message
*m
, struct bus_body_part
*part
) {
64 if (part
->memfd
>= 0) {
65 /* If we can reuse the memfd, try that. For that it
66 * can't be sealed yet. */
69 assert(part
->memfd_offset
== 0);
70 assert(part
->data
== part
->mmap_begin
);
71 bus_kernel_push_memfd(m
->bus
, part
->memfd
, part
->data
, part
->mapped
, part
->allocated
);
74 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
76 safe_close(part
->memfd
);
79 } else if (part
->munmap_this
)
80 munmap(part
->mmap_begin
, part
->mapped
);
81 else if (part
->free_this
)
88 static void message_reset_parts(sd_bus_message
*m
) {
89 struct bus_body_part
*part
;
94 while (m
->n_body_parts
> 0) {
95 struct bus_body_part
*next
= part
->next
;
96 message_free_part(m
, part
);
103 m
->cached_rindex_part
= NULL
;
104 m
->cached_rindex_part_begin
= 0;
107 static void message_reset_containers(sd_bus_message
*m
) {
112 for (i
= 0; i
< m
->n_containers
; i
++) {
113 free(m
->containers
[i
].signature
);
114 free(m
->containers
[i
].offsets
);
118 m
->containers
= NULL
;
120 m
->n_containers
= m
->containers_allocated
= 0;
121 m
->root_container
.index
= 0;
124 static void message_free(sd_bus_message
*m
) {
130 message_reset_parts(m
);
132 if (m
->release_kdbus
)
133 bus_kernel_cmd_free(m
->bus
, (uint8_t *) m
->kdbus
- (uint8_t *) m
->bus
->kdbus_buffer
);
138 sd_bus_unref(m
->bus
);
141 close_many(m
->fds
, m
->n_fds
);
145 if (m
->iovec
!= m
->iovec_fixed
)
148 if (m
->destination_ptr
) {
149 free(m
->destination_ptr
);
150 m
->destination_ptr
= NULL
;
153 message_reset_containers(m
);
154 free(m
->root_container
.signature
);
155 free(m
->root_container
.offsets
);
157 free(m
->root_container
.peeked_signature
);
159 bus_creds_done(&m
->creds
);
163 static void *message_extend_fields(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
165 size_t old_size
, new_size
, start
;
172 old_size
= sizeof(struct bus_header
) + m
->header
->fields_size
;
173 start
= ALIGN_TO(old_size
, align
);
174 new_size
= start
+ sz
;
176 if (old_size
== new_size
)
177 return (uint8_t*) m
->header
+ old_size
;
179 if (new_size
> (size_t) ((uint32_t) -1))
182 if (m
->free_header
) {
183 np
= realloc(m
->header
, ALIGN8(new_size
));
187 /* Initially, the header is allocated as part of of
188 * the sd_bus_message itself, let's replace it by
191 np
= malloc(ALIGN8(new_size
));
195 memcpy(np
, m
->header
, sizeof(struct bus_header
));
198 /* Zero out padding */
199 if (start
> old_size
)
200 memzero((uint8_t*) np
+ old_size
, start
- old_size
);
204 m
->header
->fields_size
= new_size
- sizeof(struct bus_header
);
206 /* Adjust quick access pointers */
207 m
->path
= adjust_pointer(m
->path
, op
, old_size
, m
->header
);
208 m
->interface
= adjust_pointer(m
->interface
, op
, old_size
, m
->header
);
209 m
->member
= adjust_pointer(m
->member
, op
, old_size
, m
->header
);
210 m
->destination
= adjust_pointer(m
->destination
, op
, old_size
, m
->header
);
211 m
->sender
= adjust_pointer(m
->sender
, op
, old_size
, m
->header
);
212 m
->error
.name
= adjust_pointer(m
->error
.name
, op
, old_size
, m
->header
);
214 m
->free_header
= true;
217 if (m
->n_header_offsets
>= ELEMENTSOF(m
->header_offsets
))
220 m
->header_offsets
[m
->n_header_offsets
++] = new_size
- sizeof(struct bus_header
);
223 return (uint8_t*) np
+ start
;
230 static int message_append_field_string(
242 /* dbus1 doesn't allow strings over 32bit, let's enforce this
243 * globally, to not risk convertability */
245 if (l
> (size_t) (uint32_t) -1)
248 /* Signature "(yv)" where the variant contains "s" */
250 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
252 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
253 p
= message_extend_fields(m
, 8, 1 + 7 + l
+ 1 + 1 + 1, true);
265 *ret
= (char*) p
+ 8;
268 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
269 p
= message_extend_fields(m
, 8, 4 + 4 + l
+ 1, false);
278 ((uint32_t*) p
)[1] = l
;
279 memcpy(p
+ 8, s
, l
+ 1);
282 *ret
= (char*) p
+ 8;
288 static int message_append_field_signature(
299 /* dbus1 doesn't allow signatures over 32bit, let's enforce
300 * this globally, to not risk convertability */
305 /* Signature "(yv)" where the variant contains "g" */
307 if (BUS_MESSAGE_IS_GVARIANT(m
))
308 /* For gvariant the serialization is the same as for normal strings */
309 return message_append_field_string(m
, h
, 'g', s
, ret
);
311 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
312 p
= message_extend_fields(m
, 8, 4 + 1 + l
+ 1, false);
318 p
[2] = SD_BUS_TYPE_SIGNATURE
;
321 memcpy(p
+ 5, s
, l
+ 1);
324 *ret
= (const char*) p
+ 5;
330 static int message_append_field_uint32(sd_bus_message
*m
, uint8_t h
, uint32_t x
) {
335 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
336 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
338 p
= message_extend_fields(m
, 8, 1 + 7 + 4 + 1 + 1, true);
344 *((uint32_t*) (p
+ 8)) = x
;
348 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
349 p
= message_extend_fields(m
, 8, 4 + 4, false);
355 p
[2] = SD_BUS_TYPE_UINT32
;
358 ((uint32_t*) p
)[1] = x
;
364 int bus_message_from_header(
370 const struct ucred
*ucred
,
373 sd_bus_message
**ret
) {
376 struct bus_header
*h
;
380 assert(buffer
|| length
<= 0);
381 assert(fds
|| n_fds
<= 0);
384 if (length
< sizeof(struct bus_header
))
388 if (h
->version
!= 1 &&
395 if (h
->type
== _SD_BUS_MESSAGE_TYPE_INVALID
)
398 if (h
->endian
!= BUS_LITTLE_ENDIAN
&&
399 h
->endian
!= BUS_BIG_ENDIAN
)
402 a
= ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
405 label_sz
= strlen(label
);
420 m
->creds
.pid
= ucred
->pid
;
421 m
->creds
.euid
= ucred
->uid
;
422 m
->creds
.egid
= ucred
->gid
;
424 /* Due to namespace translations some data might be
425 * missing from this ucred record. */
426 if (m
->creds
.pid
> 0)
427 m
->creds
.mask
|= SD_BUS_CREDS_PID
;
429 if (m
->creds
.euid
!= UID_INVALID
)
430 m
->creds
.mask
|= SD_BUS_CREDS_EUID
;
432 if (m
->creds
.egid
!= GID_INVALID
)
433 m
->creds
.mask
|= SD_BUS_CREDS_EGID
;
437 m
->creds
.label
= (char*) m
+ ALIGN(sizeof(sd_bus_message
)) + ALIGN(extra
);
438 memcpy(m
->creds
.label
, label
, label_sz
+ 1);
440 m
->creds
.mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
443 m
->bus
= sd_bus_ref(bus
);
449 int bus_message_from_malloc(
455 const struct ucred
*ucred
,
457 sd_bus_message
**ret
) {
463 r
= bus_message_from_header(bus
, buffer
, length
, fds
, n_fds
, ucred
, label
, 0, &m
);
467 if (length
!= BUS_MESSAGE_SIZE(m
)) {
472 sz
= length
- sizeof(struct bus_header
) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m
));
475 m
->body
.data
= (uint8_t*) buffer
+ sizeof(struct bus_header
) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m
));
477 m
->body
.sealed
= true;
482 m
->iovec
= m
->iovec_fixed
;
483 m
->iovec
[0].iov_base
= buffer
;
484 m
->iovec
[0].iov_len
= length
;
486 r
= bus_message_parse_fields(m
);
490 /* We take possession of the memory and fds now */
491 m
->free_header
= true;
502 static sd_bus_message
*message_new(sd_bus
*bus
, uint8_t type
) {
507 m
= malloc0(ALIGN(sizeof(sd_bus_message
)) + sizeof(struct bus_header
));
512 m
->header
= (struct bus_header
*) ((uint8_t*) m
+ ALIGN(sizeof(struct sd_bus_message
)));
513 m
->header
->endian
= BUS_NATIVE_ENDIAN
;
514 m
->header
->type
= type
;
515 m
->header
->version
= bus
? bus
->message_version
: 1;
516 m
->allow_fds
= !bus
|| bus
->can_fds
|| (bus
->state
!= BUS_HELLO
&& bus
->state
!= BUS_RUNNING
);
517 m
->root_container
.need_offsets
= BUS_MESSAGE_IS_GVARIANT(m
);
518 m
->bus
= sd_bus_ref(bus
);
523 _public_
int sd_bus_message_new_signal(
527 const char *interface
,
528 const char *member
) {
533 assert_return(bus
, -ENOTCONN
);
534 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
535 assert_return(object_path_is_valid(path
), -EINVAL
);
536 assert_return(interface_name_is_valid(interface
), -EINVAL
);
537 assert_return(member_name_is_valid(member
), -EINVAL
);
538 assert_return(m
, -EINVAL
);
540 t
= message_new(bus
, SD_BUS_MESSAGE_SIGNAL
);
544 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
546 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
549 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
552 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
560 sd_bus_message_unref(t
);
564 _public_
int sd_bus_message_new_method_call(
567 const char *destination
,
569 const char *interface
,
570 const char *member
) {
575 assert_return(bus
, -ENOTCONN
);
576 assert_return(bus
->state
!= BUS_UNSET
, -ENOTCONN
);
577 assert_return(!destination
|| service_name_is_valid(destination
), -EINVAL
);
578 assert_return(object_path_is_valid(path
), -EINVAL
);
579 assert_return(!interface
|| interface_name_is_valid(interface
), -EINVAL
);
580 assert_return(member_name_is_valid(member
), -EINVAL
);
581 assert_return(m
, -EINVAL
);
583 t
= message_new(bus
, SD_BUS_MESSAGE_METHOD_CALL
);
587 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_PATH
, SD_BUS_TYPE_OBJECT_PATH
, path
, &t
->path
);
590 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_MEMBER
, SD_BUS_TYPE_STRING
, member
, &t
->member
);
595 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_INTERFACE
, SD_BUS_TYPE_STRING
, interface
, &t
->interface
);
601 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &t
->destination
);
614 static int message_new_reply(
615 sd_bus_message
*call
,
617 sd_bus_message
**m
) {
622 assert_return(call
, -EINVAL
);
623 assert_return(call
->sealed
, -EPERM
);
624 assert_return(call
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EINVAL
);
625 assert_return(call
->bus
->state
!= BUS_UNSET
, -ENOTCONN
);
626 assert_return(m
, -EINVAL
);
628 t
= message_new(call
->bus
, type
);
632 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
633 t
->reply_cookie
= BUS_MESSAGE_COOKIE(call
);
635 r
= message_append_field_uint32(t
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) t
->reply_cookie
);
640 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, call
->sender
, &t
->destination
);
645 t
->dont_send
= !!(call
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
646 t
->enforced_reply_signature
= call
->enforced_reply_signature
;
656 _public_
int sd_bus_message_new_method_return(
657 sd_bus_message
*call
,
658 sd_bus_message
**m
) {
660 return message_new_reply(call
, SD_BUS_MESSAGE_METHOD_RETURN
, m
);
663 _public_
int sd_bus_message_new_method_error(
664 sd_bus_message
*call
,
666 const sd_bus_error
*e
) {
671 assert_return(sd_bus_error_is_set(e
), -EINVAL
);
672 assert_return(m
, -EINVAL
);
674 r
= message_new_reply(call
, SD_BUS_MESSAGE_METHOD_ERROR
, &t
);
678 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
683 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
688 t
->error
._need_free
= -1;
698 _public_
int sd_bus_message_new_method_errorf(
699 sd_bus_message
*call
,
705 _cleanup_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
708 assert_return(name
, -EINVAL
);
709 assert_return(m
, -EINVAL
);
711 va_start(ap
, format
);
712 bus_error_setfv(&error
, name
, format
, ap
);
715 return sd_bus_message_new_method_error(call
, m
, &error
);
718 _public_
int sd_bus_message_new_method_errno(
719 sd_bus_message
*call
,
722 const sd_bus_error
*p
) {
724 _cleanup_free_ sd_bus_error berror
= SD_BUS_ERROR_NULL
;
726 if (sd_bus_error_is_set(p
))
727 return sd_bus_message_new_method_error(call
, m
, p
);
729 sd_bus_error_set_errno(&berror
, error
);
731 return sd_bus_message_new_method_error(call
, m
, &berror
);
734 _public_
int sd_bus_message_new_method_errnof(
735 sd_bus_message
*call
,
741 _cleanup_free_ sd_bus_error berror
= SD_BUS_ERROR_NULL
;
744 va_start(ap
, format
);
745 sd_bus_error_set_errnofv(&berror
, error
, format
, ap
);
748 return sd_bus_message_new_method_error(call
, m
, &berror
);
751 void bus_message_set_sender_local(sd_bus
*bus
, sd_bus_message
*m
) {
755 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus.Local";
756 m
->creds
.well_known_names_local
= true;
757 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
760 void bus_message_set_sender_driver(sd_bus
*bus
, sd_bus_message
*m
) {
764 m
->sender
= m
->creds
.unique_name
= (char*) "org.freedesktop.DBus";
765 m
->creds
.well_known_names_driver
= true;
766 m
->creds
.mask
|= (SD_BUS_CREDS_UNIQUE_NAME
|SD_BUS_CREDS_WELL_KNOWN_NAMES
) & bus
->creds_mask
;
769 int bus_message_new_synthetic_error(
772 const sd_bus_error
*e
,
773 sd_bus_message
**m
) {
779 assert(sd_bus_error_is_set(e
));
782 t
= message_new(bus
, SD_BUS_MESSAGE_METHOD_ERROR
);
786 t
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
787 t
->reply_cookie
= cookie
;
789 r
= message_append_field_uint32(t
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) t
->reply_cookie
);
793 if (bus
&& bus
->unique_name
) {
794 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, bus
->unique_name
, &t
->destination
);
799 r
= message_append_field_string(t
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, e
->name
, &t
->error
.name
);
804 r
= message_append_basic(t
, SD_BUS_TYPE_STRING
, e
->message
, (const void**) &t
->error
.message
);
809 t
->error
._need_free
= -1;
811 bus_message_set_sender_driver(bus
, t
);
821 _public_ sd_bus_message
* sd_bus_message_ref(sd_bus_message
*m
) {
822 assert_return(m
, NULL
);
824 assert(m
->n_ref
> 0);
830 _public_ sd_bus_message
* sd_bus_message_unref(sd_bus_message
*m
) {
835 assert(m
->n_ref
> 0);
845 _public_
int sd_bus_message_get_type(sd_bus_message
*m
, uint8_t *type
) {
846 assert_return(m
, -EINVAL
);
847 assert_return(type
, -EINVAL
);
849 *type
= m
->header
->type
;
853 _public_
int sd_bus_message_get_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
854 assert_return(m
, -EINVAL
);
855 assert_return(cookie
, -EINVAL
);
856 assert_return(m
->header
->serial
!= 0, -ENODATA
);
858 *cookie
= BUS_MESSAGE_COOKIE(m
);
862 _public_
int sd_bus_message_get_reply_cookie(sd_bus_message
*m
, uint64_t *cookie
) {
863 assert_return(m
, -EINVAL
);
864 assert_return(cookie
, -EINVAL
);
865 assert_return(m
->reply_cookie
!= 0, -ENODATA
);
867 *cookie
= m
->reply_cookie
;
871 _public_
int sd_bus_message_get_expect_reply(sd_bus_message
*m
) {
872 assert_return(m
, -EINVAL
);
874 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
875 !(m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
);
878 _public_
int sd_bus_message_get_auto_start(sd_bus_message
*m
) {
879 assert_return(m
, -EINVAL
);
881 return !(m
->header
->flags
& BUS_MESSAGE_NO_AUTO_START
);
884 _public_
int sd_bus_message_get_allow_interactive_authorization(sd_bus_message
*m
) {
885 assert_return(m
, -EINVAL
);
887 return m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
&&
888 (m
->header
->flags
& BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
);
891 _public_
const char *sd_bus_message_get_path(sd_bus_message
*m
) {
892 assert_return(m
, NULL
);
897 _public_
const char *sd_bus_message_get_interface(sd_bus_message
*m
) {
898 assert_return(m
, NULL
);
903 _public_
const char *sd_bus_message_get_member(sd_bus_message
*m
) {
904 assert_return(m
, NULL
);
909 _public_
const char *sd_bus_message_get_destination(sd_bus_message
*m
) {
910 assert_return(m
, NULL
);
912 return m
->destination
;
915 _public_
const char *sd_bus_message_get_sender(sd_bus_message
*m
) {
916 assert_return(m
, NULL
);
921 _public_
const sd_bus_error
*sd_bus_message_get_error(sd_bus_message
*m
) {
922 assert_return(m
, NULL
);
923 assert_return(sd_bus_error_is_set(&m
->error
), NULL
);
928 _public_
int sd_bus_message_get_monotonic_usec(sd_bus_message
*m
, uint64_t *usec
) {
929 assert_return(m
, -EINVAL
);
930 assert_return(usec
, -EINVAL
);
932 if (m
->monotonic
<= 0)
935 *usec
= m
->monotonic
;
939 _public_
int sd_bus_message_get_realtime_usec(sd_bus_message
*m
, uint64_t *usec
) {
940 assert_return(m
, -EINVAL
);
941 assert_return(usec
, -EINVAL
);
943 if (m
->realtime
<= 0)
950 _public_
int sd_bus_message_get_seqnum(sd_bus_message
*m
, uint64_t *seqnum
) {
951 assert_return(m
, -EINVAL
);
952 assert_return(seqnum
, -EINVAL
);
961 _public_ sd_bus_creds
*sd_bus_message_get_creds(sd_bus_message
*m
) {
962 assert_return(m
, NULL
);
964 if (m
->creds
.mask
== 0)
970 _public_
int sd_bus_message_is_signal(sd_bus_message
*m
,
971 const char *interface
,
972 const char *member
) {
973 assert_return(m
, -EINVAL
);
975 if (m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
)
978 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
981 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
987 _public_
int sd_bus_message_is_method_call(sd_bus_message
*m
,
988 const char *interface
,
989 const char *member
) {
990 assert_return(m
, -EINVAL
);
992 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_CALL
)
995 if (interface
&& (!m
->interface
|| !streq(m
->interface
, interface
)))
998 if (member
&& (!m
->member
|| !streq(m
->member
, member
)))
1004 _public_
int sd_bus_message_is_method_error(sd_bus_message
*m
, const char *name
) {
1005 assert_return(m
, -EINVAL
);
1007 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
1010 if (name
&& (!m
->error
.name
|| !streq(m
->error
.name
, name
)))
1016 _public_
int sd_bus_message_set_expect_reply(sd_bus_message
*m
, int b
) {
1017 assert_return(m
, -EINVAL
);
1018 assert_return(!m
->sealed
, -EPERM
);
1019 assert_return(m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
, -EPERM
);
1022 m
->header
->flags
&= ~BUS_MESSAGE_NO_REPLY_EXPECTED
;
1024 m
->header
->flags
|= BUS_MESSAGE_NO_REPLY_EXPECTED
;
1029 _public_
int sd_bus_message_set_auto_start(sd_bus_message
*m
, int b
) {
1030 assert_return(m
, -EINVAL
);
1031 assert_return(!m
->sealed
, -EPERM
);
1034 m
->header
->flags
&= ~BUS_MESSAGE_NO_AUTO_START
;
1036 m
->header
->flags
|= BUS_MESSAGE_NO_AUTO_START
;
1041 _public_
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message
*m
, int b
) {
1042 assert_return(m
, -EINVAL
);
1043 assert_return(!m
->sealed
, -EPERM
);
1046 m
->header
->flags
|= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
1048 m
->header
->flags
&= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION
;
1053 static struct bus_container
*message_get_container(sd_bus_message
*m
) {
1056 if (m
->n_containers
== 0)
1057 return &m
->root_container
;
1059 assert(m
->containers
);
1060 return m
->containers
+ m
->n_containers
- 1;
1063 struct bus_body_part
*message_append_part(sd_bus_message
*m
) {
1064 struct bus_body_part
*part
;
1071 if (m
->n_body_parts
<= 0) {
1075 assert(m
->body_end
);
1077 part
= new0(struct bus_body_part
, 1);
1083 m
->body_end
->next
= part
;
1093 static void part_zero(struct bus_body_part
*part
, size_t sz
) {
1098 /* All other fields can be left in their defaults */
1099 assert(!part
->data
);
1100 assert(part
->memfd
< 0);
1103 part
->is_zero
= true;
1104 part
->sealed
= true;
1107 static int part_make_space(
1108 struct sd_bus_message
*m
,
1109 struct bus_body_part
*part
,
1118 assert(!part
->sealed
);
1123 if (!part
->data
&& part
->memfd
< 0) {
1124 part
->memfd
= bus_kernel_pop_memfd(m
->bus
, &part
->data
, &part
->mapped
, &part
->allocated
);
1125 part
->mmap_begin
= part
->data
;
1128 if (part
->memfd
>= 0) {
1130 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1131 uint64_t new_allocated
;
1133 new_allocated
= PAGE_ALIGN(sz
> 0 ? 2 * sz
: 1);
1134 r
= memfd_set_size(part
->memfd
, new_allocated
);
1140 part
->allocated
= new_allocated
;
1143 if (!part
->data
|| sz
> part
->mapped
) {
1146 psz
= PAGE_ALIGN(sz
> 0 ? sz
: 1);
1147 if (part
->mapped
<= 0)
1148 n
= mmap(NULL
, psz
, PROT_READ
|PROT_WRITE
, MAP_SHARED
, part
->memfd
, 0);
1150 n
= mremap(part
->mmap_begin
, part
->mapped
, psz
, MREMAP_MAYMOVE
);
1152 if (n
== MAP_FAILED
) {
1157 part
->mmap_begin
= part
->data
= n
;
1159 part
->memfd_offset
= 0;
1162 part
->munmap_this
= true;
1164 if (part
->allocated
== 0 || sz
> part
->allocated
) {
1165 size_t new_allocated
;
1167 new_allocated
= sz
> 0 ? 2 * sz
: 64;
1168 n
= realloc(part
->data
, new_allocated
);
1175 part
->allocated
= new_allocated
;
1176 part
->free_this
= true;
1181 *q
= part
->data
? (uint8_t*) part
->data
+ part
->size
: NULL
;
1187 static int message_add_offset(sd_bus_message
*m
, size_t offset
) {
1188 struct bus_container
*c
;
1191 assert(BUS_MESSAGE_IS_GVARIANT(m
));
1193 /* Add offset to current container, unless this is the first
1194 * item in it, which will have the 0 offset, which we can
1196 c
= message_get_container(m
);
1198 if (!c
->need_offsets
)
1201 if (!GREEDY_REALLOC(c
->offsets
, c
->offsets_allocated
, c
->n_offsets
+ 1))
1204 c
->offsets
[c
->n_offsets
++] = offset
;
1208 static void message_extend_containers(sd_bus_message
*m
, size_t expand
) {
1209 struct bus_container
*c
;
1216 /* Update counters */
1217 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++) {
1220 *c
->array_size
+= expand
;
1224 static void *message_extend_body(sd_bus_message
*m
, size_t align
, size_t sz
, bool add_offset
) {
1225 size_t start_body
, end_body
, padding
, added
;
1236 start_body
= ALIGN_TO((size_t) m
->header
->body_size
, align
);
1237 end_body
= start_body
+ sz
;
1239 padding
= start_body
- m
->header
->body_size
;
1240 added
= padding
+ sz
;
1242 /* Check for 32bit overflows */
1243 if (end_body
> (size_t) ((uint32_t) -1)) {
1249 struct bus_body_part
*part
= NULL
;
1253 m
->n_body_parts
<= 0 ||
1254 m
->body_end
->sealed
||
1255 padding
!= ALIGN_TO(m
->body_end
->size
, align
) - m
->body_end
->size
;
1259 part
= message_append_part(m
);
1263 part_zero(part
, padding
);
1266 part
= message_append_part(m
);
1270 r
= part_make_space(m
, part
, sz
, &p
);
1274 struct bus_container
*c
;
1276 size_t os
, start_part
, end_part
;
1282 start_part
= ALIGN_TO(part
->size
, align
);
1283 end_part
= start_part
+ sz
;
1285 r
= part_make_space(m
, part
, end_part
, &p
);
1290 memzero(p
, padding
);
1291 p
= (uint8_t*) p
+ padding
;
1294 /* Readjust pointers */
1295 for (c
= m
->containers
; c
< m
->containers
+ m
->n_containers
; c
++)
1296 c
->array_size
= adjust_pointer(c
->array_size
, op
, os
, part
->data
);
1298 m
->error
.message
= (const char*) adjust_pointer(m
->error
.message
, op
, os
, part
->data
);
1301 /* Return something that is not NULL and is aligned */
1302 p
= (uint8_t *) NULL
+ align
;
1304 m
->header
->body_size
= end_body
;
1305 message_extend_containers(m
, added
);
1308 r
= message_add_offset(m
, end_body
);
1318 static int message_push_fd(sd_bus_message
*m
, int fd
) {
1329 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
1333 f
= realloc(m
->fds
, sizeof(int) * (m
->n_fds
+ 1));
1341 m
->fds
[m
->n_fds
] = copy
;
1347 int message_append_basic(sd_bus_message
*m
, char type
, const void *p
, const void **stored
) {
1348 _cleanup_close_
int fd
= -1;
1349 struct bus_container
*c
;
1353 assert_return(m
, -EINVAL
);
1354 assert_return(!m
->sealed
, -EPERM
);
1355 assert_return(bus_type_is_basic(type
), -EINVAL
);
1356 assert_return(!m
->poisoned
, -ESTALE
);
1358 c
= message_get_container(m
);
1360 if (c
->signature
&& c
->signature
[c
->index
]) {
1361 /* Container signature is already set */
1363 if (c
->signature
[c
->index
] != type
)
1368 /* Maybe we can append to the signature? But only if this is the top-level container */
1369 if (c
->enclosing
!= 0)
1372 e
= strextend(&c
->signature
, CHAR_TO_STR(type
), NULL
);
1379 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1385 case SD_BUS_TYPE_SIGNATURE
:
1386 case SD_BUS_TYPE_STRING
:
1389 /* Fall through... */
1390 case SD_BUS_TYPE_OBJECT_PATH
:
1398 case SD_BUS_TYPE_BOOLEAN
:
1400 u8
= p
&& *(int*) p
;
1406 case SD_BUS_TYPE_UNIX_FD
:
1411 fd
= message_push_fd(m
, *(int*) p
);
1422 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
1423 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
1430 a
= message_extend_body(m
, align
, sz
, true);
1437 *stored
= (const uint8_t*) a
;
1444 case SD_BUS_TYPE_STRING
:
1445 /* To make things easy we'll serialize a NULL string
1446 * into the empty string */
1449 /* Fall through... */
1450 case SD_BUS_TYPE_OBJECT_PATH
:
1456 sz
= 4 + strlen(p
) + 1;
1459 case SD_BUS_TYPE_SIGNATURE
:
1464 sz
= 1 + strlen(p
) + 1;
1467 case SD_BUS_TYPE_BOOLEAN
:
1469 u32
= p
&& *(int*) p
;
1475 case SD_BUS_TYPE_UNIX_FD
:
1480 fd
= message_push_fd(m
, *(int*) p
);
1491 align
= bus_type_get_alignment(type
);
1492 sz
= bus_type_get_size(type
);
1499 a
= message_extend_body(m
, align
, sz
, false);
1503 if (type
== SD_BUS_TYPE_STRING
|| type
== SD_BUS_TYPE_OBJECT_PATH
) {
1504 *(uint32_t*) a
= sz
- 5;
1505 memcpy((uint8_t*) a
+ 4, p
, sz
- 4);
1508 *stored
= (const uint8_t*) a
+ 4;
1510 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
1511 *(uint8_t*) a
= sz
- 2;
1512 memcpy((uint8_t*) a
+ 1, p
, sz
- 1);
1515 *stored
= (const uint8_t*) a
+ 1;
1524 if (type
== SD_BUS_TYPE_UNIX_FD
)
1527 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1534 _public_
int sd_bus_message_append_basic(sd_bus_message
*m
, char type
, const void *p
) {
1535 return message_append_basic(m
, type
, p
, NULL
);
1538 _public_
int sd_bus_message_append_string_space(
1543 struct bus_container
*c
;
1546 assert_return(m
, -EINVAL
);
1547 assert_return(s
, -EINVAL
);
1548 assert_return(!m
->sealed
, -EPERM
);
1549 assert_return(!m
->poisoned
, -ESTALE
);
1551 c
= message_get_container(m
);
1553 if (c
->signature
&& c
->signature
[c
->index
]) {
1554 /* Container signature is already set */
1556 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
1561 /* Maybe we can append to the signature? But only if this is the top-level container */
1562 if (c
->enclosing
!= 0)
1565 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
1572 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1573 a
= message_extend_body(m
, 1, size
+ 1, true);
1579 a
= message_extend_body(m
, 4, 4 + size
+ 1, false);
1583 *(uint32_t*) a
= size
;
1589 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1595 _public_
int sd_bus_message_append_string_iovec(
1597 const struct iovec
*iov
,
1605 assert_return(m
, -EINVAL
);
1606 assert_return(!m
->sealed
, -EPERM
);
1607 assert_return(iov
|| n
== 0, -EINVAL
);
1608 assert_return(!m
->poisoned
, -ESTALE
);
1610 size
= IOVEC_TOTAL_SIZE(iov
, n
);
1612 r
= sd_bus_message_append_string_space(m
, size
, &p
);
1616 for (i
= 0; i
< n
; i
++) {
1618 if (iov
[i
].iov_base
)
1619 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1621 memset(p
, ' ', iov
[i
].iov_len
);
1623 p
+= iov
[i
].iov_len
;
1629 static int bus_message_open_array(
1631 struct bus_container
*c
,
1632 const char *contents
,
1633 uint32_t **array_size
,
1635 bool *need_offsets
) {
1645 assert(need_offsets
);
1647 if (!signature_is_single(contents
, true))
1650 if (c
->signature
&& c
->signature
[c
->index
]) {
1652 /* Verify the existing signature */
1654 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
1657 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
1660 nindex
= c
->index
+ 1 + strlen(contents
);
1664 if (c
->enclosing
!= 0)
1667 /* Extend the existing signature */
1669 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_ARRAY
), contents
, NULL
);
1675 nindex
= e
- c
->signature
;
1678 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1679 alignment
= bus_gvariant_get_alignment(contents
);
1683 /* Add alignment padding and add to offset list */
1684 if (!message_extend_body(m
, alignment
, 0, false))
1687 r
= bus_gvariant_is_fixed_size(contents
);
1691 *begin
= m
->header
->body_size
;
1692 *need_offsets
= r
== 0;
1696 struct bus_body_part
*o
;
1698 alignment
= bus_type_get_alignment(contents
[0]);
1702 a
= message_extend_body(m
, 4, 4, false);
1707 op
= m
->body_end
->data
;
1708 os
= m
->body_end
->size
;
1710 /* Add alignment between size and first element */
1711 if (!message_extend_body(m
, alignment
, 0, false))
1714 /* location of array size might have changed so let's readjust a */
1715 if (o
== m
->body_end
)
1716 a
= adjust_pointer(a
, op
, os
, m
->body_end
->data
);
1722 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1728 static int bus_message_open_variant(
1730 struct bus_container
*c
,
1731 const char *contents
) {
1737 if (!signature_is_single(contents
, false))
1740 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
1743 if (c
->signature
&& c
->signature
[c
->index
]) {
1745 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
1751 if (c
->enclosing
!= 0)
1754 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_VARIANT
), NULL
);
1761 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1762 /* Variants are always aligned to 8 */
1764 if (!message_extend_body(m
, 8, 0, false))
1771 l
= strlen(contents
);
1772 a
= message_extend_body(m
, 1, 1 + l
+ 1, false);
1777 memcpy((uint8_t*) a
+ 1, contents
, l
+ 1);
1780 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1786 static int bus_message_open_struct(
1788 struct bus_container
*c
,
1789 const char *contents
,
1791 bool *need_offsets
) {
1800 assert(need_offsets
);
1802 if (!signature_is_valid(contents
, false))
1805 if (c
->signature
&& c
->signature
[c
->index
]) {
1808 l
= strlen(contents
);
1810 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
1811 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1812 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
1815 nindex
= c
->index
+ 1 + l
+ 1;
1819 if (c
->enclosing
!= 0)
1822 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN
), contents
, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END
), NULL
);
1828 nindex
= e
- c
->signature
;
1831 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1834 alignment
= bus_gvariant_get_alignment(contents
);
1838 if (!message_extend_body(m
, alignment
, 0, false))
1841 r
= bus_gvariant_is_fixed_size(contents
);
1845 *begin
= m
->header
->body_size
;
1846 *need_offsets
= r
== 0;
1848 /* Align contents to 8 byte boundary */
1849 if (!message_extend_body(m
, 8, 0, false))
1853 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1859 static int bus_message_open_dict_entry(
1861 struct bus_container
*c
,
1862 const char *contents
,
1864 bool *need_offsets
) {
1872 assert(need_offsets
);
1874 if (!signature_is_pair(contents
))
1877 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
1880 if (c
->signature
&& c
->signature
[c
->index
]) {
1883 l
= strlen(contents
);
1885 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
1886 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
1887 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
1892 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
1895 alignment
= bus_gvariant_get_alignment(contents
);
1899 if (!message_extend_body(m
, alignment
, 0, false))
1902 r
= bus_gvariant_is_fixed_size(contents
);
1906 *begin
= m
->header
->body_size
;
1907 *need_offsets
= r
== 0;
1909 /* Align contents to 8 byte boundary */
1910 if (!message_extend_body(m
, 8, 0, false))
1917 _public_
int sd_bus_message_open_container(
1920 const char *contents
) {
1922 struct bus_container
*c
, *w
;
1923 uint32_t *array_size
= NULL
;
1925 size_t before
, begin
= 0;
1926 bool need_offsets
= false;
1929 assert_return(m
, -EINVAL
);
1930 assert_return(!m
->sealed
, -EPERM
);
1931 assert_return(contents
, -EINVAL
);
1932 assert_return(!m
->poisoned
, -ESTALE
);
1934 /* Make sure we have space for one more container */
1935 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1)) {
1940 c
= message_get_container(m
);
1942 signature
= strdup(contents
);
1948 /* Save old index in the parent container, in case we have to
1949 * abort this container */
1950 c
->saved_index
= c
->index
;
1951 before
= m
->header
->body_size
;
1953 if (type
== SD_BUS_TYPE_ARRAY
)
1954 r
= bus_message_open_array(m
, c
, contents
, &array_size
, &begin
, &need_offsets
);
1955 else if (type
== SD_BUS_TYPE_VARIANT
)
1956 r
= bus_message_open_variant(m
, c
, contents
);
1957 else if (type
== SD_BUS_TYPE_STRUCT
)
1958 r
= bus_message_open_struct(m
, c
, contents
, &begin
, &need_offsets
);
1959 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
1960 r
= bus_message_open_dict_entry(m
, c
, contents
, &begin
, &need_offsets
);
1969 /* OK, let's fill it in */
1970 w
= m
->containers
+ m
->n_containers
++;
1971 w
->enclosing
= type
;
1972 w
->signature
= signature
;
1974 w
->array_size
= array_size
;
1977 w
->n_offsets
= w
->offsets_allocated
= 0;
1979 w
->need_offsets
= need_offsets
;
1984 static size_t determine_word_size(size_t sz
, size_t extra
) {
1985 if (sz
+ extra
<= 0xFF)
1987 else if (sz
+ extra
*2 <= 0xFFFF)
1989 else if (sz
+ extra
*4 <= 0xFFFFFFFF)
1995 static size_t read_word_le(void *p
, size_t sz
) {
2005 return *(uint8_t*) p
;
2010 return le16toh(x
.u16
);
2012 return le32toh(x
.u32
);
2014 return le64toh(x
.u64
);
2016 assert_not_reached("unknown word width");
2019 static void write_word_le(void *p
, size_t sz
, size_t value
) {
2027 assert(sz
== 8 || (value
< (1ULL << (sz
*8))));
2030 *(uint8_t*) p
= value
;
2033 x
.u16
= htole16((uint16_t) value
);
2035 x
.u32
= htole32((uint32_t) value
);
2037 x
.u64
= htole64((uint64_t) value
);
2039 assert_not_reached("unknown word width");
2044 static int bus_message_close_array(sd_bus_message
*m
, struct bus_container
*c
) {
2049 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2052 if (c
->need_offsets
) {
2053 size_t payload
, sz
, i
;
2056 /* Variable-width arrays */
2058 payload
= c
->n_offsets
> 0 ? c
->offsets
[c
->n_offsets
-1] - c
->begin
: 0;
2059 sz
= determine_word_size(payload
, c
->n_offsets
);
2061 a
= message_extend_body(m
, 1, sz
* c
->n_offsets
, true);
2065 for (i
= 0; i
< c
->n_offsets
; i
++)
2066 write_word_le(a
+ sz
*i
, sz
, c
->offsets
[i
] - c
->begin
);
2070 /* Fixed-width or empty arrays */
2072 a
= message_extend_body(m
, 1, 0, true); /* let's add offset to parent */
2080 static int bus_message_close_variant(sd_bus_message
*m
, struct bus_container
*c
) {
2086 assert(c
->signature
);
2088 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2091 l
= strlen(c
->signature
);
2093 a
= message_extend_body(m
, 1, 1 + l
, true);
2098 memcpy(a
+1, c
->signature
, l
);
2103 static int bus_message_close_struct(sd_bus_message
*m
, struct bus_container
*c
, bool add_offset
) {
2104 size_t n_variable
= 0;
2113 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2116 p
= strempty(c
->signature
);
2120 r
= signature_element_length(p
, &n
);
2129 r
= bus_gvariant_is_fixed_size(t
);
2134 assert(!c
->need_offsets
|| i
<= c
->n_offsets
);
2136 /* We need to add an offset for each item that has a
2137 * variable size and that is not the last one in the
2139 if (r
== 0 && p
[n
] != 0)
2146 assert(!c
->need_offsets
|| i
== c
->n_offsets
);
2147 assert(c
->need_offsets
|| n_variable
== 0);
2149 if (n_variable
<= 0) {
2150 a
= message_extend_body(m
, 1, 0, add_offset
);
2157 assert(c
->offsets
[c
->n_offsets
-1] == m
->header
->body_size
);
2159 sz
= determine_word_size(m
->header
->body_size
- c
->begin
, n_variable
);
2161 a
= message_extend_body(m
, 1, sz
* n_variable
, add_offset
);
2165 p
= strempty(c
->signature
);
2166 for (i
= 0, j
= 0; i
< c
->n_offsets
; i
++) {
2170 r
= signature_element_length(p
, &n
);
2181 r
= bus_gvariant_is_fixed_size(t
);
2184 if (r
> 0 || p
[0] == 0)
2188 k
= n_variable
- 1 - j
;
2190 write_word_le(a
+ k
* sz
, sz
, c
->offsets
[i
] - c
->begin
);
2199 _public_
int sd_bus_message_close_container(sd_bus_message
*m
) {
2200 struct bus_container
*c
;
2203 assert_return(m
, -EINVAL
);
2204 assert_return(!m
->sealed
, -EPERM
);
2205 assert_return(m
->n_containers
> 0, -EINVAL
);
2206 assert_return(!m
->poisoned
, -ESTALE
);
2208 c
= message_get_container(m
);
2210 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2211 if (c
->signature
&& c
->signature
[c
->index
] != 0)
2216 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
)
2217 r
= bus_message_close_array(m
, c
);
2218 else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
2219 r
= bus_message_close_variant(m
, c
);
2220 else if (c
->enclosing
== SD_BUS_TYPE_STRUCT
|| c
->enclosing
== SD_BUS_TYPE_DICT_ENTRY
)
2221 r
= bus_message_close_struct(m
, c
, true);
2223 assert_not_reached("Unknown container type");
2237 static int type_stack_push(TypeStack
*stack
, unsigned max
, unsigned *i
, const char *types
, unsigned n_struct
, unsigned n_array
) {
2244 stack
[*i
].types
= types
;
2245 stack
[*i
].n_struct
= n_struct
;
2246 stack
[*i
].n_array
= n_array
;
2252 static int type_stack_pop(TypeStack
*stack
, unsigned max
, unsigned *i
, const char **types
, unsigned *n_struct
, unsigned *n_array
) {
2263 *types
= stack
[*i
].types
;
2264 *n_struct
= stack
[*i
].n_struct
;
2265 *n_array
= stack
[*i
].n_array
;
2270 int bus_message_append_ap(
2275 unsigned n_array
, n_struct
;
2276 TypeStack stack
[BUS_CONTAINER_DEPTH
];
2277 unsigned stack_ptr
= 0;
2285 n_array
= (unsigned) -1;
2286 n_struct
= strlen(types
);
2291 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
2292 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
2298 r
= sd_bus_message_close_container(m
);
2306 if (n_array
!= (unsigned) -1)
2315 case SD_BUS_TYPE_BYTE
: {
2318 x
= (uint8_t) va_arg(ap
, int);
2319 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2323 case SD_BUS_TYPE_BOOLEAN
:
2324 case SD_BUS_TYPE_INT32
:
2325 case SD_BUS_TYPE_UINT32
:
2326 case SD_BUS_TYPE_UNIX_FD
: {
2329 /* We assume a boolean is the same as int32_t */
2330 assert_cc(sizeof(int32_t) == sizeof(int));
2332 x
= va_arg(ap
, uint32_t);
2333 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2337 case SD_BUS_TYPE_INT16
:
2338 case SD_BUS_TYPE_UINT16
: {
2341 x
= (uint16_t) va_arg(ap
, int);
2342 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2346 case SD_BUS_TYPE_INT64
:
2347 case SD_BUS_TYPE_UINT64
: {
2350 x
= va_arg(ap
, uint64_t);
2351 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2355 case SD_BUS_TYPE_DOUBLE
: {
2358 x
= va_arg(ap
, double);
2359 r
= sd_bus_message_append_basic(m
, *t
, &x
);
2363 case SD_BUS_TYPE_STRING
:
2364 case SD_BUS_TYPE_OBJECT_PATH
:
2365 case SD_BUS_TYPE_SIGNATURE
: {
2368 x
= va_arg(ap
, const char*);
2369 r
= sd_bus_message_append_basic(m
, *t
, x
);
2373 case SD_BUS_TYPE_ARRAY
: {
2376 r
= signature_element_length(t
+ 1, &k
);
2382 memcpy(s
, t
+ 1, k
);
2385 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, s
);
2390 if (n_array
== (unsigned) -1) {
2395 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2401 n_array
= va_arg(ap
, unsigned);
2406 case SD_BUS_TYPE_VARIANT
: {
2409 s
= va_arg(ap
, const char*);
2413 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_VARIANT
, s
);
2417 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2422 n_struct
= strlen(s
);
2423 n_array
= (unsigned) -1;
2428 case SD_BUS_TYPE_STRUCT_BEGIN
:
2429 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
2432 r
= signature_element_length(t
, &k
);
2439 memcpy(s
, t
+ 1, k
- 2);
2442 r
= sd_bus_message_open_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
2447 if (n_array
== (unsigned) -1) {
2452 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
2458 n_array
= (unsigned) -1;
2474 _public_
int sd_bus_message_append(sd_bus_message
*m
, const char *types
, ...) {
2478 assert_return(m
, -EINVAL
);
2479 assert_return(types
, -EINVAL
);
2480 assert_return(!m
->sealed
, -EPERM
);
2481 assert_return(!m
->poisoned
, -ESTALE
);
2483 va_start(ap
, types
);
2484 r
= bus_message_append_ap(m
, types
, ap
);
2490 _public_
int sd_bus_message_append_array_space(
2500 assert_return(m
, -EINVAL
);
2501 assert_return(!m
->sealed
, -EPERM
);
2502 assert_return(bus_type_is_trivial(type
) && type
!= SD_BUS_TYPE_BOOLEAN
, -EINVAL
);
2503 assert_return(ptr
|| size
== 0, -EINVAL
);
2504 assert_return(!m
->poisoned
, -ESTALE
);
2506 /* alignment and size of the trivial types (except bool) is
2507 * identical for gvariant and dbus1 marshalling */
2508 align
= bus_type_get_alignment(type
);
2509 sz
= bus_type_get_size(type
);
2511 assert_se(align
> 0);
2517 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2521 a
= message_extend_body(m
, align
, size
, false);
2525 r
= sd_bus_message_close_container(m
);
2533 _public_
int sd_bus_message_append_array(
2541 assert_return(m
, -EINVAL
);
2542 assert_return(!m
->sealed
, -EPERM
);
2543 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2544 assert_return(ptr
|| size
== 0, -EINVAL
);
2545 assert_return(!m
->poisoned
, -ESTALE
);
2547 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2552 memcpy(p
, ptr
, size
);
2557 _public_
int sd_bus_message_append_array_iovec(
2560 const struct iovec
*iov
,
2568 assert_return(m
, -EINVAL
);
2569 assert_return(!m
->sealed
, -EPERM
);
2570 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2571 assert_return(iov
|| n
== 0, -EINVAL
);
2572 assert_return(!m
->poisoned
, -ESTALE
);
2574 size
= IOVEC_TOTAL_SIZE(iov
, n
);
2576 r
= sd_bus_message_append_array_space(m
, type
, size
, &p
);
2580 for (i
= 0; i
< n
; i
++) {
2582 if (iov
[i
].iov_base
)
2583 memcpy(p
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2585 memzero(p
, iov
[i
].iov_len
);
2587 p
= (uint8_t*) p
+ iov
[i
].iov_len
;
2593 _public_
int sd_bus_message_append_array_memfd(
2600 _cleanup_close_
int copy_fd
= -1;
2601 struct bus_body_part
*part
;
2607 assert_return(m
, -EINVAL
);
2608 assert_return(memfd
>= 0, -EINVAL
);
2609 assert_return(bus_type_is_trivial(type
), -EINVAL
);
2610 assert_return(size
> 0, -EINVAL
);
2611 assert_return(!m
->sealed
, -EPERM
);
2612 assert_return(!m
->poisoned
, -ESTALE
);
2614 r
= memfd_set_sealed(memfd
);
2618 copy_fd
= dup(memfd
);
2622 r
= memfd_get_size(memfd
, &real_size
);
2626 if (offset
== 0 && size
== (uint64_t) -1)
2628 else if (offset
+ size
> real_size
)
2631 align
= bus_type_get_alignment(type
);
2632 sz
= bus_type_get_size(type
);
2634 assert_se(align
> 0);
2637 if (offset
% align
!= 0)
2643 if (size
> (uint64_t) (uint32_t) -1)
2646 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
2650 a
= message_extend_body(m
, align
, 0, false);
2654 part
= message_append_part(m
);
2658 part
->memfd
= copy_fd
;
2659 part
->memfd_offset
= offset
;
2660 part
->sealed
= true;
2664 m
->header
->body_size
+= size
;
2665 message_extend_containers(m
, size
);
2667 return sd_bus_message_close_container(m
);
2670 _public_
int sd_bus_message_append_string_memfd(
2676 _cleanup_close_
int copy_fd
= -1;
2677 struct bus_body_part
*part
;
2678 struct bus_container
*c
;
2683 assert_return(m
, -EINVAL
);
2684 assert_return(memfd
>= 0, -EINVAL
);
2685 assert_return(size
> 0, -EINVAL
);
2686 assert_return(!m
->sealed
, -EPERM
);
2687 assert_return(!m
->poisoned
, -ESTALE
);
2689 r
= memfd_set_sealed(memfd
);
2693 copy_fd
= dup(memfd
);
2697 r
= memfd_get_size(memfd
, &real_size
);
2701 if (offset
== 0 && size
== (uint64_t) -1)
2703 else if (offset
+ size
> real_size
)
2706 /* We require this to be NUL terminated */
2710 if (size
> (uint64_t) (uint32_t) -1)
2713 c
= message_get_container(m
);
2714 if (c
->signature
&& c
->signature
[c
->index
]) {
2715 /* Container signature is already set */
2717 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRING
)
2722 /* Maybe we can append to the signature? But only if this is the top-level container */
2723 if (c
->enclosing
!= 0)
2726 e
= strextend(&c
->signature
, CHAR_TO_STR(SD_BUS_TYPE_STRING
), NULL
);
2733 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
2734 a
= message_extend_body(m
, 4, 4, false);
2738 *(uint32_t*) a
= size
- 1;
2741 part
= message_append_part(m
);
2745 part
->memfd
= copy_fd
;
2746 part
->memfd_offset
= offset
;
2747 part
->sealed
= true;
2751 m
->header
->body_size
+= size
;
2752 message_extend_containers(m
, size
);
2754 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
2755 r
= message_add_offset(m
, m
->header
->body_size
);
2762 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
2768 _public_
int sd_bus_message_append_strv(sd_bus_message
*m
, char **l
) {
2772 assert_return(m
, -EINVAL
);
2773 assert_return(!m
->sealed
, -EPERM
);
2774 assert_return(!m
->poisoned
, -ESTALE
);
2776 r
= sd_bus_message_open_container(m
, 'a', "s");
2780 STRV_FOREACH(i
, l
) {
2781 r
= sd_bus_message_append_basic(m
, 's', *i
);
2786 return sd_bus_message_close_container(m
);
2789 static int bus_message_close_header(sd_bus_message
*m
) {
2795 if (!BUS_MESSAGE_IS_GVARIANT(m
))
2798 if (m
->n_header_offsets
< 1)
2801 assert(m
->header
->fields_size
== m
->header_offsets
[m
->n_header_offsets
-1]);
2803 sz
= determine_word_size(m
->header
->fields_size
, m
->n_header_offsets
);
2805 a
= message_extend_fields(m
, 1, sz
* m
->n_header_offsets
, false);
2809 for (i
= 0; i
< m
->n_header_offsets
; i
++)
2810 write_word_le(a
+ sz
*i
, sz
, m
->header_offsets
[i
]);
2815 int bus_message_seal(sd_bus_message
*m
, uint64_t cookie
, usec_t timeout
) {
2816 struct bus_body_part
*part
;
2826 if (m
->n_containers
> 0)
2832 /* In vtables the return signature of method calls is listed,
2833 * let's check if they match if this is a response */
2834 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
&&
2835 m
->enforced_reply_signature
&&
2836 !streq(strempty(m
->root_container
.signature
), m
->enforced_reply_signature
))
2839 /* If gvariant marshalling is used we need to close the body structure */
2840 r
= bus_message_close_struct(m
, &m
->root_container
, false);
2844 /* If there's a non-trivial signature set, then add it in here */
2845 if (!isempty(m
->root_container
.signature
)) {
2846 r
= message_append_field_signature(m
, BUS_MESSAGE_HEADER_SIGNATURE
, m
->root_container
.signature
, NULL
);
2852 r
= message_append_field_uint32(m
, BUS_MESSAGE_HEADER_UNIX_FDS
, m
->n_fds
);
2857 r
= bus_message_close_header(m
);
2861 m
->header
->serial
= (uint32_t) cookie
;
2862 m
->timeout
= m
->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
? 0 : timeout
;
2864 /* Add padding at the end of the fields part, since we know
2865 * the body needs to start at an 8 byte alignment. We made
2866 * sure we allocated enough space for this, so all we need to
2867 * do here is to zero it out. */
2868 l
= BUS_MESSAGE_FIELDS_SIZE(m
);
2871 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m
) + l
, a
);
2873 /* If this is something we can send as memfd, then let's seal
2874 the memfd now. Note that we can send memfds as payload only
2875 for directed messages, and not for broadcasts. */
2876 if (m
->destination
&& m
->bus
->use_memfd
) {
2877 MESSAGE_FOREACH_PART(part
, i
, m
)
2878 if (part
->memfd
>= 0 && !part
->sealed
&& (part
->size
> MEMFD_MIN_SIZE
|| m
->bus
->use_memfd
< 0)) {
2881 /* Try to seal it if that makes
2882 * sense. First, unmap our own map to
2883 * make sure we don't keep it busy. */
2884 bus_body_part_unmap(part
);
2886 /* Then, sync up real memfd size */
2888 r
= memfd_set_size(part
->memfd
, sz
);
2892 /* Finally, try to seal */
2893 if (memfd_set_sealed(part
->memfd
) >= 0)
2894 part
->sealed
= true;
2898 m
->root_container
.end
= BUS_MESSAGE_BODY_SIZE(m
);
2899 m
->root_container
.index
= 0;
2900 m
->root_container
.offset_index
= 0;
2901 m
->root_container
.item_size
= m
->root_container
.n_offsets
> 0 ? m
->root_container
.offsets
[0] : 0;
2908 int bus_body_part_map(struct bus_body_part
*part
) {
2917 if (part
->size
<= 0)
2920 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2921 if (part
->memfd
< 0 && part
->is_zero
&& part
->size
< 8) {
2922 static const uint8_t zeroes
[7] = { };
2923 part
->data
= (void*) zeroes
;
2927 shift
= part
->memfd_offset
- ((part
->memfd_offset
/ page_size()) * page_size());
2928 psz
= PAGE_ALIGN(part
->size
+ shift
);
2930 if (part
->memfd
>= 0)
2931 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
, part
->memfd
, part
->memfd_offset
- shift
);
2932 else if (part
->is_zero
)
2933 p
= mmap(NULL
, psz
, PROT_READ
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
2937 if (p
== MAP_FAILED
)
2941 part
->mmap_begin
= p
;
2942 part
->data
= (uint8_t*) p
+ shift
;
2943 part
->munmap_this
= true;
2948 void bus_body_part_unmap(struct bus_body_part
*part
) {
2952 if (part
->memfd
< 0)
2955 if (!part
->mmap_begin
)
2958 if (!part
->munmap_this
)
2961 assert_se(munmap(part
->mmap_begin
, part
->mapped
) == 0);
2963 part
->mmap_begin
= NULL
;
2966 part
->munmap_this
= false;
2971 static int buffer_peek(const void *p
, uint32_t sz
, size_t *rindex
, size_t align
, size_t nbytes
, void **r
) {
2972 size_t k
, start
, end
;
2977 start
= ALIGN_TO((size_t) *rindex
, align
);
2978 end
= start
+ nbytes
;
2983 /* Verify that padding is 0 */
2984 for (k
= *rindex
; k
< start
; k
++)
2985 if (((const uint8_t*) p
)[k
] != 0)
2989 *r
= (uint8_t*) p
+ start
;
2996 static bool message_end_of_signature(sd_bus_message
*m
) {
2997 struct bus_container
*c
;
3001 c
= message_get_container(m
);
3002 return !c
->signature
|| c
->signature
[c
->index
] == 0;
3005 static bool message_end_of_array(sd_bus_message
*m
, size_t index
) {
3006 struct bus_container
*c
;
3010 c
= message_get_container(m
);
3011 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3014 if (BUS_MESSAGE_IS_GVARIANT(m
))
3015 return index
>= c
->end
;
3017 assert(c
->array_size
);
3018 return index
>= c
->begin
+ BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
3022 _public_
int sd_bus_message_at_end(sd_bus_message
*m
, int complete
) {
3023 assert_return(m
, -EINVAL
);
3024 assert_return(m
->sealed
, -EPERM
);
3026 if (complete
&& m
->n_containers
> 0)
3029 if (message_end_of_signature(m
))
3032 if (message_end_of_array(m
, m
->rindex
))
3038 static struct bus_body_part
* find_part(sd_bus_message
*m
, size_t index
, size_t sz
, void **p
) {
3039 struct bus_body_part
*part
;
3045 if (m
->cached_rindex_part
&& index
>= m
->cached_rindex_part_begin
) {
3046 part
= m
->cached_rindex_part
;
3047 begin
= m
->cached_rindex_part_begin
;
3057 if (index
+ sz
<= begin
+ part
->size
) {
3059 r
= bus_body_part_map(part
);
3064 *p
= (uint8_t*) part
->data
+ index
- begin
;
3066 m
->cached_rindex_part
= part
;
3067 m
->cached_rindex_part_begin
= begin
;
3072 begin
+= part
->size
;
3079 static int container_next_item(sd_bus_message
*m
, struct bus_container
*c
, size_t *rindex
) {
3086 if (!BUS_MESSAGE_IS_GVARIANT(m
))
3089 if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
3092 sz
= bus_gvariant_get_size(c
->signature
);
3096 if (c
->offset_index
+1 >= c
->n_offsets
)
3099 /* Variable-size array */
3101 alignment
= bus_gvariant_get_alignment(c
->signature
);
3102 assert(alignment
> 0);
3104 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3105 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3108 if (c
->offset_index
+1 >= (c
->end
-c
->begin
)/sz
)
3111 /* Fixed-size array */
3112 *rindex
= c
->begin
+ (c
->offset_index
+1) * sz
;
3118 } else if (c
->enclosing
== 0 ||
3119 c
->enclosing
== SD_BUS_TYPE_STRUCT
||
3120 c
->enclosing
== SD_BUS_TYPE_DICT_ENTRY
) {
3125 if (c
->offset_index
+1 >= c
->n_offsets
)
3128 r
= signature_element_length(c
->signature
+ c
->index
, &n
);
3132 r
= signature_element_length(c
->signature
+ c
->index
+ n
, &j
);
3137 memcpy(t
, c
->signature
+ c
->index
+ n
, j
);
3140 alignment
= bus_gvariant_get_alignment(t
);
3143 assert(alignment
> 0);
3145 *rindex
= ALIGN_TO(c
->offsets
[c
->offset_index
], alignment
);
3146 c
->item_size
= c
->offsets
[c
->offset_index
+1] - *rindex
;
3150 } else if (c
->enclosing
== SD_BUS_TYPE_VARIANT
)
3153 assert_not_reached("Unknown container type");
3158 /* Reached the end */
3165 static int message_peek_body(
3172 size_t k
, start
, end
, padding
;
3173 struct bus_body_part
*part
;
3180 start
= ALIGN_TO((size_t) *rindex
, align
);
3181 padding
= start
- *rindex
;
3182 end
= start
+ nbytes
;
3184 if (end
> BUS_MESSAGE_BODY_SIZE(m
))
3187 part
= find_part(m
, *rindex
, padding
, (void**) &q
);
3192 /* Verify padding */
3193 for (k
= 0; k
< padding
; k
++)
3198 part
= find_part(m
, start
, nbytes
, (void**) &q
);
3199 if (!part
|| (nbytes
> 0 && !q
))
3210 static bool validate_nul(const char *s
, size_t l
) {
3212 /* Check for NUL chars in the string */
3213 if (memchr(s
, 0, l
))
3216 /* Check for NUL termination */
3223 static bool validate_string(const char *s
, size_t l
) {
3225 if (!validate_nul(s
, l
))
3228 /* Check if valid UTF8 */
3229 if (!utf8_is_valid(s
))
3235 static bool validate_signature(const char *s
, size_t l
) {
3237 if (!validate_nul(s
, l
))
3240 /* Check if valid signature */
3241 if (!signature_is_valid(s
, true))
3247 static bool validate_object_path(const char *s
, size_t l
) {
3249 if (!validate_nul(s
, l
))
3252 if (!object_path_is_valid(s
))
3258 _public_
int sd_bus_message_read_basic(sd_bus_message
*m
, char type
, void *p
) {
3259 struct bus_container
*c
;
3264 assert_return(m
, -EINVAL
);
3265 assert_return(m
->sealed
, -EPERM
);
3266 assert_return(bus_type_is_basic(type
), -EINVAL
);
3268 if (message_end_of_signature(m
))
3271 if (message_end_of_array(m
, m
->rindex
))
3274 c
= message_get_container(m
);
3275 if (c
->signature
[c
->index
] != type
)
3280 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3282 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
)) {
3285 r
= message_peek_body(m
, &rindex
, 1, c
->item_size
, &q
);
3289 if (type
== SD_BUS_TYPE_STRING
)
3290 ok
= validate_string(q
, c
->item_size
-1);
3291 else if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3292 ok
= validate_object_path(q
, c
->item_size
-1);
3294 ok
= validate_signature(q
, c
->item_size
-1);
3300 *(const char**) p
= q
;
3304 sz
= bus_gvariant_get_size(CHAR_TO_STR(type
));
3306 if ((size_t) sz
!= c
->item_size
)
3309 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
3312 r
= message_peek_body(m
, &rindex
, align
, c
->item_size
, &q
);
3318 case SD_BUS_TYPE_BYTE
:
3320 *(uint8_t*) p
= *(uint8_t*) q
;
3323 case SD_BUS_TYPE_BOOLEAN
:
3325 *(int*) p
= !!*(uint8_t*) q
;
3328 case SD_BUS_TYPE_INT16
:
3329 case SD_BUS_TYPE_UINT16
:
3331 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3334 case SD_BUS_TYPE_INT32
:
3335 case SD_BUS_TYPE_UINT32
:
3337 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3340 case SD_BUS_TYPE_INT64
:
3341 case SD_BUS_TYPE_UINT64
:
3342 case SD_BUS_TYPE_DOUBLE
:
3344 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3347 case SD_BUS_TYPE_UNIX_FD
: {
3350 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3355 *(int*) p
= m
->fds
[j
];
3361 assert_not_reached("unexpected type");
3365 r
= container_next_item(m
, c
, &rindex
);
3372 if (IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
)) {
3376 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3380 l
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3381 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3385 if (type
== SD_BUS_TYPE_OBJECT_PATH
)
3386 ok
= validate_object_path(q
, l
);
3388 ok
= validate_string(q
, l
);
3393 *(const char**) p
= q
;
3395 } else if (type
== SD_BUS_TYPE_SIGNATURE
) {
3398 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3403 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3407 if (!validate_signature(q
, l
))
3411 *(const char**) p
= q
;
3416 align
= bus_type_get_alignment(type
);
3419 sz
= bus_type_get_size(type
);
3422 r
= message_peek_body(m
, &rindex
, align
, sz
, &q
);
3428 case SD_BUS_TYPE_BYTE
:
3430 *(uint8_t*) p
= *(uint8_t*) q
;
3433 case SD_BUS_TYPE_BOOLEAN
:
3435 *(int*) p
= !!*(uint32_t*) q
;
3438 case SD_BUS_TYPE_INT16
:
3439 case SD_BUS_TYPE_UINT16
:
3441 *(uint16_t*) p
= BUS_MESSAGE_BSWAP16(m
, *(uint16_t*) q
);
3444 case SD_BUS_TYPE_INT32
:
3445 case SD_BUS_TYPE_UINT32
:
3447 *(uint32_t*) p
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3450 case SD_BUS_TYPE_INT64
:
3451 case SD_BUS_TYPE_UINT64
:
3452 case SD_BUS_TYPE_DOUBLE
:
3454 *(uint64_t*) p
= BUS_MESSAGE_BSWAP64(m
, *(uint64_t*) q
);
3457 case SD_BUS_TYPE_UNIX_FD
: {
3460 j
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
3465 *(int*) p
= m
->fds
[j
];
3470 assert_not_reached("Unknown basic type...");
3477 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3483 static int bus_message_enter_array(
3485 struct bus_container
*c
,
3486 const char *contents
,
3487 uint32_t **array_size
,
3490 size_t *n_offsets
) {
3504 if (!signature_is_single(contents
, true))
3507 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3510 if (c
->signature
[c
->index
] != SD_BUS_TYPE_ARRAY
)
3513 if (!startswith(c
->signature
+ c
->index
+ 1, contents
))
3518 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3521 r
= message_peek_body(m
, &rindex
, 4, 4, &q
);
3525 if (BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
) > BUS_ARRAY_MAX_SIZE
)
3528 alignment
= bus_type_get_alignment(contents
[0]);
3532 r
= message_peek_body(m
, &rindex
, alignment
, 0, NULL
);
3536 *array_size
= (uint32_t*) q
;
3538 } else if (c
->item_size
<= 0) {
3540 /* gvariant: empty array */
3545 } else if (bus_gvariant_is_fixed_size(contents
)) {
3547 /* gvariant: fixed length array */
3548 *item_size
= bus_gvariant_get_size(contents
);
3553 size_t where
, p
= 0, framing
, sz
;
3556 /* gvariant: variable length array */
3557 sz
= determine_word_size(c
->item_size
, 0);
3559 where
= rindex
+ c
->item_size
- sz
;
3560 r
= message_peek_body(m
, &where
, 1, sz
, &q
);
3564 framing
= read_word_le(q
, sz
);
3565 if (framing
> c
->item_size
- sz
)
3567 if ((c
->item_size
- framing
) % sz
!= 0)
3570 *n_offsets
= (c
->item_size
- framing
) / sz
;
3572 where
= rindex
+ framing
;
3573 r
= message_peek_body(m
, &where
, 1, *n_offsets
* sz
, &q
);
3577 *offsets
= new(size_t, *n_offsets
);
3581 for (i
= 0; i
< *n_offsets
; i
++) {
3584 x
= read_word_le((uint8_t*) q
+ i
* sz
, sz
);
3585 if (x
> c
->item_size
- sz
)
3590 (*offsets
)[i
] = rindex
+ x
;
3594 *item_size
= (*offsets
)[0] - rindex
;
3599 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3600 c
->index
+= 1 + strlen(contents
);
3605 static int bus_message_enter_variant(
3607 struct bus_container
*c
,
3608 const char *contents
,
3609 size_t *item_size
) {
3621 if (!signature_is_single(contents
, false))
3624 if (*contents
== SD_BUS_TYPE_DICT_ENTRY_BEGIN
)
3627 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3630 if (c
->signature
[c
->index
] != SD_BUS_TYPE_VARIANT
)
3635 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
3638 k
= strlen(contents
);
3639 if (1+k
> c
->item_size
)
3642 where
= rindex
+ c
->item_size
- (1+k
);
3643 r
= message_peek_body(m
, &where
, 1, 1+k
, &q
);
3647 if (*(char*) q
!= 0)
3650 if (memcmp((uint8_t*) q
+1, contents
, k
))
3653 *item_size
= c
->item_size
- (1+k
);
3656 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
3661 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
3665 if (!validate_signature(q
, l
))
3668 if (!streq(q
, contents
))
3674 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3680 static int build_struct_offsets(
3682 const char *signature
,
3686 size_t *n_offsets
) {
3688 unsigned n_variable
= 0, n_total
= 0, v
;
3689 size_t previous
= 0, where
;
3700 if (isempty(signature
)) {
3707 sz
= determine_word_size(size
, 0);
3711 /* First, loop over signature and count variable elements and
3712 * elements in general. We use this to know how large the
3713 * offset array is at the end of the structure. Note that
3714 * GVariant only stores offsets for all variable size elements
3715 * that are not the last item. */
3721 r
= signature_element_length(p
, &n
);
3730 r
= bus_gvariant_is_fixed_size(t
);
3735 if (r
== 0 && p
[n
] != 0) /* except the last item */
3742 if (size
< n_variable
* sz
)
3745 where
= m
->rindex
+ size
- (n_variable
* sz
);
3746 r
= message_peek_body(m
, &where
, 1, n_variable
* sz
, &q
);
3752 *offsets
= new(size_t, n_total
);
3758 /* Second, loop again and build an offset table */
3764 r
= signature_element_length(p
, &n
);
3773 k
= bus_gvariant_get_size(t
);
3781 x
= read_word_le((uint8_t*) q
+ v
*sz
, sz
);
3784 if (m
->rindex
+ x
< previous
)
3787 /* The last item's end
3788 * is determined from
3791 x
= size
- (n_variable
* sz
);
3793 offset
= m
->rindex
+ x
;
3799 align
= bus_gvariant_get_alignment(t
);
3802 offset
= (*n_offsets
== 0 ? m
->rindex
: ALIGN_TO((*offsets
)[*n_offsets
-1], align
)) + k
;
3806 previous
= (*offsets
)[(*n_offsets
)++] = offset
;
3811 assert(*n_offsets
== n_total
);
3813 *item_size
= (*offsets
)[0] - m
->rindex
;
3817 static int enter_struct_or_dict_entry(
3819 struct bus_container
*c
,
3820 const char *contents
,
3823 size_t *n_offsets
) {
3834 if (!BUS_MESSAGE_IS_GVARIANT(m
)) {
3837 r
= message_peek_body(m
, &m
->rindex
, 8, 0, NULL
);
3841 } else if (c
->item_size
<= 0) {
3843 /* gvariant empty struct */
3848 /* gvariant with contents */
3849 return build_struct_offsets(m
, contents
, c
->item_size
, item_size
, offsets
, n_offsets
);
3854 static int bus_message_enter_struct(
3856 struct bus_container
*c
,
3857 const char *contents
,
3860 size_t *n_offsets
) {
3872 if (!signature_is_valid(contents
, false))
3875 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3878 l
= strlen(contents
);
3880 if (c
->signature
[c
->index
] != SD_BUS_TYPE_STRUCT_BEGIN
||
3881 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3882 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_STRUCT_END
)
3885 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3889 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3890 c
->index
+= 1 + l
+ 1;
3895 static int bus_message_enter_dict_entry(
3897 struct bus_container
*c
,
3898 const char *contents
,
3901 size_t *n_offsets
) {
3910 if (!signature_is_pair(contents
))
3913 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3916 if (!c
->signature
|| c
->signature
[c
->index
] == 0)
3919 l
= strlen(contents
);
3921 if (c
->signature
[c
->index
] != SD_BUS_TYPE_DICT_ENTRY_BEGIN
||
3922 !startswith(c
->signature
+ c
->index
+ 1, contents
) ||
3923 c
->signature
[c
->index
+ 1 + l
] != SD_BUS_TYPE_DICT_ENTRY_END
)
3926 r
= enter_struct_or_dict_entry(m
, c
, contents
, item_size
, offsets
, n_offsets
);
3930 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
)
3931 c
->index
+= 1 + l
+ 1;
3936 _public_
int sd_bus_message_enter_container(sd_bus_message
*m
,
3938 const char *contents
) {
3939 struct bus_container
*c
, *w
;
3940 uint32_t *array_size
= NULL
;
3943 size_t *offsets
= NULL
;
3944 size_t n_offsets
= 0, item_size
= 0;
3947 assert_return(m
, -EINVAL
);
3948 assert_return(m
->sealed
, -EPERM
);
3949 assert_return(type
!= 0 || !contents
, -EINVAL
);
3951 if (type
== 0 || !contents
) {
3955 /* Allow entering into anonymous containers */
3956 r
= sd_bus_message_peek_type(m
, &tt
, &cc
);
3960 if (type
!= 0 && type
!= tt
)
3963 if (contents
&& !streq(contents
, cc
))
3971 * We enforce a global limit on container depth, that is much
3972 * higher than the 32 structs and 32 arrays the specification
3973 * mandates. This is simpler to implement for us, and we need
3974 * this only to ensure our container array doesn't grow
3975 * without bounds. We are happy to return any data from a
3976 * message as long as the data itself is valid, even if the
3977 * overall message might be not.
3979 * Note that the message signature is validated when
3980 * parsing the headers, and that validation does check the
3983 * Note that the specification defines no limits on the depth
3984 * of stacked variants, but we do.
3986 if (m
->n_containers
>= BUS_CONTAINER_DEPTH
)
3989 if (!GREEDY_REALLOC(m
->containers
, m
->containers_allocated
, m
->n_containers
+ 1))
3992 if (message_end_of_signature(m
))
3995 if (message_end_of_array(m
, m
->rindex
))
3998 c
= message_get_container(m
);
4000 signature
= strdup(contents
);
4004 c
->saved_index
= c
->index
;
4007 if (type
== SD_BUS_TYPE_ARRAY
)
4008 r
= bus_message_enter_array(m
, c
, contents
, &array_size
, &item_size
, &offsets
, &n_offsets
);
4009 else if (type
== SD_BUS_TYPE_VARIANT
)
4010 r
= bus_message_enter_variant(m
, c
, contents
, &item_size
);
4011 else if (type
== SD_BUS_TYPE_STRUCT
)
4012 r
= bus_message_enter_struct(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4013 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
4014 r
= bus_message_enter_dict_entry(m
, c
, contents
, &item_size
, &offsets
, &n_offsets
);
4024 /* OK, let's fill it in */
4025 w
= m
->containers
+ m
->n_containers
++;
4026 w
->enclosing
= type
;
4027 w
->signature
= signature
;
4028 w
->peeked_signature
= NULL
;
4032 w
->begin
= m
->rindex
;
4033 w
->end
= m
->rindex
+ c
->item_size
;
4035 w
->array_size
= array_size
;
4036 w
->item_size
= item_size
;
4037 w
->offsets
= offsets
;
4038 w
->n_offsets
= n_offsets
;
4039 w
->offset_index
= 0;
4044 _public_
int sd_bus_message_exit_container(sd_bus_message
*m
) {
4045 struct bus_container
*c
;
4049 assert_return(m
, -EINVAL
);
4050 assert_return(m
->sealed
, -EPERM
);
4051 assert_return(m
->n_containers
> 0, -ENXIO
);
4053 c
= message_get_container(m
);
4055 if (c
->enclosing
!= SD_BUS_TYPE_ARRAY
) {
4056 if (c
->signature
&& c
->signature
[c
->index
] != 0)
4060 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4061 if (m
->rindex
< c
->end
)
4064 } else if (c
->enclosing
== SD_BUS_TYPE_ARRAY
) {
4067 l
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4068 if (c
->begin
+ l
!= m
->rindex
)
4073 free(c
->peeked_signature
);
4077 c
= message_get_container(m
);
4080 c
->index
= c
->saved_index
;
4081 r
= container_next_item(m
, c
, &m
->rindex
);
4089 static void message_quit_container(sd_bus_message
*m
) {
4090 struct bus_container
*c
;
4094 assert(m
->n_containers
> 0);
4096 c
= message_get_container(m
);
4099 assert(m
->rindex
>= c
->before
);
4100 m
->rindex
= c
->before
;
4102 /* Free container */
4107 /* Correct index of new top-level container */
4108 c
= message_get_container(m
);
4109 c
->index
= c
->saved_index
;
4112 _public_
int sd_bus_message_peek_type(sd_bus_message
*m
, char *type
, const char **contents
) {
4113 struct bus_container
*c
;
4116 assert_return(m
, -EINVAL
);
4117 assert_return(m
->sealed
, -EPERM
);
4119 if (message_end_of_signature(m
))
4122 if (message_end_of_array(m
, m
->rindex
))
4125 c
= message_get_container(m
);
4127 if (bus_type_is_basic(c
->signature
[c
->index
])) {
4131 *type
= c
->signature
[c
->index
];
4135 if (c
->signature
[c
->index
] == SD_BUS_TYPE_ARRAY
) {
4141 r
= signature_element_length(c
->signature
+c
->index
+1, &l
);
4147 sig
= strndup(c
->signature
+ c
->index
+ 1, l
);
4151 free(c
->peeked_signature
);
4152 *contents
= c
->peeked_signature
= sig
;
4156 *type
= SD_BUS_TYPE_ARRAY
;
4161 if (c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
||
4162 c
->signature
[c
->index
] == SD_BUS_TYPE_DICT_ENTRY_BEGIN
) {
4168 r
= signature_element_length(c
->signature
+c
->index
, &l
);
4173 sig
= strndup(c
->signature
+ c
->index
+ 1, l
- 2);
4177 free(c
->peeked_signature
);
4178 *contents
= c
->peeked_signature
= sig
;
4182 *type
= c
->signature
[c
->index
] == SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
;
4187 if (c
->signature
[c
->index
] == SD_BUS_TYPE_VARIANT
) {
4191 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4194 if (c
->item_size
< 2)
4197 /* Look for the NUL delimiter that
4198 separates the payload from the
4199 signature. Since the body might be
4200 in a different part that then the
4201 signature we map byte by byte. */
4203 for (k
= 2; k
<= c
->item_size
; k
++) {
4206 where
= m
->rindex
+ c
->item_size
- k
;
4207 r
= message_peek_body(m
, &where
, 1, k
, &q
);
4211 if (*(char*) q
== 0)
4215 if (k
> c
->item_size
)
4218 free(c
->peeked_signature
);
4219 c
->peeked_signature
= strndup((char*) q
+ 1, k
- 1);
4220 if (!c
->peeked_signature
)
4223 if (!signature_is_valid(c
->peeked_signature
, true))
4226 *contents
= c
->peeked_signature
;
4231 r
= message_peek_body(m
, &rindex
, 1, 1, &q
);
4236 r
= message_peek_body(m
, &rindex
, 1, l
+1, &q
);
4240 if (!validate_signature(q
, l
))
4248 *type
= SD_BUS_TYPE_VARIANT
;
4263 _public_
int sd_bus_message_rewind(sd_bus_message
*m
, int complete
) {
4264 struct bus_container
*c
;
4266 assert_return(m
, -EINVAL
);
4267 assert_return(m
->sealed
, -EPERM
);
4270 message_reset_containers(m
);
4273 c
= message_get_container(m
);
4275 c
= message_get_container(m
);
4277 c
->offset_index
= 0;
4279 m
->rindex
= c
->begin
;
4282 c
->offset_index
= 0;
4283 c
->item_size
= (c
->n_offsets
> 0 ? c
->offsets
[0] : c
->end
) - c
->begin
;
4285 return !isempty(c
->signature
);
4288 static int message_read_ap(
4293 unsigned n_array
, n_struct
;
4294 TypeStack stack
[BUS_CONTAINER_DEPTH
];
4295 unsigned stack_ptr
= 0;
4296 unsigned n_loop
= 0;
4304 /* Ideally, we'd just call ourselves recursively on every
4305 * complex type. However, the state of a va_list that is
4306 * passed to a function is undefined after that function
4307 * returns. This means we need to docode the va_list linearly
4308 * in a single stackframe. We hence implement our own
4309 * home-grown stack in an array. */
4311 n_array
= (unsigned) -1; /* length of current array entries */
4312 n_struct
= strlen(types
); /* length of current struct contents signature */
4319 if (n_array
== 0 || (n_array
== (unsigned) -1 && n_struct
== 0)) {
4320 r
= type_stack_pop(stack
, ELEMENTSOF(stack
), &stack_ptr
, &types
, &n_struct
, &n_array
);
4326 r
= sd_bus_message_exit_container(m
);
4334 if (n_array
!= (unsigned) -1)
4343 case SD_BUS_TYPE_BYTE
:
4344 case SD_BUS_TYPE_BOOLEAN
:
4345 case SD_BUS_TYPE_INT16
:
4346 case SD_BUS_TYPE_UINT16
:
4347 case SD_BUS_TYPE_INT32
:
4348 case SD_BUS_TYPE_UINT32
:
4349 case SD_BUS_TYPE_INT64
:
4350 case SD_BUS_TYPE_UINT64
:
4351 case SD_BUS_TYPE_DOUBLE
:
4352 case SD_BUS_TYPE_STRING
:
4353 case SD_BUS_TYPE_OBJECT_PATH
:
4354 case SD_BUS_TYPE_SIGNATURE
:
4355 case SD_BUS_TYPE_UNIX_FD
: {
4358 p
= va_arg(ap
, void*);
4359 r
= sd_bus_message_read_basic(m
, *t
, p
);
4372 case SD_BUS_TYPE_ARRAY
: {
4375 r
= signature_element_length(t
+ 1, &k
);
4381 memcpy(s
, t
+ 1, k
);
4384 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4395 if (n_array
== (unsigned) -1) {
4400 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4406 n_array
= va_arg(ap
, unsigned);
4411 case SD_BUS_TYPE_VARIANT
: {
4414 s
= va_arg(ap
, const char *);
4418 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, s
);
4428 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4433 n_struct
= strlen(s
);
4434 n_array
= (unsigned) -1;
4439 case SD_BUS_TYPE_STRUCT_BEGIN
:
4440 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4443 r
= signature_element_length(t
, &k
);
4449 memcpy(s
, t
+ 1, k
- 2);
4452 r
= sd_bus_message_enter_container(m
, *t
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4462 if (n_array
== (unsigned) -1) {
4467 r
= type_stack_push(stack
, ELEMENTSOF(stack
), &stack_ptr
, types
, n_struct
, n_array
);
4473 n_array
= (unsigned) -1;
4486 _public_
int sd_bus_message_read(sd_bus_message
*m
, const char *types
, ...) {
4490 assert_return(m
, -EINVAL
);
4491 assert_return(m
->sealed
, -EPERM
);
4492 assert_return(types
, -EINVAL
);
4494 va_start(ap
, types
);
4495 r
= message_read_ap(m
, types
, ap
);
4501 _public_
int sd_bus_message_skip(sd_bus_message
*m
, const char *types
) {
4504 assert_return(m
, -EINVAL
);
4505 assert_return(m
->sealed
, -EPERM
);
4507 /* If types is NULL, read exactly one element */
4509 struct bus_container
*c
;
4512 if (message_end_of_signature(m
))
4515 if (message_end_of_array(m
, m
->rindex
))
4518 c
= message_get_container(m
);
4520 r
= signature_element_length(c
->signature
+ c
->index
, &l
);
4524 types
= strndupa(c
->signature
+ c
->index
, l
);
4529 case 0: /* Nothing to drop */
4532 case SD_BUS_TYPE_BYTE
:
4533 case SD_BUS_TYPE_BOOLEAN
:
4534 case SD_BUS_TYPE_INT16
:
4535 case SD_BUS_TYPE_UINT16
:
4536 case SD_BUS_TYPE_INT32
:
4537 case SD_BUS_TYPE_UINT32
:
4538 case SD_BUS_TYPE_INT64
:
4539 case SD_BUS_TYPE_UINT64
:
4540 case SD_BUS_TYPE_DOUBLE
:
4541 case SD_BUS_TYPE_STRING
:
4542 case SD_BUS_TYPE_OBJECT_PATH
:
4543 case SD_BUS_TYPE_SIGNATURE
:
4544 case SD_BUS_TYPE_UNIX_FD
:
4546 r
= sd_bus_message_read_basic(m
, *types
, NULL
);
4550 r
= sd_bus_message_skip(m
, types
+ 1);
4556 case SD_BUS_TYPE_ARRAY
: {
4559 r
= signature_element_length(types
+ 1, &k
);
4565 memcpy(s
, types
+1, k
);
4568 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, s
);
4573 r
= sd_bus_message_skip(m
, s
);
4580 r
= sd_bus_message_exit_container(m
);
4585 r
= sd_bus_message_skip(m
, types
+ 1 + k
);
4592 case SD_BUS_TYPE_VARIANT
: {
4593 const char *contents
;
4596 r
= sd_bus_message_peek_type(m
, &x
, &contents
);
4600 if (x
!= SD_BUS_TYPE_VARIANT
)
4603 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
4607 r
= sd_bus_message_skip(m
, contents
);
4612 r
= sd_bus_message_exit_container(m
);
4616 r
= sd_bus_message_skip(m
, types
+ 1);
4623 case SD_BUS_TYPE_STRUCT_BEGIN
:
4624 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
4627 r
= signature_element_length(types
, &k
);
4633 memcpy(s
, types
+1, k
-2);
4636 r
= sd_bus_message_enter_container(m
, *types
== SD_BUS_TYPE_STRUCT_BEGIN
? SD_BUS_TYPE_STRUCT
: SD_BUS_TYPE_DICT_ENTRY
, s
);
4640 r
= sd_bus_message_skip(m
, s
);
4645 r
= sd_bus_message_exit_container(m
);
4650 r
= sd_bus_message_skip(m
, types
+ k
);
4662 _public_
int sd_bus_message_read_array(sd_bus_message
*m
,
4666 struct bus_container
*c
;
4672 assert_return(m
, -EINVAL
);
4673 assert_return(m
->sealed
, -EPERM
);
4674 assert_return(bus_type_is_trivial(type
), -EINVAL
);
4675 assert_return(ptr
, -EINVAL
);
4676 assert_return(size
, -EINVAL
);
4677 assert_return(!BUS_MESSAGE_NEED_BSWAP(m
), -ENOTSUP
);
4679 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, CHAR_TO_STR(type
));
4683 c
= message_get_container(m
);
4685 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4686 align
= bus_gvariant_get_alignment(CHAR_TO_STR(type
));
4690 sz
= c
->end
- c
->begin
;
4692 align
= bus_type_get_alignment(type
);
4696 sz
= BUS_MESSAGE_BSWAP32(m
, *c
->array_size
);
4700 /* Zero length array, let's return some aligned
4701 * pointer that is not NULL */
4702 p
= (uint8_t*) NULL
+ align
;
4704 r
= message_peek_body(m
, &m
->rindex
, align
, sz
, &p
);
4709 r
= sd_bus_message_exit_container(m
);
4713 *ptr
= (const void*) p
;
4719 message_quit_container(m
);
4723 static int message_peek_fields(
4734 return buffer_peek(BUS_MESSAGE_FIELDS(m
), BUS_MESSAGE_FIELDS_SIZE(m
), rindex
, align
, nbytes
, ret
);
4737 static int message_peek_field_uint32(
4749 if (BUS_MESSAGE_IS_GVARIANT(m
) && item_size
!= 4)
4752 /* identical for gvariant and dbus1 */
4754 r
= message_peek_fields(m
, ri
, 4, 4, &q
);
4759 *ret
= BUS_MESSAGE_BSWAP32(m
, *(uint32_t*) q
);
4764 static int message_peek_field_string(
4766 bool (*validate
)(const char *p
),
4778 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4783 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4789 r
= message_peek_field_uint32(m
, ri
, 4, &l
);
4793 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4799 if (!validate_nul(q
, l
))
4805 if (!validate_string(q
, l
))
4815 static int message_peek_field_signature(
4828 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
4833 r
= message_peek_fields(m
, ri
, 1, item_size
, &q
);
4839 r
= message_peek_fields(m
, ri
, 1, 1, &q
);
4844 r
= message_peek_fields(m
, ri
, 1, l
+1, &q
);
4849 if (!validate_signature(q
, l
))
4858 static int message_skip_fields(
4861 uint32_t array_size
,
4862 const char **signature
) {
4864 size_t original_index
;
4870 assert(!BUS_MESSAGE_IS_GVARIANT(m
));
4872 original_index
= *ri
;
4878 if (array_size
!= (uint32_t) -1 &&
4879 array_size
<= *ri
- original_index
)
4886 if (t
== SD_BUS_TYPE_STRING
) {
4888 r
= message_peek_field_string(m
, NULL
, ri
, 0, NULL
);
4894 } else if (t
== SD_BUS_TYPE_OBJECT_PATH
) {
4896 r
= message_peek_field_string(m
, object_path_is_valid
, ri
, 0, NULL
);
4902 } else if (t
== SD_BUS_TYPE_SIGNATURE
) {
4904 r
= message_peek_field_signature(m
, ri
, 0, NULL
);
4910 } else if (bus_type_is_basic(t
)) {
4913 align
= bus_type_get_alignment(t
);
4914 k
= bus_type_get_size(t
);
4915 assert(align
> 0 && k
> 0);
4917 r
= message_peek_fields(m
, ri
, align
, k
, NULL
);
4923 } else if (t
== SD_BUS_TYPE_ARRAY
) {
4925 r
= signature_element_length(*signature
+1, &l
);
4935 strncpy(sig
, *signature
+ 1, l
-1);
4938 alignment
= bus_type_get_alignment(sig
[0]);
4942 r
= message_peek_field_uint32(m
, ri
, 0, &nas
);
4945 if (nas
> BUS_ARRAY_MAX_SIZE
)
4948 r
= message_peek_fields(m
, ri
, alignment
, 0, NULL
);
4952 r
= message_skip_fields(m
, ri
, nas
, (const char**) &s
);
4957 (*signature
) += 1 + l
;
4959 } else if (t
== SD_BUS_TYPE_VARIANT
) {
4962 r
= message_peek_field_signature(m
, ri
, 0, &s
);
4966 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
4972 } else if (t
== SD_BUS_TYPE_STRUCT
||
4973 t
== SD_BUS_TYPE_DICT_ENTRY
) {
4975 r
= signature_element_length(*signature
, &l
);
4982 strncpy(sig
, *signature
+ 1, l
-1);
4985 r
= message_skip_fields(m
, ri
, (uint32_t) -1, (const char**) &s
);
4996 int bus_message_parse_fields(sd_bus_message
*m
) {
4999 uint32_t unix_fds
= 0;
5000 bool unix_fds_set
= false;
5001 void *offsets
= NULL
;
5002 unsigned n_offsets
= 0;
5008 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5011 sz
= determine_word_size(BUS_MESSAGE_FIELDS_SIZE(m
), 0);
5015 ri
= BUS_MESSAGE_FIELDS_SIZE(m
) - sz
;
5016 r
= message_peek_fields(m
, &ri
, 1, sz
, &q
);
5020 framing
= read_word_le(q
, sz
);
5021 if (framing
>= BUS_MESSAGE_FIELDS_SIZE(m
) - sz
)
5023 if ((BUS_MESSAGE_FIELDS_SIZE(m
) - framing
) % sz
!= 0)
5027 r
= message_peek_fields(m
, &ri
, 1, BUS_MESSAGE_FIELDS_SIZE(m
) - framing
, &offsets
);
5031 n_offsets
= (BUS_MESSAGE_FIELDS_SIZE(m
) - framing
) / sz
;
5036 while (ri
< BUS_MESSAGE_FIELDS_SIZE(m
)) {
5037 _cleanup_free_
char *sig
= NULL
;
5038 const char *signature
;
5040 size_t item_size
= (size_t) -1;
5042 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5049 ri
= ALIGN_TO(read_word_le((uint8_t*) offsets
+ (i
-1)*sz
, sz
), 8);
5052 r
= message_peek_fields(m
, &ri
, 8, 1, (void**) &header
);
5056 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5061 end
= read_word_le((uint8_t*) offsets
+ i
*sz
, sz
);
5066 where
= ri
= ALIGN_TO(ri
, 8);
5067 item_size
= end
- ri
;
5068 r
= message_peek_fields(m
, &where
, 1, item_size
, &q
);
5072 b
= memrchr(q
, 0, item_size
);
5076 sig
= strndup(b
+1, item_size
- (b
+1-(char*) q
));
5081 item_size
= b
- (char*) q
;
5083 r
= message_peek_field_signature(m
, &ri
, 0, &signature
);
5089 case _BUS_MESSAGE_HEADER_INVALID
:
5092 case BUS_MESSAGE_HEADER_PATH
:
5097 if (!streq(signature
, "o"))
5100 r
= message_peek_field_string(m
, object_path_is_valid
, &ri
, item_size
, &m
->path
);
5103 case BUS_MESSAGE_HEADER_INTERFACE
:
5108 if (!streq(signature
, "s"))
5111 r
= message_peek_field_string(m
, interface_name_is_valid
, &ri
, item_size
, &m
->interface
);
5114 case BUS_MESSAGE_HEADER_MEMBER
:
5119 if (!streq(signature
, "s"))
5122 r
= message_peek_field_string(m
, member_name_is_valid
, &ri
, item_size
, &m
->member
);
5125 case BUS_MESSAGE_HEADER_ERROR_NAME
:
5130 if (!streq(signature
, "s"))
5133 r
= message_peek_field_string(m
, error_name_is_valid
, &ri
, item_size
, &m
->error
.name
);
5135 m
->error
._need_free
= -1;
5139 case BUS_MESSAGE_HEADER_DESTINATION
:
5144 if (!streq(signature
, "s"))
5147 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->destination
);
5150 case BUS_MESSAGE_HEADER_SENDER
:
5155 if (!streq(signature
, "s"))
5158 r
= message_peek_field_string(m
, service_name_is_valid
, &ri
, item_size
, &m
->sender
);
5160 if (r
>= 0 && m
->sender
[0] == ':' && m
->bus
->bus_client
&& !m
->bus
->is_kernel
) {
5161 m
->creds
.unique_name
= (char*) m
->sender
;
5162 m
->creds
.mask
|= SD_BUS_CREDS_UNIQUE_NAME
& m
->bus
->creds_mask
;
5168 case BUS_MESSAGE_HEADER_SIGNATURE
: {
5172 if (m
->root_container
.signature
)
5175 if (!streq(signature
, "g"))
5178 r
= message_peek_field_signature(m
, &ri
, item_size
, &s
);
5186 free(m
->root_container
.signature
);
5187 m
->root_container
.signature
= c
;
5191 case BUS_MESSAGE_HEADER_REPLY_SERIAL
: {
5194 if (m
->reply_cookie
!= 0)
5197 if (!streq(signature
, "u"))
5200 r
= message_peek_field_uint32(m
, &ri
, item_size
, &serial
);
5204 m
->reply_cookie
= serial
;
5206 if (m
->reply_cookie
== 0)
5212 case BUS_MESSAGE_HEADER_UNIX_FDS
:
5216 if (!streq(signature
, "u"))
5219 r
= message_peek_field_uint32(m
, &ri
, item_size
, &unix_fds
);
5223 unix_fds_set
= true;
5227 if (!BUS_MESSAGE_IS_GVARIANT(m
))
5228 r
= message_skip_fields(m
, &ri
, (uint32_t) -1, (const char **) &signature
);
5237 if (m
->n_fds
!= unix_fds
)
5240 switch (m
->header
->type
) {
5242 case SD_BUS_MESSAGE_SIGNAL
:
5243 if (!m
->path
|| !m
->interface
|| !m
->member
)
5246 if (m
->reply_cookie
!= 0)
5251 case SD_BUS_MESSAGE_METHOD_CALL
:
5253 if (!m
->path
|| !m
->member
)
5256 if (m
->reply_cookie
!= 0)
5261 case SD_BUS_MESSAGE_METHOD_RETURN
:
5263 if (m
->reply_cookie
== 0)
5267 case SD_BUS_MESSAGE_METHOD_ERROR
:
5269 if (m
->reply_cookie
== 0 || !m
->error
.name
)
5274 /* Refuse non-local messages that claim they are local */
5275 if (streq_ptr(m
->path
, "/org/freedesktop/DBus/Local"))
5277 if (streq_ptr(m
->interface
, "org.freedesktop.DBus.Local"))
5279 if (streq_ptr(m
->sender
, "org.freedesktop.DBus.Local"))
5282 m
->root_container
.end
= BUS_MESSAGE_BODY_SIZE(m
);
5284 if (BUS_MESSAGE_IS_GVARIANT(m
)) {
5285 r
= build_struct_offsets(
5287 m
->root_container
.signature
,
5288 BUS_MESSAGE_BODY_SIZE(m
),
5289 &m
->root_container
.item_size
,
5290 &m
->root_container
.offsets
,
5291 &m
->root_container
.n_offsets
);
5296 /* Try to read the error message, but if we can't it's a non-issue */
5297 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
)
5298 sd_bus_message_read(m
, "s", &m
->error
.message
);
5303 _public_
int sd_bus_message_set_destination(sd_bus_message
*m
, const char *destination
) {
5304 assert_return(m
, -EINVAL
);
5305 assert_return(destination
, -EINVAL
);
5306 assert_return(!m
->sealed
, -EPERM
);
5307 assert_return(!m
->destination
, -EEXIST
);
5309 return message_append_field_string(m
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, destination
, &m
->destination
);
5312 int bus_message_get_blob(sd_bus_message
*m
, void **buffer
, size_t *sz
) {
5316 struct bus_body_part
*part
;
5322 total
= BUS_MESSAGE_SIZE(m
);
5328 e
= mempcpy(p
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
5329 MESSAGE_FOREACH_PART(part
, i
, m
)
5330 e
= mempcpy(e
, part
->data
, part
->size
);
5332 assert(total
== (size_t) ((uint8_t*) e
- (uint8_t*) p
));
5340 int bus_message_read_strv_extend(sd_bus_message
*m
, char ***l
) {
5346 r
= sd_bus_message_enter_container(m
, 'a', "s");
5353 r
= sd_bus_message_read_basic(m
, 's', &s
);
5359 r
= strv_extend(l
, s
);
5364 r
= sd_bus_message_exit_container(m
);
5371 _public_
int sd_bus_message_read_strv(sd_bus_message
*m
, char ***l
) {
5375 assert_return(m
, -EINVAL
);
5376 assert_return(m
->sealed
, -EPERM
);
5377 assert_return(l
, -EINVAL
);
5379 r
= bus_message_read_strv_extend(m
, &strv
);
5389 int bus_message_get_arg(sd_bus_message
*m
, unsigned i
, const char **str
, char ***strv
) {
5390 const char *contents
;
5399 r
= sd_bus_message_rewind(m
, true);
5404 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
5410 /* Don't match against arguments after the first one we don't understand */
5411 if (!IN_SET(type
, SD_BUS_TYPE_STRING
, SD_BUS_TYPE_OBJECT_PATH
, SD_BUS_TYPE_SIGNATURE
) &&
5412 !(type
== SD_BUS_TYPE_ARRAY
&& STR_IN_SET(contents
, "s", "o", "g")))
5418 r
= sd_bus_message_skip(m
, NULL
);
5423 if (type
== SD_BUS_TYPE_ARRAY
) {
5425 r
= sd_bus_message_read_strv(m
, strv
);
5432 r
= sd_bus_message_read_basic(m
, type
, str
);
5442 bool bus_header_is_complete(struct bus_header
*h
, size_t size
) {
5448 if (size
< sizeof(struct bus_header
))
5451 full
= sizeof(struct bus_header
) +
5452 (h
->endian
== BUS_NATIVE_ENDIAN
? h
->fields_size
: bswap_32(h
->fields_size
));
5454 return size
>= full
;
5457 int bus_header_message_size(struct bus_header
*h
, size_t *sum
) {
5463 if (h
->endian
== BUS_NATIVE_ENDIAN
) {
5464 fs
= h
->fields_size
;
5466 } else if (h
->endian
== BUS_REVERSE_ENDIAN
) {
5467 fs
= bswap_32(h
->fields_size
);
5468 bs
= bswap_32(h
->body_size
);
5472 *sum
= sizeof(struct bus_header
) + ALIGN8(fs
) + bs
;
5476 _public_
int sd_bus_message_get_errno(sd_bus_message
*m
) {
5477 assert_return(m
, EINVAL
);
5479 if (m
->header
->type
!= SD_BUS_MESSAGE_METHOD_ERROR
)
5482 return sd_bus_error_get_errno(&m
->error
);
5485 _public_
const char* sd_bus_message_get_signature(sd_bus_message
*m
, int complete
) {
5486 struct bus_container
*c
;
5488 assert_return(m
, NULL
);
5490 c
= complete
? &m
->root_container
: message_get_container(m
);
5491 return strempty(c
->signature
);
5494 _public_
int sd_bus_message_is_empty(sd_bus_message
*m
) {
5495 assert_return(m
, -EINVAL
);
5497 return isempty(m
->root_container
.signature
);
5500 _public_
int sd_bus_message_has_signature(sd_bus_message
*m
, const char *signature
) {
5501 assert_return(m
, -EINVAL
);
5503 return streq(strempty(m
->root_container
.signature
), strempty(signature
));
5506 _public_
int sd_bus_message_copy(sd_bus_message
*m
, sd_bus_message
*source
, int all
) {
5507 bool done_something
= false;
5510 assert_return(m
, -EINVAL
);
5511 assert_return(source
, -EINVAL
);
5512 assert_return(!m
->sealed
, -EPERM
);
5513 assert_return(source
->sealed
, -EPERM
);
5516 const char *contents
;
5531 r
= sd_bus_message_peek_type(source
, &type
, &contents
);
5537 done_something
= true;
5539 if (bus_type_is_container(type
) > 0) {
5541 r
= sd_bus_message_enter_container(source
, type
, contents
);
5545 r
= sd_bus_message_open_container(m
, type
, contents
);
5549 r
= sd_bus_message_copy(m
, source
, true);
5553 r
= sd_bus_message_close_container(m
);
5557 r
= sd_bus_message_exit_container(source
);
5564 r
= sd_bus_message_read_basic(source
, type
, &basic
);
5570 if (type
== SD_BUS_TYPE_OBJECT_PATH
||
5571 type
== SD_BUS_TYPE_SIGNATURE
||
5572 type
== SD_BUS_TYPE_STRING
)
5573 r
= sd_bus_message_append_basic(m
, type
, basic
.string
);
5575 r
= sd_bus_message_append_basic(m
, type
, &basic
);
5582 return done_something
;
5585 _public_
int sd_bus_message_verify_type(sd_bus_message
*m
, char type
, const char *contents
) {
5590 assert_return(m
, -EINVAL
);
5591 assert_return(m
->sealed
, -EPERM
);
5592 assert_return(!type
|| bus_type_is_valid(type
), -EINVAL
);
5593 assert_return(!contents
|| signature_is_valid(contents
, true), -EINVAL
);
5594 assert_return(type
|| contents
, -EINVAL
);
5595 assert_return(!contents
|| !type
|| bus_type_is_container(type
), -EINVAL
);
5597 r
= sd_bus_message_peek_type(m
, &t
, &c
);
5601 if (type
!= 0 && type
!= t
)
5604 if (contents
&& !streq_ptr(contents
, c
))
5610 _public_ sd_bus
*sd_bus_message_get_bus(sd_bus_message
*m
) {
5611 assert_return(m
, NULL
);
5616 int bus_message_remarshal(sd_bus
*bus
, sd_bus_message
**m
) {
5617 _cleanup_bus_message_unref_ sd_bus_message
*n
= NULL
;
5625 switch ((*m
)->header
->type
) {
5627 case SD_BUS_MESSAGE_SIGNAL
:
5628 r
= sd_bus_message_new_signal(bus
, &n
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5634 case SD_BUS_MESSAGE_METHOD_CALL
:
5635 r
= sd_bus_message_new_method_call(bus
, &n
, (*m
)->destination
, (*m
)->path
, (*m
)->interface
, (*m
)->member
);
5641 case SD_BUS_MESSAGE_METHOD_RETURN
:
5642 case SD_BUS_MESSAGE_METHOD_ERROR
:
5644 n
= message_new(bus
, (*m
)->header
->type
);
5648 n
->reply_cookie
= (*m
)->reply_cookie
;
5649 r
= message_append_field_uint32(n
, BUS_MESSAGE_HEADER_REPLY_SERIAL
, (uint32_t) n
->reply_cookie
);
5653 if ((*m
)->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
&& (*m
)->error
.name
) {
5654 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_ERROR_NAME
, SD_BUS_TYPE_STRING
, (*m
)->error
.name
, &n
->error
.message
);
5658 n
->error
._need_free
= -1;
5667 if ((*m
)->destination
&& !n
->destination
) {
5668 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_DESTINATION
, SD_BUS_TYPE_STRING
, (*m
)->destination
, &n
->destination
);
5673 if ((*m
)->sender
&& !n
->sender
) {
5674 r
= message_append_field_string(n
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, (*m
)->sender
, &n
->sender
);
5679 n
->header
->flags
|= (*m
)->header
->flags
& (BUS_MESSAGE_NO_REPLY_EXPECTED
|BUS_MESSAGE_NO_AUTO_START
);
5681 r
= sd_bus_message_copy(n
, *m
, true);
5685 timeout
= (*m
)->timeout
;
5686 if (timeout
== 0 && !((*m
)->header
->flags
& BUS_MESSAGE_NO_REPLY_EXPECTED
))
5687 timeout
= BUS_DEFAULT_TIMEOUT
;
5689 r
= bus_message_seal(n
, BUS_MESSAGE_COOKIE(*m
), timeout
);
5693 sd_bus_message_unref(*m
);
5700 int bus_message_append_sender(sd_bus_message
*m
, const char *sender
) {
5704 assert_return(!m
->sealed
, -EPERM
);
5705 assert_return(!m
->sender
, -EPERM
);
5707 return message_append_field_string(m
, BUS_MESSAGE_HEADER_SENDER
, SD_BUS_TYPE_STRING
, sender
, &m
->sender
);
5710 _public_
int sd_bus_message_get_priority(sd_bus_message
*m
, int64_t *priority
) {
5711 assert_return(m
, -EINVAL
);
5712 assert_return(priority
, -EINVAL
);
5714 *priority
= m
->priority
;
5718 _public_
int sd_bus_message_set_priority(sd_bus_message
*m
, int64_t priority
) {
5719 assert_return(m
, -EINVAL
);
5720 assert_return(!m
->sealed
, -EPERM
);
5722 m
->priority
= priority
;