-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
#include <fcntl.h>
#include <sys/mman.h>
-#include "util.h"
-#include "utf8.h"
-#include "strv.h"
-#include "time-util.h"
-#include "memfd-util.h"
-
#include "sd-bus.h"
-#include "bus-message.h"
+
+#include "alloc-util.h"
+#include "bus-gvariant.h"
#include "bus-internal.h"
-#include "bus-type.h"
+#include "bus-message.h"
#include "bus-signature.h"
-#include "bus-gvariant.h"
+#include "bus-type.h"
#include "bus-util.h"
+#include "fd-util.h"
+#include "io-util.h"
+#include "memfd-util.h"
+#include "string-util.h"
+#include "strv.h"
+#include "time-util.h"
+#include "utf8.h"
+#include "util.h"
static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
free(m->containers[i].offsets);
}
- free(m->containers);
- m->containers = NULL;
+ m->containers = mfree(m->containers);
m->n_containers = m->containers_allocated = 0;
m->root_container.index = 0;
if (m->iovec != m->iovec_fixed)
free(m->iovec);
- if (m->destination_ptr) {
- free(m->destination_ptr);
- m->destination_ptr = NULL;
- }
-
+ m->destination_ptr = mfree(m->destination_ptr);
message_reset_containers(m);
free(m->root_container.signature);
free(m->root_container.offsets);
m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
m->header->endian = BUS_NATIVE_ENDIAN;
m->header->type = type;
- m->header->version = bus ? bus->message_version : 1;
- m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
+ m->header->version = bus->message_version;
+ m->allow_fds = bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
m->bus = sd_bus_ref(bus);
const char *format,
...) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
va_list ap;
assert_return(name, -EINVAL);
int error,
const sd_bus_error *p) {
- _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
if (sd_bus_error_is_set(p))
return sd_bus_message_new_method_error(call, m, p);
return sd_bus_message_new_method_error(call, m, &berror);
}
+#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_message_new_method_errnof(
sd_bus_message *call,
sd_bus_message **m,
const char *format,
...) {
- _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
va_list ap;
va_start(ap, format);
return sd_bus_message_new_method_error(call, m, &berror);
}
+#endif // 0
void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
assert(bus);
}
_public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
- assert_return(m, NULL);
+
+ if (!m)
+ return NULL;
assert(m->n_ref > 0);
m->n_ref++;
return NULL;
}
+#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
assert_return(m, -EINVAL);
assert_return(type, -EINVAL);
return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
}
+#endif // 0
_public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
assert_return(m, -EINVAL);
_public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
assert_return(m, NULL);
- assert_return(sd_bus_error_is_set(&m->error), NULL);
+
+ if (!sd_bus_error_is_set(&m->error))
+ return NULL;
return &m->error;
}
+#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
assert_return(m, -EINVAL);
assert_return(usec, -EINVAL);
*seqnum = m->seqnum;
return 0;
}
+#endif // 0
_public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
assert_return(m, NULL);
return &m->creds;
}
+#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_message_is_signal(
sd_bus_message *m,
const char *interface,
return 1;
}
+#endif // 0
_public_ int sd_bus_message_is_method_call(
sd_bus_message *m,
return 1;
}
+#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
return 0;
}
+#endif // 0
static struct bus_container *message_get_container(sd_bus_message *m) {
assert(m);
return message_append_basic(m, type, p, NULL);
}
+#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_message_append_string_space(
sd_bus_message *m,
size_t size,
return 0;
}
+#endif // 0
static int bus_message_open_array(
sd_bus_message *m,
}
static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
+ bool fixed_size = true;
size_t n_variable = 0;
unsigned i = 0;
const char *p;
/* We need to add an offset for each item that has a
* variable size and that is not the last one in the
* list */
+ if (r == 0)
+ fixed_size = false;
if (r == 0 && p[n] != 0)
n_variable++;
assert(!c->need_offsets || i == c->n_offsets);
assert(c->need_offsets || n_variable == 0);
- if (n_variable <= 0) {
- a = message_extend_body(m, 1, 0, add_offset, false);
+ if (isempty(c->signature)) {
+ /* The unary type is encoded as fixed 1 byte padding */
+ a = message_extend_body(m, 1, 1, add_offset, false);
+ if (!a)
+ return -ENOMEM;
+
+ *a = 0;
+ } else if (n_variable <= 0) {
+ int alignment = 1;
+
+ /* Structures with fixed-size members only have to be
+ * fixed-size themselves. But gvariant requires all fixed-size
+ * elements to be sized a multiple of their alignment. Hence,
+ * we must *always* add final padding after the last member so
+ * the overall size of the structure is properly aligned. */
+ if (fixed_size)
+ alignment = bus_gvariant_get_alignment(strempty(c->signature));
+
+ assert(alignment > 0);
+
+ a = message_extend_body(m, alignment, 0, add_offset, false);
if (!a)
return -ENOMEM;
} else {
return r;
}
+#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_message_append_array_space(
sd_bus_message *m,
char type,
if (r < 0)
return r;
- if (size > 0)
- memcpy(p, ptr, size);
+ memcpy_safe(p, ptr, size);
return 0;
}
int r;
assert_return(m, -EINVAL);
- assert_return(memfd >= 0, -EINVAL);
+ assert_return(memfd >= 0, -EBADF);
assert_return(bus_type_is_trivial(type), -EINVAL);
assert_return(size > 0, -EINVAL);
assert_return(!m->sealed, -EPERM);
int r;
assert_return(m, -EINVAL);
- assert_return(memfd >= 0, -EINVAL);
+ assert_return(memfd >= 0, -EBADF);
assert_return(size > 0, -EINVAL);
assert_return(!m->sealed, -EPERM);
assert_return(!m->poisoned, -ESTALE);
return 0;
}
+#endif // 0
_public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
char **i;
signature = strempty(m->root_container.signature);
l = strlen(signature);
- sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l, 1);
- d = message_extend_body(m, 1, 1 + l + sz, false, true);
+ sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
+ d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
if (!d)
return -ENOMEM;
*(uint8_t*) d = 0;
- memcpy((uint8_t*) d + 1, signature, l);
+ *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
+ memcpy((uint8_t*) d + 2, signature, l);
+ *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
- bus_gvariant_write_word_le((uint8_t*) d + 1 + l, sz, sizeof(struct bus_header) + m->fields_size);
+ bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
m->footer = d;
- m->footer_accessible = 1 + l + sz;
+ m->footer_accessible = 1 + l + 2 + sz;
} else {
m->header->dbus1.fields_size = m->fields_size;
m->header->dbus1.body_size = m->body_size;
}
}
+#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
assert_return(m, -EINVAL);
assert_return(m->sealed, -EPERM);
return false;
}
+#endif // 0
static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
struct bus_body_part *part;
assert(n_offsets);
if (isempty(signature)) {
+ /* Unary type is encoded as *fixed* 1 byte padding */
+ r = message_peek_body(m, &m->rindex, 1, 1, &q);
+ if (r < 0)
+ return r;
+
+ if (*(uint8_t *) q != 0)
+ return -EBADMSG;
+
*item_size = 0;
*offsets = NULL;
*n_offsets = 0;
if (r < 0)
return r;
- } else if (c->item_size <= 0) {
-
- /* gvariant empty struct */
- *item_size = 0;
- *offsets = NULL;
- *n_offsets = 0;
} else
/* gvariant with contents */
return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
w->before = before;
w->begin = m->rindex;
- w->end = m->rindex + c->item_size;
+
+ /* Unary type has fixed size of 1, but virtual size of 0 */
+ if (BUS_MESSAGE_IS_GVARIANT(m) &&
+ type == SD_BUS_TYPE_STRUCT &&
+ isempty(signature))
+ w->end = m->rindex + 0;
+ else
+ w->end = m->rindex + c->item_size;
w->array_size = array_size;
w->item_size = item_size;
r = sd_bus_message_skip(m, s);
if (r < 0)
return r;
- assert(r != 0);
r = sd_bus_message_exit_container(m);
if (r < 0)
return -EBADMSG;
if (*p == 0) {
+ size_t l;
char *c;
- /* We found the beginning of the signature string, yay! */
+ /* We found the beginning of the signature
+ * string, yay! We require the body to be a
+ * structure, so verify it and then strip the
+ * opening/closing brackets. */
+
+ l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
+ if (l < 2 ||
+ p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
+ p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
+ return -EBADMSG;
- c = strndup(p + 1, ((char*) m->footer + m->footer_accessible) - p - (1 + sz));
+ c = strndup(p + 1 + 1, l - 2);
if (!c)
return -ENOMEM;
return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
}
+#if 0 /// UNNEEDED by elogind
int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
size_t total;
void *p, *e;
return 0;
}
+#endif // 0
int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
const char *s;
return 1;
}
-int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
- const char *contents;
+static int bus_message_get_arg_skip(
+ sd_bus_message *m,
+ unsigned i,
+ char *_type,
+ const char **_contents) {
+
unsigned j;
- char type;
int r;
- assert(m);
- assert(str);
- assert(strv);
-
r = sd_bus_message_rewind(m, true);
if (r < 0)
return r;
for (j = 0;; j++) {
+ const char *contents;
+ char type;
+
r = sd_bus_message_peek_type(m, &type, &contents);
if (r < 0)
return r;
!(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
return -ENXIO;
- if (j >= i)
- break;
+ if (j >= i) {
+ if (_contents)
+ *_contents = contents;
+ if (_type)
+ *_type = type;
+ return 0;
+ }
r = sd_bus_message_skip(m, NULL);
if (r < 0)
return r;
}
- if (type == SD_BUS_TYPE_ARRAY) {
+}
+
+int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
+ char type;
+ int r;
+
+ assert(m);
+ assert(str);
- r = sd_bus_message_read_strv(m, strv);
+ r = bus_message_get_arg_skip(m, i, &type, NULL);
if (r < 0)
return r;
- *str = NULL;
+ if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
+ return -ENXIO;
- } else {
- r = sd_bus_message_read_basic(m, type, str);
+ return sd_bus_message_read_basic(m, type, str);
+}
+
+int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
+ const char *contents;
+ char type;
+ int r;
+
+ assert(m);
+ assert(strv);
+
+ r = bus_message_get_arg_skip(m, i, &type, &contents);
if (r < 0)
return r;
- *strv = NULL;
- }
+ if (type != SD_BUS_TYPE_ARRAY)
+ return -ENXIO;
+ if (!STR_IN_SET(contents, "s", "o", "g"))
+ return -ENXIO;
- return 0;
+ return sd_bus_message_read_strv(m, strv);
}
_public_ int sd_bus_message_get_errno(sd_bus_message *m) {
return strempty(c->signature);
}
+#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_message_is_empty(sd_bus_message *m) {
assert_return(m, -EINVAL);
return streq(strempty(m->root_container.signature), strempty(signature));
}
+#endif // 0
_public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
bool done_something = false;
return done_something;
}
+#if 0 /// UNNEEDED by elogind
_public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
const char *c;
char t;
return 1;
}
+#endif // 0
_public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
assert_return(m, NULL);
}
int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
- _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
usec_t timeout;
int r;
return 0;
}
+#if 0 /// UNNEEDED by elogind
int bus_message_append_sender(sd_bus_message *m, const char *sender) {
assert(m);
assert(sender);
m->priority = priority;
return 0;
}
+#endif // 0