sd-bus.c revision 969987ea93a7fdcd2c87b551eb0adf0bd9338b32
0d8efe3535b3ce9ecbc2c6482007edfc3ac492d0Dave Reisner/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
0d8efe3535b3ce9ecbc2c6482007edfc3ac492d0Dave Reisner This file is part of systemd.
0d8efe3535b3ce9ecbc2c6482007edfc3ac492d0Dave Reisner Copyright 2013 Lennart Poettering
0d8efe3535b3ce9ecbc2c6482007edfc3ac492d0Dave Reisner systemd is free software; you can redistribute it and/or modify it
0d8efe3535b3ce9ecbc2c6482007edfc3ac492d0Dave Reisner under the terms of the GNU Lesser General Public License as published by
0d8efe3535b3ce9ecbc2c6482007edfc3ac492d0Dave Reisner the Free Software Foundation; either version 2.1 of the License, or
0d8efe3535b3ce9ecbc2c6482007edfc3ac492d0Dave Reisner (at your option) any later version.
328b5bc96e452b67ae2eb3dee3a09ff3ce03f662Dave Reisner systemd is distributed in the hope that it will be useful, but
328b5bc96e452b67ae2eb3dee3a09ff3ce03f662Dave Reisner WITHOUT ANY WARRANTY; without even the implied warranty of
328b5bc96e452b67ae2eb3dee3a09ff3ce03f662Dave Reisner MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
328b5bc96e452b67ae2eb3dee3a09ff3ce03f662Dave Reisner Lesser General Public License for more details.
328b5bc96e452b67ae2eb3dee3a09ff3ce03f662Dave Reisner You should have received a copy of the GNU Lesser General Public License
328b5bc96e452b67ae2eb3dee3a09ff3ce03f662Dave Reisner along with systemd; If not, see <http://www.gnu.org/licenses/>.
0d8efe3535b3ce9ecbc2c6482007edfc3ac492d0Dave Reisnerstatic int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
0d8efe3535b3ce9ecbc2c6482007edfc3ac492d0Dave Reisner if (b->output_fd >= 0 && b->output_fd != b->input_fd)
0d8efe3535b3ce9ecbc2c6482007edfc3ac492d0Dave Reisnerstatic void bus_node_destroy(sd_bus *b, struct node *n) {
struct node_vtable *v;
struct node_enumerator *e;
assert(b);
while (n->child)
while ((c = n->callbacks)) {
free(c);
while ((v = n->vtables)) {
free(v);
while ((e = n->enumerators)) {
free(e);
if (n->parent)
free(n);
struct filter_callback *f;
struct node *n;
assert(b);
bus_close_fds(b);
if (b->kdbus_buffer)
for (i = 0; i < b->rqueue_size; i++)
for (i = 0; i < b->wqueue_size; i++)
while ((f = b->filter_callbacks)) {
free(f);
bus_node_destroy(b, n);
free(b);
sd_bus *r;
return -ENOMEM;
if (!r->wqueue) {
free(r);
return -ENOMEM;
*ret = r;
return -ENOMEM;
return -ENOMEM;
free(p);
return -ENOMEM;
static int hello_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
return -EBADMSG;
return -ENOMEM;
bus,
size_t l, n = 0;
char *r = NULL;
assert(p);
assert(*p);
if (key) {
if (*value)
return -EINVAL;
free(r);
free(r);
free(r);
return -ENOMEM;
return -ENOMEM;
*value = r;
static void skip_address_key(const char **p) {
assert(p);
assert(*p);
size_t l;
assert(b);
assert(p);
assert(*p);
skip_address_key(p);
return -EINVAL;
return -EINVAL;
if (path) {
return -E2BIG;
} else if (abstract) {
return -E2BIG;
assert(b);
assert(p);
assert(*p);
skip_address_key(p);
return -EINVAL;
if (family) {
return -EINVAL;
if (r == EAI_SYSTEM)
return -errno;
return -EADDRNOTAVAIL;
unsigned n_argv = 0, j;
assert(b);
assert(p);
assert(*p);
goto fail;
goto fail;
unsigned ul;
errno = 0;
r = -EINVAL;
goto fail;
r = -ENOMEM;
goto fail;
argv = x;
goto fail;
skip_address_key(p);
if (!path) {
r = -EINVAL;
goto fail;
if (!argv[j]) {
r = -EINVAL;
goto fail;
if (!argv[0]) {
r = -ENOMEM;
goto fail;
fail:
for (j = 0; j < n_argv; j++)
assert(b);
assert(p);
assert(*p);
skip_address_key(p);
if (!path)
return -EINVAL;
assert(b);
assert(p);
assert(*p);
skip_address_key(p);
if (!machine)
return -EINVAL;
strncpy(b->sockaddr.un.sun_path, "/var/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + sizeof("/var/run/dbus/system_bus_socket") - 1;
assert(b);
b->sockaddr_size = 0;
assert(b);
if (!b->address)
if (guid) {
assert(b);
sd_bus_close(b);
if (b->exec_path) {
r = bus_socket_exec(b);
b->last_connect_error = -r;
} else if (b->kernel) {
r = bus_kernel_connect(b);
b->last_connect_error = -r;
} else if (b->machine) {
r = bus_container_connect(b);
b->last_connect_error = -r;
r = bus_socket_connect(b);
b->last_connect_error = -r;
r = bus_parse_next_address(b);
assert(b);
return bus_start_address(b);
assert(b);
return -errno;
return bus_kernel_take_fd(b);
return bus_socket_take_fd(b);
return -EINVAL;
else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->kernel || bus->machine)
return -EINVAL;
sd_bus *b;
r = sd_bus_new(&b);
r = sd_bus_set_address(b, e);
goto fail;
b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/dbus/system_bus_socket") - 1;
b->bus_client = true;
r = sd_bus_start(b);
goto fail;
*ret = b;
fail:
bus_free(b);
sd_bus *b;
size_t l;
r = sd_bus_new(&b);
r = sd_bus_set_address(b, e);
goto fail;
r = -ENOENT;
goto fail;
l = strlen(e);
r = -E2BIG;
goto fail;
b->bus_client = true;
r = sd_bus_start(b);
goto fail;
*ret = b;
fail:
bus_free(b);
char *p = NULL;
return -ENOMEM;
return -ENOMEM;
free(p);
return -ENOMEM;
return -ENOMEM;
free(p);
if (!bus)
return bus;
return NULL;
assert(m);
return -EPERM;
if (m->sealed) {
int r, ret = 0;
return ret;
return ret;
assert(m);
int r, ret = 0;
assert(m);
return ret;
return ret;
if (m->n_fds > 0) {
return -ENOTSUP;
sd_bus_message **q;
return -ENOBUFS;
return -ENOMEM;
if (serial)
_public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *serial) {
if (!destination)
return -EEXIST;
if (usec == 0)
static int timeout_compare(const void *a, const void *b) {
const struct reply_callback *x = a, *y = b;
sd_bus_message *m,
void *userdata,
struct reply_callback *c;
return -ENOMEM;
free(c);
if (c->timeout != 0) {
c->timeout = 0;
struct reply_callback *c;
if (c->timeout != 0)
free(c);
return -ENOTCONN;
sd_bus_message *m,
bool room = false;
if (!room) {
sd_bus_message **q;
return -ENOBUFS;
return -ENOMEM;
room = true;
if (incoming) {
if (reply)
return -EIO;
return -ELOOP;
room = false;
if (timeout > 0) {
usec_t n;
if (n >= timeout)
return -ETIMEDOUT;
int flags = 0;
return flags;
struct reply_callback *c;
*timeout_usec = 0;
*timeout_usec = 0;
struct reply_callback *c;
usec_t n;
if (c->timeout > n)
bus,
c->serial,
free(c);
assert(m);
return -EIO;
return -EIO;
struct reply_callback *c;
assert(m);
if (c->timeout != 0)
r = sd_bus_message_rewind(m, true);
free(c);
struct filter_callback *l;
assert(m);
r = sd_bus_message_rewind(m, true);
assert(m);
assert(m);
m, &reply,
assert(m);
goto finish;
goto finish;
goto finish;
goto finish;
goto finish;
goto null_message;
goto null_message;
goto null_message;
goto null_message;
if (ret) {
r = sd_bus_message_rewind(m, true);
*ret = m;
m = NULL;
if (r >= 0 && ret)
struct reply_callback *c;
bus,
c->serial,
if (c->timeout != 0)
free(c);
goto finish;
bus,
"/org/freedesktop/DBus/Local",
goto finish;
goto finish;
if (ret) {
*ret = m;
m = NULL;
case BUS_UNSET:
case BUS_CLOSED:
return -ENOTCONN;
case BUS_OPENING:
if (ret)
case BUS_AUTHENTICATING:
if (ret)
case BUS_RUNNING:
case BUS_HELLO:
if (ret)
case BUS_CLOSING:
if (need_more)
e |= POLLIN;
m = timeout_usec;
p[0].events = e;
return -errno;
void *userdata) {
struct filter_callback *f;
return -ENOMEM;
void *userdata) {
struct filter_callback *f;
free(f);
const char *match,
void *userdata) {
unsigned n_components = 0;
goto finish;
goto finish;
r = bus_match_add(&bus->match_callbacks, components, n_components, callback, userdata, cookie, NULL);
const char *match,
void *userdata) {
unsigned n_components = 0;
assert(s);
if (event)
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
fail:
if (!ret)
return !!*default_bus;
if (*default_bus) {
r = bus_open(&b);
*default_bus = b;
*ret = b;
if (b->tid != 0) {
if (b->event)
return -ENXIO;
return NULL;
*(t++) = hexchar(*f);
return NULL;