diff options
author | Lennart Poettering <lennart@poettering.net> | 2013-05-14 22:24:26 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2013-05-14 22:28:45 +0200 |
commit | bc7fd8cdbef54ebd3902cdd455ecad3e095f7450 (patch) | |
tree | 74df33906ba2efeae69c6d77f3b94d17171e55d5 /src/libsystemd-bus/bus-socket.c | |
parent | a3dc35472f3a48ea8445ad7a943e2ff253170417 (diff) |
bus: properly handle message bodies that are a chain of memory areas rather than a single one
Diffstat (limited to 'src/libsystemd-bus/bus-socket.c')
-rw-r--r-- | src/libsystemd-bus/bus-socket.c | 50 |
1 files changed, 41 insertions, 9 deletions
diff --git a/src/libsystemd-bus/bus-socket.c b/src/libsystemd-bus/bus-socket.c index 8a86b02c68..4dafe1fdb7 100644 --- a/src/libsystemd-bus/bus-socket.c +++ b/src/libsystemd-bus/bus-socket.c @@ -58,7 +58,7 @@ static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) { } } -static void append_iovec(sd_bus_message *m, const void *p, size_t sz) { +static int append_iovec(sd_bus_message *m, const void *p, size_t sz) { assert(m); assert(p); assert(sz > 0); @@ -66,22 +66,51 @@ static void append_iovec(sd_bus_message *m, const void *p, size_t sz) { m->iovec[m->n_iovec].iov_base = (void*) p; m->iovec[m->n_iovec].iov_len = sz; m->n_iovec++; + + return 0; } -static void bus_message_setup_iovec(sd_bus_message *m) { +static int bus_message_setup_iovec(sd_bus_message *m) { + struct bus_body_part *part; + unsigned n; + int r; + assert(m); assert(m->sealed); if (m->n_iovec > 0) - return; + return 0; + + assert(!m->iovec); + + n = 1 + !!m->fields + m->n_body_parts; + if (n < ELEMENTSOF(m->iovec_fixed)) + m->iovec = m->iovec_fixed; + else { + m->iovec = new(struct iovec, n); + if (!m->iovec) + return -ENOMEM; + } + + r = append_iovec(m, m->header, sizeof(*m->header)); + if (r < 0) + return r; + + if (m->fields) { + r = append_iovec(m, m->fields, ALIGN8(m->header->fields_size)); + if (r < 0) + return r; + } - append_iovec(m, m->header, sizeof(*m->header)); + for (part = &m->body; part && part->size > 0; part = part->next) { + r = append_iovec(m, part->data, part->size); + if (r < 0) + return r; + } - if (m->fields) - append_iovec(m, m->fields, ALIGN8(m->header->fields_size)); + assert(n == m->n_iovec); - if (m->body) - append_iovec(m, m->body, m->header->body_size); + return 0; } bool bus_socket_auth_needs_write(sd_bus *b) { @@ -749,6 +778,7 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) { ssize_t k; size_t n; unsigned j; + int r; assert(bus); assert(m); @@ -758,7 +788,9 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) { if (*idx >= BUS_MESSAGE_SIZE(m)) return 0; - bus_message_setup_iovec(m); + r = bus_message_setup_iovec(m); + if (r < 0) + return r; n = m->n_iovec * sizeof(struct iovec); iov = alloca(n); |