bus-message.c revision 102d8f8169427cb68cdebf5ee0f0e07788e9c2b2
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek This file is part of systemd.
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek Copyright 2013 Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek under the terms of the GNU Lesser General Public License as published by
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek the Free Software Foundation; either version 2.1 of the License, or
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek (at your option) any later version.
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek systemd is distributed in the hope that it will be useful, but
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek WITHOUT ANY WARRANTY; without even the implied warranty of
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek Lesser General Public License for more details.
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek You should have received a copy of the GNU Lesser General Public License
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek along with systemd; If not, see <http://www.gnu.org/licenses/>.
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringstatic void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return (void*) p;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return (void*) p;
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering if ((uint8_t*) p >= (uint8_t*) old_base + sz)
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering return (void*) p;
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstatic void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering /* If we can reuse the memfd, try that. For that it
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering * can't be sealed yet. */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped);
7f1ad696a273703789b624fe0b209fb63e953016Lennart Poettering assert_se(munmap(part->data, part->mapped) == 0);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek close_nointr_nofail(part->memfd);
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poetteringstatic void message_reset_parts(sd_bus_message *m) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek struct bus_body_part *next = part->next;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek m->cached_rindex_part_begin = 0;
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poetteringstatic void message_reset_containers(sd_bus_message *m) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek for (i = 0; i < m->n_containers; i++)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic void message_free(sd_bus_message *m) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek ioctl(m->bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poetteringstatic void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz) {
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek size_t old_size, new_size, start;
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering old_size = sizeof(struct bus_header) + m->header->fields_size;
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering np = realloc(m->header, ALIGN8(new_size));
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering /* Initially, the header is allocated as part of of
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering * the sd_bus_message itself, let's replace it by
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering * dynamic data */
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek memcpy(np, m->header, sizeof(struct bus_header));
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Zero out padding */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek memset((uint8_t*) np + old_size, 0, start - old_size);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek m->header->fields_size = new_size - sizeof(struct bus_header);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Adjust quick access pointers */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek m->path = adjust_pointer(m->path, op, old_size, m->header);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek m->interface = adjust_pointer(m->interface, op, old_size, m->header);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek m->member = adjust_pointer(m->member, op, old_size, m->header);
4608af4333d0f7f5f8e3bc632801b04ef07d246dLennart Poettering m->destination = adjust_pointer(m->destination, op, old_size, m->header);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek m->sender = adjust_pointer(m->sender, op, old_size, m->header);
65089b82401cd395786a7987c470056ff3f01151Lennart Poettering m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int message_append_field_string(
23ad4dd8844c582929115a11ed2830a1371568d6Jan Alexander Steffens (heftig) if (l > (size_t) (uint32_t) -1)
23ad4dd8844c582929115a11ed2830a1371568d6Jan Alexander Steffens (heftig) /* field id byte + signature length + signature 's' + NUL + string length + string + NUL */
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt p = message_extend_fields(m, 8, 4 + 4 + l + 1);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int message_append_field_signature(
43cf8388ea4ffed1801468d4b650d6e48eefce9eMichal Schmidt /* field id byte + signature length + signature 'g' + NUL + string length + string + NUL */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek p = message_extend_fields(m, 8, 4 + 1 + l + 1);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* field id byte + signature length + signature 'u' + NUL + value */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek p = message_extend_fields(m, 8, 4 + 4);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (length < sizeof(struct bus_header))
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering m->label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering r = bus_message_from_header(buffer, length, fds, n_fds, ucred, label, 0, &m);
63c8666b824e8762ffb73647e1caee165dfbc868Zbigniew Jędrzejewski-Szmek if (length != BUS_MESSAGE_SIZE(m)) {
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering m->body.size = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = bus_message_parse_fields(m);
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering /* We take possession of the memory and fds now */
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poetteringstatic sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering m->header->endian = SD_BUS_NATIVE_ENDIAN;
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering m->header->version = bus ? bus->message_version : 1;
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering assert_return(object_path_is_valid(path), -EINVAL);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering assert_return(interface_name_is_valid(interface), -EINVAL);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering assert_return(member_name_is_valid(member), -EINVAL);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_new_method_call(
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(!destination || service_name_is_valid(destination), -EINVAL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(object_path_is_valid(path), -EINVAL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(member_name_is_valid(member), -EINVAL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
8266e1c04db8cabe3c68510a0c1f07c09ecdb2e8Lennart Poettering assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering t->reply_serial = BUS_MESSAGE_SERIAL(call);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek t->dont_send = !!(call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering_public_ int sd_bus_message_new_method_return(
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return message_new_reply(bus, call, SD_BUS_MESSAGE_METHOD_RETURN, m);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering_public_ int sd_bus_message_new_method_error(
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(sd_bus_error_is_set(e), -EINVAL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = message_new_reply(bus, call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_new_method_errorf(
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek r = bus_error_setfv(&error, name, format, ap);
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek return sd_bus_message_new_method_error(bus, call, &error, m);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering_public_ int sd_bus_message_new_method_errno(
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return sd_bus_message_new_method_error(bus, call, p, m);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return sd_bus_message_new_method_error(bus, call, &berror, m);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering_public_ int sd_bus_message_new_method_errnof(
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering r = bus_error_set_errnofv(&berror, error, format, ap);
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering return sd_bus_message_new_method_error(bus, call, &berror, m);
ef1673d16907726d83bdff2e57b5261997a85020Mirco Tischler t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek_public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek_public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek assert_return(m->header->serial != 0, -ENOENT);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek *serial = BUS_MESSAGE_SERIAL(m);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek assert_return(m->reply_serial != 0, -ENOENT);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_no_reply(sd_bus_message *m) {
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek return m->header->type == SD_BUS_MESSAGE_METHOD_CALL ? !!(m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek_public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
19cace379f3f680d3201cd257ab3ca6708b2d45dLennart Poettering_public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek_public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering_public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering assert_return(sd_bus_error_is_set(&m->error), NULL);
da4993920cdf5527b8528f0a483b54ab3cbc1971Kay Sievers_public_ int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) {
8a0889dfdafa3054c894e54852d8a9e3a7e8390bLennart Poettering_public_ int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(m->pid > 0, -ESRCH);
b6fa25552e538eca207072e12d223e3523b21a19Evgeny Vereshchagin_public_ int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(m->tid > 0, -ESRCH);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_pid_starttime(sd_bus_message *m, uint64_t *usec) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(m->pid_starttime > 0, -ESRCH);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_selinux_context(sd_bus_message *m, const char **ret) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(m->label, -ESRCH);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(m->monotonic > 0, -ESRCH);
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer_public_ int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(m->realtime > 0, -ESRCH);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_comm(sd_bus_message *m, const char **ret) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_tid_comm(sd_bus_message *m, const char **ret) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_exe(sd_bus_message *m, const char **ret) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_cgroup(sd_bus_message *m, const char **ret) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(m->cgroup, -ESRCH);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_unit(sd_bus_message *m, const char **ret) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(m->cgroup, -ESRCH);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = cg_path_get_unit(m->cgroup, &m->unit);
caa2f4c0c9613b2e02aafa308c8fb092576014a9Zbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_user_unit(sd_bus_message *m, const char **ret) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(m->cgroup, -ESRCH);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = cg_path_get_user_unit(m->cgroup, &m->user_unit);
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering_public_ int sd_bus_message_get_session(sd_bus_message *m, const char **ret) {
433dd100442e8197868def975c6fd38b48dc6439Lukas Nykryn r = cg_path_get_session(m->cgroup, &m->session);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_owner_uid(sd_bus_message *m, uid_t *uid) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(m->cgroup, -ESRCH);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return cg_path_get_owner_uid(m->cgroup, uid);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt_public_ int sd_bus_message_get_cmdline(sd_bus_message *m, char ***cmdline) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(m->cmdline, -ESRCH);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek for (p = m->cmdline, n = 0; p < m->cmdline + m->cmdline_length; p++)
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt for (p = m->cmdline, i = 0, first = true; p < m->cmdline + m->cmdline_length; p++) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek m->cmdline_array[i++] = (char*) p;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_audit_sessionid(sd_bus_message *m, uint32_t *sessionid) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_get_audit_loginuid(sd_bus_message *m, uid_t *uid) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(m->audit, -ESRCH);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_has_effective_cap(sd_bus_message *m, int capability) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(capability < 0, -EINVAL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return !!(m->capability[2 * sz + (capability / 8)] & (1 << (capability % 8)));
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_is_signal(sd_bus_message *m,
93b73b064c663d6248bebfbbbd82989b5ca10fc5Lennart Poettering const char *member) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (interface && (!m->interface || !streq(m->interface, interface)))
fbb634117d0b0ebd5b105e65b141e75ae9af7f8fLennart Poettering if (member && (!m->member || !streq(m->member, member)))
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_is_method_call(sd_bus_message *m,
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (interface && (!m->interface || !streq(m->interface, interface)))
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering if (member && (!m->member || !streq(m->member, member)))
253f59dff9c93ee1d2c33444b5715e42bc1c6889Lennart Poettering_public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (name && (!m->error.name || !streq(m->error.name, name)))
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek_public_ int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(!m->sealed, -EPERM);
804ae586d475d77946debb22c1bc9ee049d4750cLennart Poettering assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
c6878637502b1717a110a9a7e8bba32a8583fcdfLennart Poettering m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
763c7aa288485cf5ab627fe1d25ff58e76f9dacbZbigniew Jędrzejewski-Szmek m->header->flags &= ~SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic struct bus_container *message_get_container(sd_bus_message *m) {
a315ac4e076c4ce7ce3e5c95792cf916d5e918c5Lennart Poettering return m->containers + m->n_containers - 1;
a315ac4e076c4ce7ce3e5c95792cf916d5e918c5Lennart Poetteringstruct bus_body_part *message_append_part(sd_bus_message *m) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poetteringstatic void part_zero(struct bus_body_part *part, size_t sz) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering /* All other fields can be left in their defaults */
a315ac4e076c4ce7ce3e5c95792cf916d5e918c5Lennart Poettering part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped);
a315ac4e076c4ce7ce3e5c95792cf916d5e918c5Lennart Poettering r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &u);
a315ac4e076c4ce7ce3e5c95792cf916d5e918c5Lennart Poettering size_t psz = PAGE_ALIGN(sz > 0 ? sz : 1);
a315ac4e076c4ce7ce3e5c95792cf916d5e918c5Lennart Poettering n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
a315ac4e076c4ce7ce3e5c95792cf916d5e918c5Lennart Poettering n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
a315ac4e076c4ce7ce3e5c95792cf916d5e918c5Lennart Poettering *q = part->data ? (uint8_t*) part->data + part->size : NULL;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poetteringstatic void message_extend_containers(sd_bus_message *m, size_t expand) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Update counters */
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering for (c = m->containers; c < m->containers + m->n_containers; c++)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poetteringstatic void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek size_t start_body, end_body, padding, start_part, end_part, added;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering start_body = ALIGN_TO((size_t) m->header->body_size, align);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering padding = start_body - m->header->body_size;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering /* Check for 32bit overflows */
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (end_body > (size_t) ((uint32_t) -1)) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek start_part = ALIGN_TO(part->size, align);
d581d9d91fa5c42ce7828a7d0b1334d370cf1670Susant Sahani /* Readjust pointers */
d581d9d91fa5c42ce7828a7d0b1334d370cf1670Susant Sahani for (c = m->containers; c < m->containers + m->n_containers; c++)
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer c->array_size = adjust_pointer(c->array_size, op, os, part->data);
d581d9d91fa5c42ce7828a7d0b1334d370cf1670Susant Sahani m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekint message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(!m->sealed, -EPERM);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(bus_type_is_basic(type), -EINVAL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(!m->poisoned, -ESTALE);
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen if (c->signature && c->signature[c->index]) {
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen /* Container signature is already set */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Maybe we can append to the signature? But only if this is the top-level container*/
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* To make things easy we'll serialize a NULL string
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering * into the empty string */
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk /* Fall through... */
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk assert_cc(sizeof(int) == sizeof(uint32_t));
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering z = *(int*) p;
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
28def94cc8fd4394b20e2155d7130166662343c4Dave Reisner if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
0c24bb2346b6b6232d67aacd5236b56ea4989de4Lennart Poettering } else if (type == SD_BUS_TYPE_SIGNATURE) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek } else if (type == SD_BUS_TYPE_UNIX_FD) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (c->enclosing != SD_BUS_TYPE_ARRAY)
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering_public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return message_append_basic(m, type, p, NULL);
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering_public_ int sd_bus_message_append_string_space(sd_bus_message *m, size_t size, char **s) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_return(!m->sealed, -EPERM);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (c->signature && c->signature[c->index]) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Container signature is already set */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (c->signature[c->index] != SD_BUS_TYPE_STRING)
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt /* Maybe we can append to the signature? But only if this is the top-level container*/
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek a = message_extend_body(m, 4, 4 + size + 1);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek *s = (char*) a + 4;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (c->enclosing != SD_BUS_TYPE_ARRAY)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int bus_message_open_array(
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!signature_is_single(contents, true))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering alignment = bus_type_get_alignment(contents[0]);
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (c->signature && c->signature[c->index]) {
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* Verify the existing signature */
4ec3cd7391e119b597375c547cf4ed50fce9f115Lennart Poettering if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
13790add4bf648fed816361794d8277a75253410Lennart Poettering if (!startswith(c->signature + c->index + 1, contents))
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek nindex = c->index + 1 + strlen(contents);
13790add4bf648fed816361794d8277a75253410Lennart Poettering /* Extend the existing signature */
7d18d348da26fdbb392c76b0f5edb7f06282afbbZbigniew Jędrzejewski-Szmek e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
37b7affefde5443680d73642a990ce86776e28afZbigniew Jędrzejewski-Szmek a = message_extend_body(m, 4, 4);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Add alignment between size and first element */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (!message_extend_body(m, alignment, 0))
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (c->enclosing != SD_BUS_TYPE_ARRAY)
7d18d348da26fdbb392c76b0f5edb7f06282afbbZbigniew Jędrzejewski-Szmek /* location of array size might have changed so let's readjust a */
7d18d348da26fdbb392c76b0f5edb7f06282afbbZbigniew Jędrzejewski-Szmek a = adjust_pointer(a, op, os, m->body_end->data);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int bus_message_open_variant(
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (!signature_is_single(contents, false))
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
e9174f29c7e3ee45137537b126458718913a3ec5Lennart Poettering if (c->signature && c->signature[c->index]) {
e9174f29c7e3ee45137537b126458718913a3ec5Lennart Poettering if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek a = message_extend_body(m, 1, 1 + l + 1);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek memcpy((uint8_t*) a + 1, contents, l + 1);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (c->enclosing != SD_BUS_TYPE_ARRAY)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int bus_message_open_struct(
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (c->signature && c->signature[c->index]) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering !startswith(c->signature + c->index + 1, contents) ||
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek /* Align contents to 8 byte boundary */
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (c->enclosing != SD_BUS_TYPE_ARRAY)
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering if (c->signature && c->signature[c->index]) {
size_t l;
return -ENXIO;
return -ENXIO;
return -ENOMEM;
sd_bus_message *m,
char type,
const char *contents) {
struct bus_container *c, *w;
char *signature;
m->poisoned = true;
return -ENOMEM;
m->containers = w;
c = message_get_container(m);
if (!signature) {
m->poisoned = true;
return -ENOMEM;
r = -EINVAL;
w += m->n_containers++;
w->index = 0;
struct bus_container *c;
c = message_get_container(m);
return -EINVAL;
m->n_containers--;
const char *types;
unsigned n_struct;
unsigned n_array;
} TypeStack;
static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
if (*i >= max)
return -EINVAL;
static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
sd_bus_message *m,
const char *types,
unsigned stack_ptr = 0;
assert(m);
if (!types)
r = sd_bus_message_close_container(m);
t = types;
n_array --;
types ++;
n_struct--;
case SD_BUS_TYPE_BYTE: {
uint8_t x;
r = sd_bus_message_append_basic(m, *t, &x);
case SD_BUS_TYPE_BOOLEAN:
case SD_BUS_TYPE_INT32:
case SD_BUS_TYPE_UINT32:
case SD_BUS_TYPE_UNIX_FD: {
uint32_t x;
r = sd_bus_message_append_basic(m, *t, &x);
case SD_BUS_TYPE_INT16:
case SD_BUS_TYPE_UINT16: {
uint16_t x;
r = sd_bus_message_append_basic(m, *t, &x);
case SD_BUS_TYPE_INT64:
case SD_BUS_TYPE_UINT64:
case SD_BUS_TYPE_DOUBLE: {
uint64_t x;
r = sd_bus_message_append_basic(m, *t, &x);
case SD_BUS_TYPE_STRING:
case SD_BUS_TYPE_OBJECT_PATH:
case SD_BUS_TYPE_SIGNATURE: {
r = sd_bus_message_append_basic(m, *t, x);
case SD_BUS_TYPE_ARRAY: {
size_t k;
types += k;
n_struct -= k;
n_struct = k;
case SD_BUS_TYPE_VARIANT: {
return -EINVAL;
types = s;
case SD_BUS_TYPE_STRUCT_BEGIN:
case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
size_t k;
r = signature_element_length(t, &k);
r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
r = -EINVAL;
char type,
void **ptr) {
return -EINVAL;
return -ENOMEM;
r = sd_bus_message_close_container(m);
*ptr = a;
char type,
const void *ptr,
if (size > 0)
char type,
return -EINVAL;
if (!memfd)
return -EINVAL;
if (m->sealed)
return -EPERM;
return -EINVAL;
if (m->poisoned)
return -ESTALE;
if (copy_fd < 0)
return copy_fd;
return -EINVAL;
return -EINVAL;
return -ENOMEM;
if (!part)
return -ENOMEM;
return sd_bus_message_close_container(m);
struct bus_container *c;
if (copy_fd < 0)
return copy_fd;
if (size == 0)
return -EINVAL;
return -EINVAL;
c = message_get_container(m);
return -ENXIO;
if (c->enclosing != 0)
return -ENXIO;
m->poisoned = true;
return -ENOMEM;
return -ENOMEM;
if (!part)
return -ENOMEM;
c->index++;
STRV_FOREACH(i, l) {
return sd_bus_message_close_container(m);
return -EINVAL;
if (p == MAP_FAILED)
return -errno;
static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
return -EBADMSG;
if (((const uint8_t*) p)[k] != 0)
return -EBADMSG;
struct bus_container *c;
assert(m);
c = message_get_container(m);
struct bus_container *c;
assert(m);
c = message_get_container(m);
if (!c->array_size)
if (message_end_of_signature(m))
assert(m);
begin = 0;
while (part) {
return NULL;
return NULL;
return part;
return NULL;
static int message_peek_body(
sd_bus_message *m,
void **ret) {
uint8_t *q;
assert(m);
return -EBADMSG;
if (!part)
return -EBADMSG;
for (k = 0; k < padding; k++)
return -EBADMSG;
if (!part || !q)
return -EBADMSG;
if (ret)
*ret = q;
if (memchr(s, 0, l))
if (!validate_nul(s, l))
if (!utf8_is_valid(s))
if (!validate_nul(s, l))
if (!signature_is_valid(s, true))
if (!validate_nul(s, l))
if (!object_path_is_valid(s))
struct bus_container *c;
if (message_end_of_signature(m))
return -ENXIO;
c = message_get_container(m);
return -ENXIO;
switch (type) {
case SD_BUS_TYPE_STRING:
case SD_BUS_TYPE_OBJECT_PATH: {
uint32_t l;
return -EBADMSG;
if (!validate_object_path(q, l))
return -EBADMSG;
if (!validate_string(q, l))
return -EBADMSG;
case SD_BUS_TYPE_SIGNATURE: {
uint8_t l;
l = *(uint8_t*) q;
return -EBADMSG;
if (!validate_signature(q, l))
return -EBADMSG;
switch (type) {
case SD_BUS_TYPE_BYTE:
case SD_BUS_TYPE_BOOLEAN:
*(int*) p = !!*(uint32_t*) q;
case SD_BUS_TYPE_INT16:
case SD_BUS_TYPE_UINT16:
case SD_BUS_TYPE_INT32:
case SD_BUS_TYPE_UINT32:
case SD_BUS_TYPE_INT64:
case SD_BUS_TYPE_UINT64:
case SD_BUS_TYPE_DOUBLE:
case SD_BUS_TYPE_UNIX_FD: {
uint32_t j;
if (j >= m->n_fds)
return -EBADMSG;
*(int*) p = m->fds[j];
c->index++;
static int bus_message_enter_array(
sd_bus_message *m,
struct bus_container *c,
const char *contents,
int r, alignment;
assert(m);
assert(c);
return -EINVAL;
if (alignment < 0)
return alignment;
return -ENXIO;
return -ENXIO;
return -EBADMSG;
return -EBADMSG;
static int bus_message_enter_variant(
sd_bus_message *m,
struct bus_container *c,
const char *contents) {
uint8_t l;
assert(m);
assert(c);
return -EINVAL;
return -EINVAL;
return -ENXIO;
l = *(uint8_t*) q;
return -EBADMSG;
if (!validate_signature(q, l))
return -EBADMSG;
return -ENXIO;
c->index++;
static int bus_message_enter_struct(
sd_bus_message *m,
struct bus_container *c,
const char *contents) {
size_t l;
assert(m);
assert(c);
return -EINVAL;
return -ENXIO;
static int bus_message_enter_dict_entry(
sd_bus_message *m,
struct bus_container *c,
const char *contents) {
size_t l;
assert(m);
assert(c);
return -EINVAL;
return -ENXIO;
return -ENXIO;
char type,
const char *contents) {
struct bus_container *c, *w;
char *signature;
const char *cc;
char tt;
return -ENXIO;
return -ENXIO;
return -EBADMSG;
return -ENOMEM;
m->containers = w;
if (message_end_of_signature(m))
return -ENXIO;
c = message_get_container(m);
if (!signature)
return -ENOMEM;
r = -EINVAL;
w += m->n_containers++;
w->index = 0;
struct bus_container *c;
c = message_get_container(m);
uint32_t l;
return -EBUSY;
return -EINVAL;
m->n_containers--;
struct bus_container *c;
assert(m);
c = message_get_container(m);
m->n_containers--;
c = message_get_container(m);
struct bus_container *c;
if (message_end_of_signature(m))
goto eof;
goto eof;
c = message_get_container(m);
if (contents)
if (type)
if (contents) {
size_t l;
char *sig;
if (!sig)
return -ENOMEM;
if (type)
if (contents) {
size_t l;
char *sig;
if (!sig)
return -ENOMEM;
if (type)
*type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
if (contents) {
goto eof;
l = *(uint8_t*) q;
return -EBADMSG;
if (!validate_signature(q, l))
return -EBADMSG;
*contents = q;
if (type)
return -EINVAL;
eof:
if (type)
*type = 0;
if (contents)
struct bus_container *c;
if (complete) {
m->rindex = 0;
c = message_get_container(m);
c = message_get_container(m);
c->index = 0;
static int message_read_ap(
sd_bus_message *m,
const char *types,
unsigned stack_ptr = 0;
unsigned n_loop = 0;
assert(m);
n_loop++;
r = sd_bus_message_exit_container(m);
t = types;
n_array --;
types ++;
n_struct--;
case SD_BUS_TYPE_BYTE:
case SD_BUS_TYPE_BOOLEAN:
case SD_BUS_TYPE_INT16:
case SD_BUS_TYPE_UINT16:
case SD_BUS_TYPE_INT32:
case SD_BUS_TYPE_UINT32:
case SD_BUS_TYPE_INT64:
case SD_BUS_TYPE_UINT64:
case SD_BUS_TYPE_DOUBLE:
case SD_BUS_TYPE_STRING:
case SD_BUS_TYPE_OBJECT_PATH:
case SD_BUS_TYPE_SIGNATURE:
case SD_BUS_TYPE_UNIX_FD: {
r = sd_bus_message_read_basic(m, *t, p);
return -ENXIO;
case SD_BUS_TYPE_ARRAY: {
size_t k;
return -ENXIO;
types += k;
n_struct -= k;
n_struct = k;
case SD_BUS_TYPE_VARIANT: {
return -EINVAL;
return -ENXIO;
types = s;
case SD_BUS_TYPE_STRUCT_BEGIN:
case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
size_t k;
r = signature_element_length(t, &k);
r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
return -ENXIO;
return -EINVAL;
switch (*types) {
case SD_BUS_TYPE_BYTE:
case SD_BUS_TYPE_BOOLEAN:
case SD_BUS_TYPE_INT16:
case SD_BUS_TYPE_UINT16:
case SD_BUS_TYPE_INT32:
case SD_BUS_TYPE_UINT32:
case SD_BUS_TYPE_INT64:
case SD_BUS_TYPE_UINT64:
case SD_BUS_TYPE_DOUBLE:
case SD_BUS_TYPE_STRING:
case SD_BUS_TYPE_OBJECT_PATH:
case SD_BUS_TYPE_SIGNATURE:
case SD_BUS_TYPE_UNIX_FD:
case SD_BUS_TYPE_ARRAY: {
size_t k;
r = sd_bus_message_skip(m, s);
r = sd_bus_message_exit_container(m);
case SD_BUS_TYPE_VARIANT: {
const char *contents;
if (x != SD_BUS_TYPE_VARIANT)
return -ENXIO;
assert(r != 0);
r = sd_bus_message_exit_container(m);
case SD_BUS_TYPE_STRUCT_BEGIN:
case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
size_t k;
r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
r = sd_bus_message_skip(m, s);
assert(r != 0);
r = sd_bus_message_exit_container(m);
return -EINVAL;
char type,
const void **ptr,
struct bus_container *c;
if (align < 0)
return align;
c = message_get_container(m);
goto fail;
r = -EBADMSG;
goto fail;
r = sd_bus_message_exit_container(m);
goto fail;
*ptr = (const void*) p;
fail:
static int message_peek_fields(
sd_bus_message *m,
void **ret) {
assert(m);
static int message_peek_field_uint32(
sd_bus_message *m,
assert(m);
if (ret)
static int message_peek_field_string(
sd_bus_message *m,
bool (*validate)(const char *p),
const char **ret) {
uint32_t l;
assert(m);
if (validate) {
if (!validate_nul(q, l))
return -EBADMSG;
if (!validate(q))
return -EBADMSG;
if (!validate_string(q, l))
return -EBADMSG;
if (ret)
*ret = q;
static int message_peek_field_signature(
sd_bus_message *m,
const char **ret) {
size_t l;
assert(m);
l = *(uint8_t*) q;
if (!validate_signature(q, l))
return -EBADMSG;
if (ret)
*ret = q;
static int message_skip_fields(
sd_bus_message *m,
const char **signature) {
assert(m);
size_t l;
t = **signature;
if (t == SD_BUS_TYPE_STRING) {
(*signature)++;
} else if (t == SD_BUS_TYPE_OBJECT_PATH) {
(*signature)++;
} else if (t == SD_BUS_TYPE_SIGNATURE) {
(*signature)++;
} else if (bus_type_is_basic(t)) {
k = bus_type_get_size(t);
(*signature)++;
} else if (t == SD_BUS_TYPE_ARRAY) {
int alignment;
s = sig;
if (alignment < 0)
return alignment;
return -EBADMSG;
} else if (t == SD_BUS_TYPE_VARIANT) {
(*signature)++;
} else if (t == SD_BUS_TYPE_STRUCT ||
t == SD_BUS_TYPE_DICT_ENTRY) {
s = sig;
*signature += l;
return -EINVAL;
assert(m);
const char *signature;
switch (*header) {
return -EBADMSG;
if (m->path)
return -EBADMSG;
return -EBADMSG;
if (m->interface)
return -EBADMSG;
return -EBADMSG;
if (m->member)
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
if (m->destination)
return -EBADMSG;
return -EBADMSG;
if (m->sender)
return -EBADMSG;
return -EBADMSG;
case SD_BUS_MESSAGE_HEADER_SIGNATURE: {
return -EBADMSG;
return -EBADMSG;
c = strdup(s);
return -ENOMEM;
if (m->reply_serial != 0)
return -EBADMSG;
return -EBADMSG;
if (m->reply_serial == 0)
return -EBADMSG;
if (unix_fds != 0)
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
if (unix_fds == 0)
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
case SD_BUS_MESSAGE_SIGNAL:
return -EBADMSG;
return -EBADMSG;
if (m->reply_serial == 0)
return -EBADMSG;
return -EBADMSG;
size_t l, a;
assert(m);
if (m->sealed)
return -EPERM;
if (m->n_containers > 0)
return -EBADMSG;
if (m->poisoned)
return -ESTALE;
r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
if (m->n_fds > 0) {
l = BUS_MESSAGE_FIELDS_SIZE(m);
a = ALIGN8(l) - l;
m->sealed = true;
return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
assert(m);
f = stdout;
if (with_header) {
fprintf(f,
m->n_ref,
m->reply_serial,
m->n_body_parts);
fprintf(f,
if (m->pid != 0)
if (m->tid != 0)
if (m->uid_valid)
if (m->gid_valid)
if (m->pid_starttime != 0)
if (m->monotonic != 0)
if (m->realtime != 0)
if (m->exe)
if (m->comm)
if (m->tid_comm)
if (m->label)
if (m->cgroup)
sd_bus_message_get_unit(m, &u);
if (uu)
sd_bus_message_get_session(m, &s);
if (c != cmdline)
fputs(*c, f);
r = sd_bus_message_rewind(m, true);
char type;
double d64;
const char *string;
} basic;
r = sd_bus_message_exit_container(m);
level--;
if (!prefix)
return log_oom();
if (!prefix)
return log_oom();
level ++;
assert(r > 0);
switch (type) {
case SD_BUS_TYPE_BYTE:
case SD_BUS_TYPE_BOOLEAN:
case SD_BUS_TYPE_INT16:
case SD_BUS_TYPE_UINT16:
case SD_BUS_TYPE_INT32:
case SD_BUS_TYPE_UINT32:
case SD_BUS_TYPE_INT64:
case SD_BUS_TYPE_UINT64:
case SD_BUS_TYPE_DOUBLE:
case SD_BUS_TYPE_STRING:
case SD_BUS_TYPE_OBJECT_PATH:
case SD_BUS_TYPE_SIGNATURE:
case SD_BUS_TYPE_UNIX_FD:
assert(m);
return -ENOMEM;
*buffer = p;
assert(m);
assert(l);
r = strv_extend(l, s);
r = sd_bus_message_exit_container(m);
*l = strv;
const char *t = NULL;
assert(m);
r = sd_bus_message_rewind(m, true);
return NULL;
char type;
return NULL;
return NULL;
return NULL;
assert(h);
assert(h);
return -EBADMSG;
struct bus_container *c;
bool done_something = false;
const char *contents;
char type;
double d64;
const char *string;
} basic;
done_something = true;
r = sd_bus_message_close_container(m);
assert(r > 0);
} while (all);
return done_something;
r = sd_bus_message_peek_type(m, &t, &c);