free(b->wqueue);
b->rqueue = b->wqueue = NULL;
+ b->rqueue_allocated = b->wqueue_allocated = 0;
b->rqueue_size = b->wqueue_size = 0;
}
/* We guarantee that wqueue always has space for at least one
* entry */
- r->wqueue = new(sd_bus_message*, 1);
- if (!r->wqueue) {
+ if (!GREEDY_REALLOC(r->wqueue, r->wqueue_allocated, 1)) {
free(r);
return -ENOMEM;
}
}
static int parse_address_key(const char **p, const char *key, char **value) {
- size_t l, n = 0;
+ size_t l, n = 0, allocated = 0;
const char *a;
char *r = NULL;
a = *p;
while (*a != ';' && *a != ',' && *a != 0) {
- char c, *t;
+ char c;
if (*a == '%') {
int x, y;
a++;
}
- t = realloc(r, n + 2);
- if (!t) {
- free(r);
+ if (!GREEDY_REALLOC(r, allocated, n + 2))
return -ENOMEM;
- }
- r = t;
r[n++] = c;
}
char *path = NULL;
unsigned n_argv = 0, j;
char **argv = NULL;
+ size_t allocated = 0;
int r;
assert(b);
(*p) ++;
if (ul >= n_argv) {
- char **x;
-
- x = realloc(argv, sizeof(char*) * (ul + 2));
- if (!x) {
+ if (!GREEDY_REALLOC0(argv, allocated, ul + 2)) {
r = -ENOMEM;
goto fail;
}
- memset(x + n_argv, 0, sizeof(char*) * (ul - n_argv + 2));
-
- argv = x;
n_argv = ul + 1;
}
assert(b);
assert(m);
- if (b->message_version != 0 &&
- m->header->version != b->message_version)
- return -EPERM;
-
- if (b->message_endian != 0 &&
- m->header->endian != b->message_endian)
- return -EPERM;
-
if (m->sealed) {
/* If we copy the same message to multiple
* destinations, avoid using the same serial
return bus_message_seal(m, ++b->serial, timeout);
}
+static int bus_remarshal_message(sd_bus *b, sd_bus_message **m) {
+ assert(b);
+
+ /* Do packet version and endianess already match? */
+ if ((b->message_version == 0 || b->message_version == (*m)->header->version) &&
+ (b->message_endian == 0 || b->message_endian == (*m)->header->endian))
+ return 0;
+
+ /* No? Then remarshal! */
+ return bus_message_remarshal(b, m);
+}
+
int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) {
assert(b);
assert(m);
}
int bus_rqueue_make_room(sd_bus *bus) {
- sd_bus_message **q;
- unsigned x;
-
- x = bus->rqueue_size + 1;
-
- if (bus->rqueue_allocated >= x)
- return 0;
+ assert(bus);
- if (x > BUS_RQUEUE_MAX)
+ if (bus->rqueue_size >= BUS_RQUEUE_MAX)
return -ENOBUFS;
- q = realloc(bus->rqueue, x * sizeof(sd_bus_message*));
- if (!q)
+ if (!GREEDY_REALLOC(bus->rqueue, bus->rqueue_allocated, bus->rqueue_size + 1))
return -ENOMEM;
- bus->rqueue = q;
- bus->rqueue_allocated = x;
-
return 0;
}
}
}
-_public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
+_public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *serial) {
+ _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
int r;
assert_return(bus, -EINVAL);
if (r < 0)
return r;
+ /* Remarshall if we have to. This will possible unref the
+ * message and place a replacement in m */
+ r = bus_remarshal_message(bus, &m);
+ if (r < 0)
+ return r;
+
/* If this is a reply and no reply was requested, then let's
* suppress this, if we can */
if (m->dont_send && !serial)
bus->windex = idx;
}
} else {
- sd_bus_message **q;
-
/* Just append it to the queue. */
if (bus->wqueue_size >= BUS_WQUEUE_MAX)
return -ENOBUFS;
- q = realloc(bus->wqueue, sizeof(sd_bus_message*) * (bus->wqueue_size + 1));
- if (!q)
+ if (!GREEDY_REALLOC(bus->wqueue, bus->wqueue_allocated, bus->wqueue_size + 1))
return -ENOMEM;
- bus->wqueue = q;
- q[bus->wqueue_size ++] = sd_bus_message_ref(m);
+ bus->wqueue[bus->wqueue_size ++] = sd_bus_message_ref(m);
}
if (serial)
_public_ int sd_bus_call_async(
sd_bus *bus,
- sd_bus_message *m,
+ sd_bus_message *_m,
sd_bus_message_handler_t callback,
void *userdata,
uint64_t usec,
uint64_t *serial) {
+ _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
struct reply_callback *c;
int r;
if (r < 0)
return r;
+ r = bus_remarshal_message(bus, &m);
+ if (r < 0)
+ return r;
+
c = new0(struct reply_callback, 1);
if (!c)
return -ENOMEM;
_public_ int sd_bus_call(
sd_bus *bus,
- sd_bus_message *m,
+ sd_bus_message *_m,
uint64_t usec,
sd_bus_error *error,
sd_bus_message **reply) {
+ _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
usec_t timeout;
uint64_t serial;
unsigned i;
if (r < 0)
return r;
+ r = bus_remarshal_message(bus, &m);
+ if (r < 0)
+ return r;
+
r = sd_bus_send(bus, m, &serial);
if (r < 0)
return r;
}
_public_ int sd_bus_default_system(sd_bus **ret) {
- static __thread sd_bus *default_system_bus = NULL;
+ static thread_local sd_bus *default_system_bus = NULL;
return bus_default(sd_bus_open_system, &default_system_bus, ret);
}
_public_ int sd_bus_default_user(sd_bus **ret) {
- static __thread sd_bus *default_user_bus = NULL;
+ static thread_local sd_bus *default_user_bus = NULL;
return bus_default(sd_bus_open_user, &default_user_bus, ret);
}
*ret = c;
return 0;
}
+
+_public_ int sd_bus_try_close(sd_bus *bus) {
+ int r;
+
+ assert_return(bus, -EINVAL);
+ assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+ assert_return(bus->is_kernel, -ENOTSUP);
+
+ if (bus->rqueue_size > 0)
+ return -EBUSY;
+
+ r = bus_kernel_try_close(bus);
+ if (r < 0)
+ return r;
+
+ sd_bus_close(bus);
+ return 0;
+}