mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-10-30 23:21:08 +03:00
bus: allow two different fds for input/output in sd_bus_set_fd()
This is useful so that we can speak D-Bus over a FIFO pair such as stdin+stdout.
This commit is contained in:
parent
7989e1f2d7
commit
e82c950997
@ -74,7 +74,7 @@ enum bus_auth {
|
||||
struct sd_bus {
|
||||
unsigned n_ref;
|
||||
enum bus_state state;
|
||||
int fd;
|
||||
int input_fd, output_fd;
|
||||
int message_version;
|
||||
|
||||
bool negotiate_fds:1;
|
||||
|
@ -88,7 +88,7 @@ static int bus_socket_write_auth(sd_bus *b) {
|
||||
mh.msg_iov = b->auth_iovec + b->auth_index;
|
||||
mh.msg_iovlen = ELEMENTSOF(b->auth_iovec) - b->auth_index;
|
||||
|
||||
k = sendmsg(b->fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
|
||||
k = sendmsg(b->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
|
||||
if (k < 0)
|
||||
return errno == EAGAIN ? 0 : -errno;
|
||||
|
||||
@ -463,7 +463,7 @@ static int bus_socket_read_auth(sd_bus *b) {
|
||||
mh.msg_control = &control;
|
||||
mh.msg_controllen = sizeof(control);
|
||||
|
||||
k = recvmsg(b->fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
|
||||
k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
|
||||
if (k < 0)
|
||||
return errno == EAGAIN ? 0 : -errno;
|
||||
if (k == 0)
|
||||
@ -515,12 +515,12 @@ static int bus_socket_setup(sd_bus *b) {
|
||||
/* Enable SO_PASSCRED + SO_PASSEC. We try this on any
|
||||
* socket, just in case. */
|
||||
enable = !b->bus_client;
|
||||
setsockopt(b->fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable));
|
||||
setsockopt(b->fd, SOL_SOCKET, SO_PASSSEC, &enable, sizeof(enable));
|
||||
setsockopt(b->input_fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable));
|
||||
setsockopt(b->input_fd, SOL_SOCKET, SO_PASSSEC, &enable, sizeof(enable));
|
||||
|
||||
/* Increase the buffers to a MB */
|
||||
fd_inc_rcvbuf(b->fd, 1024*1024);
|
||||
fd_inc_sndbuf(b->fd, 1024*1024);
|
||||
fd_inc_rcvbuf(b->input_fd, 1024*1024);
|
||||
fd_inc_sndbuf(b->output_fd, 1024*1024);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -577,13 +577,17 @@ static int bus_socket_start_auth(sd_bus *b) {
|
||||
b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_DEFAULT_TIMEOUT;
|
||||
|
||||
sl = sizeof(domain);
|
||||
r = getsockopt(b->fd, SOL_SOCKET, SO_DOMAIN, &domain, &sl);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
if (domain != AF_UNIX)
|
||||
r = getsockopt(b->input_fd, SOL_SOCKET, SO_DOMAIN, &domain, &sl);
|
||||
if (r < 0 || domain != AF_UNIX)
|
||||
b->negotiate_fds = false;
|
||||
|
||||
if (b->output_fd != b->input_fd) {
|
||||
r = getsockopt(b->output_fd, SOL_SOCKET, SO_DOMAIN, &domain, &sl);
|
||||
if (r < 0 || domain != AF_UNIX)
|
||||
b->negotiate_fds = false;
|
||||
}
|
||||
|
||||
|
||||
if (b->is_server)
|
||||
return bus_socket_read_auth(b);
|
||||
else
|
||||
@ -594,18 +598,21 @@ int bus_socket_connect(sd_bus *b) {
|
||||
int r;
|
||||
|
||||
assert(b);
|
||||
assert(b->fd < 0);
|
||||
assert(b->input_fd < 0);
|
||||
assert(b->output_fd < 0);
|
||||
assert(b->sockaddr.sa.sa_family != AF_UNSPEC);
|
||||
|
||||
b->fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
||||
if (b->fd < 0)
|
||||
b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
||||
if (b->input_fd < 0)
|
||||
return -errno;
|
||||
|
||||
b->output_fd = b->input_fd;
|
||||
|
||||
r = bus_socket_setup(b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = connect(b->fd, &b->sockaddr.sa, b->sockaddr_size);
|
||||
r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
|
||||
if (r < 0) {
|
||||
if (errno == EINPROGRESS)
|
||||
return 1;
|
||||
@ -617,15 +624,16 @@ int bus_socket_connect(sd_bus *b) {
|
||||
}
|
||||
|
||||
int bus_socket_exec(sd_bus *b) {
|
||||
int s[2];
|
||||
int s[2], r;
|
||||
pid_t pid;
|
||||
|
||||
assert(b);
|
||||
assert(b->fd < 0);
|
||||
assert(b->input_fd < 0);
|
||||
assert(b->output_fd < 0);
|
||||
assert(b->exec_path);
|
||||
|
||||
b->fd = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, s);
|
||||
if (b->fd < 0)
|
||||
r = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, s);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
pid = fork();
|
||||
@ -636,8 +644,9 @@ int bus_socket_exec(sd_bus *b) {
|
||||
if (pid == 0) {
|
||||
/* Child */
|
||||
|
||||
close_all_fds(s, 2);
|
||||
close_nointr_nofail(s[0]);
|
||||
reset_all_signal_handlers();
|
||||
|
||||
close_all_fds(s+1, 1);
|
||||
|
||||
assert_se(dup3(s[1], STDIN_FILENO, 0) == STDIN_FILENO);
|
||||
assert_se(dup3(s[1], STDOUT_FILENO, 0) == STDOUT_FILENO);
|
||||
@ -661,7 +670,7 @@ int bus_socket_exec(sd_bus *b) {
|
||||
}
|
||||
|
||||
close_nointr_nofail(s[1]);
|
||||
b->fd = s[0];
|
||||
b->output_fd = b->input_fd = s[0];
|
||||
|
||||
return bus_socket_start_auth(b);
|
||||
}
|
||||
@ -714,7 +723,7 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
|
||||
mh.msg_iov = iov;
|
||||
mh.msg_iovlen = m->n_iovec;
|
||||
|
||||
k = sendmsg(bus->fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
|
||||
k = sendmsg(bus->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
|
||||
if (k < 0)
|
||||
return errno == EAGAIN ? 0 : -errno;
|
||||
|
||||
@ -854,7 +863,7 @@ int bus_socket_read_message(sd_bus *bus, sd_bus_message **m) {
|
||||
mh.msg_control = &control;
|
||||
mh.msg_controllen = sizeof(control);
|
||||
|
||||
k = recvmsg(bus->fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
|
||||
k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
|
||||
if (k < 0)
|
||||
return errno == EAGAIN ? 0 : -errno;
|
||||
if (k == 0)
|
||||
@ -924,7 +933,7 @@ int bus_socket_process_opening(sd_bus *b) {
|
||||
assert(b->state == BUS_OPENING);
|
||||
|
||||
zero(p);
|
||||
p.fd = b->fd;
|
||||
p.fd = b->output_fd;
|
||||
p.events = POLLOUT;
|
||||
|
||||
r = poll(&p, 1, 0);
|
||||
@ -934,7 +943,7 @@ int bus_socket_process_opening(sd_bus *b) {
|
||||
if (!(p.revents & (POLLOUT|POLLERR|POLLHUP)))
|
||||
return 0;
|
||||
|
||||
r = getsockopt(b->fd, SOL_SOCKET, SO_ERROR, &error, &slen);
|
||||
r = getsockopt(b->output_fd, SOL_SOCKET, SO_ERROR, &error, &slen);
|
||||
if (r < 0)
|
||||
b->last_connect_error = errno;
|
||||
else if (error != 0)
|
||||
|
@ -48,8 +48,7 @@ static void bus_free(sd_bus *b) {
|
||||
|
||||
assert(b);
|
||||
|
||||
if (b->fd >= 0)
|
||||
close_nointr_nofail(b->fd);
|
||||
sd_bus_close(b);
|
||||
|
||||
free(b->rbuffer);
|
||||
free(b->unique_name);
|
||||
@ -101,7 +100,7 @@ int sd_bus_new(sd_bus **ret) {
|
||||
return -ENOMEM;
|
||||
|
||||
r->n_ref = 1;
|
||||
r->fd = -1;
|
||||
r->input_fd = r->output_fd = -1;
|
||||
r->message_version = 1;
|
||||
r->negotiate_fds = true;
|
||||
|
||||
@ -137,15 +136,18 @@ int sd_bus_set_address(sd_bus *bus, const char *address) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_bus_set_fd(sd_bus *bus, int fd) {
|
||||
int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
|
||||
if (!bus)
|
||||
return -EINVAL;
|
||||
if (bus->state != BUS_UNSET)
|
||||
return -EPERM;
|
||||
if (fd < 0)
|
||||
if (input_fd < 0)
|
||||
return -EINVAL;
|
||||
if (output_fd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
bus->fd = fd;
|
||||
bus->input_fd = input_fd;
|
||||
bus->output_fd = output_fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -679,10 +681,7 @@ static int bus_start_address(sd_bus *b) {
|
||||
assert(b);
|
||||
|
||||
for (;;) {
|
||||
if (b->fd >= 0) {
|
||||
close_nointr_nofail(b->fd);
|
||||
b->fd = -1;
|
||||
}
|
||||
sd_bus_close(b);
|
||||
|
||||
if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
|
||||
|
||||
@ -720,15 +719,27 @@ static int bus_start_fd(sd_bus *b) {
|
||||
int r;
|
||||
|
||||
assert(b);
|
||||
assert(b->input_fd >= 0);
|
||||
assert(b->output_fd >= 0);
|
||||
|
||||
r = fd_nonblock(b->fd, true);
|
||||
r = fd_nonblock(b->input_fd, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = fd_cloexec(b->fd, true);
|
||||
r = fd_cloexec(b->input_fd, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (b->input_fd != b->output_fd) {
|
||||
r = fd_nonblock(b->output_fd, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = fd_cloexec(b->output_fd, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return bus_socket_take_fd(b);
|
||||
}
|
||||
|
||||
@ -745,7 +756,7 @@ int sd_bus_start(sd_bus *bus) {
|
||||
if (bus->is_server && bus->bus_client)
|
||||
return -EINVAL;
|
||||
|
||||
if (bus->fd >= 0)
|
||||
if (bus->input_fd >= 0)
|
||||
r = bus_start_fd(bus);
|
||||
else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path)
|
||||
r = bus_start_address(bus);
|
||||
@ -848,11 +859,13 @@ fail:
|
||||
void sd_bus_close(sd_bus *bus) {
|
||||
if (!bus)
|
||||
return;
|
||||
if (bus->fd < 0)
|
||||
return;
|
||||
|
||||
close_nointr_nofail(bus->fd);
|
||||
bus->fd = -1;
|
||||
if (bus->input_fd >= 0)
|
||||
close_nointr_nofail(bus->input_fd);
|
||||
if (bus->output_fd >= 0 && bus->output_fd != bus->input_fd)
|
||||
close_nointr_nofail(bus->output_fd);
|
||||
|
||||
bus->input_fd = bus->output_fd = -1;
|
||||
}
|
||||
|
||||
sd_bus *sd_bus_ref(sd_bus *bus) {
|
||||
@ -882,7 +895,7 @@ int sd_bus_is_open(sd_bus *bus) {
|
||||
if (!bus)
|
||||
return -EINVAL;
|
||||
|
||||
return bus->state != BUS_UNSET && bus->fd >= 0;
|
||||
return bus->state != BUS_UNSET && bus->input_fd >= 0;
|
||||
}
|
||||
|
||||
int sd_bus_can_send(sd_bus *bus, char type) {
|
||||
@ -890,7 +903,7 @@ int sd_bus_can_send(sd_bus *bus, char type) {
|
||||
|
||||
if (!bus)
|
||||
return -EINVAL;
|
||||
if (bus->fd < 0)
|
||||
if (bus->output_fd < 0)
|
||||
return -ENOTCONN;
|
||||
|
||||
if (type == SD_BUS_TYPE_UNIX_FD) {
|
||||
@ -941,7 +954,7 @@ static int dispatch_wqueue(sd_bus *bus) {
|
||||
assert(bus);
|
||||
assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
|
||||
|
||||
if (bus->fd < 0)
|
||||
if (bus->output_fd < 0)
|
||||
return -ENOTCONN;
|
||||
|
||||
while (bus->wqueue_size > 0) {
|
||||
@ -984,7 +997,7 @@ static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
|
||||
assert(m);
|
||||
assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
|
||||
|
||||
if (bus->fd < 0)
|
||||
if (bus->input_fd < 0)
|
||||
return -ENOTCONN;
|
||||
|
||||
if (bus->rqueue_size > 0) {
|
||||
@ -1020,7 +1033,7 @@ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
|
||||
return -EINVAL;
|
||||
if (bus->state == BUS_UNSET)
|
||||
return -ENOTCONN;
|
||||
if (bus->fd < 0)
|
||||
if (bus->output_fd < 0)
|
||||
return -ENOTCONN;
|
||||
if (!m)
|
||||
return -EINVAL;
|
||||
@ -1129,7 +1142,7 @@ int sd_bus_send_with_reply(
|
||||
return -EINVAL;
|
||||
if (bus->state == BUS_UNSET)
|
||||
return -ENOTCONN;
|
||||
if (bus->fd < 0)
|
||||
if (bus->output_fd < 0)
|
||||
return -ENOTCONN;
|
||||
if (!m)
|
||||
return -EINVAL;
|
||||
@ -1211,7 +1224,7 @@ int bus_ensure_running(sd_bus *bus) {
|
||||
|
||||
assert(bus);
|
||||
|
||||
if (bus->fd < 0)
|
||||
if (bus->input_fd < 0)
|
||||
return -ENOTCONN;
|
||||
if (bus->state == BUS_UNSET)
|
||||
return -ENOTCONN;
|
||||
@ -1248,7 +1261,7 @@ int sd_bus_send_with_reply_and_block(
|
||||
|
||||
if (!bus)
|
||||
return -EINVAL;
|
||||
if (bus->fd < 0)
|
||||
if (bus->output_fd < 0)
|
||||
return -ENOTCONN;
|
||||
if (bus->state == BUS_UNSET)
|
||||
return -ENOTCONN;
|
||||
@ -1358,11 +1371,12 @@ int sd_bus_send_with_reply_and_block(
|
||||
int sd_bus_get_fd(sd_bus *bus) {
|
||||
if (!bus)
|
||||
return -EINVAL;
|
||||
|
||||
if (bus->fd < 0)
|
||||
if (bus->input_fd < 0)
|
||||
return -ENOTCONN;
|
||||
if (bus->input_fd != bus->output_fd)
|
||||
return -EPERM;
|
||||
|
||||
return bus->fd;
|
||||
return bus->input_fd;
|
||||
}
|
||||
|
||||
int sd_bus_get_events(sd_bus *bus) {
|
||||
@ -1372,7 +1386,7 @@ int sd_bus_get_events(sd_bus *bus) {
|
||||
return -EINVAL;
|
||||
if (bus->state == BUS_UNSET)
|
||||
return -ENOTCONN;
|
||||
if (bus->fd < 0)
|
||||
if (bus->input_fd < 0)
|
||||
return -ENOTCONN;
|
||||
|
||||
if (bus->state == BUS_OPENING)
|
||||
@ -1403,7 +1417,7 @@ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
|
||||
return -EINVAL;
|
||||
if (bus->state == BUS_UNSET)
|
||||
return -ENOTCONN;
|
||||
if (bus->fd < 0)
|
||||
if (bus->input_fd < 0)
|
||||
return -ENOTCONN;
|
||||
|
||||
if (bus->state == BUS_AUTHENTICATING) {
|
||||
@ -1824,7 +1838,7 @@ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
|
||||
|
||||
if (!bus)
|
||||
return -EINVAL;
|
||||
if (bus->fd < 0)
|
||||
if (bus->input_fd < 0)
|
||||
return -ENOTCONN;
|
||||
|
||||
switch (bus->state) {
|
||||
@ -1859,14 +1873,14 @@ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
|
||||
}
|
||||
|
||||
static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
|
||||
struct pollfd p;
|
||||
int r, e;
|
||||
struct pollfd p[2];
|
||||
int r, e, n;
|
||||
struct timespec ts;
|
||||
usec_t until, m;
|
||||
|
||||
assert(bus);
|
||||
|
||||
if (bus->fd < 0)
|
||||
if (bus->input_fd < 0)
|
||||
return -ENOTCONN;
|
||||
|
||||
e = sd_bus_get_events(bus);
|
||||
@ -1882,19 +1896,28 @@ static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
|
||||
if (r == 0)
|
||||
m = (uint64_t) -1;
|
||||
else {
|
||||
usec_t n;
|
||||
n = now(CLOCK_MONOTONIC);
|
||||
m = until > n ? until - n : 0;
|
||||
usec_t nw;
|
||||
nw = now(CLOCK_MONOTONIC);
|
||||
m = until > nw ? until - nw : 0;
|
||||
}
|
||||
|
||||
if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
|
||||
m = timeout_usec;
|
||||
|
||||
zero(p);
|
||||
p.fd = bus->fd;
|
||||
p.events = e;
|
||||
p[0].fd = bus->input_fd;
|
||||
|
||||
r = ppoll(&p, 1, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
|
||||
if (bus->output_fd == bus->input_fd) {
|
||||
p[0].events = e;
|
||||
n = 1;
|
||||
} else {
|
||||
p[0].events = e & POLLIN;
|
||||
p[1].fd = bus->output_fd;
|
||||
p[1].events = e & POLLOUT;
|
||||
n = 2;
|
||||
}
|
||||
|
||||
r = ppoll(p, n, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
@ -1907,7 +1930,7 @@ int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
|
||||
return -EINVAL;
|
||||
if (bus->state == BUS_UNSET)
|
||||
return -ENOTCONN;
|
||||
if (bus->fd < 0)
|
||||
if (bus->input_fd < 0)
|
||||
return -ENOTCONN;
|
||||
if (bus->rqueue_size > 0)
|
||||
return 0;
|
||||
@ -1922,7 +1945,7 @@ int sd_bus_flush(sd_bus *bus) {
|
||||
return -EINVAL;
|
||||
if (bus->state == BUS_UNSET)
|
||||
return -ENOTCONN;
|
||||
if (bus->fd < 0)
|
||||
if (bus->output_fd < 0)
|
||||
return -ENOTCONN;
|
||||
|
||||
r = bus_ensure_running(bus);
|
||||
|
@ -53,7 +53,7 @@ static void *server(void *p) {
|
||||
assert_se(sd_id128_randomize(&id) >= 0);
|
||||
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
assert_se(sd_bus_set_fd(bus, c->fds[0]) >= 0);
|
||||
assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
|
||||
assert_se(sd_bus_set_server(bus, 1, id) >= 0);
|
||||
assert_se(sd_bus_set_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0);
|
||||
assert_se(sd_bus_set_anonymous(bus, c->server_anonymous_auth) >= 0);
|
||||
@ -132,7 +132,7 @@ static int client(struct context *c) {
|
||||
int r;
|
||||
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
assert_se(sd_bus_set_fd(bus, c->fds[1]) >= 0);
|
||||
assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
|
||||
assert_se(sd_bus_set_negotiate_fds(bus, c->client_negotiate_unix_fds) >= 0);
|
||||
assert_se(sd_bus_set_anonymous(bus, c->client_anonymous_auth) >= 0);
|
||||
assert_se(sd_bus_start(bus) >= 0);
|
||||
|
Loading…
Reference in New Issue
Block a user