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/>.
28 #include "time-util.h"
29 #include "cgroup-util.h"
32 #include "bus-message.h"
33 #include "bus-internal.h"
35 #include "bus-signature.h"
37 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
39 static void reset_containers(sd_bus_message *m) {
44 for (i = 0; i < m->n_containers; i++)
45 free(m->containers[i].signature);
51 m->root_container.index = 0;
54 static void message_free(sd_bus_message *m) {
70 close_many(m->fds, m->n_fds);
74 free(m->cmdline_array);
77 free(m->root_container.signature);
79 free(m->peeked_signature);
87 static void* buffer_extend(void **p, uint32_t *sz, size_t align, size_t extend) {
95 start = ALIGN_TO((size_t) *sz, align);
99 return (uint8_t*) *p + start;
101 if (n > (size_t) ((uint32_t) -1))
108 /* Zero out padding */
110 memset((uint8_t*) k + *sz, 0, start - *sz);
115 return (uint8_t*) k + start;
118 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz) {
124 p = buffer_extend(&m->fields, &m->header->fields_size, align, sz);
128 if (o != m->fields) {
129 /* Adjust quick access pointers */
132 m->path = (const char*) m->fields + (m->path - (const char*) o);
134 m->interface = (const char*) m->fields + (m->interface - (const char*) o);
136 m->member = (const char*) m->fields + (m->member - (const char*) o);
138 m->destination = (const char*) m->fields + (m->destination - (const char*) o);
140 m->sender = (const char*) m->fields + (m->sender - (const char*) o);
142 m->error.name = (const char*) m->fields + (m->error.name - (const char*) o);
145 m->free_fields = true;
150 static int message_append_field_string(
163 if (l > (size_t) (uint32_t) -1)
166 /* field id byte + signature length + signature 's' + NUL + string length + string + NUL */
167 p = message_extend_fields(m, 8, 4 + 4 + l + 1);
176 ((uint32_t*) p)[1] = l;
177 memcpy(p + 8, s, l + 1);
180 *ret = (const char*) p + 8;
185 static int message_append_field_signature(
200 /* field id byte + signature length + signature 'g' + NUL + string length + string + NUL */
201 p = message_extend_fields(m, 8, 4 + 1 + l + 1);
207 p[2] = SD_BUS_TYPE_SIGNATURE;
210 memcpy(p + 5, s, l + 1);
213 *ret = (const char*) p + 5;
218 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
223 /* field id byte + signature length + signature 'u' + NUL + value */
224 p = message_extend_fields(m, 8, 4 + 4);
230 p[2] = SD_BUS_TYPE_UINT32;
233 ((uint32_t*) p)[1] = x;
238 int bus_message_from_header(
243 const struct ucred *ucred,
246 sd_bus_message **ret) {
249 struct bus_header *h;
252 assert(buffer || length <= 0);
253 assert(fds || n_fds <= 0);
256 if (length < sizeof(struct bus_header))
266 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
269 if (h->endian != SD_BUS_LITTLE_ENDIAN &&
270 h->endian != SD_BUS_BIG_ENDIAN)
273 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
276 label_sz = strlen(label);
294 m->uid_valid = m->gid_valid = true;
298 m->label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
299 memcpy(m->label, label, label_sz + 1);
306 int bus_message_from_malloc(
311 const struct ucred *ucred,
313 sd_bus_message **ret) {
318 r = bus_message_from_header(buffer, length, fds, n_fds, ucred, label, 0, &m);
322 if (length != BUS_MESSAGE_SIZE(m)) {
327 m->fields = (uint8_t*) buffer + sizeof(struct bus_header);
328 m->body = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
331 m->iovec[0].iov_base = buffer;
332 m->iovec[0].iov_len = length;
334 r = bus_message_parse_fields(m);
338 /* We take possession of the memory and fds now */
339 m->free_header = true;
350 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
353 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
358 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
359 m->header->endian = SD_BUS_NATIVE_ENDIAN;
360 m->header->type = type;
361 m->header->version = bus ? bus->message_version : 1;
362 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
367 int sd_bus_message_new_signal(
370 const char *interface,
372 sd_bus_message **m) {
385 if (bus && bus->state == BUS_UNSET)
388 t = message_new(bus, SD_BUS_MESSAGE_TYPE_SIGNAL);
392 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
394 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
397 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
400 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
408 sd_bus_message_unref(t);
412 int sd_bus_message_new_method_call(
414 const char *destination,
416 const char *interface,
418 sd_bus_message **m) {
429 if (bus && bus->state == BUS_UNSET)
432 t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_CALL);
436 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
439 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
444 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
450 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
463 static int message_new_reply(
465 sd_bus_message *call,
467 sd_bus_message **m) {
476 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
480 if (bus && bus->state == BUS_UNSET)
483 t = message_new(bus, type);
487 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
488 t->reply_serial = BUS_MESSAGE_SERIAL(call);
490 r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
495 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->sender);
500 t->dont_send = !!(call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED);
510 int sd_bus_message_new_method_return(
512 sd_bus_message *call,
513 sd_bus_message **m) {
515 return message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_RETURN, m);
518 int sd_bus_message_new_method_error(
520 sd_bus_message *call,
521 const sd_bus_error *e,
522 sd_bus_message **m) {
527 if (!sd_bus_error_is_set(e))
532 r = message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_ERROR, &t);
536 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
541 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
554 sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
558 assert(m->n_ref > 0);
564 sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
568 assert(m->n_ref > 0);
577 int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
583 *type = m->header->type;
587 int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
592 if (m->header->serial == 0)
595 *serial = BUS_MESSAGE_SERIAL(m);
599 int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
604 if (m->reply_serial == 0)
607 *serial = m->reply_serial;
611 int sd_bus_message_get_no_reply(sd_bus_message *m) {
615 return m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL ? !!(m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
618 const char *sd_bus_message_get_path(sd_bus_message *m) {
625 const char *sd_bus_message_get_interface(sd_bus_message *m) {
632 const char *sd_bus_message_get_member(sd_bus_message *m) {
638 const char *sd_bus_message_get_destination(sd_bus_message *m) {
642 return m->destination;
645 const char *sd_bus_message_get_sender(sd_bus_message *m) {
652 const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
656 if (!sd_bus_error_is_set(&m->error))
662 int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) {
674 int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) {
686 int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) {
698 int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) {
710 int sd_bus_message_get_pid_starttime(sd_bus_message *m, uint64_t *usec) {
715 if (m->pid_starttime <= 0)
718 *usec = m->pid_starttime;
722 int sd_bus_message_get_selinux_context(sd_bus_message *m, const char **ret) {
732 int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
737 if (m->monotonic <= 0)
740 *usec = m->monotonic;
744 int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
749 if (m->realtime <= 0)
756 int sd_bus_message_get_comm(sd_bus_message *m, const char **ret) {
768 int sd_bus_message_get_tid_comm(sd_bus_message *m, const char **ret) {
780 int sd_bus_message_get_exe(sd_bus_message *m, const char **ret) {
792 int sd_bus_message_get_cgroup(sd_bus_message *m, const char **ret) {
804 int sd_bus_message_get_unit(sd_bus_message *m, const char **ret) {
815 r = cg_path_get_unit(m->cgroup, &m->unit);
824 int sd_bus_message_get_user_unit(sd_bus_message *m, const char **ret) {
835 r = cg_path_get_user_unit(m->cgroup, &m->user_unit);
844 int sd_bus_message_get_session(sd_bus_message *m, const char **ret) {
855 r = cg_path_get_session(m->cgroup, &m->session);
864 int sd_bus_message_get_owner_uid(sd_bus_message *m, uid_t *uid) {
872 return cg_path_get_owner_uid(m->cgroup, uid);
875 int sd_bus_message_get_cmdline(sd_bus_message *m, char ***cmdline) {
886 for (p = m->cmdline, n = 0; p < m->cmdline + m->cmdline_length; p++)
890 m->cmdline_array = new(char*, n + 1);
891 if (!m->cmdline_array)
894 for (p = m->cmdline, i = 0, first = true; p < m->cmdline + m->cmdline_length; p++) {
896 m->cmdline_array[i++] = (char*) p;
901 m->cmdline_array[i] = NULL;
902 *cmdline = m->cmdline_array;
907 int sd_bus_message_get_audit_sessionid(sd_bus_message *m, uint32_t *sessionid) {
915 *sessionid = m->audit->sessionid;
919 int sd_bus_message_get_audit_loginuid(sd_bus_message *m, uid_t *uid) {
927 *uid = m->audit->loginuid;
931 int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member) {
935 if (m->header->type != SD_BUS_MESSAGE_TYPE_SIGNAL)
938 if (interface && (!m->interface || !streq(m->interface, interface)))
941 if (member && (!m->member || !streq(m->member, member)))
947 int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member) {
951 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
954 if (interface && (!m->interface || !streq(m->interface, interface)))
957 if (member && (!m->member || !streq(m->member, member)))
963 int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
967 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
970 if (name && (!m->error.name || !streq(m->error.name, name)))
976 int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
981 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
985 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
987 m->header->flags &= ~SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
992 static struct bus_container *message_get_container(sd_bus_message *m) {
995 if (m->n_containers == 0)
996 return &m->root_container;
998 assert(m->containers);
999 return m->containers + m->n_containers - 1;
1002 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
1005 struct bus_container *c;
1011 added = m->header->body_size;
1013 p = buffer_extend(&m->body, &m->header->body_size, align, sz);
1017 added = m->header->body_size - added;
1019 for (c = m->containers; c < m->containers + m->n_containers; c++)
1020 if (c->array_size) {
1021 c->array_size = (uint32_t*) ((uint8_t*) m->body + ((uint8_t*) c->array_size - (uint8_t*) o));
1022 *c->array_size += added;
1026 if (m->error.message)
1027 m->error.message = (const char*) m->body + (m->error.message - (const char*) o);
1030 m->free_body = true;
1035 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1036 struct bus_container *c;
1051 if (!bus_type_is_basic(type))
1054 c = message_get_container(m);
1056 if (c->signature && c->signature[c->index]) {
1057 /* Container signature is already set */
1059 if (c->signature[c->index] != type)
1062 /* Maybe we can append to the signature? But only if this is the top-level container*/
1063 if (c->enclosing != 0)
1066 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1073 case SD_BUS_TYPE_STRING:
1074 case SD_BUS_TYPE_OBJECT_PATH:
1077 sz = 4 + strlen(p) + 1;
1080 case SD_BUS_TYPE_SIGNATURE:
1083 sz = 1 + strlen(p) + 1;
1086 case SD_BUS_TYPE_BOOLEAN:
1089 assert_cc(sizeof(int) == sizeof(uint32_t));
1095 case SD_BUS_TYPE_UNIX_FD: {
1098 if (!m->allow_fds) {
1111 fd = fcntl(z, F_DUPFD_CLOEXEC, 3);
1117 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1131 align = bus_type_get_alignment(type);
1132 sz = bus_type_get_size(type);
1139 a = message_extend_body(m, align, sz);
1145 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1146 *(uint32_t*) a = sz - 5;
1147 memcpy((uint8_t*) a + 4, p, sz - 4);
1150 *stored = (const uint8_t*) a + 4;
1152 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1153 *(uint8_t*) a = sz - 1;
1154 memcpy((uint8_t*) a + 1, p, sz - 1);
1157 *stored = (const uint8_t*) a + 1;
1158 } else if (type == SD_BUS_TYPE_UNIX_FD) {
1159 *(uint32_t*) a = fdi;
1173 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1179 /* Truncate extended signature again */
1181 c->signature[c->index] = 0;
1184 close_nointr_nofail(fd);
1189 int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1190 return message_append_basic(m, type, p, NULL);
1193 static int bus_message_open_array(
1195 struct bus_container *c,
1196 const char *contents,
1197 uint32_t **array_size) {
1210 if (!signature_is_single(contents))
1213 alignment = bus_type_get_alignment(contents[0]);
1217 if (c->signature && c->signature[c->index]) {
1219 /* Verify the existing signature */
1221 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1224 if (!startswith(c->signature + c->index + 1, contents))
1227 nindex = c->index + 1 + strlen(contents);
1229 if (c->enclosing != 0)
1232 /* Extend the existing signature */
1234 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1238 nindex = e - c->signature;
1241 saved = m->header->body_size;
1242 a = message_extend_body(m, 4, 4);
1244 /* Truncate extended signature again */
1246 c->signature[c->index] = 0;
1252 if (!message_extend_body(m, alignment, 0)) {
1253 /* Add alignment between size and first element */
1255 c->signature[c->index] = 0;
1257 m->header->body_size = saved;
1261 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1264 /* m->body might have changed so let's readjust a */
1265 a = (uint8_t*) m->body + ((uint8_t*) a - (uint8_t*) b);
1272 static int bus_message_open_variant(
1274 struct bus_container *c,
1275 const char *contents) {
1285 if (!signature_is_single(contents))
1288 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1291 if (c->signature && c->signature[c->index]) {
1293 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1297 if (c->enclosing != 0)
1300 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1305 l = strlen(contents);
1306 a = message_extend_body(m, 1, 1 + l + 1);
1308 /* Truncate extended signature again */
1310 c->signature[c->index] = 0;
1316 memcpy((uint8_t*) a + 1, contents, l + 1);
1318 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1324 static int bus_message_open_struct(
1326 struct bus_container *c,
1327 const char *contents) {
1336 if (!signature_is_valid(contents, false))
1339 if (c->signature && c->signature[c->index]) {
1342 l = strlen(contents);
1344 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1345 !startswith(c->signature + c->index + 1, contents) ||
1346 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1349 nindex = c->index + 1 + l + 1;
1351 if (c->enclosing != 0)
1354 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1358 nindex = e - c->signature;
1361 /* Align contents to 8 byte boundary */
1362 if (!message_extend_body(m, 8, 0)) {
1364 c->signature[c->index] = 0;
1369 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1375 static int bus_message_open_dict_entry(
1377 struct bus_container *c,
1378 const char *contents) {
1386 if (!signature_is_pair(contents))
1389 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1392 if (c->signature && c->signature[c->index]) {
1395 l = strlen(contents);
1397 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1398 !startswith(c->signature + c->index + 1, contents) ||
1399 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1402 nindex = c->index + 1 + l + 1;
1406 /* Align contents to 8 byte boundary */
1407 if (!message_extend_body(m, 8, 0))
1410 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1416 int sd_bus_message_open_container(
1419 const char *contents) {
1421 struct bus_container *c, *w;
1422 uint32_t *array_size = NULL;
1433 /* Make sure we have space for one more container */
1434 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1439 c = message_get_container(m);
1441 signature = strdup(contents);
1445 if (type == SD_BUS_TYPE_ARRAY)
1446 r = bus_message_open_array(m, c, contents, &array_size);
1447 else if (type == SD_BUS_TYPE_VARIANT)
1448 r = bus_message_open_variant(m, c, contents);
1449 else if (type == SD_BUS_TYPE_STRUCT)
1450 r = bus_message_open_struct(m, c, contents);
1451 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1452 r = bus_message_open_dict_entry(m, c, contents);
1461 /* OK, let's fill it in */
1462 w += m->n_containers++;
1463 w->enclosing = type;
1464 w->signature = signature;
1466 w->array_size = array_size;
1472 int sd_bus_message_close_container(sd_bus_message *m) {
1473 struct bus_container *c;
1479 if (m->n_containers <= 0)
1482 c = message_get_container(m);
1483 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1484 if (c->signature && c->signature[c->index] != 0)
1500 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
1507 stack[*i].types = types;
1508 stack[*i].n_struct = n_struct;
1509 stack[*i].n_array = n_array;
1515 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
1526 *types = stack[*i].types;
1527 *n_struct = stack[*i].n_struct;
1528 *n_array = stack[*i].n_array;
1533 int bus_message_append_ap(
1538 unsigned n_array, n_struct;
1539 TypeStack stack[BUS_CONTAINER_DEPTH];
1540 unsigned stack_ptr = 0;
1548 n_array = (unsigned) -1;
1549 n_struct = strlen(types);
1554 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
1555 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
1561 r = sd_bus_message_close_container(m);
1569 if (n_array != (unsigned) -1)
1578 case SD_BUS_TYPE_BYTE: {
1581 x = (uint8_t) va_arg(ap, int);
1582 r = sd_bus_message_append_basic(m, *t, &x);
1586 case SD_BUS_TYPE_BOOLEAN:
1587 case SD_BUS_TYPE_INT32:
1588 case SD_BUS_TYPE_UINT32:
1589 case SD_BUS_TYPE_UNIX_FD: {
1592 /* We assume a boolean is the same as int32_t */
1593 assert_cc(sizeof(int32_t) == sizeof(int));
1595 x = va_arg(ap, uint32_t);
1596 r = sd_bus_message_append_basic(m, *t, &x);
1600 case SD_BUS_TYPE_INT16:
1601 case SD_BUS_TYPE_UINT16: {
1604 x = (uint16_t) va_arg(ap, int);
1605 r = sd_bus_message_append_basic(m, *t, &x);
1609 case SD_BUS_TYPE_INT64:
1610 case SD_BUS_TYPE_UINT64:
1611 case SD_BUS_TYPE_DOUBLE: {
1614 x = va_arg(ap, uint64_t);
1615 r = sd_bus_message_append_basic(m, *t, &x);
1619 case SD_BUS_TYPE_STRING:
1620 case SD_BUS_TYPE_OBJECT_PATH:
1621 case SD_BUS_TYPE_SIGNATURE: {
1624 x = va_arg(ap, const char*);
1625 r = sd_bus_message_append_basic(m, *t, x);
1629 case SD_BUS_TYPE_ARRAY: {
1632 r = signature_element_length(t + 1, &k);
1638 memcpy(s, t + 1, k);
1641 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1646 if (n_array == (unsigned) -1) {
1651 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
1657 n_array = va_arg(ap, unsigned);
1662 case SD_BUS_TYPE_VARIANT: {
1665 s = va_arg(ap, const char*);
1669 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
1673 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
1678 n_struct = strlen(s);
1679 n_array = (unsigned) -1;
1684 case SD_BUS_TYPE_STRUCT_BEGIN:
1685 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
1688 r = signature_element_length(t, &k);
1695 memcpy(s, t + 1, k - 2);
1698 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
1703 if (n_array == (unsigned) -1) {
1708 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
1714 n_array = (unsigned) -1;
1730 int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
1741 va_start(ap, types);
1742 r = bus_message_append_ap(m, types, ap);
1748 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
1754 start = ALIGN_TO((size_t) *rindex, align);
1760 /* Verify that padding is 0 */
1761 for (k = *rindex; k < start; k++)
1762 if (((const uint8_t*) p)[k] != 0)
1766 *r = (uint8_t*) p + start;
1773 static bool message_end_of_array(sd_bus_message *m, size_t index) {
1774 struct bus_container *c;
1778 c = message_get_container(m);
1782 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
1785 static int message_peek_body(sd_bus_message *m, size_t *rindex, size_t align, size_t nbytes, void **ret) {
1790 if (message_end_of_array(m, *rindex))
1793 return buffer_peek(m->body, BUS_MESSAGE_BODY_SIZE(m), rindex, align, nbytes, ret);
1796 static bool validate_nul(const char *s, size_t l) {
1798 /* Check for NUL chars in the string */
1799 if (memchr(s, 0, l))
1802 /* Check for NUL termination */
1809 static bool validate_string(const char *s, size_t l) {
1811 if (!validate_nul(s, l))
1814 /* Check if valid UTF8 */
1815 if (!utf8_is_valid(s))
1821 static bool validate_signature(const char *s, size_t l) {
1823 if (!validate_nul(s, l))
1826 /* Check if valid signature */
1827 if (!signature_is_valid(s, true))
1833 static bool validate_object_path(const char *s, size_t l) {
1835 if (!validate_nul(s, l))
1838 if (!object_path_is_valid(s))
1844 int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
1845 struct bus_container *c;
1853 if (!bus_type_is_basic(type))
1858 c = message_get_container(m);
1860 if (!c->signature || c->signature[c->index] == 0)
1863 if (c->signature[c->index] != type)
1868 case SD_BUS_TYPE_STRING:
1869 case SD_BUS_TYPE_OBJECT_PATH: {
1874 r = message_peek_body(m, &rindex, 4, 4, &q);
1878 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1879 r = message_peek_body(m, &rindex, 1, l+1, &q);
1885 if (type == SD_BUS_TYPE_OBJECT_PATH) {
1886 if (!validate_object_path(q, l))
1889 if (!validate_string(q, l))
1894 *(const char**) p = q;
1898 case SD_BUS_TYPE_SIGNATURE: {
1903 r = message_peek_body(m, &rindex, 1, 1, &q);
1908 r = message_peek_body(m, &rindex, 1, l+1, &q);
1914 if (!validate_signature(q, l))
1918 *(const char**) p = q;
1926 align = bus_type_get_alignment(type);
1927 sz = bus_type_get_size(type);
1928 assert(align > 0 && sz > 0);
1931 r = message_peek_body(m, &rindex, align, sz, &q);
1937 case SD_BUS_TYPE_BYTE:
1938 *(uint8_t*) p = *(uint8_t*) q;
1941 case SD_BUS_TYPE_BOOLEAN:
1942 *(int*) p = !!*(uint32_t*) q;
1945 case SD_BUS_TYPE_INT16:
1946 case SD_BUS_TYPE_UINT16:
1947 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
1950 case SD_BUS_TYPE_INT32:
1951 case SD_BUS_TYPE_UINT32:
1952 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1955 case SD_BUS_TYPE_INT64:
1956 case SD_BUS_TYPE_UINT64:
1957 case SD_BUS_TYPE_DOUBLE:
1958 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
1961 case SD_BUS_TYPE_UNIX_FD: {
1964 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1968 *(int*) p = m->fds[j];
1973 assert_not_reached("Unknown basic type...");
1982 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1988 static int bus_message_enter_array(
1990 struct bus_container *c,
1991 const char *contents,
1992 uint32_t **array_size) {
2003 if (!signature_is_single(contents))
2006 alignment = bus_type_get_alignment(contents[0]);
2010 if (!c->signature || c->signature[c->index] == 0)
2013 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
2016 if (!startswith(c->signature + c->index + 1, contents))
2020 r = message_peek_body(m, &rindex, 4, 4, &q);
2024 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
2027 r = message_peek_body(m, &rindex, alignment, 0, NULL);
2033 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2034 c->index += 1 + strlen(contents);
2038 *array_size = (uint32_t*) q;
2043 static int bus_message_enter_variant(
2045 struct bus_container *c,
2046 const char *contents) {
2057 if (!signature_is_single(contents))
2060 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
2063 if (!c->signature || c->signature[c->index] == 0)
2066 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
2070 r = message_peek_body(m, &rindex, 1, 1, &q);
2075 r = message_peek_body(m, &rindex, 1, l+1, &q);
2081 if (!validate_signature(q, l))
2084 if (!streq(q, contents))
2087 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2095 static int bus_message_enter_struct(
2097 struct bus_container *c,
2098 const char *contents) {
2107 if (!signature_is_valid(contents, false))
2110 if (!c->signature || c->signature[c->index] == 0)
2113 l = strlen(contents);
2115 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
2116 !startswith(c->signature + c->index + 1, contents) ||
2117 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
2120 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
2124 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2125 c->index += 1 + l + 1;
2130 static int bus_message_enter_dict_entry(
2132 struct bus_container *c,
2133 const char *contents) {
2142 if (!signature_is_pair(contents))
2145 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2148 if (!c->signature || c->signature[c->index] == 0)
2151 l = strlen(contents);
2153 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2154 !startswith(c->signature + c->index + 1, contents) ||
2155 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2158 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
2162 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2163 c->index += 1 + l + 1;
2168 int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents) {
2169 struct bus_container *c, *w;
2170 uint32_t *array_size = NULL;
2182 * We enforce a global limit on container depth, that is much
2183 * higher than the 32 structs and 32 arrays the specification
2184 * mandates. This is simpler to implement for us, and we need
2185 * this only to ensure our container array doesn't grow
2186 * without bounds. We are happy to return any data from a
2187 * message as long as the data itself is valid, even if the
2188 * overall message might be not.
2190 * Note that the message signature is validated when
2191 * parsing the headers, and that validation does check the
2194 * Note that the specification defines no limits on the depth
2195 * of stacked variants, but we do.
2197 if (m->n_containers >= BUS_CONTAINER_DEPTH)
2200 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
2205 c = message_get_container(m);
2207 if (!c->signature || c->signature[c->index] == 0)
2210 signature = strdup(contents);
2214 if (type == SD_BUS_TYPE_ARRAY)
2215 r = bus_message_enter_array(m, c, contents, &array_size);
2216 else if (type == SD_BUS_TYPE_VARIANT)
2217 r = bus_message_enter_variant(m, c, contents);
2218 else if (type == SD_BUS_TYPE_STRUCT)
2219 r = bus_message_enter_struct(m, c, contents);
2220 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2221 r = bus_message_enter_dict_entry(m, c, contents);
2230 /* OK, let's fill it in */
2231 w += m->n_containers++;
2232 w->enclosing = type;
2233 w->signature = signature;
2235 w->array_size = array_size;
2236 w->begin = m->rindex;
2241 int sd_bus_message_exit_container(sd_bus_message *m) {
2242 struct bus_container *c;
2248 if (m->n_containers <= 0)
2251 c = message_get_container(m);
2252 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2255 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
2256 if (c->begin + l != m->rindex)
2260 if (c->signature && c->signature[c->index] != 0)
2270 int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
2271 struct bus_container *c;
2279 c = message_get_container(m);
2281 if (!c->signature || c->signature[c->index] == 0)
2284 if (message_end_of_array(m, m->rindex))
2287 if (bus_type_is_basic(c->signature[c->index])) {
2291 *type = c->signature[c->index];
2295 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
2301 r = signature_element_length(c->signature+c->index+1, &l);
2307 sig = strndup(c->signature + c->index + 1, l);
2311 free(m->peeked_signature);
2312 m->peeked_signature = sig;
2318 *type = SD_BUS_TYPE_ARRAY;
2323 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
2324 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
2330 r = signature_element_length(c->signature+c->index, &l);
2335 sig = strndup(c->signature + c->index + 1, l - 2);
2339 free(m->peeked_signature);
2340 m->peeked_signature = sig;
2346 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
2351 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
2357 r = message_peek_body(m, &rindex, 1, 1, &q);
2364 r = message_peek_body(m, &rindex, 1, l+1, &q);
2370 if (!validate_signature(q, l))
2377 *type = SD_BUS_TYPE_VARIANT;
2386 *type = c->enclosing;
2392 int sd_bus_message_rewind(sd_bus_message *m, int complete) {
2393 struct bus_container *c;
2401 reset_containers(m);
2403 m->root_container.index = 0;
2405 c = message_get_container(m);
2407 c = message_get_container(m);
2410 m->rindex = c->begin;
2413 return !isempty(c->signature);
2415 static int message_read_ap(
2420 unsigned n_array, n_struct;
2421 TypeStack stack[BUS_CONTAINER_DEPTH];
2422 unsigned stack_ptr = 0;
2430 /* Ideally, we'd just call ourselves recursively on every
2431 * complex type. However, the state of a va_list that is
2432 * passed to a function is undefined after that function
2433 * returns. This means we need to docode the va_list linearly
2434 * in a single stackframe. We hence implement our own
2435 * home-grown stack in an array. */
2437 n_array = (unsigned) -1;
2438 n_struct = strlen(types);
2443 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2444 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2450 r = sd_bus_message_exit_container(m);
2458 if (n_array != (unsigned) -1)
2467 case SD_BUS_TYPE_BYTE:
2468 case SD_BUS_TYPE_BOOLEAN:
2469 case SD_BUS_TYPE_INT16:
2470 case SD_BUS_TYPE_UINT16:
2471 case SD_BUS_TYPE_INT32:
2472 case SD_BUS_TYPE_UINT32:
2473 case SD_BUS_TYPE_INT64:
2474 case SD_BUS_TYPE_UINT64:
2475 case SD_BUS_TYPE_DOUBLE:
2476 case SD_BUS_TYPE_STRING:
2477 case SD_BUS_TYPE_OBJECT_PATH:
2478 case SD_BUS_TYPE_SIGNATURE:
2479 case SD_BUS_TYPE_UNIX_FD: {
2482 p = va_arg(ap, void*);
2483 r = sd_bus_message_read_basic(m, *t, p);
2492 case SD_BUS_TYPE_ARRAY: {
2495 r = signature_element_length(t + 1, &k);
2501 memcpy(s, t + 1, k);
2504 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
2511 if (n_array == (unsigned) -1) {
2516 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2522 n_array = va_arg(ap, unsigned);
2527 case SD_BUS_TYPE_VARIANT: {
2530 s = va_arg(ap, const char *);
2534 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
2540 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2545 n_struct = strlen(s);
2546 n_array = (unsigned) -1;
2551 case SD_BUS_TYPE_STRUCT_BEGIN:
2552 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2555 r = signature_element_length(t, &k);
2561 memcpy(s, t + 1, k - 2);
2564 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2571 if (n_array == (unsigned) -1) {
2576 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2582 n_array = (unsigned) -1;
2595 int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
2606 va_start(ap, types);
2607 r = message_read_ap(m, types, ap);
2613 static int message_peek_fields(
2624 return buffer_peek(m->fields, BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
2627 static int message_peek_field_uint32(
2638 r = message_peek_fields(m, ri, 4, 4, &q);
2643 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2648 static int message_peek_field_string(
2650 bool (*validate)(const char *p),
2661 r = message_peek_field_uint32(m, ri, &l);
2665 r = message_peek_fields(m, ri, 1, l+1, &q);
2670 if (!validate_nul(q, l))
2676 if (!validate_string(q, l))
2686 static int message_peek_field_signature(
2698 r = message_peek_fields(m, ri, 1, 1, &q);
2703 r = message_peek_fields(m, ri, 1, l+1, &q);
2707 if (!validate_signature(q, l))
2716 static int message_skip_fields(
2719 uint32_t array_size,
2720 const char **signature) {
2722 size_t original_index;
2729 original_index = *ri;
2735 if (array_size != (uint32_t) -1 &&
2736 array_size <= *ri - original_index)
2743 if (t == SD_BUS_TYPE_STRING) {
2745 r = message_peek_field_string(m, NULL, ri, NULL);
2751 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
2753 r = message_peek_field_string(m, object_path_is_valid, ri, NULL);
2759 } else if (t == SD_BUS_TYPE_SIGNATURE) {
2761 r = message_peek_field_signature(m, ri, NULL);
2767 } else if (bus_type_is_basic(t)) {
2770 align = bus_type_get_alignment(t);
2771 k = bus_type_get_size(t);
2772 assert(align > 0 && k > 0);
2774 r = message_peek_fields(m, ri, align, k, NULL);
2780 } else if (t == SD_BUS_TYPE_ARRAY) {
2782 r = signature_element_length(*signature+1, &l);
2792 strncpy(sig, *signature + 1, l-1);
2795 alignment = bus_type_get_alignment(sig[0]);
2799 r = message_peek_field_uint32(m, ri, &nas);
2802 if (nas > BUS_ARRAY_MAX_SIZE)
2805 r = message_peek_fields(m, ri, alignment, 0, NULL);
2809 r = message_skip_fields(m, ri, nas, (const char**) &s);
2814 (*signature) += 1 + l;
2816 } else if (t == SD_BUS_TYPE_VARIANT) {
2819 r = message_peek_field_signature(m, ri, &s);
2823 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
2829 } else if (t == SD_BUS_TYPE_STRUCT ||
2830 t == SD_BUS_TYPE_DICT_ENTRY) {
2832 r = signature_element_length(*signature, &l);
2839 strncpy(sig, *signature + 1, l-1);
2842 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
2853 int bus_message_parse_fields(sd_bus_message *m) {
2856 uint32_t unix_fds = 0;
2860 for (ri = 0; ri < BUS_MESSAGE_FIELDS_SIZE(m); ) {
2861 const char *signature;
2864 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
2868 r = message_peek_field_signature(m, &ri, &signature);
2873 case _SD_BUS_MESSAGE_HEADER_INVALID:
2876 case SD_BUS_MESSAGE_HEADER_PATH:
2881 if (!streq(signature, "o"))
2884 r = message_peek_field_string(m, object_path_is_valid, &ri, &m->path);
2887 case SD_BUS_MESSAGE_HEADER_INTERFACE:
2892 if (!streq(signature, "s"))
2895 r = message_peek_field_string(m, interface_name_is_valid, &ri, &m->interface);
2898 case SD_BUS_MESSAGE_HEADER_MEMBER:
2903 if (!streq(signature, "s"))
2906 r = message_peek_field_string(m, member_name_is_valid, &ri, &m->member);
2909 case SD_BUS_MESSAGE_HEADER_ERROR_NAME:
2914 if (!streq(signature, "s"))
2917 r = message_peek_field_string(m, error_name_is_valid, &ri, &m->error.name);
2920 case SD_BUS_MESSAGE_HEADER_DESTINATION:
2925 if (!streq(signature, "s"))
2928 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->destination);
2931 case SD_BUS_MESSAGE_HEADER_SENDER:
2936 if (!streq(signature, "s"))
2939 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->sender);
2943 case SD_BUS_MESSAGE_HEADER_SIGNATURE: {
2947 if (m->root_container.signature)
2950 if (!streq(signature, "g"))
2953 r = message_peek_field_signature(m, &ri, &s);
2961 free(m->root_container.signature);
2962 m->root_container.signature = c;
2966 case SD_BUS_MESSAGE_HEADER_REPLY_SERIAL:
2967 if (m->reply_serial != 0)
2970 if (!streq(signature, "u"))
2973 r = message_peek_field_uint32(m, &ri, &m->reply_serial);
2977 if (m->reply_serial == 0)
2982 case SD_BUS_MESSAGE_HEADER_UNIX_FDS:
2986 if (!streq(signature, "u"))
2989 r = message_peek_field_uint32(m, &ri, &unix_fds);
2999 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
3006 if (m->n_fds != unix_fds)
3009 if (isempty(m->root_container.signature) != (BUS_MESSAGE_BODY_SIZE(m) == 0))
3012 switch (m->header->type) {
3014 case SD_BUS_MESSAGE_TYPE_SIGNAL:
3015 if (!m->path || !m->interface || !m->member)
3019 case SD_BUS_MESSAGE_TYPE_METHOD_CALL:
3021 if (!m->path || !m->member)
3026 case SD_BUS_MESSAGE_TYPE_METHOD_RETURN:
3028 if (m->reply_serial == 0)
3032 case SD_BUS_MESSAGE_TYPE_METHOD_ERROR:
3034 if (m->reply_serial == 0 || !m->error.name)
3039 /* Try to read the error message, but if we can't it's a non-issue */
3040 if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
3041 sd_bus_message_read(m, "s", &m->error.message);
3046 int bus_message_seal(sd_bus_message *m, uint64_t serial) {
3055 if (m->n_containers > 0)
3058 /* If there's a non-trivial signature set, then add it in here */
3059 if (!isempty(m->root_container.signature)) {
3060 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
3066 r = message_append_field_uint32(m, SD_BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
3071 l = BUS_MESSAGE_FIELDS_SIZE(m);
3075 /* Add padding at the end, since we know the body
3076 * needs to start at an 8 byte alignment. */
3079 p = message_extend_fields(m, 1, a);
3084 m->header->fields_size -= a;
3087 m->header->serial = serial;
3093 int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
3103 return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
3106 int bus_message_dump(sd_bus_message *m) {
3107 const char *u = NULL, *uu = NULL, *s = NULL;
3108 char **cmdline = NULL;
3111 uid_t owner, audit_loginuid;
3112 uint32_t audit_sessionid;
3116 printf("Message %p\n"
3123 "\tfields_size=%u\n"
3128 "\tdestination=%s\n"
3131 "\treply_serial=%u\n"
3133 "\terror.message=%s\n"
3141 BUS_MESSAGE_SERIAL(m),
3142 BUS_MESSAGE_FIELDS_SIZE(m),
3143 BUS_MESSAGE_BODY_SIZE(m),
3145 strna(m->interface),
3147 strna(m->destination),
3149 strna(m->root_container.signature),
3151 strna(m->error.name),
3152 strna(m->error.message),
3156 printf("\tpid=%lu\n", (unsigned long) m->pid);
3158 printf("\ttid=%lu\n", (unsigned long) m->tid);
3160 printf("\tuid=%lu\n", (unsigned long) m->uid);
3162 printf("\tgid=%lu\n", (unsigned long) m->gid);
3163 if (m->pid_starttime != 0)
3164 printf("\tpid_starttime=%llu\n", (unsigned long long) m->pid_starttime);
3165 if (m->monotonic != 0)
3166 printf("\tmonotonic=%llu\n", (unsigned long long) m->monotonic);
3167 if (m->realtime != 0)
3168 printf("\trealtime=%llu\n", (unsigned long long) m->realtime);
3170 printf("\texe=[%s]\n", m->exe);
3172 printf("\tcomm=[%s]\n", m->comm);
3174 printf("\ttid_comm=[%s]\n", m->tid_comm);
3176 printf("\tlabel=[%s]\n", m->label);
3178 printf("\tcgroup=[%s]\n", m->cgroup);
3180 sd_bus_message_get_unit(m, &u);
3182 printf("\tunit=[%s]\n", u);
3183 sd_bus_message_get_user_unit(m, &uu);
3185 printf("\tuser_unit=[%s]\n", uu);
3186 sd_bus_message_get_session(m, &s);
3188 printf("\tsession=[%s]\n", s);
3189 if (sd_bus_message_get_owner_uid(m, &owner) >= 0)
3190 printf("\towner_uid=%lu\n", (unsigned long) owner);
3191 if (sd_bus_message_get_audit_loginuid(m, &audit_loginuid) >= 0)
3192 printf("\taudit_loginuid=%lu\n", (unsigned long) audit_loginuid);
3193 if (sd_bus_message_get_audit_sessionid(m, &audit_sessionid) >= 0)
3194 printf("\taudit_sessionid=%lu\n", (unsigned long) audit_sessionid);
3196 if (sd_bus_message_get_cmdline(m, &cmdline) >= 0) {
3199 fputs("\tcmdline=[", stdout);
3200 STRV_FOREACH(c, cmdline) {
3207 fputs("]\n", stdout);
3210 r = sd_bus_message_rewind(m, true);
3212 log_error("Failed to rewind: %s", strerror(-r));
3216 printf("BEGIN_MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
3219 _cleanup_free_ char *prefix = NULL;
3220 const char *contents = NULL;
3235 r = sd_bus_message_peek_type(m, &type, &contents);
3237 log_error("Failed to peek type: %s", strerror(-r));
3244 r = sd_bus_message_exit_container(m);
3246 log_error("Failed to exit container: %s", strerror(-r));
3252 prefix = strrep("\t", level);
3256 if (type == SD_BUS_TYPE_ARRAY)
3257 printf("%s} END_ARRAY \n", prefix);
3258 else if (type == SD_BUS_TYPE_VARIANT)
3259 printf("%s} END_VARIANT\n", prefix);
3260 else if (type == SD_BUS_TYPE_STRUCT)
3261 printf("%s} END_STRUCT\n", prefix);
3262 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3263 printf("%s} END_DICT_ENTRY\n", prefix);
3268 prefix = strrep("\t", level);
3272 if (bus_type_is_container(type) > 0) {
3273 r = sd_bus_message_enter_container(m, type, contents);
3275 log_error("Failed to enter container: %s", strerror(-r));
3279 if (type == SD_BUS_TYPE_ARRAY)
3280 printf("%sBEGIN_ARRAY \"%s\" {\n", prefix, contents);
3281 else if (type == SD_BUS_TYPE_VARIANT)
3282 printf("%sBEGIN_VARIANT \"%s\" {\n", prefix, contents);
3283 else if (type == SD_BUS_TYPE_STRUCT)
3284 printf("%sBEGIN_STRUCT \"%s\" {\n", prefix, contents);
3285 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3286 printf("%sBEGIN_DICT_ENTRY \"%s\" {\n", prefix, contents);
3293 r = sd_bus_message_read_basic(m, type, &basic);
3295 log_error("Failed to get basic: %s", strerror(-r));
3301 case SD_BUS_TYPE_BYTE:
3302 printf("%sBYTE: %u\n", prefix, basic.u8);
3305 case SD_BUS_TYPE_BOOLEAN:
3306 printf("%sBOOLEAN: %s\n", prefix, yes_no(basic.i));
3309 case SD_BUS_TYPE_INT16:
3310 printf("%sINT16: %i\n", prefix, basic.s16);
3313 case SD_BUS_TYPE_UINT16:
3314 printf("%sUINT16: %u\n", prefix, basic.u16);
3317 case SD_BUS_TYPE_INT32:
3318 printf("%sINT32: %i\n", prefix, basic.s32);
3321 case SD_BUS_TYPE_UINT32:
3322 printf("%sUINT32: %u\n", prefix, basic.u32);
3325 case SD_BUS_TYPE_INT64:
3326 printf("%sINT64: %lli\n", prefix, (long long) basic.s64);
3329 case SD_BUS_TYPE_UINT64:
3330 printf("%sUINT64: %llu\n", prefix, (unsigned long long) basic.u64);
3333 case SD_BUS_TYPE_DOUBLE:
3334 printf("%sDOUBLE: %g\n", prefix, basic.d64);
3337 case SD_BUS_TYPE_STRING:
3338 printf("%sSTRING: \"%s\"\n", prefix, basic.string);
3341 case SD_BUS_TYPE_OBJECT_PATH:
3342 printf("%sOBJECT_PATH: \"%s\"\n", prefix, basic.string);
3345 case SD_BUS_TYPE_SIGNATURE:
3346 printf("%sSIGNATURE: \"%s\"\n", prefix, basic.string);
3349 case SD_BUS_TYPE_UNIX_FD:
3350 printf("%sUNIX_FD: %i\n", prefix, basic.i);
3354 assert_not_reached("Unknown basic type.");
3358 printf("} END_MESSAGE\n");
3362 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
3370 total = BUS_MESSAGE_SIZE(m);
3376 e = mempcpy(p, m->header, sizeof(*m->header));
3379 e = mempcpy(e, m->fields, m->header->fields_size);
3381 if (m->header->fields_size % 8 != 0)
3382 e = mempset(e, 0, 8 - (m->header->fields_size % 8));
3386 e = mempcpy(e, m->body, m->header->body_size);
3388 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
3396 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
3402 r = sd_bus_message_enter_container(m, 'a', "s");
3409 r = sd_bus_message_read_basic(m, 's', &s);
3415 r = strv_extend(l, s);
3420 r = sd_bus_message_exit_container(m);
3427 const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
3429 const char *t = NULL;
3434 r = sd_bus_message_rewind(m, true);
3438 for (j = 0; j <= i; j++) {
3441 r = sd_bus_message_peek_type(m, &type, NULL);
3445 if (type != SD_BUS_TYPE_STRING &&
3446 type != SD_BUS_TYPE_OBJECT_PATH &&
3447 type != SD_BUS_TYPE_SIGNATURE)
3450 r = sd_bus_message_read_basic(m, type, &t);
3458 int bus_header_size(struct bus_header *h, size_t *sum) {
3464 if (h->endian == SD_BUS_NATIVE_ENDIAN) {
3465 fs = h->fields_size;
3467 } else if (h->endian == SD_BUS_REVERSE_ENDIAN) {
3468 fs = bswap_32(h->fields_size);
3469 bs = bswap_32(h->body_size);
3473 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;