summaryrefslogtreecommitdiff
path: root/src/libsystemd/sd-bus
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd/sd-bus')
-rw-r--r--src/libsystemd/sd-bus/bus-bloom.c12
-rw-r--r--src/libsystemd/sd-bus/bus-bloom.h3
-rw-r--r--src/libsystemd/sd-bus/bus-common-errors.c44
-rw-r--r--src/libsystemd/sd-bus/bus-common-errors.h17
-rw-r--r--src/libsystemd/sd-bus/bus-container.c130
-rw-r--r--src/libsystemd/sd-bus/bus-container.h2
-rw-r--r--src/libsystemd/sd-bus/bus-control.c86
-rw-r--r--src/libsystemd/sd-bus/bus-control.h3
-rw-r--r--src/libsystemd/sd-bus/bus-convenience.c177
-rw-r--r--src/libsystemd/sd-bus/bus-creds.c56
-rw-r--r--src/libsystemd/sd-bus/bus-creds.h2
-rw-r--r--src/libsystemd/sd-bus/bus-dump.c80
-rw-r--r--src/libsystemd/sd-bus/bus-dump.h4
-rw-r--r--src/libsystemd/sd-bus/bus-error.c71
-rw-r--r--src/libsystemd/sd-bus/bus-error.h3
-rw-r--r--src/libsystemd/sd-bus/bus-gvariant.c25
-rw-r--r--src/libsystemd/sd-bus/bus-gvariant.h2
-rw-r--r--src/libsystemd/sd-bus/bus-internal.c7
-rw-r--r--src/libsystemd/sd-bus/bus-internal.h36
-rw-r--r--src/libsystemd/sd-bus/bus-introspect.c27
-rw-r--r--src/libsystemd/sd-bus/bus-introspect.h3
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.c156
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.h2
-rw-r--r--src/libsystemd/sd-bus/bus-match.c95
-rw-r--r--src/libsystemd/sd-bus/bus-match.h8
-rw-r--r--src/libsystemd/sd-bus/bus-message.c221
-rw-r--r--src/libsystemd/sd-bus/bus-message.h12
-rw-r--r--src/libsystemd/sd-bus/bus-objects.c187
-rw-r--r--src/libsystemd/sd-bus/bus-objects.h2
-rw-r--r--src/libsystemd/sd-bus/bus-protocol.h2
-rw-r--r--src/libsystemd/sd-bus/bus-signature.c2
-rw-r--r--src/libsystemd/sd-bus/bus-signature.h2
-rw-r--r--src/libsystemd/sd-bus/bus-slot.c11
-rw-r--r--src/libsystemd/sd-bus/bus-slot.h3
-rw-r--r--src/libsystemd/sd-bus/bus-socket.c47
-rw-r--r--src/libsystemd/sd-bus/bus-socket.h2
-rw-r--r--src/libsystemd/sd-bus/bus-track.c272
-rw-r--r--src/libsystemd/sd-bus/bus-track.h3
-rw-r--r--src/libsystemd/sd-bus/bus-type.c2
-rw-r--r--src/libsystemd/sd-bus/bus-type.h5
-rw-r--r--src/libsystemd/sd-bus/busctl-introspect.c21
-rw-r--r--src/libsystemd/sd-bus/busctl-introspect.h2
-rw-r--r--src/libsystemd/sd-bus/busctl.c223
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c602
-rw-r--r--src/libsystemd/sd-bus/test-bus-benchmark.c22
-rw-r--r--src/libsystemd/sd-bus/test-bus-chat.c44
-rw-r--r--src/libsystemd/sd-bus/test-bus-cleanup.c21
-rw-r--r--src/libsystemd/sd-bus/test-bus-creds.c16
-rw-r--r--src/libsystemd/sd-bus/test-bus-error.c40
-rw-r--r--src/libsystemd/sd-bus/test-bus-gvariant.c18
-rw-r--r--src/libsystemd/sd-bus/test-bus-introspect.c6
-rw-r--r--src/libsystemd/sd-bus/test-bus-kernel-bloom.c16
-rw-r--r--src/libsystemd/sd-bus/test-bus-kernel.c16
-rw-r--r--src/libsystemd/sd-bus/test-bus-marshal.c62
-rw-r--r--src/libsystemd/sd-bus/test-bus-match.c21
-rw-r--r--src/libsystemd/sd-bus/test-bus-objects.c45
-rw-r--r--src/libsystemd/sd-bus/test-bus-proxy.c109
-rw-r--r--src/libsystemd/sd-bus/test-bus-server.c18
-rw-r--r--src/libsystemd/sd-bus/test-bus-signature.c8
-rw-r--r--src/libsystemd/sd-bus/test-bus-track.c113
-rw-r--r--src/libsystemd/sd-bus/test-bus-zero-copy.c17
61 files changed, 2033 insertions, 1231 deletions
diff --git a/src/libsystemd/sd-bus/bus-bloom.c b/src/libsystemd/sd-bus/bus-bloom.c
index 91fab90cb0..112769fcb6 100644
--- a/src/libsystemd/sd-bus/bus-bloom.c
+++ b/src/libsystemd/sd-bus/bus-bloom.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,9 +17,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-#include "siphash24.h"
#include "bus-bloom.h"
+#include "siphash24.h"
+#include "util.h"
static inline void set_bit(uint64_t filter[], unsigned long b) {
filter[b >> 6] |= 1ULL << (b & 63);
@@ -45,7 +43,7 @@ static void bloom_add_data(
const void *data, /* Data to hash */
size_t n) { /* Size of data to hash in bytes */
- uint8_t h[8];
+ uint64_t h;
uint64_t m;
unsigned w, i, c = 0;
unsigned hash_index;
@@ -72,11 +70,11 @@ static void bloom_add_data(
for (d = 0; d < w; d++) {
if (c <= 0) {
- siphash24(h, data, n, hash_keys[hash_index++].bytes);
+ h = siphash24(data, n, hash_keys[hash_index++].bytes);
c += 8;
}
- p = (p << 8ULL) | (uint64_t) h[8 - c];
+ p = (p << 8ULL) | (uint64_t) ((uint8_t *)&h)[8 - c];
c--;
}
diff --git a/src/libsystemd/sd-bus/bus-bloom.h b/src/libsystemd/sd-bus/bus-bloom.h
index a9350d7f51..c824622b95 100644
--- a/src/libsystemd/sd-bus/bus-bloom.h
+++ b/src/libsystemd/sd-bus/bus-bloom.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -22,6 +20,7 @@
***/
#include <stdbool.h>
+#include <stddef.h>
#include <stdint.h>
/*
diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c
index 52f8dfd3be..d2a826bf6e 100644
--- a/src/libsystemd/sd-bus/bus-common-errors.c
+++ b/src/libsystemd/sd-bus/bus-common-errors.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -22,12 +20,14 @@
#include <errno.h>
#include "sd-bus.h"
-#include "bus-error.h"
+
#include "bus-common-errors.h"
+#include "bus-error.h"
BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_UNIT, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_PID, ESRCH),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_EXISTS, EEXIST),
SD_BUS_ERROR_MAP(BUS_ERROR_LOAD_FAILED, EIO),
SD_BUS_ERROR_MAP(BUS_ERROR_JOB_FAILED, EREMOTEIO),
@@ -38,17 +38,23 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, EDEADLK),
SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC, EDEADLK),
SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, EDEADLK),
- SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_MASKED, EBADR),
+ SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_MASKED, ESHUTDOWN),
+ SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_GENERATED, EADDRNOTAVAIL),
+ SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_LINKED, ELOOP),
SD_BUS_ERROR_MAP(BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, EBADR),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_ISOLATION, EPERM),
SD_BUS_ERROR_MAP(BUS_ERROR_SHUTTING_DOWN, ECANCELED),
SD_BUS_ERROR_MAP(BUS_ERROR_SCOPE_NOT_RUNNING, EHOSTDOWN),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DYNAMIC_USER, ESRCH),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NOT_REFERENCED, EUNATCH),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_IMAGE, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_MACHINE_FOR_PID, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_MACHINE_EXISTS, EEXIST),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_PRIVATE_NETWORKING, ENOSYS),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_USER_MAPPING, ENXIO),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_GROUP_MAPPING, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SESSION, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SESSION_FOR_PID, ENXIO),
@@ -61,17 +67,43 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_NOT_TAKEN, EINVAL),
SD_BUS_ERROR_MAP(BUS_ERROR_OPERATION_IN_PROGRESS, EINPROGRESS),
SD_BUS_ERROR_MAP(BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, EOPNOTSUPP),
+ SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_BUSY, EBUSY),
SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, EALREADY),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_PROCESS, ESRCH),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_NAME_SERVERS, EIO),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_NAME_SERVERS, ESRCH),
SD_BUS_ERROR_MAP(BUS_ERROR_INVALID_REPLY, EINVAL),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_RR, ENOENT),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_RESOURCES, ENOMEM),
SD_BUS_ERROR_MAP(BUS_ERROR_CNAME_LOOP, EDEADLK),
SD_BUS_ERROR_MAP(BUS_ERROR_ABORTED, ECANCELED),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SERVICE, EUNATCH),
+ SD_BUS_ERROR_MAP(BUS_ERROR_DNSSEC_FAILED, EHOSTUNREACH),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_TRUST_ANCHOR, EHOSTUNREACH),
+ SD_BUS_ERROR_MAP(BUS_ERROR_RR_TYPE_UNSUPPORTED, EOPNOTSUPP),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_LINK, ENXIO),
+ SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY, EBUSY),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN, ENETDOWN),
+
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "FORMERR", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "SERVFAIL", EHOSTDOWN),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXDOMAIN", ENXIO),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTIMP", ENOSYS),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "REFUSED", EACCES),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YXDOMAIN", EEXIST),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YRRSET", EEXIST),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXRRSET", ENOENT),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTAUTH", EACCES),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTZONE", EREMOTE),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADVERS", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADKEY", EKEYREJECTED),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTIME", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADMODE", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADNAME", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADALG", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTRUNC", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADCOOKIE", EBADR),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_TRANSFER, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_TRANSFER_IN_PROGRESS, EBUSY),
diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h
index 0dbfbddcf6..525b79fa77 100644
--- a/src/libsystemd/sd-bus/bus-common-errors.h
+++ b/src/libsystemd/sd-bus/bus-common-errors.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -25,6 +23,7 @@
#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
#define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID"
+#define BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID "org.freedesktop.systemd1.NoUnitForInvocationID"
#define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists"
#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
@@ -36,16 +35,22 @@
#define BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC "org.freedesktop.systemd1.TransactionOrderIsCyclic"
#define BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE "org.freedesktop.systemd1.TransactionIsDestructive"
#define BUS_ERROR_UNIT_MASKED "org.freedesktop.systemd1.UnitMasked"
+#define BUS_ERROR_UNIT_GENERATED "org.freedesktop.systemd1.UnitGenerated"
+#define BUS_ERROR_UNIT_LINKED "org.freedesktop.systemd1.UnitLinked"
#define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable"
#define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation"
#define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown"
#define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning"
+#define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.systemd1.NoSuchDynamicUser"
+#define BUS_ERROR_NOT_REFERENCED "org.freedesktop.systemd1.NotReferenced"
#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
#define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage"
#define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"
#define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists"
#define BUS_ERROR_NO_PRIVATE_NETWORKING "org.freedesktop.machine1.NoPrivateNetworking"
+#define BUS_ERROR_NO_SUCH_USER_MAPPING "org.freedesktop.machine1.NoSuchUserMapping"
+#define BUS_ERROR_NO_SUCH_GROUP_MAPPING "org.freedesktop.machine1.NoSuchGroupMapping"
#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
@@ -67,9 +72,15 @@
#define BUS_ERROR_NO_NAME_SERVERS "org.freedesktop.resolve1.NoNameServers"
#define BUS_ERROR_INVALID_REPLY "org.freedesktop.resolve1.InvalidReply"
#define BUS_ERROR_NO_SUCH_RR "org.freedesktop.resolve1.NoSuchRR"
-#define BUS_ERROR_NO_RESOURCES "org.freedesktop.resolve1.NoResources"
#define BUS_ERROR_CNAME_LOOP "org.freedesktop.resolve1.CNameLoop"
#define BUS_ERROR_ABORTED "org.freedesktop.resolve1.Aborted"
+#define BUS_ERROR_NO_SUCH_SERVICE "org.freedesktop.resolve1.NoSuchService"
+#define BUS_ERROR_DNSSEC_FAILED "org.freedesktop.resolve1.DnssecFailed"
+#define BUS_ERROR_NO_TRUST_ANCHOR "org.freedesktop.resolve1.NoTrustAnchor"
+#define BUS_ERROR_RR_TYPE_UNSUPPORTED "org.freedesktop.resolve1.ResourceRecordTypeUnsupported"
+#define BUS_ERROR_NO_SUCH_LINK "org.freedesktop.resolve1.NoSuchLink"
+#define BUS_ERROR_LINK_BUSY "org.freedesktop.resolve1.LinkBusy"
+#define BUS_ERROR_NETWORK_DOWN "org.freedesktop.resolve1.NetworkDown"
#define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError."
#define BUS_ERROR_NO_SUCH_TRANSFER "org.freedesktop.import1.NoSuchTransfer"
diff --git a/src/libsystemd/sd-bus/bus-container.c b/src/libsystemd/sd-bus/bus-container.c
index fa7a207448..3191d27ded 100644
--- a/src/libsystemd/sd-bus/bus-container.c
+++ b/src/libsystemd/sd-bus/bus-container.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,20 +17,23 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
#include <fcntl.h>
+#include <unistd.h>
-#include "util.h"
-#include "process-util.h"
+#include "bus-container.h"
#include "bus-internal.h"
#include "bus-socket.h"
-#include "bus-container.h"
+#include "fd-util.h"
+#include "process-util.h"
+#include "util.h"
int bus_container_connect_socket(sd_bus *b) {
- _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
+ _cleanup_close_pair_ int pair[2] = { -1, -1 };
+ _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
pid_t child;
siginfo_t si;
- int r;
+ int r, error_buf = 0;
+ ssize_t n;
assert(b);
assert(b->input_fd < 0);
@@ -45,7 +46,7 @@ int bus_container_connect_socket(sd_bus *b) {
return r;
}
- r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &rootfd);
+ r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
if (r < 0)
return r;
@@ -57,6 +58,9 @@ int bus_container_connect_socket(sd_bus *b) {
bus_socket_setup(b);
+ if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
+ return -errno;
+
child = fork();
if (child < 0)
return -errno;
@@ -64,9 +68,11 @@ int bus_container_connect_socket(sd_bus *b) {
if (child == 0) {
pid_t grandchild;
- r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd);
+ pair[0] = safe_close(pair[0]);
+
+ r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
if (r < 0)
- _exit(255);
+ _exit(EXIT_FAILURE);
/* We just changed PID namespace, however it will only
* take effect on the children we now fork. Hence,
@@ -77,16 +83,16 @@ int bus_container_connect_socket(sd_bus *b) {
grandchild = fork();
if (grandchild < 0)
- _exit(255);
+ _exit(EXIT_FAILURE);
if (grandchild == 0) {
r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
if (r < 0) {
- if (errno == EINPROGRESS)
- _exit(1);
-
- _exit(255);
+ /* Try to send error up */
+ error_buf = errno;
+ (void) write(pair[1], &error_buf, sizeof(error_buf));
+ _exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
@@ -94,24 +100,41 @@ int bus_container_connect_socket(sd_bus *b) {
r = wait_for_terminate(grandchild, &si);
if (r < 0)
- _exit(255);
+ _exit(EXIT_FAILURE);
if (si.si_code != CLD_EXITED)
- _exit(255);
+ _exit(EXIT_FAILURE);
_exit(si.si_status);
}
+ pair[1] = safe_close(pair[1]);
+
r = wait_for_terminate(child, &si);
if (r < 0)
return r;
+ n = read(pair[0], &error_buf, sizeof(error_buf));
+ if (n < 0)
+ return -errno;
+
+ if (n > 0) {
+ if (n != sizeof(error_buf))
+ return -EIO;
+
+ if (error_buf < 0)
+ return -EIO;
+
+ if (error_buf == EINPROGRESS)
+ return 1;
+
+ if (error_buf > 0)
+ return -error_buf;
+ }
+
if (si.si_code != CLD_EXITED)
return -EIO;
- if (si.si_status == 1)
- return 1;
-
if (si.si_status != EXIT_SUCCESS)
return -EIO;
@@ -120,20 +143,27 @@ int bus_container_connect_socket(sd_bus *b) {
int bus_container_connect_kernel(sd_bus *b) {
_cleanup_close_pair_ int pair[2] = { -1, -1 };
- _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
+ _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
union {
struct cmsghdr cmsghdr;
uint8_t buf[CMSG_SPACE(sizeof(int))];
} control = {};
+ int error_buf = 0;
+ struct iovec iov = {
+ .iov_base = &error_buf,
+ .iov_len = sizeof(error_buf),
+ };
struct msghdr mh = {
.msg_control = &control,
.msg_controllen = sizeof(control),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
};
struct cmsghdr *cmsg;
pid_t child;
siginfo_t si;
- int r;
- _cleanup_close_ int fd = -1;
+ int r, fd = -1;
+ ssize_t n;
assert(b);
assert(b->input_fd < 0);
@@ -146,11 +176,11 @@ int bus_container_connect_kernel(sd_bus *b) {
return r;
}
- r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &rootfd);
+ r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
if (r < 0)
return r;
- if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
+ if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
return -errno;
child = fork();
@@ -162,7 +192,7 @@ int bus_container_connect_kernel(sd_bus *b) {
pair[0] = safe_close(pair[0]);
- r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd);
+ r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
if (r < 0)
_exit(EXIT_FAILURE);
@@ -178,20 +208,16 @@ int bus_container_connect_kernel(sd_bus *b) {
_exit(EXIT_FAILURE);
if (grandchild == 0) {
-
fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
+ if (fd < 0) {
+ /* Try to send error up */
+ error_buf = errno;
+ (void) write(pair[1], &error_buf, sizeof(error_buf));
_exit(EXIT_FAILURE);
+ }
- cmsg = CMSG_FIRSTHDR(&mh);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = CMSG_LEN(sizeof(int));
- memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
-
- mh.msg_controllen = cmsg->cmsg_len;
-
- if (sendmsg(pair[1], &mh, MSG_NOSIGNAL) < 0)
+ r = send_one_fd(pair[1], fd, 0);
+ if (r < 0)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
@@ -213,20 +239,17 @@ int bus_container_connect_kernel(sd_bus *b) {
if (r < 0)
return r;
- if (si.si_code != CLD_EXITED)
- return -EIO;
-
- if (si.si_status != EXIT_SUCCESS)
- return -EIO;
-
- if (recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) < 0)
+ n = recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
+ if (n < 0)
return -errno;
- CMSG_FOREACH(cmsg, &mh)
+ CMSG_FOREACH(cmsg, &mh) {
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
int *fds;
unsigned n_fds;
+ assert(fd < 0);
+
fds = (int*) CMSG_DATA(cmsg);
n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
@@ -237,9 +260,18 @@ int bus_container_connect_kernel(sd_bus *b) {
fd = fds[0];
}
+ }
+
+ /* If there's an fd passed, we are good. */
+ if (fd >= 0) {
+ b->input_fd = b->output_fd = fd;
+ return bus_kernel_take_fd(b);
+ }
- b->input_fd = b->output_fd = fd;
- fd = -1;
+ /* If there's an error passed, use it */
+ if (n == sizeof(error_buf) && error_buf > 0)
+ return -error_buf;
- return bus_kernel_take_fd(b);
+ /* Otherwise, we have no clue */
+ return -EIO;
}
diff --git a/src/libsystemd/sd-bus/bus-container.h b/src/libsystemd/sd-bus/bus-container.h
index c6f757a99b..509ef45624 100644
--- a/src/libsystemd/sd-bus/bus-container.h
+++ b/src/libsystemd/sd-bus/bus-container.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c
index c53666ddd0..52128e7b5c 100644
--- a/src/libsystemd/sd-bus/bus-control.c
+++ b/src/libsystemd/sd-bus/bus-control.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -23,17 +21,22 @@
#include <valgrind/memcheck.h>
#endif
-#include <stddef.h>
#include <errno.h>
+#include <stddef.h>
-#include "strv.h"
#include "sd-bus.h"
+
+#include "alloc-util.h"
+#include "bus-bloom.h"
+#include "bus-control.h"
#include "bus-internal.h"
#include "bus-message.h"
-#include "bus-control.h"
-#include "bus-bloom.h"
#include "bus-util.h"
-#include "capability.h"
+#include "capability-util.h"
+#include "stdio-util.h"
+#include "string-util.h"
+#include "strv.h"
+#include "user-util.h"
_public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
int r;
@@ -86,7 +89,7 @@ static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags
}
static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
uint32_t ret, param = 0;
int r;
@@ -182,7 +185,7 @@ static int bus_release_name_kernel(sd_bus *bus, const char *name) {
}
static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
uint32_t ret;
int r;
@@ -256,11 +259,9 @@ static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
name_list = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
KDBUS_FOREACH(name, name_list, cmd.list_size) {
-
struct kdbus_item *item;
- const char *entry_name = NULL;
- if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id) {
+ if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id && !(name->flags & KDBUS_HELLO_ACTIVATOR)) {
char *n;
if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) {
@@ -275,15 +276,15 @@ static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
previous_id = name->id;
}
- KDBUS_ITEM_FOREACH(item, name, items)
- if (item->type == KDBUS_ITEM_OWNED_NAME)
- entry_name = item->name.name;
-
- if (entry_name && service_name_is_valid(entry_name)) {
- r = strv_extend(x, entry_name);
- if (r < 0) {
- r = -ENOMEM;
- goto fail;
+ KDBUS_ITEM_FOREACH(item, name, items) {
+ if (item->type == KDBUS_ITEM_OWNED_NAME) {
+ if (service_name_is_valid(item->name.name)) {
+ r = strv_extend(x, item->name.name);
+ if (r < 0) {
+ r = -ENOMEM;
+ goto fail;
+ }
+ }
}
}
}
@@ -323,7 +324,7 @@ static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activata
}
static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_strv_free_ char **x = NULL, **y = NULL;
int r;
@@ -644,7 +645,7 @@ int bus_get_name_creds_kdbus(
bool allow_activator,
sd_bus_creds **creds) {
- _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
struct kdbus_cmd_info *cmd;
struct kdbus_info *conn_info;
size_t size, l;
@@ -677,6 +678,7 @@ int bus_get_name_creds_kdbus(
(mask & (SD_BUS_CREDS_PPID|
SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
+ SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
@@ -750,8 +752,8 @@ static int bus_get_name_creds_dbus1(
uint64_t mask,
sd_bus_creds **creds) {
- _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
- _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
const char *unique = NULL;
pid_t pid = 0;
int r;
@@ -794,6 +796,7 @@ static int bus_get_name_creds_dbus1(
((mask & SD_BUS_CREDS_AUGMENT) &&
(mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
+ SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
@@ -855,7 +858,7 @@ static int bus_get_name_creds_dbus1(
}
if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
- _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;
const void *p = NULL;
size_t sz = 0;
@@ -927,7 +930,7 @@ _public_ int sd_bus_get_name_creds(
}
static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
- _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
struct kdbus_cmd_info cmd = {
.size = sizeof(struct kdbus_cmd_info),
};
@@ -946,6 +949,7 @@ static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **
(mask & (SD_BUS_CREDS_PPID|
SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
+ SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
@@ -976,10 +980,14 @@ static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **
}
static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
- _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
pid_t pid = 0;
+ bool do_label;
int r;
- bool do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
+
+ assert(bus);
+
+ do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
/* Avoid allocating anything if we have no chance of returning useful data */
if (!bus->ucred_valid && !do_label)
@@ -1126,8 +1134,7 @@ static int add_name_change_match(sd_bus *bus,
item->name_change.old_id.id = old_owner_id;
item->name_change.new_id.id = new_owner_id;
- if (name)
- memcpy(item->name_change.name, name, l);
+ memcpy_safe(item->name_change.name, name, l);
/* If the old name is unset or empty, then
* this can match against added names */
@@ -1311,7 +1318,16 @@ int bus_add_match_internal_kernel(
break;
}
- case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
+ case BUS_MATCH_ARG_HAS...BUS_MATCH_ARG_HAS_LAST: {
+ char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
+
+ xsprintf(buf, "arg%i-has", c->type - BUS_MATCH_ARG_HAS);
+ bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
+ using_bloom = true;
+ break;
+ }
+
+ case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST:
/*
* XXX: DBus spec defines arg[0..63]path= matching to be
* a two-way glob. That is, if either string is a prefix
@@ -1325,7 +1341,6 @@ int bus_add_match_internal_kernel(
* to properly support multiple-matches here.
*/
break;
- }
case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
@@ -1336,7 +1351,7 @@ int bus_add_match_internal_kernel(
break;
}
- case BUS_MATCH_DESTINATION: {
+ case BUS_MATCH_DESTINATION:
/*
* Kernel only supports matching on destination IDs, but
* not on destination names. So just skip the
@@ -1354,7 +1369,6 @@ int bus_add_match_internal_kernel(
matches_name_change = false;
break;
- }
case BUS_MATCH_ROOT:
case BUS_MATCH_VALUE:
@@ -1529,7 +1543,7 @@ int bus_remove_match_internal(
}
_public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
const char *mid;
int r;
diff --git a/src/libsystemd/sd-bus/bus-control.h b/src/libsystemd/sd-bus/bus-control.h
index 5009ca8e61..c181aa7959 100644
--- a/src/libsystemd/sd-bus/bus-control.h
+++ b/src/libsystemd/sd-bus/bus-control.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -22,6 +20,7 @@
***/
#include "sd-bus.h"
+
#include "bus-match.h"
int bus_add_match_internal(sd_bus *bus, const char *match, struct bus_match_component *components, unsigned n_components, uint64_t cookie);
diff --git a/src/libsystemd/sd-bus/bus-convenience.c b/src/libsystemd/sd-bus/bus-convenience.c
index dfd82e746d..2d06bf541f 100644
--- a/src/libsystemd/sd-bus/bus-convenience.c
+++ b/src/libsystemd/sd-bus/bus-convenience.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -22,8 +20,9 @@
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-signature.h"
-#include "bus-util.h"
#include "bus-type.h"
+#include "bus-util.h"
+#include "string-util.h"
_public_ int sd_bus_emit_signal(
sd_bus *bus,
@@ -32,7 +31,7 @@ _public_ int sd_bus_emit_signal(
const char *member,
const char *types, ...) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert_return(bus, -EINVAL);
@@ -69,7 +68,7 @@ _public_ int sd_bus_call_method_async(
void *userdata,
const char *types, ...) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert_return(bus, -EINVAL);
@@ -105,18 +104,20 @@ _public_ int sd_bus_call_method(
sd_bus_message **reply,
const char *types, ...) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
+ bus_assert_return(bus, -EINVAL, error);
+ bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
+ if (!BUS_IS_OPEN(bus->state)) {
+ r = -ENOTCONN;
+ goto fail;
+ }
r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member);
if (r < 0)
- return r;
+ goto fail;
if (!isempty(types)) {
va_list ap;
@@ -125,17 +126,20 @@ _public_ int sd_bus_call_method(
r = bus_message_append_ap(m, types, ap);
va_end(ap);
if (r < 0)
- return r;
+ goto fail;
}
return sd_bus_call(bus, m, 0, error, reply);
+
+fail:
+ return sd_bus_error_set_errno(error, r);
}
_public_ int sd_bus_reply_method_return(
sd_bus_message *call,
const char *types, ...) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert_return(call, -EINVAL);
@@ -171,7 +175,7 @@ _public_ int sd_bus_reply_method_error(
sd_bus_message *call,
const sd_bus_error *e) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert_return(call, -EINVAL);
@@ -200,7 +204,7 @@ _public_ int sd_bus_reply_method_errorf(
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(call, -EINVAL);
@@ -227,7 +231,7 @@ _public_ int sd_bus_reply_method_errno(
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;
assert_return(call, -EINVAL);
assert_return(call->sealed, -EPERM);
@@ -255,7 +259,7 @@ _public_ int sd_bus_reply_method_errnof(
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;
assert_return(call, -EINVAL);
@@ -290,15 +294,17 @@ _public_ int sd_bus_get_property(
sd_bus_message *rep = NULL;
int r;
- assert_return(bus, -EINVAL);
- assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
- assert_return(member_name_is_valid(member), -EINVAL);
- assert_return(reply, -EINVAL);
- assert_return(signature_is_single(type, false), -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
+ bus_assert_return(bus, -EINVAL, error);
+ bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
+ bus_assert_return(member_name_is_valid(member), -EINVAL, error);
+ bus_assert_return(reply, -EINVAL, error);
+ bus_assert_return(signature_is_single(type, false), -EINVAL, error);
+ bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
+ if (!BUS_IS_OPEN(bus->state)) {
+ r = -ENOTCONN;
+ goto fail;
+ }
r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
if (r < 0)
@@ -307,11 +313,14 @@ _public_ int sd_bus_get_property(
r = sd_bus_message_enter_container(rep, 'v', type);
if (r < 0) {
sd_bus_message_unref(rep);
- return r;
+ goto fail;
}
*reply = rep;
return 0;
+
+fail:
+ return sd_bus_error_set_errno(error, r);
}
_public_ int sd_bus_get_property_trivial(
@@ -323,18 +332,20 @@ _public_ int sd_bus_get_property_trivial(
sd_bus_error *error,
char type, void *ptr) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
int r;
- assert_return(bus, -EINVAL);
- assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
- assert_return(member_name_is_valid(member), -EINVAL);
- assert_return(bus_type_is_trivial(type), -EINVAL);
- assert_return(ptr, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
+ bus_assert_return(bus, -EINVAL, error);
+ bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
+ bus_assert_return(member_name_is_valid(member), -EINVAL, error);
+ bus_assert_return(bus_type_is_trivial(type), -EINVAL, error);
+ bus_assert_return(ptr, -EINVAL, error);
+ bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
+ if (!BUS_IS_OPEN(bus->state)) {
+ r = -ENOTCONN;
+ goto fail;
+ }
r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
if (r < 0)
@@ -342,13 +353,16 @@ _public_ int sd_bus_get_property_trivial(
r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type));
if (r < 0)
- return r;
+ goto fail;
r = sd_bus_message_read_basic(reply, type, ptr);
if (r < 0)
- return r;
+ goto fail;
return 0;
+
+fail:
+ return sd_bus_error_set_errno(error, r);
}
_public_ int sd_bus_get_property_string(
@@ -360,19 +374,21 @@ _public_ int sd_bus_get_property_string(
sd_bus_error *error,
char **ret) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
const char *s;
char *n;
int r;
- assert_return(bus, -EINVAL);
- assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
- assert_return(member_name_is_valid(member), -EINVAL);
- assert_return(ret, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
+ bus_assert_return(bus, -EINVAL, error);
+ bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
+ bus_assert_return(member_name_is_valid(member), -EINVAL, error);
+ bus_assert_return(ret, -EINVAL, error);
+ bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
+ if (!BUS_IS_OPEN(bus->state)) {
+ r = -ENOTCONN;
+ goto fail;
+ }
r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
if (r < 0)
@@ -380,18 +396,23 @@ _public_ int sd_bus_get_property_string(
r = sd_bus_message_enter_container(reply, 'v', "s");
if (r < 0)
- return r;
+ goto fail;
r = sd_bus_message_read_basic(reply, 's', &s);
if (r < 0)
- return r;
+ goto fail;
n = strdup(s);
- if (!n)
- return -ENOMEM;
+ if (!n) {
+ r = -ENOMEM;
+ goto fail;
+ }
*ret = n;
return 0;
+
+fail:
+ return sd_bus_error_set_errno(error, r);
}
_public_ int sd_bus_get_property_strv(
@@ -403,17 +424,19 @@ _public_ int sd_bus_get_property_strv(
sd_bus_error *error,
char ***ret) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
int r;
- assert_return(bus, -EINVAL);
- assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
- assert_return(member_name_is_valid(member), -EINVAL);
- assert_return(ret, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
+ bus_assert_return(bus, -EINVAL, error);
+ bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
+ bus_assert_return(member_name_is_valid(member), -EINVAL, error);
+ bus_assert_return(ret, -EINVAL, error);
+ bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
+ if (!BUS_IS_OPEN(bus->state)) {
+ r = -ENOTCONN;
+ goto fail;
+ }
r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
if (r < 0)
@@ -421,13 +444,16 @@ _public_ int sd_bus_get_property_strv(
r = sd_bus_message_enter_container(reply, 'v', NULL);
if (r < 0)
- return r;
+ goto fail;
r = sd_bus_message_read_strv(reply, ret);
if (r < 0)
- return r;
+ goto fail;
return 0;
+
+fail:
+ return sd_bus_error_set_errno(error, r);
}
_public_ int sd_bus_set_property(
@@ -439,42 +465,47 @@ _public_ int sd_bus_set_property(
sd_bus_error *error,
const char *type, ...) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
va_list ap;
int r;
- assert_return(bus, -EINVAL);
- assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
- assert_return(member_name_is_valid(member), -EINVAL);
- assert_return(signature_is_single(type, false), -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
+ bus_assert_return(bus, -EINVAL, error);
+ bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
+ bus_assert_return(member_name_is_valid(member), -EINVAL, error);
+ bus_assert_return(signature_is_single(type, false), -EINVAL, error);
+ bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
+ if (!BUS_IS_OPEN(bus->state)) {
+ r = -ENOTCONN;
+ goto fail;
+ }
r = sd_bus_message_new_method_call(bus, &m, destination, path, "org.freedesktop.DBus.Properties", "Set");
if (r < 0)
- return r;
+ goto fail;
r = sd_bus_message_append(m, "ss", strempty(interface), member);
if (r < 0)
- return r;
+ goto fail;
r = sd_bus_message_open_container(m, 'v', type);
if (r < 0)
- return r;
+ goto fail;
va_start(ap, type);
r = bus_message_append_ap(m, type, ap);
va_end(ap);
if (r < 0)
- return r;
+ goto fail;
r = sd_bus_message_close_container(m);
if (r < 0)
- return r;
+ goto fail;
return sd_bus_call(bus, m, 0, error, NULL);
+
+fail:
+ return sd_bus_error_set_errno(error, r);
}
_public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds) {
@@ -522,7 +553,7 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b
}
_public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
uid_t our_uid;
bool know_caps = false;
int r;
diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c
index 1c365b7fcd..c4f693dee9 100644
--- a/src/libsystemd/sd-bus/bus-creds.c
+++ b/src/libsystemd/sd-bus/bus-creds.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,22 +17,28 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
#include <linux/capability.h>
+#include <stdlib.h>
-#include "util.h"
-#include "formats-util.h"
-#include "process-util.h"
-#include "terminal-util.h"
-#include "capability.h"
-#include "cgroup-util.h"
-#include "fileio.h"
-#include "audit.h"
+#include "alloc-util.h"
+#include "audit-util.h"
+#include "bus-creds.h"
+#include "bus-label.h"
#include "bus-message.h"
#include "bus-util.h"
+#include "capability-util.h"
+#include "cgroup-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "formats-util.h"
+#include "hexdecoct.h"
+#include "parse-util.h"
+#include "process-util.h"
+#include "string-util.h"
#include "strv.h"
-#include "bus-creds.h"
-#include "bus-label.h"
+#include "terminal-util.h"
+#include "user-util.h"
+#include "util.h"
enum {
CAP_OFFSET_INHERITABLE = 0,
@@ -69,7 +73,9 @@ void bus_creds_done(sd_bus_creds *c) {
}
_public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
- assert_return(c, NULL);
+
+ if (!c)
+ return NULL;
if (c->allocated) {
assert(c->n_ref > 0);
@@ -107,11 +113,9 @@ _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
free(c->cgroup_root);
free(c->description);
- free(c->supplementary_gids);
- c->supplementary_gids = NULL;
+ c->supplementary_gids = mfree(c->supplementary_gids);
- strv_free(c->well_known_names);
- c->well_known_names = NULL;
+ c->well_known_names = strv_free(c->well_known_names);
bus_creds_done(c);
@@ -1015,10 +1019,8 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
if (r != -EPERM && r != -EACCES)
return r;
} else {
- if (c->cmdline_size == 0) {
- free(c->cmdline);
- c->cmdline = NULL;
- }
+ if (c->cmdline_size == 0)
+ c->cmdline = mfree(c->cmdline);
c->mask |= SD_BUS_CREDS_CMDLINE;
}
@@ -1062,8 +1064,8 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
r = audit_session_from_pid(pid, &c->audit_session_id);
- if (r == -ENXIO) {
- /* ENXIO means: no audit session id assigned */
+ if (r == -ENODATA) {
+ /* ENODATA means: no audit session id assigned */
c->audit_session_id = AUDIT_SESSION_INVALID;
c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
} else if (r < 0) {
@@ -1075,8 +1077,8 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
- if (r == -ENXIO) {
- /* ENXIO means: no audit login uid assigned */
+ if (r == -ENODATA) {
+ /* ENODATA means: no audit login uid assigned */
c->audit_login_uid = UID_INVALID;
c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
} else if (r < 0) {
@@ -1116,7 +1118,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
}
int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
- _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *n = NULL;
int r;
assert(c);
diff --git a/src/libsystemd/sd-bus/bus-creds.h b/src/libsystemd/sd-bus/bus-creds.h
index 209d216123..df8a1f1005 100644
--- a/src/libsystemd/sd-bus/bus-creds.h
+++ b/src/libsystemd/sd-bus/bus-creds.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c
index 9db86adb7f..21a6b20a11 100644
--- a/src/libsystemd/sd-bus/bus-dump.c
+++ b/src/libsystemd/sd-bus/bus-dump.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,18 +17,21 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-#include "capability.h"
-#include "strv.h"
-#include "macro.h"
+#include "alloc-util.h"
+#include "bus-dump.h"
+#include "bus-internal.h"
+#include "bus-message.h"
+#include "bus-type.h"
#include "cap-list.h"
+#include "capability-util.h"
+#include "fileio.h"
#include "formats-util.h"
+#include "locale-util.h"
+#include "macro.h"
+#include "string-util.h"
+#include "strv.h"
#include "terminal-util.h"
-
-#include "bus-message.h"
-#include "bus-internal.h"
-#include "bus-type.h"
-#include "bus-dump.h"
+#include "util.h"
static char *indent(unsigned level, unsigned flags) {
char *p;
@@ -73,8 +74,8 @@ int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) {
"%s%s%s Type=%s%s%s Endian=%c Flags=%u Version=%u Priority=%"PRIi64,
m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() :
m->header->type == SD_BUS_MESSAGE_METHOD_RETURN ? ansi_highlight_green() :
- m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", draw_special_char(DRAW_TRIANGULAR_BULLET), ansi_highlight_off(),
- ansi_highlight(), bus_message_type_to_string(m->header->type), ansi_highlight_off(),
+ m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", special_glyph(TRIANGULAR_BULLET), ansi_normal(),
+ ansi_highlight(), bus_message_type_to_string(m->header->type), ansi_normal(),
m->header->endian,
m->header->flags,
m->header->version,
@@ -93,15 +94,15 @@ int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) {
fputs("\n", f);
if (m->sender)
- fprintf(f, " Sender=%s%s%s", ansi_highlight(), m->sender, ansi_highlight_off());
+ fprintf(f, " Sender=%s%s%s", ansi_highlight(), m->sender, ansi_normal());
if (m->destination)
- fprintf(f, " Destination=%s%s%s", ansi_highlight(), m->destination, ansi_highlight_off());
+ fprintf(f, " Destination=%s%s%s", ansi_highlight(), m->destination, ansi_normal());
if (m->path)
- fprintf(f, " Path=%s%s%s", ansi_highlight(), m->path, ansi_highlight_off());
+ fprintf(f, " Path=%s%s%s", ansi_highlight(), m->path, ansi_normal());
if (m->interface)
- fprintf(f, " Interface=%s%s%s", ansi_highlight(), m->interface, ansi_highlight_off());
+ fprintf(f, " Interface=%s%s%s", ansi_highlight(), m->interface, ansi_normal());
if (m->member)
- fprintf(f, " Member=%s%s%s", ansi_highlight(), m->member, ansi_highlight_off());
+ fprintf(f, " Member=%s%s%s", ansi_highlight(), m->member, ansi_normal());
if (m->sender || m->destination || m->path || m->interface || m->member)
fputs("\n", f);
@@ -110,8 +111,8 @@ int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) {
fprintf(f,
" ErrorName=%s%s%s"
" ErrorMessage=%s\"%s\"%s\n",
- ansi_highlight_red(), strna(m->error.name), ansi_highlight_off(),
- ansi_highlight_red(), strna(m->error.message), ansi_highlight_off());
+ ansi_highlight_red(), strna(m->error.name), ansi_normal(),
+ ansi_highlight_red(), strna(m->error.message), ansi_normal());
if (m->monotonic != 0)
fprintf(f, " Monotonic="USEC_FMT, m->monotonic);
@@ -197,7 +198,7 @@ int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) {
else if (type == SD_BUS_TYPE_DICT_ENTRY)
fprintf(f, "%sDICT_ENTRY \"%s\" {\n", prefix, contents);
- level ++;
+ level++;
continue;
}
@@ -211,55 +212,55 @@ int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) {
switch (type) {
case SD_BUS_TYPE_BYTE:
- fprintf(f, "%sBYTE %s%u%s;\n", prefix, ansi_highlight(), basic.u8, ansi_highlight_off());
+ fprintf(f, "%sBYTE %s%u%s;\n", prefix, ansi_highlight(), basic.u8, ansi_normal());
break;
case SD_BUS_TYPE_BOOLEAN:
- fprintf(f, "%sBOOLEAN %s%s%s;\n", prefix, ansi_highlight(), true_false(basic.i), ansi_highlight_off());
+ fprintf(f, "%sBOOLEAN %s%s%s;\n", prefix, ansi_highlight(), true_false(basic.i), ansi_normal());
break;
case SD_BUS_TYPE_INT16:
- fprintf(f, "%sINT16 %s%i%s;\n", prefix, ansi_highlight(), basic.s16, ansi_highlight_off());
+ fprintf(f, "%sINT16 %s%i%s;\n", prefix, ansi_highlight(), basic.s16, ansi_normal());
break;
case SD_BUS_TYPE_UINT16:
- fprintf(f, "%sUINT16 %s%u%s;\n", prefix, ansi_highlight(), basic.u16, ansi_highlight_off());
+ fprintf(f, "%sUINT16 %s%u%s;\n", prefix, ansi_highlight(), basic.u16, ansi_normal());
break;
case SD_BUS_TYPE_INT32:
- fprintf(f, "%sINT32 %s%i%s;\n", prefix, ansi_highlight(), basic.s32, ansi_highlight_off());
+ fprintf(f, "%sINT32 %s%i%s;\n", prefix, ansi_highlight(), basic.s32, ansi_normal());
break;
case SD_BUS_TYPE_UINT32:
- fprintf(f, "%sUINT32 %s%u%s;\n", prefix, ansi_highlight(), basic.u32, ansi_highlight_off());
+ fprintf(f, "%sUINT32 %s%u%s;\n", prefix, ansi_highlight(), basic.u32, ansi_normal());
break;
case SD_BUS_TYPE_INT64:
- fprintf(f, "%sINT64 %s%"PRIi64"%s;\n", prefix, ansi_highlight(), basic.s64, ansi_highlight_off());
+ fprintf(f, "%sINT64 %s%"PRIi64"%s;\n", prefix, ansi_highlight(), basic.s64, ansi_normal());
break;
case SD_BUS_TYPE_UINT64:
- fprintf(f, "%sUINT64 %s%"PRIu64"%s;\n", prefix, ansi_highlight(), basic.u64, ansi_highlight_off());
+ fprintf(f, "%sUINT64 %s%"PRIu64"%s;\n", prefix, ansi_highlight(), basic.u64, ansi_normal());
break;
case SD_BUS_TYPE_DOUBLE:
- fprintf(f, "%sDOUBLE %s%g%s;\n", prefix, ansi_highlight(), basic.d64, ansi_highlight_off());
+ fprintf(f, "%sDOUBLE %s%g%s;\n", prefix, ansi_highlight(), basic.d64, ansi_normal());
break;
case SD_BUS_TYPE_STRING:
- fprintf(f, "%sSTRING \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
+ fprintf(f, "%sSTRING \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_normal());
break;
case SD_BUS_TYPE_OBJECT_PATH:
- fprintf(f, "%sOBJECT_PATH \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
+ fprintf(f, "%sOBJECT_PATH \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_normal());
break;
case SD_BUS_TYPE_SIGNATURE:
- fprintf(f, "%sSIGNATURE \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
+ fprintf(f, "%sSIGNATURE \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_normal());
break;
case SD_BUS_TYPE_UNIX_FD:
- fprintf(f, "%sUNIX_FD %s%i%s;\n", prefix, ansi_highlight(), basic.i, ansi_highlight_off());
+ fprintf(f, "%sUNIX_FD %s%i%s;\n", prefix, ansi_highlight(), basic.i, ansi_normal());
break;
default:
@@ -327,7 +328,7 @@ static void dump_capabilities(
fputs("\n", f);
if (!terse)
- fputs(ansi_highlight_off(), f);
+ fputs(ansi_normal(), f);
}
int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) {
@@ -352,7 +353,7 @@ int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) {
prefix = "";
color = ansi_highlight();
- off = ansi_highlight_off();
+ off = ansi_normal();
suffix = strjoina(off, "\n");
}
@@ -551,9 +552,8 @@ int bus_pcap_header(size_t snaplen, FILE *f) {
hdr.snaplen = (uint32_t) snaplen;
fwrite(&hdr, 1, sizeof(hdr), f);
- fflush(f);
- return 0;
+ return fflush_and_check(f);
}
int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f) {
@@ -598,7 +598,5 @@ int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f) {
snaplen -= w;
}
- fflush(f);
-
- return 0;
+ return fflush_and_check(f);
}
diff --git a/src/libsystemd/sd-bus/bus-dump.h b/src/libsystemd/sd-bus/bus-dump.h
index d2522edeba..874e86d09c 100644
--- a/src/libsystemd/sd-bus/bus-dump.h
+++ b/src/libsystemd/sd-bus/bus-dump.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -21,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <stdbool.h>
+#include <stdio.h>
#include "sd-bus.h"
diff --git a/src/libsystemd/sd-bus/bus-error.c b/src/libsystemd/sd-bus/bus-error.c
index dac157be16..378f7a377a 100644
--- a/src/libsystemd/sd-bus/bus-error.c
+++ b/src/libsystemd/sd-bus/bus-error.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -20,17 +18,19 @@
***/
#include <errno.h>
-#include <stdlib.h>
#include <stdarg.h>
#include <stdbool.h>
-#include <string.h>
#include <stdio.h>
-
-#include "util.h"
-#include "errno-list.h"
+#include <stdlib.h>
+#include <string.h>
#include "sd-bus.h"
+
+#include "alloc-util.h"
#include "bus-error.h"
+#include "errno-list.h"
+#include "string-util.h"
+#include "util.h"
BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = {
SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Failed", EACCES),
@@ -89,14 +89,14 @@ static int bus_error_name_to_errno(const char *name) {
p = startswith(name, "System.Error.");
if (p) {
r = errno_from_name(p);
- if (r <= 0)
+ if (r < 0)
return EIO;
return r;
}
- if (additional_error_maps) {
- for (map = additional_error_maps; *map; map++) {
+ if (additional_error_maps)
+ for (map = additional_error_maps; *map; map++)
for (m = *map;; m++) {
/* For additional error maps the end marker is actually the end marker */
if (m->code == BUS_ERROR_MAP_END_MARKER)
@@ -105,15 +105,13 @@ static int bus_error_name_to_errno(const char *name) {
if (streq(m->name, name))
return m->code;
}
- }
- }
m = __start_BUS_ERROR_MAP;
while (m < __stop_BUS_ERROR_MAP) {
/* For magic ELF error maps, the end marker might
* appear in the middle of things, since multiple maps
* might appear in the same section. Hence, let's skip
- * over it, but realign the pointer to the netx 8byte
+ * over it, but realign the pointer to the next 8 byte
* boundary, which is the selected alignment for the
* arrays. */
if (m->code == BUS_ERROR_MAP_END_MARKER) {
@@ -254,25 +252,24 @@ int bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_li
if (!name)
return 0;
- if (!e)
- goto finish;
- assert_return(!bus_error_is_dirty(e), -EINVAL);
+ if (e) {
+ assert_return(!bus_error_is_dirty(e), -EINVAL);
- e->name = strdup(name);
- if (!e->name) {
- *e = BUS_ERROR_OOM;
- return -ENOMEM;
- }
+ e->name = strdup(name);
+ if (!e->name) {
+ *e = BUS_ERROR_OOM;
+ return -ENOMEM;
+ }
- /* If we hit OOM on formatting the pretty message, we ignore
- * this, since we at least managed to write the error name */
- if (format)
- (void) vasprintf((char**) &e->message, format, ap);
+ /* If we hit OOM on formatting the pretty message, we ignore
+ * this, since we at least managed to write the error name */
+ if (format)
+ (void) vasprintf((char**) &e->message, format, ap);
- e->_need_free = 1;
+ e->_need_free = 1;
+ }
-finish:
return -bus_error_name_to_errno(name);
}
@@ -563,7 +560,7 @@ _public_ int sd_bus_error_set_errnof(sd_bus_error *e, int error, const char *for
const char *bus_error_message(const sd_bus_error *e, int error) {
if (e) {
- /* Sometimes the D-Bus server is a little bit too verbose with
+ /* Sometimes, the D-Bus server is a little bit too verbose with
* its error messages, so let's override them here */
if (sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED))
return "Access denied";
@@ -578,27 +575,29 @@ const char *bus_error_message(const sd_bus_error *e, int error) {
return strerror(error);
}
+static bool map_ok(const sd_bus_error_map *map) {
+ for (; map->code != BUS_ERROR_MAP_END_MARKER; map++)
+ if (!map->name || map->code <=0)
+ return false;
+ return true;
+}
+
_public_ int sd_bus_error_add_map(const sd_bus_error_map *map) {
const sd_bus_error_map **maps = NULL;
unsigned n = 0;
assert_return(map, -EINVAL);
+ assert_return(map_ok(map), -EINVAL);
- if (additional_error_maps) {
- for (;; n++) {
- if (additional_error_maps[n] == NULL)
- break;
-
+ if (additional_error_maps)
+ for (; additional_error_maps[n] != NULL; n++)
if (additional_error_maps[n] == map)
return 0;
- }
- }
maps = realloc_multiply(additional_error_maps, sizeof(struct sd_bus_error_map*), n + 2);
if (!maps)
return -ENOMEM;
-
maps[n] = map;
maps[n+1] = NULL;
diff --git a/src/libsystemd/sd-bus/bus-error.h b/src/libsystemd/sd-bus/bus-error.h
index fb0199c948..e2c4cf4b3f 100644
--- a/src/libsystemd/sd-bus/bus-error.h
+++ b/src/libsystemd/sd-bus/bus-error.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -24,6 +22,7 @@
#include <stdbool.h>
#include "sd-bus.h"
+
#include "macro.h"
bool bus_error_is_dirty(sd_bus_error *e);
diff --git a/src/libsystemd/sd-bus/bus-gvariant.c b/src/libsystemd/sd-bus/bus-gvariant.c
index 2d18a4e6c1..58782767fa 100644
--- a/src/libsystemd/sd-bus/bus-gvariant.c
+++ b/src/libsystemd/sd-bus/bus-gvariant.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,9 +17,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "bus-type.h"
#include "bus-gvariant.h"
#include "bus-signature.h"
+#include "bus-type.h"
int bus_gvariant_get_size(const char *signature) {
const char *p;
@@ -75,14 +73,19 @@ int bus_gvariant_get_size(const char *signature) {
case SD_BUS_TYPE_STRUCT_BEGIN:
case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
- char t[n-1];
-
- memcpy(t, p + 1, n - 2);
- t[n - 2] = 0;
-
- r = bus_gvariant_get_size(t);
- if (r < 0)
- return r;
+ if (n == 2) {
+ /* unary type () has fixed size of 1 */
+ r = 1;
+ } else {
+ char t[n-1];
+
+ memcpy(t, p + 1, n - 2);
+ t[n - 2] = 0;
+
+ r = bus_gvariant_get_size(t);
+ if (r < 0)
+ return r;
+ }
sum += r;
break;
diff --git a/src/libsystemd/sd-bus/bus-gvariant.h b/src/libsystemd/sd-bus/bus-gvariant.h
index 875d34b59b..6da637fb05 100644
--- a/src/libsystemd/sd-bus/bus-gvariant.h
+++ b/src/libsystemd/sd-bus/bus-gvariant.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
diff --git a/src/libsystemd/sd-bus/bus-internal.c b/src/libsystemd/sd-bus/bus-internal.c
index fea796cd30..caca679086 100644
--- a/src/libsystemd/sd-bus/bus-internal.c
+++ b/src/libsystemd/sd-bus/bus-internal.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,8 +17,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "bus-message.h"
+#include "alloc-util.h"
#include "bus-internal.h"
+#include "bus-message.h"
+#include "hexdecoct.h"
+#include "string-util.h"
bool object_path_is_valid(const char *p) {
const char *q;
diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
index c3e20ee1bf..bb0414c4d6 100644
--- a/src/libsystemd/sd-bus/bus-internal.h
+++ b/src/libsystemd/sd-bus/bus-internal.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -21,21 +19,21 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/socket.h>
#include <pthread.h>
-
-#include "hashmap.h"
-#include "prioq.h"
-#include "list.h"
-#include "util.h"
-#include "refcnt.h"
-#include "socket-util.h"
+#include <sys/socket.h>
#include "sd-bus.h"
+
#include "bus-error.h"
-#include "bus-match.h"
#include "bus-kernel.h"
+#include "bus-match.h"
+#include "hashmap.h"
#include "kdbus.h"
+#include "list.h"
+#include "prioq.h"
+#include "refcnt.h"
+#include "socket-util.h"
+#include "util.h"
struct reply_callback {
sd_bus_message_handler_t callback;
@@ -211,6 +209,9 @@ struct sd_bus {
bool is_system:1;
bool is_user:1;
bool allow_interactive_authorization:1;
+ bool exit_on_disconnect:1;
+ bool exited:1;
+ bool exit_triggered:1;
int use_memfd;
@@ -322,12 +323,13 @@ struct sd_bus {
sd_bus_track *track_queue;
LIST_HEAD(sd_bus_slot, slots);
+ LIST_HEAD(sd_bus_track, tracks);
};
#define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
-#define BUS_WQUEUE_MAX 1024
-#define BUS_RQUEUE_MAX 64*1024
+#define BUS_WQUEUE_MAX (192*1024)
+#define BUS_RQUEUE_MAX (192*1024)
#define BUS_MESSAGE_SIZE_MAX (64*1024*1024)
#define BUS_AUTH_SIZE_MAX (64*1024)
@@ -381,7 +383,7 @@ char *bus_address_escape(const char *v);
* bus from the callback doesn't destroy the object we are working
* on */
#define BUS_DONT_DESTROY(bus) \
- _cleanup_bus_unref_ _unused_ sd_bus *_dont_destroy_##bus = sd_bus_ref(bus)
+ _cleanup_(sd_bus_unrefp) _unused_ sd_bus *_dont_destroy_##bus = sd_bus_ref(bus)
int bus_set_address_system(sd_bus *bus);
int bus_set_address_user(sd_bus *bus);
@@ -393,3 +395,9 @@ int bus_remove_match_by_string(sd_bus *bus, const char *match, sd_bus_message_ha
int bus_get_root_path(sd_bus *bus);
int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error);
+
+#define bus_assert_return(expr, r, error) \
+ do { \
+ if (!assert_log(expr, #expr)) \
+ return sd_bus_error_set_errno(error, r); \
+ } while (false)
diff --git a/src/libsystemd/sd-bus/bus-introspect.c b/src/libsystemd/sd-bus/bus-introspect.c
index e2f4550c7e..8f93edb8da 100644
--- a/src/libsystemd/sd-bus/bus-introspect.c
+++ b/src/libsystemd/sd-bus/bus-introspect.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,11 +17,14 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-#include "bus-introspect.h"
-#include "bus-signature.h"
#include "bus-internal.h"
+#include "bus-introspect.h"
#include "bus-protocol.h"
+#include "bus-signature.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "string-util.h"
+#include "util.h"
int introspect_begin(struct introspect *i, bool trusted) {
assert(i);
@@ -81,6 +82,9 @@ static void introspect_write_flags(struct introspect *i, int type, int flags) {
fputs(" <annotation name=\"org.freedesktop.DBus.Method.NoReply\" value=\"true\"/>\n", i->f);
if (type == _SD_BUS_VTABLE_PROPERTY || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) {
+ if (flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)
+ fputs(" <annotation name=\"org.freedesktop.systemd1.Explicit\" value=\"true\"/>\n", i->f);
+
if (flags & SD_BUS_VTABLE_PROPERTY_CONST)
fputs(" <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"const\"/>\n", i->f);
else if (flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)
@@ -179,10 +183,10 @@ int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_b
assert(reply);
fputs("</node>\n", i->f);
- fflush(i->f);
- if (ferror(i->f))
- return -ENOMEM;
+ r = fflush_and_check(i->f);
+ if (r < 0)
+ return r;
r = sd_bus_message_new_method_return(m, &q);
if (r < 0)
@@ -201,11 +205,8 @@ int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_b
void introspect_free(struct introspect *i) {
assert(i);
- if (i->f)
- fclose(i->f);
-
- if (i->introspection)
- free(i->introspection);
+ safe_fclose(i->f);
+ free(i->introspection);
zero(*i);
}
diff --git a/src/libsystemd/sd-bus/bus-introspect.h b/src/libsystemd/sd-bus/bus-introspect.h
index 1914e6cb8b..8e2f3800ca 100644
--- a/src/libsystemd/sd-bus/bus-introspect.h
+++ b/src/libsystemd/sd-bus/bus-introspect.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -24,6 +22,7 @@
#include <stdio.h>
#include "sd-bus.h"
+
#include "set.h"
struct introspect {
diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
index e3fac01f92..59398b841d 100644
--- a/src/libsystemd/sd-bus/bus-kernel.c
+++ b/src/libsystemd/sd-bus/bus-kernel.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -34,19 +32,24 @@
#include <libgen.h>
#undef basename
-#include "util.h"
-#include "strv.h"
-#include "memfd-util.h"
-#include "capability.h"
-#include "fileio.h"
-#include "formats-util.h"
-
+#include "alloc-util.h"
+#include "bus-bloom.h"
#include "bus-internal.h"
-#include "bus-message.h"
#include "bus-kernel.h"
-#include "bus-bloom.h"
-#include "bus-util.h"
#include "bus-label.h"
+#include "bus-message.h"
+#include "bus-util.h"
+#include "capability-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "formats-util.h"
+#include "memfd-util.h"
+#include "parse-util.h"
+#include "stdio-util.h"
+#include "string-util.h"
+#include "strv.h"
+#include "user-util.h"
+#include "util.h"
#define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
@@ -168,6 +171,27 @@ static void add_bloom_arg(void *data, size_t size, unsigned n_hash, unsigned i,
bloom_add_prefixes(data, size, n_hash, buf, t, '/');
}
+static void add_bloom_arg_has(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) {
+ char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
+ char *e;
+
+ assert(data);
+ assert(size > 0);
+ assert(i < 64);
+ assert(t);
+
+ e = stpcpy(buf, "arg");
+ if (i < 10)
+ *(e++) = '0' + (char) i;
+ else {
+ *(e++) = '0' + (char) (i / 10);
+ *(e++) = '0' + (char) (i % 10);
+ }
+
+ strcpy(e, "-has");
+ bloom_add_pair(data, size, n_hash, buf, t);
+}
+
static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) {
void *data;
unsigned i;
@@ -212,7 +236,9 @@ static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter
return r;
add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
- } if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) {
+ }
+
+ if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) {
/* As well as array of simple strings of any kinds */
r = sd_bus_message_enter_container(m, type, contents);
@@ -220,7 +246,7 @@ static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter
return r;
while ((r = sd_bus_message_read_basic(m, contents[0], &t)) > 0)
- add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
+ add_bloom_arg_has(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
if (r < 0)
return r;
@@ -242,8 +268,8 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
struct bus_body_part *part;
struct kdbus_item *d;
const char *destination;
- bool well_known;
- uint64_t unique;
+ bool well_known = false;
+ uint64_t dst_id;
size_t sz, dl;
unsigned i;
int r;
@@ -260,13 +286,21 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
destination = m->destination ?: m->destination_ptr;
if (destination) {
- r = bus_kernel_parse_unique_name(destination, &unique);
+ r = bus_kernel_parse_unique_name(destination, &dst_id);
if (r < 0)
return r;
-
- well_known = r == 0;
+ if (r == 0) {
+ well_known = true;
+
+ /* verify_destination_id will usually be 0, which makes the kernel
+ * driver only look at the provided well-known name. Otherwise,
+ * the kernel will make sure the provided destination id matches
+ * the owner of the provided well-known-name, and fail if they
+ * differ. Currently, this is only needed for bus-proxyd. */
+ dst_id = m->verify_destination_id;
+ }
} else
- well_known = false;
+ dst_id = KDBUS_DST_ID_BROADCAST;
sz = offsetof(struct kdbus_msg, items);
@@ -304,15 +338,7 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0) |
((m->header->type == SD_BUS_MESSAGE_SIGNAL) ? KDBUS_MSG_SIGNAL : 0);
- if (well_known)
- /* verify_destination_id will usually be 0, which makes the kernel driver only look
- * at the provided well-known name. Otherwise, the kernel will make sure the provided
- * destination id matches the owner of the provided weel-known-name, and fail if they
- * differ. Currently, this is only needed for bus-proxyd. */
- m->kdbus->dst_id = m->verify_destination_id;
- else
- m->kdbus->dst_id = destination ? unique : KDBUS_DST_ID_BROADCAST;
-
+ m->kdbus->dst_id = dst_id;
m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS;
m->kdbus->cookie = m->header->dbus2.cookie;
m->kdbus->priority = m->priority;
@@ -774,6 +800,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
case KDBUS_ITEM_FDS:
case KDBUS_ITEM_SECLABEL:
+ case KDBUS_ITEM_BLOOM_FILTER:
break;
default:
@@ -821,7 +848,8 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
if (k->src_id == KDBUS_SRC_ID_KERNEL)
bus_message_set_sender_driver(bus, m);
else {
- snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
+ xsprintf(m->sender_buffer, ":1.%llu",
+ (unsigned long long)k->src_id);
m->sender = m->creds.unique_name = m->sender_buffer;
}
@@ -832,7 +860,8 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
else if (k->dst_id == KDBUS_DST_ID_NAME)
m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */
else {
- snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
+ xsprintf(m->destination_buffer, ":1.%llu",
+ (unsigned long long)k->dst_id);
m->destination = m->destination_buffer;
}
@@ -1114,7 +1143,7 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call
r = ioctl(bus->output_fd, KDBUS_CMD_SEND, &cmd);
if (r < 0) {
- _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;
sd_bus_message *reply;
if (errno == EAGAIN || errno == EINTR)
@@ -1193,7 +1222,7 @@ static int push_name_owner_changed(
const char *new_owner,
const struct kdbus_timestamp *ts) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(bus);
@@ -1280,7 +1309,7 @@ static int translate_reply(
const struct kdbus_item *d,
const struct kdbus_timestamp *ts) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(bus);
@@ -1332,8 +1361,7 @@ static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
KDBUS_ITEM_FOREACH(d, k, items) {
if (d->type == KDBUS_ITEM_TIMESTAMP)
ts = &d->timestamp;
-
- if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
+ else if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
if (found)
return -EBADMSG;
found = d;
@@ -1410,12 +1438,12 @@ int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *al
if (!bus || !bus->is_kernel)
return -EOPNOTSUPP;
- assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
+ assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0);
if (bus->n_memfd_cache <= 0) {
int r;
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
+ assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
r = memfd_new(bus->description);
if (r < 0)
@@ -1437,7 +1465,7 @@ int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *al
*allocated = c->allocated;
fd = c->fd;
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
+ assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
return fd;
}
@@ -1461,10 +1489,10 @@ void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, si
return;
}
- assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
+ assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0);
if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
+ assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
close_and_munmap(fd, address, mapped);
return;
@@ -1484,7 +1512,7 @@ void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, si
c->allocated = allocated;
}
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
+ assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
}
void bus_kernel_flush_memfd(sd_bus *b) {
@@ -1665,50 +1693,6 @@ int bus_kernel_open_bus_fd(const char *bus, char **path) {
return fd;
}
-int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **ep_path) {
- _cleanup_free_ char *path = NULL;
- struct kdbus_cmd *make;
- struct kdbus_item *n;
- const char *name;
- int fd;
-
- fd = bus_kernel_open_bus_fd(bus_name, &path);
- if (fd < 0)
- return fd;
-
- make = alloca0_align(ALIGN8(offsetof(struct kdbus_cmd, items)) +
- ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + strlen(ep_name) + 1),
- 8);
- make->size = ALIGN8(offsetof(struct kdbus_cmd, items));
- make->flags = KDBUS_MAKE_ACCESS_WORLD;
-
- n = make->items;
- sprintf(n->str, UID_FMT "-%s", getuid(), ep_name);
- n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
- n->type = KDBUS_ITEM_MAKE_NAME;
- make->size += ALIGN8(n->size);
- name = n->str;
-
- if (ioctl(fd, KDBUS_CMD_ENDPOINT_MAKE, make) < 0) {
- safe_close(fd);
- return -errno;
- }
-
- if (ep_path) {
- char *p;
-
- p = strjoin(dirname(path), "/", name, NULL);
- if (!p) {
- safe_close(fd);
- return -ENOMEM;
- }
-
- *ep_path = p;
- }
-
- return fd;
-}
-
int bus_kernel_try_close(sd_bus *bus) {
struct kdbus_cmd byebye = { .size = sizeof(byebye) };
diff --git a/src/libsystemd/sd-bus/bus-kernel.h b/src/libsystemd/sd-bus/bus-kernel.h
index bb4dff6d82..53ba3bdcf3 100644
--- a/src/libsystemd/sd-bus/bus-kernel.h
+++ b/src/libsystemd/sd-bus/bus-kernel.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c
index 132b37526e..db01f21135 100644
--- a/src/libsystemd/sd-bus/bus-match.c
+++ b/src/libsystemd/sd-bus/bus-match.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,10 +17,15 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "bus-internal.h"
-#include "bus-message.h"
#include "bus-match.h"
+#include "bus-message.h"
#include "bus-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "hexdecoct.h"
+#include "string-util.h"
#include "strv.h"
/* Example:
@@ -62,12 +65,13 @@
*/
static inline bool BUS_MATCH_IS_COMPARE(enum bus_match_node_type t) {
- return t >= BUS_MATCH_SENDER && t <= BUS_MATCH_ARG_NAMESPACE_LAST;
+ return t >= BUS_MATCH_SENDER && t <= BUS_MATCH_ARG_HAS_LAST;
}
static inline bool BUS_MATCH_CAN_HASH(enum bus_match_node_type t) {
return (t >= BUS_MATCH_MESSAGE_TYPE && t <= BUS_MATCH_PATH) ||
- (t >= BUS_MATCH_ARG && t <= BUS_MATCH_ARG_LAST);
+ (t >= BUS_MATCH_ARG && t <= BUS_MATCH_ARG_LAST) ||
+ (t >= BUS_MATCH_ARG_HAS && t <= BUS_MATCH_ARG_HAS_LAST);
}
static void bus_match_node_free(struct bus_match_node *node) {
@@ -179,12 +183,16 @@ static bool value_node_test(
case BUS_MATCH_INTERFACE:
case BUS_MATCH_MEMBER:
case BUS_MATCH_PATH:
- case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: {
- char **i;
+ case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
if (value_str)
return streq_ptr(node->value.str, value_str);
+ return false;
+
+ case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST: {
+ char **i;
+
STRV_FOREACH(i, value_strv)
if (streq_ptr(node->value.str, *i))
return true;
@@ -192,33 +200,20 @@ static bool value_node_test(
return false;
}
- case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: {
- char **i;
-
+ case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
if (value_str)
return namespace_simple_pattern(node->value.str, value_str);
- STRV_FOREACH(i, value_strv)
- if (namespace_simple_pattern(node->value.str, *i))
- return true;
return false;
- }
case BUS_MATCH_PATH_NAMESPACE:
return path_simple_pattern(node->value.str, value_str);
- case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: {
- char **i;
-
+ case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
if (value_str)
return path_complex_pattern(node->value.str, value_str);
- STRV_FOREACH(i, value_strv)
- if (path_complex_pattern(node->value.str, *i))
- return true;
-
return false;
- }
default:
assert_not_reached("Invalid node type");
@@ -249,6 +244,7 @@ static bool value_node_same(
case BUS_MATCH_MEMBER:
case BUS_MATCH_PATH:
case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
+ case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST:
case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
case BUS_MATCH_PATH_NAMESPACE:
case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
@@ -319,7 +315,7 @@ int bus_match_run(
/* Run the callback. And then invoke siblings. */
if (node->leaf.callback->callback) {
- _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
sd_bus_slot *slot;
slot = container_of(node->leaf.callback, sd_bus_slot, match_callback);
@@ -372,15 +368,19 @@ int bus_match_run(
break;
case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
- (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG, &test_str, &test_strv);
+ (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG, &test_str);
break;
case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
- (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_PATH, &test_str, &test_strv);
+ (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_PATH, &test_str);
break;
case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
- (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_NAMESPACE, &test_str, &test_strv);
+ (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_NAMESPACE, &test_str);
+ break;
+
+ case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST:
+ (void) bus_message_get_arg_strv(m, node->type - BUS_MATCH_ARG_HAS, &test_strv);
break;
default:
@@ -429,6 +429,9 @@ int bus_match_run(
r = bus_match_run(bus, c, m);
if (r != 0)
return r;
+
+ if (bus && bus->match_callbacks_modified)
+ return 0;
}
}
@@ -743,6 +746,32 @@ enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n
return t;
}
+ if (n == 7 && startswith(k, "arg") && startswith(k + 4, "has")) {
+ int j;
+
+ j = undecchar(k[3]);
+ if (j < 0)
+ return -EINVAL;
+
+ return BUS_MATCH_ARG_HAS + j;
+ }
+
+ if (n == 8 && startswith(k, "arg") && startswith(k + 5, "has")) {
+ enum bus_match_node_type t;
+ int a, b;
+
+ a = undecchar(k[3]);
+ b = undecchar(k[4]);
+ if (a <= 0 || b < 0)
+ return -EINVAL;
+
+ t = BUS_MATCH_ARG_HAS + a * 10 + b;
+ if (t > BUS_MATCH_ARG_HAS_LAST)
+ return -EINVAL;
+
+ return t;
+ }
+
return -EINVAL;
}
@@ -861,8 +890,7 @@ int bus_match_parse(
if (r < 0)
goto fail;
- free(value);
- value = NULL;
+ value = mfree(value);
} else
u = 0;
@@ -910,10 +938,11 @@ fail:
}
char *bus_match_to_string(struct bus_match_component *components, unsigned n_components) {
- _cleanup_free_ FILE *f = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
char *buffer = NULL;
size_t size = 0;
unsigned i;
+ int r;
if (n_components <= 0)
return strdup("");
@@ -942,8 +971,8 @@ char *bus_match_to_string(struct bus_match_component *components, unsigned n_com
fputc('\'', f);
}
- fflush(f);
- if (ferror(f))
+ r = fflush_and_check(f);
+ if (r < 0)
return NULL;
return buffer;
@@ -1111,6 +1140,10 @@ const char* bus_match_node_type_to_string(enum bus_match_node_type t, char buf[]
snprintf(buf, l, "arg%inamespace", t - BUS_MATCH_ARG_NAMESPACE);
return buf;
+ case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST:
+ snprintf(buf, l, "arg%ihas", t - BUS_MATCH_ARG_HAS);
+ return buf;
+
default:
return NULL;
}
diff --git a/src/libsystemd/sd-bus/bus-match.h b/src/libsystemd/sd-bus/bus-match.h
index 56516be9fa..8cbbb63b11 100644
--- a/src/libsystemd/sd-bus/bus-match.h
+++ b/src/libsystemd/sd-bus/bus-match.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -21,10 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "hashmap.h"
-
#include "sd-bus.h"
+#include "hashmap.h"
+
enum bus_match_node_type {
BUS_MATCH_ROOT,
BUS_MATCH_VALUE,
@@ -44,6 +42,8 @@ enum bus_match_node_type {
BUS_MATCH_ARG_PATH_LAST = BUS_MATCH_ARG_PATH + 63,
BUS_MATCH_ARG_NAMESPACE,
BUS_MATCH_ARG_NAMESPACE_LAST = BUS_MATCH_ARG_NAMESPACE + 63,
+ BUS_MATCH_ARG_HAS,
+ BUS_MATCH_ARG_HAS_LAST = BUS_MATCH_ARG_HAS + 63,
_BUS_MATCH_NODE_TYPE_MAX,
_BUS_MATCH_NODE_TYPE_INVALID = -1
};
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
index 18685be8ff..5cec804e32 100644
--- a/src/libsystemd/sd-bus/bus-message.c
+++ b/src/libsystemd/sd-bus/bus-message.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -23,19 +21,23 @@
#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);
@@ -113,8 +115,7 @@ static void message_reset_containers(sd_bus_message *m) {
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;
@@ -144,11 +145,7 @@ static void message_free(sd_bus_message *m) {
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);
@@ -184,7 +181,7 @@ static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, b
if (!np)
goto poison;
} else {
- /* Initially, the header is allocated as part of of
+ /* Initially, the header is allocated as part of
* the sd_bus_message itself, let's replace it by
* dynamic data */
@@ -608,8 +605,8 @@ static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
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);
@@ -803,7 +800,7 @@ _public_ int sd_bus_message_new_method_errorf(
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);
@@ -822,7 +819,7 @@ _public_ int sd_bus_message_new_method_errno(
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);
@@ -839,7 +836,7 @@ _public_ int sd_bus_message_new_method_errnof(
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);
@@ -920,7 +917,9 @@ fail:
}
_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++;
@@ -1028,7 +1027,9 @@ _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
_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;
}
@@ -1130,10 +1131,7 @@ _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
assert_return(!m->sealed, -EPERM);
assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
- if (b)
- m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
- else
- m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
+ SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
return 0;
}
@@ -1142,10 +1140,7 @@ _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
- if (b)
- m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
- else
- m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
+ SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
return 0;
}
@@ -1154,10 +1149,7 @@ _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
- if (b)
- m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
- else
- m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
+ SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
return 0;
}
@@ -1197,7 +1189,7 @@ struct bus_body_part *message_append_part(sd_bus_message *m) {
part->memfd = -1;
m->body_end = part;
- m->n_body_parts ++;
+ m->n_body_parts++;
return part;
}
@@ -1642,7 +1634,7 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void
}
if (type == SD_BUS_TYPE_UNIX_FD)
- m->n_fds ++;
+ m->n_fds++;
if (c->enclosing != SD_BUS_TYPE_ARRAY)
c->index++;
@@ -2209,7 +2201,14 @@ static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c,
assert(!c->need_offsets || i == c->n_offsets);
assert(c->need_offsets || n_variable == 0);
- if (n_variable <= 0) {
+ 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
@@ -2379,9 +2378,9 @@ int bus_message_append_ap(
t = types;
if (n_array != (unsigned) -1)
- n_array --;
+ n_array--;
else {
- types ++;
+ types++;
n_struct--;
}
@@ -2623,8 +2622,7 @@ _public_ int sd_bus_message_append_array(
if (r < 0)
return r;
- if (size > 0)
- memcpy(p, ptr, size);
+ memcpy_safe(p, ptr, size);
return 0;
}
@@ -2680,7 +2678,7 @@ _public_ int sd_bus_message_append_array_memfd(
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);
@@ -2756,7 +2754,7 @@ _public_ int sd_bus_message_append_string_memfd(
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);
@@ -2867,7 +2865,7 @@ static int bus_message_close_header(sd_bus_message *m) {
/* The actual user data is finished now, we just complete the
variant and struct now (at least on gvariant). Remember
- this position, so that during parsing we know where to to
+ this position, so that during parsing we know where to
put the outer container end. */
m->user_body_size = m->body_size;
@@ -2899,18 +2897,20 @@ static int bus_message_close_header(sd_bus_message *m) {
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;
@@ -3814,6 +3814,14 @@ static int build_struct_offsets(
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;
@@ -3849,7 +3857,7 @@ static int build_struct_offsets(
if (r < 0)
return r;
if (r == 0 && p[n] != 0) /* except the last item */
- n_variable ++;
+ n_variable++;
n_total++;
p += n;
@@ -3954,12 +3962,6 @@ static int enter_struct_or_dict_entry(
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);
@@ -4146,7 +4148,14 @@ _public_ int sd_bus_message_enter_container(sd_bus_message *m,
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;
@@ -4448,9 +4457,9 @@ static int message_read_ap(
t = types;
if (n_array != (unsigned) -1)
- n_array --;
+ n_array--;
else {
- types ++;
+ types++;
n_struct--;
}
@@ -4756,7 +4765,6 @@ _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
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)
@@ -5164,11 +5172,21 @@ int bus_message_parse_fields(sd_bus_message *m) {
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. */
- c = strndup(p + 1, ((char*) m->footer + m->footer_accessible) - p - (1 + sz));
+ 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 + 1, l - 2);
if (!c)
return -ENOMEM;
@@ -5589,21 +5607,23 @@ _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
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;
@@ -5615,31 +5635,56 @@ int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char **
!(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) {
+}
- r = sd_bus_message_read_strv(m, strv);
- if (r < 0)
- return r;
+int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
+ char type;
+ int r;
+
+ assert(m);
+ assert(str);
- *str = NULL;
+ r = bus_message_get_arg_skip(m, i, &type, NULL);
+ if (r < 0)
+ return r;
- } else {
- r = sd_bus_message_read_basic(m, type, str);
- if (r < 0)
- return r;
+ if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
+ return -ENXIO;
- *strv = NULL;
- }
+ return sd_bus_message_read_basic(m, type, str);
+}
- return 0;
+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;
+
+ if (type != SD_BUS_TYPE_ARRAY)
+ return -ENXIO;
+ if (!STR_IN_SET(contents, "s", "o", "g"))
+ return -ENXIO;
+
+ return sd_bus_message_read_strv(m, strv);
}
_public_ int sd_bus_message_get_errno(sd_bus_message *m) {
@@ -5783,7 +5828,7 @@ _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
}
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;
diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h
index 088d5b1109..4710c106b9 100644
--- a/src/libsystemd/sd-bus/bus-message.h
+++ b/src/libsystemd/sd-bus/bus-message.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -21,15 +19,16 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdbool.h>
#include <byteswap.h>
+#include <stdbool.h>
#include <sys/socket.h>
-#include "macro.h"
#include "sd-bus.h"
-#include "time-util.h"
+
#include "bus-creds.h"
#include "bus-protocol.h"
+#include "macro.h"
+#include "time-util.h"
struct bus_container {
char enclosing;
@@ -218,7 +217,8 @@ int bus_message_from_malloc(
const char *label,
sd_bus_message **ret);
-int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv);
+int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str);
+int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv);
int bus_message_append_ap(sd_bus_message *m, const char *types, va_list ap);
diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
index cbdf6552f9..9bd07ffcab 100644
--- a/src/libsystemd/sd-bus/bus-objects.c
+++ b/src/libsystemd/sd-bus/bus-objects.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,16 +17,18 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "strv.h"
-#include "set.h"
+#include "alloc-util.h"
#include "bus-internal.h"
+#include "bus-introspect.h"
#include "bus-message.h"
-#include "bus-type.h"
+#include "bus-objects.h"
#include "bus-signature.h"
-#include "bus-introspect.h"
-#include "bus-util.h"
#include "bus-slot.h"
-#include "bus-objects.h"
+#include "bus-type.h"
+#include "bus-util.h"
+#include "set.h"
+#include "string-util.h"
+#include "strv.h"
static int node_vtable_get_userdata(
sd_bus *bus,
@@ -68,6 +68,12 @@ static int node_vtable_get_userdata(
return 1;
}
+static void *vtable_method_convert_userdata(const sd_bus_vtable *p, void *u) {
+ assert(p);
+
+ return (uint8_t*) u + p->x.method.offset;
+}
+
static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) {
assert(p);
@@ -139,7 +145,7 @@ static int add_enumerated_to_set(
continue;
}
- if (!object_path_is_valid(*k)){
+ if (!object_path_is_valid(*k)) {
free(*k);
r = -EINVAL;
continue;
@@ -163,10 +169,18 @@ static int add_enumerated_to_set(
return 0;
}
+enum {
+ /* if set, add_subtree() works recursively */
+ CHILDREN_RECURSIVE = (1U << 1),
+ /* if set, add_subtree() scans object-manager hierarchies recursively */
+ CHILDREN_SUBHIERARCHIES = (1U << 0),
+};
+
static int add_subtree_to_set(
sd_bus *bus,
const char *prefix,
struct node *n,
+ unsigned int flags,
Set *s,
sd_bus_error *error) {
@@ -198,11 +212,14 @@ static int add_subtree_to_set(
if (r < 0 && r != -EEXIST)
return r;
- r = add_subtree_to_set(bus, prefix, i, s, error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
+ if ((flags & CHILDREN_RECURSIVE) &&
+ ((flags & CHILDREN_SUBHIERARCHIES) || !i->object_managers)) {
+ r = add_subtree_to_set(bus, prefix, i, flags, s, error);
+ if (r < 0)
+ return r;
+ if (bus->nodes_modified)
+ return 0;
+ }
}
return 0;
@@ -212,6 +229,7 @@ static int get_child_nodes(
sd_bus *bus,
const char *prefix,
struct node *n,
+ unsigned int flags,
Set **_s,
sd_bus_error *error) {
@@ -227,7 +245,7 @@ static int get_child_nodes(
if (!s)
return -ENOMEM;
- r = add_subtree_to_set(bus, prefix, n, s, error);
+ r = add_subtree_to_set(bus, prefix, n, flags, s, error);
if (r < 0) {
set_free_free(s);
return r;
@@ -252,7 +270,7 @@ static int node_callbacks_run(
assert(found_object);
LIST_FOREACH(callbacks, c, first) {
- _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
sd_bus_slot *slot;
if (bus->nodes_modified)
@@ -319,7 +337,7 @@ static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c,
if (cap == 0)
cap = CAP_SYS_ADMIN;
else
- cap --;
+ cap--;
r = sd_bus_query_sender_privilege(m, cap);
if (r < 0)
@@ -337,7 +355,7 @@ static int method_callbacks_run(
bool require_fallback,
bool *found_object) {
- _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;
const char *signature;
void *u;
int r;
@@ -360,6 +378,8 @@ static int method_callbacks_run(
if (bus->nodes_modified)
return 0;
+ u = vtable_method_convert_userdata(c->vtable, u);
+
*found_object = true;
if (c->last_iteration == bus->iteration_counter)
@@ -558,8 +578,8 @@ static int property_get_set_callbacks_run(
bool is_get,
bool *found_object) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
sd_bus_slot *slot;
void *u = NULL;
int r;
@@ -738,6 +758,9 @@ static int vtable_append_all_properties(
if (v->flags & SD_BUS_VTABLE_HIDDEN)
continue;
+ if (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)
+ continue;
+
r = vtable_append_one_property(bus, reply, path, c, v, userdata, error);
if (r < 0)
return r;
@@ -756,7 +779,7 @@ static int property_get_all_callbacks_run(
const char *iface,
bool *found_object) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
struct node_vtable *c;
bool found_interface;
int r;
@@ -779,7 +802,7 @@ static int property_get_all_callbacks_run(
streq(iface, "org.freedesktop.DBus.Introspectable");
LIST_FOREACH(vtables, c, first) {
- _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;
void *u;
if (require_fallback && !c->is_fallback)
@@ -856,7 +879,7 @@ static int bus_node_exists(
}
LIST_FOREACH(vtables, c, n->vtables) {
- _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;
if (require_fallback && !c->is_fallback)
continue;
@@ -878,8 +901,8 @@ static int process_introspect(
bool require_fallback,
bool *found_object) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_set_free_free_ Set *s = NULL;
const char *previous_interface = NULL;
struct introspect intro;
@@ -892,7 +915,7 @@ static int process_introspect(
assert(n);
assert(found_object);
- r = get_child_nodes(bus, m->path, n, &s, &error);
+ r = get_child_nodes(bus, m->path, n, 0, &s, &error);
if (r < 0)
return bus_maybe_reply_error(m, r, &error);
if (bus->nodes_modified)
@@ -1139,8 +1162,8 @@ static int process_get_managed_objects(
bool require_fallback,
bool *found_object) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_set_free_free_ Set *s = NULL;
Iterator i;
char *path;
@@ -1158,16 +1181,12 @@ static int process_get_managed_objects(
if (require_fallback || !n->object_managers)
return 0;
- r = get_child_nodes(bus, m->path, n, &s, &error);
+ r = get_child_nodes(bus, m->path, n, CHILDREN_RECURSIVE, &s, &error);
if (r < 0)
return r;
if (bus->nodes_modified)
return 0;
- r = set_put_strdup(s, m->path);
- if (r < 0)
- return r;
-
r = sd_bus_message_new_method_return(m, &reply);
if (r < 0)
return r;
@@ -1467,6 +1486,32 @@ void bus_node_gc(sd_bus *b, struct node *n) {
free(n);
}
+static int bus_find_parent_object_manager(sd_bus *bus, struct node **out, const char *path) {
+ struct node *n;
+
+ assert(bus);
+ assert(path);
+
+ n = hashmap_get(bus->nodes, path);
+ if (!n) {
+ char *prefix;
+
+ prefix = alloca(strlen(path) + 1);
+ OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
+ n = hashmap_get(bus->nodes, prefix);
+ if (n)
+ break;
+ }
+ }
+
+ while (n && !n->object_managers)
+ n = n->parent;
+
+ if (out)
+ *out = n;
+ return !!n;
+}
+
static int bus_add_object(
sd_bus *bus,
sd_bus_slot **slot,
@@ -1533,25 +1578,14 @@ _public_ int sd_bus_add_fallback(
return bus_add_object(bus, slot, true, prefix, callback, userdata);
}
-static unsigned long vtable_member_hash_func(const void *a, const uint8_t hash_key[HASH_KEY_SIZE]) {
+static void vtable_member_hash_func(const void *a, struct siphash *state) {
const struct vtable_member *m = a;
- uint8_t hash_key2[HASH_KEY_SIZE];
- unsigned long ret;
assert(m);
- ret = string_hash_func(m->path, hash_key);
-
- /* Use a slightly different hash key for the interface */
- memcpy(hash_key2, hash_key, HASH_KEY_SIZE);
- hash_key2[0]++;
- ret ^= string_hash_func(m->interface, hash_key2);
-
- /* And an even different one for the member */
- hash_key2[0]++;
- ret ^= string_hash_func(m->member, hash_key2);
-
- return ret;
+ string_hash_func(m->path, state);
+ string_hash_func(m->interface, state);
+ string_hash_func(m->member, state);
}
static int vtable_member_compare_func(const void *a, const void *b) {
@@ -1707,8 +1741,9 @@ static int add_object_vtable_internal(
if (!member_name_is_valid(v->x.property.member) ||
!signature_is_single(v->x.property.signature, false) ||
!(v->x.property.get || bus_type_is_basic(v->x.property.signature[0]) || streq(v->x.property.signature, "as")) ||
- v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY ||
+ (v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) ||
(!!(v->flags & SD_BUS_VTABLE_PROPERTY_CONST) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) > 1 ||
+ ((v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) && (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)) ||
(v->flags & SD_BUS_VTABLE_UNPRIVILEGED && v->type == _SD_BUS_VTABLE_PROPERTY)) {
r = -EINVAL;
goto fail;
@@ -1844,8 +1879,8 @@ static int emit_properties_changed_on_interface(
bool *found_interface,
char **names) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
bool has_invalidating = false, has_changing = false;
struct vtable_member key = {};
struct node_vtable *c;
@@ -2139,7 +2174,7 @@ static int object_added_append_all_prefix(
return 0;
LIST_FOREACH(vtables, c, n->vtables) {
- _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;
void *u = NULL;
if (require_fallback && !c->is_fallback)
@@ -2268,7 +2303,8 @@ static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *p
_public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
BUS_DONT_DESTROY(bus);
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ struct node *object_manager;
int r;
/*
@@ -2289,11 +2325,17 @@ _public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
+ r = bus_find_parent_object_manager(bus, &object_manager, path);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ESRCH;
+
do {
bus->nodes_modified = false;
m = sd_bus_message_unref(m);
- r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
+ r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
if (r < 0)
return r;
@@ -2345,7 +2387,7 @@ static int object_removed_append_all_prefix(
return 0;
LIST_FOREACH(vtables, c, n->vtables) {
- _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;
void *u = NULL;
if (require_fallback && !c->is_fallback)
@@ -2431,7 +2473,8 @@ static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char
_public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) {
BUS_DONT_DESTROY(bus);
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ struct node *object_manager;
int r;
/*
@@ -2452,11 +2495,17 @@ _public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) {
if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
+ r = bus_find_parent_object_manager(bus, &object_manager, path);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ESRCH;
+
do {
bus->nodes_modified = false;
m = sd_bus_message_unref(m);
- r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
+ r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
if (r < 0)
return r;
@@ -2492,7 +2541,7 @@ static int interfaces_added_append_one_prefix(
const char *interface,
bool require_fallback) {
- _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;
bool found_interface = false;
struct node_vtable *c;
struct node *n;
@@ -2587,7 +2636,8 @@ static int interfaces_added_append_one(
_public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) {
BUS_DONT_DESTROY(bus);
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ struct node *object_manager;
char **i;
int r;
@@ -2601,11 +2651,17 @@ _public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, ch
if (strv_isempty(interfaces))
return 0;
+ r = bus_find_parent_object_manager(bus, &object_manager, path);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ESRCH;
+
do {
bus->nodes_modified = false;
m = sd_bus_message_unref(m);
- r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
+ r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
if (r < 0)
return r;
@@ -2664,7 +2720,8 @@ _public_ int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const c
}
_public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ struct node *object_manager;
int r;
assert_return(bus, -EINVAL);
@@ -2677,7 +2734,13 @@ _public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path,
if (strv_isempty(interfaces))
return 0;
- r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
+ r = bus_find_parent_object_manager(bus, &object_manager, path);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ESRCH;
+
+ r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
if (r < 0)
return r;
diff --git a/src/libsystemd/sd-bus/bus-objects.h b/src/libsystemd/sd-bus/bus-objects.h
index 4373fae89c..e0b8c534ed 100644
--- a/src/libsystemd/sd-bus/bus-objects.h
+++ b/src/libsystemd/sd-bus/bus-objects.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
diff --git a/src/libsystemd/sd-bus/bus-protocol.h b/src/libsystemd/sd-bus/bus-protocol.h
index 183af89a63..9d180cb284 100644
--- a/src/libsystemd/sd-bus/bus-protocol.h
+++ b/src/libsystemd/sd-bus/bus-protocol.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
diff --git a/src/libsystemd/sd-bus/bus-signature.c b/src/libsystemd/sd-bus/bus-signature.c
index 1e5bf4821d..7bc243494a 100644
--- a/src/libsystemd/sd-bus/bus-signature.c
+++ b/src/libsystemd/sd-bus/bus-signature.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
diff --git a/src/libsystemd/sd-bus/bus-signature.h b/src/libsystemd/sd-bus/bus-signature.h
index c4fed0b53d..1e0cd7f587 100644
--- a/src/libsystemd/sd-bus/bus-signature.h
+++ b/src/libsystemd/sd-bus/bus-signature.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c
index b149ea16da..8e9074c7df 100644
--- a/src/libsystemd/sd-bus/bus-slot.c
+++ b/src/libsystemd/sd-bus/bus-slot.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -20,9 +18,12 @@
***/
#include "sd-bus.h"
+
+#include "alloc-util.h"
#include "bus-control.h"
#include "bus-objects.h"
#include "bus-slot.h"
+#include "string-util.h"
sd_bus_slot *bus_slot_allocate(
sd_bus *bus,
@@ -54,7 +55,9 @@ sd_bus_slot *bus_slot_allocate(
}
_public_ sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot) {
- assert_return(slot, NULL);
+
+ if (!slot)
+ return NULL;
assert(slot->n_ref > 0);
@@ -203,7 +206,7 @@ _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
assert(slot->n_ref > 0);
if (slot->n_ref > 1) {
- slot->n_ref --;
+ slot->n_ref--;
return NULL;
}
diff --git a/src/libsystemd/sd-bus/bus-slot.h b/src/libsystemd/sd-bus/bus-slot.h
index 23a15e4d02..3b8b94dc6b 100644
--- a/src/libsystemd/sd-bus/bus-slot.h
+++ b/src/libsystemd/sd-bus/bus-slot.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -22,6 +20,7 @@
***/
#include "sd-bus.h"
+
#include "bus-internal.h"
sd_bus_slot *bus_slot_allocate(sd_bus *bus, bool floating, BusSlotType type, size_t extra, void *userdata);
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index 735a775cb4..cfd7753139 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -20,22 +18,29 @@
***/
#include <endian.h>
+#include <poll.h>
#include <stdlib.h>
#include <unistd.h>
-#include <poll.h>
+#include "sd-bus.h"
#include "sd-daemon.h"
-#include "util.h"
-#include "macro.h"
-#include "missing.h"
-#include "utf8.h"
-#include "formats-util.h"
-#include "signal-util.h"
-#include "sd-bus.h"
-#include "bus-socket.h"
+#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-message.h"
+#include "bus-socket.h"
+#include "fd-util.h"
+#include "formats-util.h"
+#include "hexdecoct.h"
+#include "macro.h"
+#include "missing.h"
+#include "selinux-util.h"
+#include "signal-util.h"
+#include "stdio-util.h"
+#include "string-util.h"
+#include "user-util.h"
+#include "utf8.h"
+#include "util.h"
#define SNDBUF_SIZE (8*1024*1024)
@@ -55,7 +60,7 @@ static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) {
i->iov_base = NULL;
i->iov_len = 0;
- (*idx) ++;
+ (*idx)++;
}
}
@@ -216,7 +221,7 @@ static int bus_socket_auth_verify_client(sd_bus *b) {
peer.bytes[i/2] = ((uint8_t) x << 4 | (uint8_t) y);
}
- if (!sd_id128_equal(b->server_id, SD_ID128_NULL) &&
+ if (!sd_id128_is_null(b->server_id) &&
!sd_id128_equal(b->server_id, peer))
return -EPERM;
@@ -345,7 +350,7 @@ static int bus_socket_auth_write(sd_bus *b, const char *t) {
if (!p)
return -ENOMEM;
- memcpy(p, b->auth_iovec[0].iov_base, b->auth_iovec[0].iov_len);
+ memcpy_safe(p, b->auth_iovec[0].iov_base, b->auth_iovec[0].iov_len);
memcpy(p + b->auth_iovec[0].iov_len, t, l);
b->auth_iovec[0].iov_base = p;
@@ -602,9 +607,11 @@ static void bus_get_peercred(sd_bus *b) {
b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0;
/* Get the SELinux context of the peer */
- r = getpeersec(b->input_fd, &b->label);
- if (r < 0 && r != -EOPNOTSUPP)
- log_debug_errno(r, "Failed to determine peer security context: %m");
+ if (mac_selinux_have()) {
+ r = getpeersec(b->input_fd, &b->label);
+ if (r < 0 && r != -EOPNOTSUPP)
+ log_debug_errno(r, "Failed to determine peer security context: %m");
+ }
}
static int bus_socket_start_auth_client(sd_bus *b) {
@@ -780,7 +787,7 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
n = m->n_iovec * sizeof(struct iovec);
iov = alloca(n);
- memcpy(iov, m->iovec, n);
+ memcpy_safe(iov, m->iovec, n);
j = 0;
iovec_advance(iov, &j, *idx);
@@ -985,13 +992,13 @@ int bus_socket_read_message(sd_bus *bus) {
return -EIO;
}
- f = realloc(bus->fds, sizeof(int) + (bus->n_fds + n));
+ f = realloc(bus->fds, sizeof(int) * (bus->n_fds + n));
if (!f) {
close_many((int*) CMSG_DATA(cmsg), n);
return -ENOMEM;
}
- memcpy(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int));
+ memcpy_safe(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int));
bus->fds = f;
bus->n_fds += n;
} else
diff --git a/src/libsystemd/sd-bus/bus-socket.h b/src/libsystemd/sd-bus/bus-socket.h
index 5a1c7d4cf2..684feead74 100644
--- a/src/libsystemd/sd-bus/bus-socket.h
+++ b/src/libsystemd/sd-bus/bus-socket.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c
index e43891be25..00e93a215f 100644
--- a/src/libsystemd/sd-bus/bus-track.c
+++ b/src/libsystemd/sd-bus/bus-track.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -20,20 +18,33 @@
***/
#include "sd-bus.h"
-#include "bus-util.h"
+
+#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-track.h"
+#include "bus-util.h"
+
+struct track_item {
+ unsigned n_ref;
+ char *name;
+ sd_bus_slot *slot;
+};
struct sd_bus_track {
unsigned n_ref;
+ unsigned n_adding; /* are we in the process of adding a new name? */
sd_bus *bus;
sd_bus_track_handler_t handler;
void *userdata;
Hashmap *names;
LIST_FIELDS(sd_bus_track, queue);
Iterator iterator;
- bool in_queue;
- bool modified;
+ bool in_list:1; /* In bus->tracks? */
+ bool in_queue:1; /* In bus->track_queue? */
+ bool modified:1;
+ bool recursive:1;
+
+ LIST_FIELDS(sd_bus_track, tracks);
};
#define MATCH_PREFIX \
@@ -56,15 +67,47 @@ struct sd_bus_track {
_x; \
})
+static struct track_item* track_item_free(struct track_item *i) {
+
+ if (!i)
+ return NULL;
+
+ sd_bus_slot_unref(i->slot);
+ free(i->name);
+ free(i);
+
+ return NULL;
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free);
+
static void bus_track_add_to_queue(sd_bus_track *track) {
assert(track);
+ /* Adds the bus track object to the queue of objects we should dispatch next, subject to a number of
+ * conditions. */
+
+ /* Already in the queue? */
if (track->in_queue)
return;
+ /* if we are currently in the process of adding a new name, then let's not enqueue this just yet, let's wait
+ * until the addition is complete. */
+ if (track->n_adding > 0)
+ return;
+
+ /* still referenced? */
+ if (hashmap_size(track->names) > 0)
+ return;
+
+ /* Nothing to call? */
if (!track->handler)
return;
+ /* Already closed? */
+ if (!track->in_list)
+ return;
+
LIST_PREPEND(queue, track->bus->track_queue, track);
track->in_queue = true;
}
@@ -79,6 +122,24 @@ static void bus_track_remove_from_queue(sd_bus_track *track) {
track->in_queue = false;
}
+static int bus_track_remove_name_fully(sd_bus_track *track, const char *name) {
+ struct track_item *i;
+
+ assert(track);
+ assert(name);
+
+ i = hashmap_remove(track->names, name);
+ if (!i)
+ return 0;
+
+ track_item_free(i);
+
+ bus_track_add_to_queue(track);
+
+ track->modified = true;
+ return 1;
+}
+
_public_ int sd_bus_track_new(
sd_bus *bus,
sd_bus_track **track,
@@ -102,6 +163,9 @@ _public_ int sd_bus_track_new(
t->userdata = userdata;
t->bus = sd_bus_ref(bus);
+ LIST_PREPEND(tracks, bus->tracks, t);
+ t->in_list = true;
+
bus_track_add_to_queue(t);
*track = t;
@@ -109,7 +173,9 @@ _public_ int sd_bus_track_new(
}
_public_ sd_bus_track* sd_bus_track_ref(sd_bus_track *track) {
- assert_return(track, NULL);
+
+ if (!track)
+ return NULL;
assert(track->n_ref > 0);
@@ -119,7 +185,7 @@ _public_ sd_bus_track* sd_bus_track_ref(sd_bus_track *track) {
}
_public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
- const char *n;
+ struct track_item *i;
if (!track)
return NULL;
@@ -127,12 +193,15 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
assert(track->n_ref > 0);
if (track->n_ref > 1) {
- track->n_ref --;
+ track->n_ref--;
return NULL;
}
- while ((n = hashmap_first_key(track->names)))
- sd_bus_track_remove_name(track, n);
+ while ((i = hashmap_steal_first(track->names)))
+ track_item_free(i);
+
+ if (track->in_list)
+ LIST_REMOVE(tracks, track->bus->tracks, track);
bus_track_remove_from_queue(track);
hashmap_free(track->names);
@@ -154,49 +223,76 @@ static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus
if (r < 0)
return 0;
- sd_bus_track_remove_name(track, name);
+ bus_track_remove_name_fully(track, name);
return 0;
}
_public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
- _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
- _cleanup_free_ char *n = NULL;
+ _cleanup_(track_item_freep) struct track_item *n = NULL;
+ struct track_item *i;
const char *match;
int r;
assert_return(track, -EINVAL);
assert_return(service_name_is_valid(name), -EINVAL);
+ i = hashmap_get(track->names, name);
+ if (i) {
+ if (track->recursive) {
+ unsigned k = track->n_ref + 1;
+
+ if (k < track->n_ref) /* Check for overflow */
+ return -EOVERFLOW;
+
+ track->n_ref = k;
+ }
+
+ bus_track_remove_from_queue(track);
+ return 0;
+ }
+
r = hashmap_ensure_allocated(&track->names, &string_hash_ops);
if (r < 0)
return r;
- n = strdup(name);
+ n = new0(struct track_item, 1);
if (!n)
return -ENOMEM;
+ n->name = strdup(name);
+ if (!n->name)
+ return -ENOMEM;
/* First, subscribe to this name */
- match = MATCH_FOR_NAME(n);
- r = sd_bus_add_match(track->bus, &slot, match, on_name_owner_changed, track);
- if (r < 0)
+ match = MATCH_FOR_NAME(name);
+
+ bus_track_remove_from_queue(track); /* don't dispatch this while we work in it */
+
+ track->n_adding++; /* make sure we aren't dispatched while we synchronously add this match */
+ r = sd_bus_add_match(track->bus, &n->slot, match, on_name_owner_changed, track);
+ track->n_adding--;
+ if (r < 0) {
+ bus_track_add_to_queue(track);
return r;
+ }
- r = hashmap_put(track->names, n, slot);
- if (r == -EEXIST)
- return 0;
- if (r < 0)
+ r = hashmap_put(track->names, n->name, n);
+ if (r < 0) {
+ bus_track_add_to_queue(track);
return r;
+ }
- /* Second, check if it is currently existing, or maybe
- * doesn't, or maybe disappeared already. */
- r = sd_bus_get_name_creds(track->bus, n, 0, NULL);
+ /* Second, check if it is currently existing, or maybe doesn't, or maybe disappeared already. */
+ track->n_adding++; /* again, make sure this isn't dispatch while we are working in it */
+ r = sd_bus_get_name_creds(track->bus, name, 0, NULL);
+ track->n_adding--;
if (r < 0) {
- hashmap_remove(track->names, n);
+ hashmap_remove(track->names, name);
+ bus_track_add_to_queue(track);
return r;
}
+ n->n_ref = 1;
n = NULL;
- slot = NULL;
bus_track_remove_from_queue(track);
track->modified = true;
@@ -205,37 +301,48 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
}
_public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) {
- _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
- _cleanup_free_ char *n = NULL;
+ struct track_item *i;
assert_return(name, -EINVAL);
- if (!track)
+ if (!track) /* Treat a NULL track object as an empty track object */
return 0;
- slot = hashmap_remove2(track->names, (char*) name, (void**) &n);
- if (!slot)
- return 0;
+ if (!track->recursive)
+ return bus_track_remove_name_fully(track, name);
- if (hashmap_isempty(track->names))
- bus_track_add_to_queue(track);
+ i = hashmap_get(track->names, name);
+ if (!i)
+ return -EUNATCH;
+ if (i->n_ref <= 0)
+ return -EUNATCH;
- track->modified = true;
+ i->n_ref--;
+
+ if (i->n_ref <= 0)
+ return bus_track_remove_name_fully(track, name);
return 1;
}
_public_ unsigned sd_bus_track_count(sd_bus_track *track) {
- if (!track)
+
+ if (!track) /* Let's consider a NULL object equivalent to an empty object */
return 0;
+ /* This signature really should have returned an int, so that we can propagate errors. But well, ... Also, note
+ * that this returns the number of names being watched, and multiple references to the same name are not
+ * counted. */
+
return hashmap_size(track->names);
}
_public_ const char* sd_bus_track_contains(sd_bus_track *track, const char *name) {
- assert_return(track, NULL);
assert_return(name, NULL);
+ if (!track) /* Let's consider a NULL object equivalent to an empty object */
+ return NULL;
+
return hashmap_get(track->names, (void*) name) ? name : NULL;
}
@@ -271,6 +378,9 @@ _public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) {
assert_return(track, -EINVAL);
assert_return(m, -EINVAL);
+ if (sd_bus_message_get_bus(m) != track->bus)
+ return -EINVAL;
+
sender = sd_bus_message_get_sender(m);
if (!sender)
return -EINVAL;
@@ -281,9 +391,14 @@ _public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) {
_public_ int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m) {
const char *sender;
- assert_return(track, -EINVAL);
assert_return(m, -EINVAL);
+ if (!track) /* Treat a NULL track object as an empty track object */
+ return 0;
+
+ if (sd_bus_message_get_bus(m) != track->bus)
+ return -EINVAL;
+
sender = sd_bus_message_get_sender(m);
if (!sender)
return -EINVAL;
@@ -301,7 +416,6 @@ void bus_track_dispatch(sd_bus_track *track) {
int r;
assert(track);
- assert(track->in_queue);
assert(track->handler);
bus_track_remove_from_queue(track);
@@ -317,6 +431,34 @@ void bus_track_dispatch(sd_bus_track *track) {
sd_bus_track_unref(track);
}
+void bus_track_close(sd_bus_track *track) {
+ struct track_item *i;
+
+ assert(track);
+
+ /* Called whenever our bus connected is closed. If so, and our track object is non-empty, dispatch it
+ * immediately, as we are closing now, but first flush out all names. */
+
+ if (!track->in_list)
+ return; /* We already closed this one, don't close it again. */
+
+ /* Remember that this one is closed now */
+ LIST_REMOVE(tracks, track->bus->tracks, track);
+ track->in_list = false;
+
+ /* If there's no name in this one anyway, we don't have to dispatch */
+ if (hashmap_isempty(track->names))
+ return;
+
+ /* Let's flush out all names */
+ while ((i = hashmap_steal_first(track->names)))
+ track_item_free(i);
+
+ /* Invoke handler */
+ if (track->handler)
+ bus_track_dispatch(track);
+}
+
_public_ void *sd_bus_track_get_userdata(sd_bus_track *track) {
assert_return(track, NULL);
@@ -333,3 +475,55 @@ _public_ void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata) {
return ret;
}
+
+_public_ int sd_bus_track_set_recursive(sd_bus_track *track, int b) {
+ assert_return(track, -EINVAL);
+
+ if (track->recursive == !!b)
+ return 0;
+
+ if (!hashmap_isempty(track->names))
+ return -EBUSY;
+
+ track->recursive = b;
+ return 0;
+}
+
+_public_ int sd_bus_track_get_recursive(sd_bus_track *track) {
+ assert_return(track, -EINVAL);
+
+ return track->recursive;
+}
+
+_public_ int sd_bus_track_count_sender(sd_bus_track *track, sd_bus_message *m) {
+ const char *sender;
+
+ assert_return(m, -EINVAL);
+
+ if (!track) /* Let's consider a NULL object equivalent to an empty object */
+ return 0;
+
+ if (sd_bus_message_get_bus(m) != track->bus)
+ return -EINVAL;
+
+ sender = sd_bus_message_get_sender(m);
+ if (!sender)
+ return -EINVAL;
+
+ return sd_bus_track_count_name(track, sender);
+}
+
+_public_ int sd_bus_track_count_name(sd_bus_track *track, const char *name) {
+ struct track_item *i;
+
+ assert_return(service_name_is_valid(name), -EINVAL);
+
+ if (!track) /* Let's consider a NULL object equivalent to an empty object */
+ return 0;
+
+ i = hashmap_get(track->names, name);
+ if (!i)
+ return 0;
+
+ return i->n_ref;
+}
diff --git a/src/libsystemd/sd-bus/bus-track.h b/src/libsystemd/sd-bus/bus-track.h
index f8690a5239..26bd05f5c7 100644
--- a/src/libsystemd/sd-bus/bus-track.h
+++ b/src/libsystemd/sd-bus/bus-track.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -22,3 +20,4 @@
***/
void bus_track_dispatch(sd_bus_track *track);
+void bus_track_close(sd_bus_track *track);
diff --git a/src/libsystemd/sd-bus/bus-type.c b/src/libsystemd/sd-bus/bus-type.c
index 6bc7b880a6..c692afc580 100644
--- a/src/libsystemd/sd-bus/bus-type.c
+++ b/src/libsystemd/sd-bus/bus-type.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
diff --git a/src/libsystemd/sd-bus/bus-type.h b/src/libsystemd/sd-bus/bus-type.h
index 581574ab73..5c87eb5f08 100644
--- a/src/libsystemd/sd-bus/bus-type.h
+++ b/src/libsystemd/sd-bus/bus-type.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -23,9 +21,10 @@
#include <stdbool.h>
-#include "macro.h"
#include "sd-bus.h"
+#include "macro.h"
+
bool bus_type_is_valid(char c) _const_;
bool bus_type_is_valid_in_signature(char c) _const_;
bool bus_type_is_basic(char c) _const_;
diff --git a/src/libsystemd/sd-bus/busctl-introspect.c b/src/libsystemd/sd-bus/busctl-introspect.c
index 15c10da7e9..b09509f8e1 100644
--- a/src/libsystemd/sd-bus/busctl-introspect.c
+++ b/src/libsystemd/sd-bus/busctl-introspect.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,11 +17,13 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-#include "xml.h"
-#include "sd-bus-vtable.h"
+#include "sd-bus.h"
+#include "alloc-util.h"
#include "busctl-introspect.h"
+#include "string-util.h"
+#include "util.h"
+#include "xml.h"
#define NODE_DEPTH_MAX 16
@@ -55,8 +55,7 @@ static void context_reset_member(Context *c) {
}
static void context_reset_interface(Context *c) {
- free(c->interface_name);
- c->interface_name = NULL;
+ c->interface_name = mfree(c->interface_name);
c->interface_flags = 0;
context_reset_member(c);
@@ -462,9 +461,8 @@ static int parse_xml_node(Context *context, const char *prefix, unsigned n_depth
}
}
- free(argument_type);
- free(argument_direction);
- argument_type = argument_direction = NULL;
+ argument_type = mfree(argument_type);
+ argument_direction = mfree(argument_direction);
}
state = STATE_METHOD;
@@ -604,8 +602,7 @@ static int parse_xml_node(Context *context, const char *prefix, unsigned n_depth
if (!strextend(&context->member_signature, argument_type, NULL))
return log_oom();
- free(argument_type);
- argument_type = NULL;
+ argument_type = mfree(argument_type);
}
state = STATE_SIGNAL;
diff --git a/src/libsystemd/sd-bus/busctl-introspect.h b/src/libsystemd/sd-bus/busctl-introspect.h
index ea807d5973..d922e352db 100644
--- a/src/libsystemd/sd-bus/busctl-introspect.h
+++ b/src/libsystemd/sd-bus/busctl-introspect.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c
index 6aaaf0e5ec..2c3f591053 100644
--- a/src/libsystemd/sd-bus/busctl.c
+++ b/src/libsystemd/sd-bus/busctl.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,22 +19,27 @@
#include <getopt.h>
-#include "strv.h"
-#include "util.h"
-#include "log.h"
-#include "build.h"
-#include "pager.h"
-#include "path-util.h"
-#include "set.h"
-
#include "sd-bus.h"
-#include "bus-internal.h"
-#include "bus-util.h"
+
+#include "alloc-util.h"
#include "bus-dump.h"
+#include "bus-internal.h"
#include "bus-signature.h"
#include "bus-type.h"
+#include "bus-util.h"
#include "busctl-introspect.h"
+#include "escape.h"
+#include "fd-util.h"
+#include "locale-util.h"
+#include "log.h"
+#include "pager.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "set.h"
+#include "strv.h"
#include "terminal-util.h"
+#include "user-util.h"
+#include "util.h"
static bool arg_no_pager = false;
static bool arg_legend = true;
@@ -59,15 +62,6 @@ static bool arg_allow_interactive_authorization = true;
static bool arg_augment_creds = true;
static usec_t arg_timeout = 0;
-static void pager_open_if_enabled(void) {
-
- /* Cache result before we open the pager */
- if (arg_no_pager)
- return;
-
- pager_open(false);
-}
-
#define NAME_IS_ACQUIRED INT_TO_PTR(1)
#define NAME_IS_ACTIVATABLE INT_TO_PTR(2)
@@ -92,7 +86,7 @@ static int list_bus_names(sd_bus *bus, char **argv) {
if (r < 0)
return log_error_errno(r, "Failed to list names: %m");
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
names = hashmap_new(&string_hash_ops);
if (!names)
@@ -132,7 +126,7 @@ static int list_bus_names(sd_bus *bus, char **argv) {
}
STRV_FOREACH(i, merged) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
sd_id128_t mid;
if (hashmap_get(names, *i) == NAME_IS_ACTIVATABLE) {
@@ -255,8 +249,8 @@ static void print_subtree(const char *prefix, const char *path, char **l) {
l++;
}
- vertical = strjoina(prefix, draw_special_char(DRAW_TREE_VERTICAL));
- space = strjoina(prefix, draw_special_char(DRAW_TREE_SPACE));
+ vertical = strjoina(prefix, special_glyph(TREE_VERTICAL));
+ space = strjoina(prefix, special_glyph(TREE_SPACE));
for (;;) {
bool has_more = false;
@@ -277,7 +271,7 @@ static void print_subtree(const char *prefix, const char *path, char **l) {
n++;
}
- printf("%s%s%s\n", prefix, draw_special_char(has_more ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT), *l);
+ printf("%s%s%s\n", prefix, special_glyph(has_more ? TREE_BRANCH : TREE_RIGHT), *l);
print_subtree(has_more ? vertical : space, *l, l);
l = n;
@@ -286,7 +280,7 @@ static void print_subtree(const char *prefix, const char *path, char **l) {
static void print_tree(const char *prefix, char **l) {
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
prefix = strempty(prefix);
@@ -329,8 +323,8 @@ static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *p
.on_path = on_path,
};
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *xml;
int r;
@@ -406,7 +400,7 @@ static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool m
p = NULL;
}
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
l = set_get_strv(done);
if (!l)
@@ -435,7 +429,7 @@ static int tree(sd_bus *bus, char **argv) {
if (r < 0)
return log_error_errno(r, "Failed to get name list: %m");
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
STRV_FOREACH(i, names) {
int q;
@@ -449,7 +443,7 @@ static int tree(sd_bus *bus, char **argv) {
if (not_first)
printf("\n");
- printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_highlight_off());
+ printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal());
q = tree_one(bus, *i, NULL, true);
if (q < 0 && r >= 0)
@@ -465,8 +459,8 @@ static int tree(sd_bus *bus, char **argv) {
printf("\n");
if (argv[2]) {
- pager_open_if_enabled();
- printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_highlight_off());
+ pager_open(arg_no_pager, false);
+ printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal());
}
q = tree_one(bus, *i, NULL, !!argv[2]);
@@ -498,8 +492,10 @@ static int format_cmdline(sd_bus_message *m, FILE *f, bool needs_space) {
} basic;
r = sd_bus_message_peek_type(m, &type, &contents);
- if (r <= 0)
+ if (r < 0)
return r;
+ if (r == 0)
+ return needs_space;
if (bus_type_is_container(type) > 0) {
@@ -530,18 +526,23 @@ static int format_cmdline(sd_bus_message *m, FILE *f, bool needs_space) {
fputc(' ', f);
fprintf(f, "%u", n);
+ needs_space = true;
+
} else if (type == SD_BUS_TYPE_VARIANT) {
if (needs_space)
fputc(' ', f);
fprintf(f, "%s", contents);
+ needs_space = true;
}
- r = format_cmdline(m, f, needs_space || IN_SET(type, SD_BUS_TYPE_ARRAY, SD_BUS_TYPE_VARIANT));
+ r = format_cmdline(m, f, needs_space);
if (r < 0)
return r;
+ needs_space = r > 0;
+
r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
@@ -629,22 +630,24 @@ typedef struct Member {
uint64_t flags;
} Member;
-static unsigned long member_hash_func(const void *p, const uint8_t hash_key[]) {
+static void member_hash_func(const void *p, struct siphash *state) {
const Member *m = p;
- unsigned long ul;
+ uint64_t arity = 1;
assert(m);
assert(m->type);
- ul = string_hash_func(m->type, hash_key);
+ string_hash_func(m->type, state);
+
+ arity += !!m->name + !!m->interface;
+
+ uint64_hash_func(&arity, state);
if (m->name)
- ul ^= string_hash_func(m->name, hash_key);
+ string_hash_func(m->name, state);
if (m->interface)
- ul ^= string_hash_func(m->interface, hash_key);
-
- return ul;
+ string_hash_func(m->interface, state);
}
static int member_compare_func(const void *a, const void *b) {
@@ -656,28 +659,15 @@ static int member_compare_func(const void *a, const void *b) {
assert(x->type);
assert(y->type);
- if (!x->interface && y->interface)
- return -1;
- if (x->interface && !y->interface)
- return 1;
- if (x->interface && y->interface) {
- d = strcmp(x->interface, y->interface);
- if (d != 0)
- return d;
- }
+ d = strcmp_ptr(x->interface, y->interface);
+ if (d != 0)
+ return d;
d = strcmp(x->type, y->type);
if (d != 0)
return d;
- if (!x->name && y->name)
- return -1;
- if (x->name && !y->name)
- return 1;
- if (x->name && y->name)
- return strcmp(x->name, y->name);
-
- return 0;
+ return strcmp_ptr(x->name, y->name);
}
static int member_compare_funcp(const void *a, const void *b) {
@@ -873,8 +863,8 @@ static int introspect(sd_bus *bus, char **argv) {
.on_property = on_property,
};
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(member_set_freep) Set *members = NULL;
Iterator i;
Member *m;
@@ -993,7 +983,7 @@ static int introspect(sd_bus *bus, char **argv) {
return bus_log_parse_error(r);
}
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
name_width = strlen("NAME");
type_width = strlen("TYPE");
@@ -1065,7 +1055,7 @@ static int introspect(sd_bus *bus, char **argv) {
is_interface ? ansi_highlight() : "",
is_interface ? "" : ".",
- !is_interface + (int) name_width, strdash(streq_ptr(m->type, "interface") ? m->interface : m->name),
- is_interface ? ansi_highlight_off() : "",
+ is_interface ? ansi_normal() : "",
(int) type_width, strdash(m->type),
(int) signature_width, strdash(m->signature),
(int) result_width, rv,
@@ -1089,10 +1079,21 @@ static int message_pcap(sd_bus_message *m, FILE *f) {
}
static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FILE *f)) {
- bool added_something = false;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char **i;
+ uint32_t flags = 0;
int r;
+ /* upgrade connection; it's not used for anything else after this call */
+ r = sd_bus_message_new_method_call(bus, &message, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus.Monitoring", "BecomeMonitor");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_open_container(message, 'a', "s");
+ if (r < 0)
+ return bus_log_create_error(r);
+
STRV_FOREACH(i, argv+1) {
_cleanup_free_ char *m = NULL;
@@ -1105,31 +1106,44 @@ static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FIL
if (!m)
return log_oom();
- r = sd_bus_add_match(bus, NULL, m, NULL, NULL);
+ r = sd_bus_message_append_basic(message, 's', m);
if (r < 0)
- return log_error_errno(r, "Failed to add match: %m");
+ return bus_log_create_error(r);
- added_something = true;
+ free(m);
+ m = strjoin("destination='", *i, "'", NULL);
+ if (!m)
+ return log_oom();
+
+ r = sd_bus_message_append_basic(message, 's', m);
+ if (r < 0)
+ return bus_log_create_error(r);
}
STRV_FOREACH(i, arg_matches) {
- r = sd_bus_add_match(bus, NULL, *i, NULL, NULL);
+ r = sd_bus_message_append_basic(message, 's', *i);
if (r < 0)
- return log_error_errno(r, "Failed to add match: %m");
-
- added_something = true;
+ return bus_log_create_error(r);
}
- if (!added_something) {
- r = sd_bus_add_match(bus, NULL, "", NULL, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to add match: %m");
+ r = sd_bus_message_close_container(message);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append_basic(message, 'u', &flags);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_call(bus, message, arg_timeout, &error, NULL);
+ if (r < 0) {
+ log_error("%s", bus_error_message(&error, r));
+ return r;
}
log_info("Monitoring bus message stream.");
for (;;) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
r = sd_bus_process(bus, &m);
if (r < 0)
@@ -1179,7 +1193,7 @@ static int capture(sd_bus *bus, char *argv[]) {
}
static int status(sd_bus *bus, char *argv[]) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
pid_t pid;
int r;
@@ -1209,15 +1223,15 @@ static int status(sd_bus *bus, char *argv[]) {
r = sd_bus_get_address(bus, &address);
if (r >= 0)
- printf("BusAddress=%s%s%s\n", ansi_highlight(), address, ansi_highlight_off());
+ printf("BusAddress=%s%s%s\n", ansi_highlight(), address, ansi_normal());
r = sd_bus_get_scope(bus, &scope);
if (r >= 0)
- printf("BusScope=%s%s%s\n", ansi_highlight(), scope, ansi_highlight_off());
+ printf("BusScope=%s%s%s\n", ansi_highlight(), scope, ansi_normal());
r = sd_bus_get_bus_id(bus, &bus_id);
if (r >= 0)
- printf("BusID=%s" SD_ID128_FORMAT_STR "%s\n", ansi_highlight(), SD_ID128_FORMAT_VAL(bus_id), ansi_highlight_off());
+ printf("BusID=%s" SD_ID128_FORMAT_STR "%s\n", ansi_highlight(), SD_ID128_FORMAT_VAL(bus_id), ansi_normal());
r = sd_bus_get_owner_creds(
bus,
@@ -1486,8 +1500,8 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, char
}
static int call(sd_bus *bus, char *argv[]) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
int r;
assert(bus);
@@ -1551,7 +1565,7 @@ static int call(sd_bus *bus, char *argv[]) {
if (r == 0 && !arg_quiet) {
if (arg_verbose) {
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = bus_message_dump(reply, stdout, 0);
if (r < 0)
@@ -1573,7 +1587,7 @@ static int call(sd_bus *bus, char *argv[]) {
}
static int get_property(sd_bus *bus, char *argv[]) {
- _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;
unsigned n;
char **i;
int r;
@@ -1587,7 +1601,7 @@ static int get_property(sd_bus *bus, char *argv[]) {
}
STRV_FOREACH(i, argv + 4) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
const char *contents = NULL;
char type;
@@ -1606,7 +1620,7 @@ static int get_property(sd_bus *bus, char *argv[]) {
return bus_log_parse_error(r);
if (arg_verbose) {
- pager_open_if_enabled();
+ pager_open(arg_no_pager, false);
r = bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_SUBTREE_ONLY);
if (r < 0)
@@ -1631,8 +1645,8 @@ static int get_property(sd_bus *bus, char *argv[]) {
}
static int set_property(sd_bus *bus, char *argv[]) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
unsigned n;
char **p;
int r;
@@ -1697,6 +1711,7 @@ static int help(void) {
" --acquired Only show acquired names\n"
" --activatable Only show activatable names\n"
" --match=MATCH Only show matching messages\n"
+ " --size=SIZE Maximum length of captured packet\n"
" --list Don't show tree, but simple object path list\n"
" --quiet Don't show method call reply\n"
" --verbose Show result values in long format\n"
@@ -1789,9 +1804,7 @@ static int parse_argv(int argc, char *argv[]) {
return help();
case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(SYSTEMD_FEATURES);
- return 0;
+ return version();
case ARG_NO_PAGER:
arg_no_pager = true;
@@ -1835,20 +1848,20 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_SIZE: {
- off_t o;
+ uint64_t sz;
- r = parse_size(optarg, 0, &o);
+ r = parse_size(optarg, 1024, &sz);
if (r < 0) {
log_error("Failed to parse size: %s", optarg);
return r;
}
- if ((off_t) (size_t) o != o) {
+ if ((uint64_t) (size_t) sz != sz) {
log_error("Size out of range.");
return -E2BIG;
}
- arg_snaplen = (size_t) o;
+ arg_snaplen = (size_t) sz;
break;
}
@@ -1974,7 +1987,7 @@ static int busctl_main(sd_bus *bus, int argc, char *argv[]) {
}
int main(int argc, char *argv[]) {
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ sd_bus *bus = NULL;
int r;
log_parse_environment();
@@ -1990,8 +2003,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
- if (streq_ptr(argv[optind], "monitor") ||
- streq_ptr(argv[optind], "capture")) {
+ if (STRPTR_IN_SET(argv[optind], "monitor", "capture")) {
r = sd_bus_set_monitor(bus, true);
if (r < 0) {
@@ -2018,15 +2030,15 @@ int main(int argc, char *argv[]) {
}
}
+ r = sd_bus_set_bus_client(bus, true);
+ if (r < 0) {
+ log_error_errno(r, "Failed to set bus client: %m");
+ goto finish;
+ }
+
if (arg_address)
r = sd_bus_set_address(bus, arg_address);
else {
- r = sd_bus_set_bus_client(bus, true);
- if (r < 0) {
- log_error_errno(r, "Failed to set bus client: %m");
- goto finish;
- }
-
switch (arg_transport) {
case BUS_TRANSPORT_LOCAL:
@@ -2065,6 +2077,7 @@ int main(int argc, char *argv[]) {
r = busctl_main(bus, argc, argv);
finish:
+ sd_bus_flush_close_unref(bus);
pager_close();
strv_free(arg_matches);
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index 0ca225c617..d746348544 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -20,34 +18,40 @@
***/
#include <endian.h>
-#include <stdlib.h>
-#include <unistd.h>
#include <netdb.h>
#include <poll.h>
-#include <sys/mman.h>
#include <pthread.h>
-
-#include "util.h"
-#include "macro.h"
-#include "strv.h"
-#include "missing.h"
-#include "def.h"
-#include "cgroup-util.h"
-#include "bus-label.h"
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <unistd.h>
#include "sd-bus.h"
+
+#include "alloc-util.h"
+#include "bus-container.h"
+#include "bus-control.h"
#include "bus-internal.h"
-#include "bus-message.h"
-#include "bus-type.h"
-#include "bus-socket.h"
#include "bus-kernel.h"
-#include "bus-control.h"
+#include "bus-label.h"
+#include "bus-message.h"
#include "bus-objects.h"
-#include "bus-util.h"
-#include "bus-container.h"
#include "bus-protocol.h"
-#include "bus-track.h"
#include "bus-slot.h"
+#include "bus-socket.h"
+#include "bus-track.h"
+#include "bus-type.h"
+#include "bus-util.h"
+#include "cgroup-util.h"
+#include "def.h"
+#include "fd-util.h"
+#include "hexdecoct.h"
+#include "hostname-util.h"
+#include "macro.h"
+#include "missing.h"
+#include "parse-util.h"
+#include "string-util.h"
+#include "strv.h"
+#include "util.h"
#define log_debug_bus_message(m) \
do { \
@@ -68,18 +72,18 @@ static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
static int attach_io_events(sd_bus *b);
static void detach_io_events(sd_bus *b);
+static thread_local sd_bus *default_system_bus = NULL;
+static thread_local sd_bus *default_user_bus = NULL;
+static thread_local sd_bus *default_starter_bus = NULL;
+
static void bus_close_fds(sd_bus *b) {
assert(b);
detach_io_events(b);
- if (b->input_fd >= 0)
- safe_close(b->input_fd);
-
- if (b->output_fd >= 0 && b->output_fd != b->input_fd)
+ if (b->input_fd != b->output_fd)
safe_close(b->output_fd);
-
- b->input_fd = b->output_fd = -1;
+ b->output_fd = b->input_fd = safe_close(b->input_fd);
}
static void bus_reset_queues(sd_bus *b) {
@@ -88,15 +92,13 @@ static void bus_reset_queues(sd_bus *b) {
while (b->rqueue_size > 0)
sd_bus_message_unref(b->rqueue[--b->rqueue_size]);
- free(b->rqueue);
- b->rqueue = NULL;
+ b->rqueue = mfree(b->rqueue);
b->rqueue_allocated = 0;
while (b->wqueue_size > 0)
sd_bus_message_unref(b->wqueue[--b->wqueue_size]);
- free(b->wqueue);
- b->wqueue = NULL;
+ b->wqueue = mfree(b->wqueue);
b->wqueue_allocated = 0;
}
@@ -105,6 +107,7 @@ static void bus_free(sd_bus *b) {
assert(b);
assert(!b->track_queue);
+ assert(!b->tracks);
b->state = BUS_CLOSED;
@@ -220,8 +223,8 @@ _public_ int sd_bus_set_address(sd_bus *bus, const char *address) {
_public_ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
assert_return(bus, -EINVAL);
assert_return(bus->state == BUS_UNSET, -EPERM);
- assert_return(input_fd >= 0, -EINVAL);
- assert_return(output_fd >= 0, -EINVAL);
+ assert_return(input_fd >= 0, -EBADF);
+ assert_return(output_fd >= 0, -EBADF);
assert_return(!bus_pid_changed(bus), -ECHILD);
bus->input_fd = input_fd;
@@ -311,10 +314,7 @@ _public_ int sd_bus_negotiate_creds(sd_bus *bus, int b, uint64_t mask) {
assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
- if (b)
- bus->creds_mask |= mask;
- else
- bus->creds_mask &= ~mask;
+ SET_FLAG(bus->creds_mask, mask, b);
/* The well knowns we need unconditionally, so that matches can work */
bus->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
@@ -415,7 +415,7 @@ static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *e
}
static int bus_send_hello(sd_bus *bus) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(bus);
@@ -528,7 +528,7 @@ static void skip_address_key(const char **p) {
*p += strcspn(*p, ",");
if (**p == ',')
- (*p) ++;
+ (*p)++;
}
static int parse_unix_address(sd_bus *b, const char **p, char **guid) {
@@ -693,7 +693,7 @@ static int parse_exec_address(sd_bus *b, const char **p, char **guid) {
goto fail;
}
- (*p) ++;
+ (*p)++;
if (ul >= n_argv) {
if (!GREEDY_REALLOC0(argv, allocated, ul + 2)) {
@@ -825,8 +825,7 @@ static int parse_container_unix_address(sd_bus *b, const char **p, char **guid)
b->machine = machine;
machine = NULL;
} else {
- free(b->machine);
- b->machine = NULL;
+ b->machine = mfree(b->machine);
}
if (pid) {
@@ -838,7 +837,7 @@ static int parse_container_unix_address(sd_bus *b, const char **p, char **guid)
b->sockaddr.un.sun_family = AF_UNIX;
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) + strlen("/var/run/dbus/system_bus_socket");
+ b->sockaddr_size = SOCKADDR_UN_LEN(b->sockaddr.un);
return 0;
}
@@ -885,8 +884,7 @@ static int parse_container_kernel_address(sd_bus *b, const char **p, char **guid
b->machine = machine;
machine = NULL;
} else {
- free(b->machine);
- b->machine = NULL;
+ b->machine = mfree(b->machine);
}
if (pid) {
@@ -896,10 +894,9 @@ static int parse_container_kernel_address(sd_bus *b, const char **p, char **guid
} else
b->nspid = 0;
- free(b->kernel);
- b->kernel = strdup("/sys/fs/kdbus/0-system/bus");
- if (!b->kernel)
- return -ENOMEM;
+ r = free_and_strdup(&b->kernel, "/sys/fs/kdbus/0-system/bus");
+ if (r < 0)
+ return r;
return 0;
}
@@ -909,15 +906,11 @@ static void bus_reset_parsed_address(sd_bus *b) {
zero(b->sockaddr);
b->sockaddr_size = 0;
- strv_free(b->exec_argv);
- free(b->exec_path);
- b->exec_path = NULL;
- b->exec_argv = NULL;
+ b->exec_argv = strv_free(b->exec_argv);
+ b->exec_path = mfree(b->exec_path);
b->server_id = SD_ID128_NULL;
- free(b->kernel);
- b->kernel = NULL;
- free(b->machine);
- b->machine = NULL;
+ b->kernel = mfree(b->kernel);
+ b->machine = mfree(b->machine);
b->nspid = 0;
}
@@ -1012,6 +1005,8 @@ static int bus_parse_next_address(sd_bus *b) {
}
static int bus_start_address(sd_bus *b) {
+ bool container_kdbus_available = false;
+ bool kdbus_available = false;
int r;
assert(b);
@@ -1021,17 +1016,40 @@ static int bus_start_address(sd_bus *b) {
bus_close_fds(b);
+ /*
+ * Usually, if you provide multiple different bus-addresses, we
+ * try all of them in order. We use the first one that
+ * succeeds. However, if you mix kernel and unix addresses, we
+ * never try unix-addresses if a previous kernel address was
+ * tried and kdbus was available. This is required to prevent
+ * clients to fallback to the bus-proxy if kdbus is available
+ * but failed (eg., too many connections).
+ */
+
if (b->exec_path)
r = bus_socket_exec(b);
- else if ((b->nspid > 0 || b->machine) && b->kernel)
+ else if ((b->nspid > 0 || b->machine) && b->kernel) {
r = bus_container_connect_kernel(b);
- else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC)
- r = bus_container_connect_socket(b);
- else if (b->kernel)
+ if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT))
+ container_kdbus_available = true;
+
+ } else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC) {
+ if (!container_kdbus_available)
+ r = bus_container_connect_socket(b);
+ else
+ skipped = true;
+
+ } else if (b->kernel) {
r = bus_kernel_connect(b);
- else if (b->sockaddr.sa.sa_family != AF_UNSPEC)
- r = bus_socket_connect(b);
- else
+ if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT))
+ kdbus_available = true;
+
+ } else if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
+ if (!kdbus_available)
+ r = bus_socket_connect(b);
+ else
+ skipped = true;
+ } else
skipped = true;
if (!skipped) {
@@ -1224,6 +1242,8 @@ fail:
int bus_set_address_user(sd_bus *b) {
const char *e;
+ uid_t uid;
+ int r;
assert(b);
@@ -1231,6 +1251,10 @@ int bus_set_address_user(sd_bus *b) {
if (e)
return sd_bus_set_address(b, e);
+ r = cg_pid_get_owner_uid(0, &uid);
+ if (r < 0)
+ uid = getuid();
+
e = secure_getenv("XDG_RUNTIME_DIR");
if (e) {
_cleanup_free_ char *ee = NULL;
@@ -1239,9 +1263,9 @@ int bus_set_address_user(sd_bus *b) {
if (!ee)
return -ENOMEM;
- (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT, getuid(), ee);
+ (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT, uid, ee);
} else
- (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid());
+ (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT, uid);
if (!b->address)
return -ENOMEM;
@@ -1452,7 +1476,9 @@ static void bus_enter_closing(sd_bus *bus) {
}
_public_ sd_bus *sd_bus_ref(sd_bus *bus) {
- assert_return(bus, NULL);
+
+ if (!bus)
+ return NULL;
assert_se(REFCNT_INC(bus->n_ref) >= 2);
@@ -1640,7 +1666,7 @@ static int dispatch_wqueue(sd_bus *bus) {
* it got full, then all bets are off
* anyway. */
- bus->wqueue_size --;
+ bus->wqueue_size--;
sd_bus_message_unref(bus->wqueue[0]);
memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
bus->windex = 0;
@@ -1689,7 +1715,7 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd
/* Dispatch a queued message */
*m = bus->rqueue[0];
- bus->rqueue_size --;
+ bus->rqueue_size--;
memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
return 1;
}
@@ -1706,7 +1732,7 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd
}
static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie, bool hint_sync_call) {
- _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
int r;
assert_return(m, -EINVAL);
@@ -1753,7 +1779,7 @@ static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie,
r = bus_write_message(bus, m, hint_sync_call, &idx);
if (r < 0) {
- if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
+ if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
bus_enter_closing(bus);
return -ECONNRESET;
}
@@ -1781,7 +1807,7 @@ static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie,
if (!GREEDY_REALLOC(bus->wqueue, bus->wqueue_allocated, bus->wqueue_size + 1))
return -ENOMEM;
- bus->wqueue[bus->wqueue_size ++] = sd_bus_message_ref(m);
+ bus->wqueue[bus->wqueue_size++] = sd_bus_message_ref(m);
}
finish:
@@ -1854,8 +1880,8 @@ _public_ int sd_bus_call_async(
void *userdata,
uint64_t usec) {
- _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
- _cleanup_bus_slot_unref_ sd_bus_slot *s = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
+ _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *s = NULL;
int r;
assert_return(m, -EINVAL);
@@ -1953,43 +1979,45 @@ _public_ int sd_bus_call(
sd_bus_error *error,
sd_bus_message **reply) {
- _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
usec_t timeout;
uint64_t cookie;
unsigned i;
int r;
- assert_return(m, -EINVAL);
- assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
- assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL);
- assert_return(!bus_error_is_dirty(error), -EINVAL);
+ bus_assert_return(m, -EINVAL, error);
+ bus_assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL, error);
+ bus_assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL, error);
+ bus_assert_return(!bus_error_is_dirty(error), -EINVAL, error);
if (!bus)
bus = m->bus;
- assert_return(!bus_pid_changed(bus), -ECHILD);
- assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS);
+ bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
+ bus_assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS, error);
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
+ if (!BUS_IS_OPEN(bus->state)) {
+ r = -ENOTCONN;
+ goto fail;
+ }
r = bus_ensure_running(bus);
if (r < 0)
- return r;
+ goto fail;
i = bus->rqueue_size;
r = bus_seal_message(bus, m, usec);
if (r < 0)
- return r;
+ goto fail;
r = bus_remarshal_message(bus, &m);
if (r < 0)
- return r;
+ goto fail;
r = bus_send_internal(bus, m, &cookie, true);
if (r < 0)
- return r;
+ goto fail;
timeout = calc_elapse(m->timeout);
@@ -2020,14 +2048,17 @@ _public_ int sd_bus_call(
}
r = sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry.");
+ sd_bus_message_unref(incoming);
+ return r;
- } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
+ } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) {
r = sd_bus_error_copy(error, &incoming->error);
- else
+ sd_bus_message_unref(incoming);
+ return r;
+ } else {
r = -EIO;
-
- sd_bus_message_unref(incoming);
- return r;
+ goto fail;
+ }
} else if (BUS_MESSAGE_COOKIE(incoming) == cookie &&
bus->unique_name &&
@@ -2043,7 +2074,8 @@ _public_ int sd_bus_call(
* immediately. */
sd_bus_message_unref(incoming);
- return -ELOOP;
+ r = -ELOOP;
+ goto fail;
}
/* Try to read more, right-away */
@@ -2052,12 +2084,12 @@ _public_ int sd_bus_call(
r = bus_read_message(bus, false, 0);
if (r < 0) {
- if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
+ if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
bus_enter_closing(bus);
- return -ECONNRESET;
+ r = -ECONNRESET;
}
- return r;
+ goto fail;
}
if (r > 0)
continue;
@@ -2066,8 +2098,10 @@ _public_ int sd_bus_call(
usec_t n;
n = now(CLOCK_MONOTONIC);
- if (n >= timeout)
- return -ETIMEDOUT;
+ if (n >= timeout) {
+ r = -ETIMEDOUT;
+ goto fail;
+ }
left = timeout - n;
} else
@@ -2075,20 +2109,25 @@ _public_ int sd_bus_call(
r = bus_poll(bus, true, left);
if (r < 0)
- return r;
- if (r == 0)
- return -ETIMEDOUT;
+ goto fail;
+ if (r == 0) {
+ r = -ETIMEDOUT;
+ goto fail;
+ }
r = dispatch_wqueue(bus);
if (r < 0) {
- if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
+ if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
bus_enter_closing(bus);
- return -ECONNRESET;
+ r = -ECONNRESET;
}
- return r;
+ goto fail;
}
}
+
+fail:
+ return sd_bus_error_set_errno(error, r);
}
_public_ int sd_bus_get_fd(sd_bus *bus) {
@@ -2179,8 +2218,8 @@ _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
}
static int process_timeout(sd_bus *bus) {
- _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
- _cleanup_bus_message_unref_ sd_bus_message* m = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message* m = NULL;
struct reply_callback *c;
sd_bus_slot *slot;
usec_t n;
@@ -2216,7 +2255,7 @@ static int process_timeout(sd_bus *bus) {
slot = container_of(c, sd_bus_slot, reply_callback);
- bus->iteration_counter ++;
+ bus->iteration_counter++;
bus->current_message = m;
bus->current_slot = sd_bus_slot_ref(slot);
@@ -2261,8 +2300,8 @@ static int process_hello(sd_bus *bus, sd_bus_message *m) {
}
static int process_reply(sd_bus *bus, sd_bus_message *m) {
- _cleanup_bus_message_unref_ sd_bus_message *synthetic_reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *synthetic_reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
struct reply_callback *c;
sd_bus_slot *slot;
int r;
@@ -2341,7 +2380,7 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
}
static int process_filter(sd_bus *bus, sd_bus_message *m) {
- _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
struct filter_callback *l;
int r;
@@ -2407,7 +2446,7 @@ static int process_match(sd_bus *bus, sd_bus_message *m) {
}
static int process_builtin(sd_bus *bus, sd_bus_message *m) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
int r;
assert(bus);
@@ -2539,7 +2578,7 @@ static int dispatch_track(sd_bus *bus) {
}
static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **ret) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
int r;
assert(bus);
@@ -2602,62 +2641,101 @@ null_message:
return r;
}
-static int process_closing(sd_bus *bus, sd_bus_message **ret) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
- struct reply_callback *c;
+static int bus_exit_now(sd_bus *bus) {
+ assert(bus);
+
+ /* Exit due to close, if this is requested. If this is bus object is attached to an event source, invokes
+ * sd_event_exit(), otherwise invokes libc exit(). */
+
+ if (bus->exited) /* did we already exit? */
+ return 0;
+ if (!bus->exit_triggered) /* was the exit condition triggered? */
+ return 0;
+ if (!bus->exit_on_disconnect) /* Shall we actually exit on disconnection? */
+ return 0;
+
+ bus->exited = true; /* never exit more than once */
+
+ log_debug("Bus connection disconnected, exiting.");
+
+ if (bus->event)
+ return sd_event_exit(bus->event, EXIT_FAILURE);
+ else
+ exit(EXIT_FAILURE);
+
+ assert_not_reached("exit() didn't exit?");
+}
+
+static int process_closing_reply_callback(sd_bus *bus, struct reply_callback *c) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ sd_bus_slot *slot;
int r;
assert(bus);
- assert(bus->state == BUS_CLOSING);
+ assert(c);
- c = ordered_hashmap_first(bus->reply_callbacks);
- if (c) {
- _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
- sd_bus_slot *slot;
+ r = bus_message_new_synthetic_error(
+ bus,
+ c->cookie,
+ &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"),
+ &m);
+ if (r < 0)
+ return r;
- /* First, fail all outstanding method calls */
- r = bus_message_new_synthetic_error(
- bus,
- c->cookie,
- &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"),
- &m);
- if (r < 0)
- return r;
+ r = bus_seal_synthetic_message(bus, m);
+ if (r < 0)
+ return r;
- r = bus_seal_synthetic_message(bus, m);
- if (r < 0)
- return r;
+ if (c->timeout != 0) {
+ prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
+ c->timeout = 0;
+ }
- if (c->timeout != 0) {
- prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
- c->timeout = 0;
- }
+ ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);
+ c->cookie = 0;
- ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);
- c->cookie = 0;
+ slot = container_of(c, sd_bus_slot, reply_callback);
- slot = container_of(c, sd_bus_slot, reply_callback);
+ bus->iteration_counter++;
- bus->iteration_counter++;
+ bus->current_message = m;
+ bus->current_slot = sd_bus_slot_ref(slot);
+ bus->current_handler = c->callback;
+ bus->current_userdata = slot->userdata;
+ r = c->callback(m, slot->userdata, &error_buffer);
+ bus->current_userdata = NULL;
+ bus->current_handler = NULL;
+ bus->current_slot = NULL;
+ bus->current_message = NULL;
- bus->current_message = m;
- bus->current_slot = sd_bus_slot_ref(slot);
- bus->current_handler = c->callback;
- bus->current_userdata = slot->userdata;
- r = c->callback(m, slot->userdata, &error_buffer);
- bus->current_userdata = NULL;
- bus->current_handler = NULL;
- bus->current_slot = NULL;
- bus->current_message = NULL;
+ if (slot->floating) {
+ bus_slot_disconnect(slot);
+ sd_bus_slot_unref(slot);
+ }
- if (slot->floating) {
- bus_slot_disconnect(slot);
- sd_bus_slot_unref(slot);
- }
+ sd_bus_slot_unref(slot);
- sd_bus_slot_unref(slot);
+ return bus_maybe_reply_error(m, r, &error_buffer);
+}
+
+static int process_closing(sd_bus *bus, sd_bus_message **ret) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ struct reply_callback *c;
+ int r;
+
+ assert(bus);
+ assert(bus->state == BUS_CLOSING);
+
+ /* First, fail all outstanding method calls */
+ c = ordered_hashmap_first(bus->reply_callbacks);
+ if (c)
+ return process_closing_reply_callback(bus, c);
- return bus_maybe_reply_error(m, r, &error_buffer);
+ /* Then, fake-drop all remaining bus tracking references */
+ if (bus->tracks) {
+ bus_track_close(bus->tracks);
+ return 1;
}
/* Then, synthesize a Disconnected message */
@@ -2689,6 +2767,10 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) {
if (r != 0)
goto finish;
+ /* Nothing else to do, exit now, if the condition holds */
+ bus->exit_triggered = true;
+ (void) bus_exit_now(bus);
+
if (ret) {
*ret = m;
m = NULL;
@@ -2728,7 +2810,7 @@ static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priorit
case BUS_OPENING:
r = bus_socket_process_opening(bus);
- if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
+ if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
bus_enter_closing(bus);
r = 1;
} else if (r < 0)
@@ -2739,7 +2821,7 @@ static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priorit
case BUS_AUTHENTICATING:
r = bus_socket_process_authenticating(bus);
- if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
+ if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
bus_enter_closing(bus);
r = 1;
} else if (r < 0)
@@ -2753,7 +2835,7 @@ static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priorit
case BUS_RUNNING:
case BUS_HELLO:
r = process_running(bus, hint_priority, priority, ret);
- if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
+ if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
bus_enter_closing(bus);
r = 1;
@@ -2876,7 +2958,7 @@ _public_ int sd_bus_flush(sd_bus *bus) {
for (;;) {
r = dispatch_wqueue(bus);
if (r < 0) {
- if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
+ if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
bus_enter_closing(bus);
return -ECONNRESET;
}
@@ -3316,14 +3398,11 @@ static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus
}
_public_ int sd_bus_default_system(sd_bus **ret) {
- 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_local sd_bus *default_user_bus = NULL;
+_public_ int sd_bus_default_user(sd_bus **ret) {
return bus_default(sd_bus_open_user, &default_user_bus, ret);
}
@@ -3350,7 +3429,6 @@ _public_ int sd_bus_default(sd_bus **ret) {
e = secure_getenv("DBUS_STARTER_ADDRESS");
if (e) {
- static thread_local sd_bus *default_starter_bus = NULL;
return bus_default(sd_bus_open, &default_starter_bus, ret);
}
@@ -3422,6 +3500,171 @@ _public_ int sd_bus_path_decode(const char *path, const char *prefix, char **ext
return 1;
}
+_public_ int sd_bus_path_encode_many(char **out, const char *path_template, ...) {
+ _cleanup_strv_free_ char **labels = NULL;
+ char *path, *path_pos, **label_pos;
+ const char *sep, *template_pos;
+ size_t path_length;
+ va_list list;
+ int r;
+
+ assert_return(out, -EINVAL);
+ assert_return(path_template, -EINVAL);
+
+ path_length = strlen(path_template);
+
+ va_start(list, path_template);
+ for (sep = strchr(path_template, '%'); sep; sep = strchr(sep + 1, '%')) {
+ const char *arg;
+ char *label;
+
+ arg = va_arg(list, const char *);
+ if (!arg) {
+ va_end(list);
+ return -EINVAL;
+ }
+
+ label = bus_label_escape(arg);
+ if (!label) {
+ va_end(list);
+ return -ENOMEM;
+ }
+
+ r = strv_consume(&labels, label);
+ if (r < 0) {
+ va_end(list);
+ return r;
+ }
+
+ /* add label length, but account for the format character */
+ path_length += strlen(label) - 1;
+ }
+ va_end(list);
+
+ path = malloc(path_length + 1);
+ if (!path)
+ return -ENOMEM;
+
+ path_pos = path;
+ label_pos = labels;
+
+ for (template_pos = path_template; *template_pos; ) {
+ sep = strchrnul(template_pos, '%');
+ path_pos = mempcpy(path_pos, template_pos, sep - template_pos);
+ if (!*sep)
+ break;
+
+ path_pos = stpcpy(path_pos, *label_pos++);
+ template_pos = sep + 1;
+ }
+
+ *path_pos = 0;
+ *out = path;
+ return 0;
+}
+
+_public_ int sd_bus_path_decode_many(const char *path, const char *path_template, ...) {
+ _cleanup_strv_free_ char **labels = NULL;
+ const char *template_pos, *path_pos;
+ char **label_pos;
+ va_list list;
+ int r;
+
+ /*
+ * This decodes an object-path based on a template argument. The
+ * template consists of a verbatim path, optionally including special
+ * directives:
+ *
+ * - Each occurrence of '%' in the template matches an arbitrary
+ * substring of a label in the given path. At most one such
+ * directive is allowed per label. For each such directive, the
+ * caller must provide an output parameter (char **) via va_arg. If
+ * NULL is passed, the given label is verified, but not returned.
+ * For each matched label, the *decoded* label is stored in the
+ * passed output argument, and the caller is responsible to free
+ * it. Note that the output arguments are only modified if the
+ * actualy path matched the template. Otherwise, they're left
+ * untouched.
+ *
+ * This function returns <0 on error, 0 if the path does not match the
+ * template, 1 if it matched.
+ */
+
+ assert_return(path, -EINVAL);
+ assert_return(path_template, -EINVAL);
+
+ path_pos = path;
+
+ for (template_pos = path_template; *template_pos; ) {
+ const char *sep;
+ size_t length;
+ char *label;
+
+ /* verify everything until the next '%' matches verbatim */
+ sep = strchrnul(template_pos, '%');
+ length = sep - template_pos;
+ if (strncmp(path_pos, template_pos, length))
+ return 0;
+
+ path_pos += length;
+ template_pos += length;
+
+ if (!*template_pos)
+ break;
+
+ /* We found the next '%' character. Everything up until here
+ * matched. We now skip ahead to the end of this label and make
+ * sure it matches the tail of the label in the path. Then we
+ * decode the string in-between and save it for later use. */
+
+ ++template_pos; /* skip over '%' */
+
+ sep = strchrnul(template_pos, '/');
+ length = sep - template_pos; /* length of suffix to match verbatim */
+
+ /* verify the suffixes match */
+ sep = strchrnul(path_pos, '/');
+ if (sep - path_pos < (ssize_t)length ||
+ strncmp(sep - length, template_pos, length))
+ return 0;
+
+ template_pos += length; /* skip over matched label */
+ length = sep - path_pos - length; /* length of sub-label to decode */
+
+ /* store unescaped label for later use */
+ label = bus_label_unescape_n(path_pos, length);
+ if (!label)
+ return -ENOMEM;
+
+ r = strv_consume(&labels, label);
+ if (r < 0)
+ return r;
+
+ path_pos = sep; /* skip decoded label and suffix */
+ }
+
+ /* end of template must match end of path */
+ if (*path_pos)
+ return 0;
+
+ /* copy the labels over to the caller */
+ va_start(list, path_template);
+ for (label_pos = labels; label_pos && *label_pos; ++label_pos) {
+ char **arg;
+
+ arg = va_arg(list, char **);
+ if (arg)
+ *arg = *label_pos;
+ else
+ free(*label_pos);
+ }
+ va_end(list);
+
+ free(labels);
+ labels = NULL;
+ return 1;
+}
+
_public_ int sd_bus_try_close(sd_bus *bus) {
int r;
@@ -3573,3 +3816,38 @@ _public_ int sd_bus_is_monitor(sd_bus *bus) {
return !!(bus->hello_flags & KDBUS_HELLO_MONITOR);
}
+
+static void flush_close(sd_bus *bus) {
+ if (!bus)
+ return;
+
+ /* Flushes and closes the specified bus. We take a ref before,
+ * to ensure the flushing does not cause the bus to be
+ * unreferenced. */
+
+ sd_bus_flush_close_unref(sd_bus_ref(bus));
+}
+
+_public_ void sd_bus_default_flush_close(void) {
+ flush_close(default_starter_bus);
+ flush_close(default_user_bus);
+ flush_close(default_system_bus);
+}
+
+_public_ int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b) {
+ assert_return(bus, -EINVAL);
+
+ /* Turns on exit-on-disconnect, and triggers it immediately if the bus connection was already
+ * disconnected. Note that this is triggered exclusively on disconnections triggered by the server side, never
+ * from the client side. */
+ bus->exit_on_disconnect = b;
+
+ /* If the exit condition was triggered already, exit immediately. */
+ return bus_exit_now(bus);
+}
+
+_public_ int sd_bus_get_exit_on_disconnect(sd_bus *bus) {
+ assert_return(bus, -EINVAL);
+
+ return bus->exit_on_disconnect;
+}
diff --git a/src/libsystemd/sd-bus/test-bus-benchmark.c b/src/libsystemd/sd-bus/test-bus-benchmark.c
index d14110aa04..56ac2ab3dd 100644
--- a/src/libsystemd/sd-bus/test-bus-benchmark.c
+++ b/src/libsystemd/sd-bus/test-bus-benchmark.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,14 +19,16 @@
#include <sys/wait.h>
-#include "def.h"
-#include "util.h"
-#include "time-util.h"
-
#include "sd-bus.h"
-#include "bus-kernel.h"
+
+#include "alloc-util.h"
#include "bus-internal.h"
+#include "bus-kernel.h"
#include "bus-util.h"
+#include "def.h"
+#include "fd-util.h"
+#include "time-util.h"
+#include "util.h"
#define MAX_SIZE (2*1024*1024)
@@ -44,7 +44,7 @@ static void server(sd_bus *b, size_t *result) {
int r;
for (;;) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
r = sd_bus_process(b, &m);
assert_se(r >= 0);
@@ -78,7 +78,7 @@ static void server(sd_bus *b, size_t *result) {
}
static void transaction(sd_bus *b, size_t sz, const char *server_name) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
uint8_t *p;
assert_se(sd_bus_message_new_method_call(b, &m, server_name, "/", "benchmark.server", "Work") >= 0);
@@ -90,7 +90,7 @@ static void transaction(sd_bus *b, size_t sz, const char *server_name) {
}
static void client_bisect(const char *address, const char *server_name) {
- _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *x = NULL;
size_t lsize, rsize, csize;
sd_bus *b;
int r;
@@ -164,7 +164,7 @@ static void client_bisect(const char *address, const char *server_name) {
}
static void client_chart(Type type, const char *address, const char *server_name, int fd) {
- _cleanup_bus_message_unref_ sd_bus_message *x = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *x = NULL;
size_t csize;
sd_bus *b;
int r;
diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c
index 754335b5e7..fc60830059 100644
--- a/src/libsystemd/sd-bus/test-bus-chat.c
+++ b/src/libsystemd/sd-bus/test-bus-chat.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,21 +17,23 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
+#include <fcntl.h>
#include <pthread.h>
+#include <stdlib.h>
#include <unistd.h>
-#include <fcntl.h>
-
-#include "log.h"
-#include "util.h"
-#include "macro.h"
-#include "formats-util.h"
#include "sd-bus.h"
+
+#include "alloc-util.h"
#include "bus-error.h"
-#include "bus-match.h"
#include "bus-internal.h"
+#include "bus-match.h"
#include "bus-util.h"
+#include "fd-util.h"
+#include "formats-util.h"
+#include "log.h"
+#include "macro.h"
+#include "util.h"
static int match_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m)));
@@ -119,9 +119,7 @@ static int server_init(sd_bus **_bus) {
return 0;
fail:
- if (bus)
- sd_bus_unref(bus);
-
+ sd_bus_unref(bus);
return r;
}
@@ -130,7 +128,7 @@ static int server(sd_bus *bus) {
bool client1_gone = false, client2_gone = false;
while (!client1_gone || !client2_gone) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
pid_t pid = 0;
const char *label = NULL;
@@ -261,9 +259,9 @@ fail:
}
static void* client1(void*p) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *hello;
int r;
_cleanup_close_pair_ int pp[2] = { -1, -1 };
@@ -331,7 +329,7 @@ static void* client1(void*p) {
finish:
if (bus) {
- _cleanup_bus_message_unref_ sd_bus_message *q;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *q;
r = sd_bus_message_new_method_call(
bus,
@@ -353,16 +351,16 @@ finish:
static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
bool *x = userdata;
- log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m)));
+ log_error_errno(sd_bus_message_get_errno(m), "Quit callback: %m");
*x = 1;
return 1;
}
static void* client2(void*p) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
bool quit = false;
const char *mid;
int r;
@@ -499,7 +497,7 @@ static void* client2(void*p) {
finish:
if (bus) {
- _cleanup_bus_message_unref_ sd_bus_message *q;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *q;
r = sd_bus_message_new_method_call(
bus,
diff --git a/src/libsystemd/sd-bus/test-bus-cleanup.c b/src/libsystemd/sd-bus/test-bus-cleanup.c
index f586880593..250a5b2908 100644
--- a/src/libsystemd/sd-bus/test-bus-cleanup.c
+++ b/src/libsystemd/sd-bus/test-bus-cleanup.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -22,20 +20,21 @@
#include <stdio.h>
#include "sd-bus.h"
-#include "bus-util.h"
+
#include "bus-internal.h"
#include "bus-message.h"
+#include "bus-util.h"
#include "refcnt.h"
static void test_bus_new(void) {
- _cleanup_bus_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
assert_se(sd_bus_new(&bus) == 0);
printf("after new: refcount %u\n", REFCNT_GET(bus->n_ref));
}
static int test_bus_open(void) {
- _cleanup_bus_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
r = sd_bus_open_system(&bus);
@@ -50,7 +49,7 @@ static int test_bus_open(void) {
static void test_bus_new_method_call(void) {
sd_bus *bus = NULL;
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
assert_se(sd_bus_open_system(&bus) >= 0);
@@ -58,13 +57,13 @@ static void test_bus_new_method_call(void) {
printf("after message_new_method_call: refcount %u\n", REFCNT_GET(bus->n_ref));
- sd_bus_unref(bus);
- printf("after bus_unref: refcount %u\n", m->n_ref);
+ sd_bus_flush_close_unref(bus);
+ printf("after bus_flush_close_unref: refcount %u\n", m->n_ref);
}
static void test_bus_new_signal(void) {
sd_bus *bus = NULL;
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
assert_se(sd_bus_open_system(&bus) >= 0);
@@ -72,8 +71,8 @@ static void test_bus_new_signal(void) {
printf("after message_new_signal: refcount %u\n", REFCNT_GET(bus->n_ref));
- sd_bus_unref(bus);
- printf("after bus_unref: refcount %u\n", m->n_ref);
+ sd_bus_flush_close_unref(bus);
+ printf("after bus_flush_close_unref: refcount %u\n", m->n_ref);
}
int main(int argc, char **argv) {
diff --git a/src/libsystemd/sd-bus/test-bus-creds.c b/src/libsystemd/sd-bus/test-bus-creds.c
index edd5033db2..6fdcfa4128 100644
--- a/src/libsystemd/sd-bus/test-bus-creds.c
+++ b/src/libsystemd/sd-bus/test-bus-creds.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -20,14 +18,26 @@
***/
#include "sd-bus.h"
+
#include "bus-dump.h"
#include "bus-util.h"
+#include "cgroup-util.h"
int main(int argc, char *argv[]) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
int r;
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
+ if (cg_all_unified() == -ENOMEDIUM) {
+ log_info("Skipping test: /sys/fs/cgroup/ not available");
+ return EXIT_TEST_SKIP;
+ }
+
r = sd_bus_creds_new_from_pid(&creds, 0, _SD_BUS_CREDS_ALL);
+ log_full_errno(r < 0 ? LOG_ERR : LOG_DEBUG, r, "sd_bus_creds_new_from_pid: %m");
assert_se(r >= 0);
bus_creds_dump(creds, NULL, true);
diff --git a/src/libsystemd/sd-bus/test-bus-error.c b/src/libsystemd/sd-bus/test-bus-error.c
index 5753c04b0e..66a3874f10 100644
--- a/src/libsystemd/sd-bus/test-bus-error.c
+++ b/src/libsystemd/sd-bus/test-bus-error.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -20,13 +18,14 @@
***/
#include "sd-bus.h"
+
+#include "bus-common-errors.h"
#include "bus-error.h"
#include "bus-util.h"
#include "errno-list.h"
-#include "bus-common-errors.h"
static void test_error(void) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
const sd_bus_error const_error = SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "const error");
const sd_bus_error temporarily_const_error = {
.name = SD_BUS_ERROR_ACCESS_DENIED,
@@ -43,7 +42,15 @@ static void test_error(void) {
assert_se(sd_bus_error_is_set(&error));
sd_bus_error_free(&error);
+ /* Check with no error */
+ assert_se(!sd_bus_error_is_set(&error));
+ assert_se(sd_bus_error_setf(&error, NULL, "yyy %i", -1) == 0);
+ assert_se(error.name == NULL);
+ assert_se(error.message == NULL);
+ assert_se(!sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND));
+ assert_se(sd_bus_error_get_errno(&error) == 0);
assert_se(!sd_bus_error_is_set(&error));
+
assert_se(sd_bus_error_setf(&error, SD_BUS_ERROR_FILE_NOT_FOUND, "yyy %i", -1) == -ENOENT);
assert_se(streq(error.name, SD_BUS_ERROR_FILE_NOT_FOUND));
assert_se(streq(error.message, "yyy -1"));
@@ -111,6 +118,16 @@ static void test_error(void) {
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR));
assert_se(sd_bus_error_get_errno(&error) == EIO);
assert_se(sd_bus_error_is_set(&error));
+ sd_bus_error_free(&error);
+
+ /* Check with no error */
+ assert_se(!sd_bus_error_is_set(&error));
+ assert_se(sd_bus_error_set_errnof(&error, 0, "Waldi %c", 'X') == 0);
+ assert_se(error.name == NULL);
+ assert_se(error.message == NULL);
+ assert_se(!sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR));
+ assert_se(sd_bus_error_get_errno(&error) == 0);
+ assert_se(!sd_bus_error_is_set(&error));
}
extern const sd_bus_error_map __start_BUS_ERROR_MAP[];
@@ -129,7 +146,7 @@ static void dump_mapping_table(void) {
}
printf("%s -> %i/%s\n", strna(m->name), m->code, strna(errno_to_name(m->code)));
- m ++;
+ m++;
}
printf("---------------------------\n");
}
@@ -166,6 +183,16 @@ static const sd_bus_error_map test_errors4[] = {
SD_BUS_ERROR_MAP_END
};
+static const sd_bus_error_map test_errors_bad1[] = {
+ SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-1", 0),
+ SD_BUS_ERROR_MAP_END
+};
+
+static const sd_bus_error_map test_errors_bad2[] = {
+ SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-1", -1),
+ SD_BUS_ERROR_MAP_END
+};
+
static void test_errno_mapping_custom(void) {
assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error", NULL) == -5);
assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-2", NULL) == -52);
@@ -189,6 +216,9 @@ static void test_errno_mapping_custom(void) {
assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-y", NULL) == -EIO);
assert_se(sd_bus_error_set(NULL, BUS_ERROR_NO_SUCH_UNIT, NULL) == -ENOENT);
+
+ assert_se(sd_bus_error_add_map(test_errors_bad1) == -EINVAL);
+ assert_se(sd_bus_error_add_map(test_errors_bad2) == -EINVAL);
}
int main(int argc, char *argv[]) {
diff --git a/src/libsystemd/sd-bus/test-bus-gvariant.c b/src/libsystemd/sd-bus/test-bus-gvariant.c
index 9b7dd2e499..83f114a0fe 100644
--- a/src/libsystemd/sd-bus/test-bus-gvariant.c
+++ b/src/libsystemd/sd-bus/test-bus-gvariant.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -23,14 +21,16 @@
#include <glib.h>
#endif
-#include "util.h"
-#include "macro.h"
#include "sd-bus.h"
+
+#include "alloc-util.h"
+#include "bus-dump.h"
#include "bus-gvariant.h"
-#include "bus-util.h"
#include "bus-internal.h"
#include "bus-message.h"
-#include "bus-dump.h"
+#include "bus-util.h"
+#include "macro.h"
+#include "util.h"
static void test_bus_gvariant_is_fixed_size(void) {
assert_se(bus_gvariant_is_fixed_size("") > 0);
@@ -59,7 +59,7 @@ static void test_bus_gvariant_is_fixed_size(void) {
static void test_bus_gvariant_get_size(void) {
assert_se(bus_gvariant_get_size("") == 0);
- assert_se(bus_gvariant_get_size("()") == 0);
+ assert_se(bus_gvariant_get_size("()") == 1);
assert_se(bus_gvariant_get_size("y") == 1);
assert_se(bus_gvariant_get_size("u") == 4);
assert_se(bus_gvariant_get_size("b") == 1);
@@ -131,8 +131,8 @@ static void test_bus_gvariant_get_alignment(void) {
}
static void test_marshal(void) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *n = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *n = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_free_ void *blob;
size_t sz;
int r;
diff --git a/src/libsystemd/sd-bus/test-bus-introspect.c b/src/libsystemd/sd-bus/test-bus-introspect.c
index b2caa02870..4425cfae26 100644
--- a/src/libsystemd/sd-bus/test-bus-introspect.c
+++ b/src/libsystemd/sd-bus/test-bus-introspect.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,8 +17,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "log.h"
#include "bus-introspect.h"
+#include "log.h"
static int prop_get(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
return -EINVAL;
@@ -41,7 +39,7 @@ static const sd_bus_vtable vtable[] = {
SD_BUS_PROPERTY("AReadOnlyDeprecatedProperty", "(ut)", prop_get, 0, SD_BUS_VTABLE_DEPRECATED),
SD_BUS_PROPERTY("ChangingProperty", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Invalidating", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
- SD_BUS_PROPERTY("Constant", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("Constant", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EXPLICIT),
SD_BUS_VTABLE_END
};
diff --git a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c
index 90eb1f2a33..eb6179d7d2 100644
--- a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c
+++ b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,12 +17,14 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-#include "log.h"
-
#include "sd-bus.h"
+
+#include "alloc-util.h"
#include "bus-kernel.h"
#include "bus-util.h"
+#include "fd-util.h"
+#include "log.h"
+#include "util.h"
static int test_match(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
int *found = userdata;
@@ -45,7 +45,7 @@ static void test_one(
_cleanup_close_ int bus_ref = -1;
_cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL;
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
sd_bus *a, *b;
int r, found = 0;
@@ -108,8 +108,10 @@ int main(int argc, char *argv[]) {
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "member='Pi_ep'", false);
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "arg0='foobar'", true);
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "arg0='foo_bar'", false);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0='foobar'", true);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0='foobar'", false);
test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0='foo_bar'", false);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0has='foobar'", true);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0has='foo_bar'", false);
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar'", true);
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar2'", false);
diff --git a/src/libsystemd/sd-bus/test-bus-kernel.c b/src/libsystemd/sd-bus/test-bus-kernel.c
index 6506eaab2e..2214817312 100644
--- a/src/libsystemd/sd-bus/test-bus-kernel.c
+++ b/src/libsystemd/sd-bus/test-bus-kernel.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,19 +19,21 @@
#include <fcntl.h>
-#include "util.h"
-#include "log.h"
-
#include "sd-bus.h"
+
+#include "alloc-util.h"
+#include "bus-dump.h"
#include "bus-kernel.h"
#include "bus-util.h"
-#include "bus-dump.h"
+#include "fd-util.h"
+#include "log.h"
+#include "util.h"
int main(int argc, char *argv[]) {
_cleanup_close_ int bus_ref = -1;
_cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL, *bname = NULL;
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *ua = NULL, *ub = NULL, *the_string = NULL;
sd_bus *a, *b;
int r, pipe_fds[2];
diff --git a/src/libsystemd/sd-bus/test-bus-marshal.c b/src/libsystemd/sd-bus/test-bus-marshal.c
index 59deaea89f..a28cc5b79e 100644
--- a/src/libsystemd/sd-bus/test-bus-marshal.c
+++ b/src/libsystemd/sd-bus/test-bus-marshal.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,8 +17,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
#include <math.h>
+#include <stdlib.h>
#ifdef HAVE_GLIB
#include <gio/gio.h>
@@ -30,14 +28,17 @@
#include <dbus/dbus.h>
#endif
-#include "log.h"
-#include "util.h"
-
#include "sd-bus.h"
-#include "bus-message.h"
-#include "bus-util.h"
+
+#include "alloc-util.h"
#include "bus-dump.h"
#include "bus-label.h"
+#include "bus-message.h"
+#include "bus-util.h"
+#include "fd-util.h"
+#include "hexdecoct.h"
+#include "log.h"
+#include "util.h"
static void test_bus_path_encode_unique(void) {
_cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
@@ -66,6 +67,36 @@ static void test_bus_path_encode(void) {
assert_se(sd_bus_path_decode(e, "/foo/bar", &f) > 0 && streq(f, "foo.bar"));
}
+static void test_bus_path_encode_many(void) {
+ _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *f = NULL;
+
+ assert_se(sd_bus_path_decode_many("/foo/bar", "/prefix/%", NULL) == 0);
+ assert_se(sd_bus_path_decode_many("/prefix/bar", "/prefix/%bar", NULL) == 1);
+ assert_se(sd_bus_path_decode_many("/foo/bar", "/prefix/%/suffix", NULL) == 0);
+ assert_se(sd_bus_path_decode_many("/prefix/foobar/suffix", "/prefix/%/suffix", &a) == 1 && streq_ptr(a, "foobar"));
+ assert_se(sd_bus_path_decode_many("/prefix/one_foo_two/mid/three_bar_four/suffix", "/prefix/one_%_two/mid/three_%_four/suffix", &b, &c) == 1 && streq_ptr(b, "foo") && streq_ptr(c, "bar"));
+ assert_se(sd_bus_path_decode_many("/prefix/one_foo_two/mid/three_bar_four/suffix", "/prefix/one_%_two/mid/three_%_four/suffix", NULL, &d) == 1 && streq_ptr(d, "bar"));
+
+ assert_se(sd_bus_path_decode_many("/foo/bar", "/foo/bar/%", NULL) == 0);
+ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/bar%", NULL) == 0);
+ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/bar", NULL) == 0);
+ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%bar", NULL) == 0);
+ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/bar/suffix") == 1);
+ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%%/suffix", NULL, NULL) == 0); /* multiple '%' are treated verbatim */
+ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/suffi", NULL) == 0);
+ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/suffix", &e) == 1 && streq_ptr(e, "bar"));
+ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/%", NULL, NULL) == 1);
+ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/%/%", NULL, NULL, NULL) == 1);
+ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "%/%/%", NULL, NULL, NULL) == 0);
+ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/%", NULL, NULL) == 0);
+ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/%/", NULL, NULL) == 0);
+ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/", NULL) == 0);
+ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%", NULL) == 0);
+ assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "%", NULL) == 0);
+
+ assert_se(sd_bus_path_encode_many(&f, "/prefix/one_%_two/mid/three_%_four/suffix", "foo", "bar") >= 0 && streq_ptr(f, "/prefix/one_foo_two/mid/three_bar_four/suffix"));
+}
+
static void test_bus_label_escape_one(const char *a, const char *b) {
_cleanup_free_ char *t = NULL, *x = NULL, *y = NULL;
@@ -90,7 +121,7 @@ static void test_bus_label_escape(void) {
}
int main(int argc, char *argv[]) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *copy = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *copy = NULL;
int r, boolean;
const char *x, *x2, *y, *z, *a, *b, *c, *d, *a_signature;
uint8_t u, v;
@@ -102,7 +133,7 @@ int main(int argc, char *argv[]) {
_cleanup_free_ char *first = NULL, *second = NULL, *third = NULL;
_cleanup_fclose_ FILE *ms = NULL;
size_t first_size = 0, second_size = 0, third_size = 0;
- _cleanup_bus_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
double dbl;
uint64_t u64;
@@ -134,6 +165,9 @@ int main(int argc, char *argv[]) {
r = sd_bus_message_append(m, "y(ty)y(yt)y", 8, 777ULL, 7, 9, 77, 7777ULL, 10);
assert_se(r >= 0);
+ r = sd_bus_message_append(m, "()");
+ assert_se(r >= 0);
+
r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3");
assert_se(r >= 0);
@@ -210,6 +244,8 @@ int main(int argc, char *argv[]) {
log_error("%s", error.message);
else
dbus_message_unref(w);
+
+ dbus_error_free(&error);
}
#endif
@@ -271,6 +307,9 @@ int main(int argc, char *argv[]) {
assert_se(r > 0);
assert_se(v == 10);
+ r = sd_bus_message_read(m, "()");
+ assert_se(r > 0);
+
r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d);
assert_se(r > 0);
assert_se(boolean);
@@ -350,7 +389,7 @@ int main(int argc, char *argv[]) {
assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0);
- r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y");
+ r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y()");
assert_se(r >= 0);
assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0);
@@ -387,6 +426,7 @@ int main(int argc, char *argv[]) {
test_bus_label_escape();
test_bus_path_encode();
test_bus_path_encode_unique();
+ test_bus_path_encode_many();
return 0;
}
diff --git a/src/libsystemd/sd-bus/test-bus-match.c b/src/libsystemd/sd-bus/test-bus-match.c
index 83cb5c62c2..29c4529f95 100644
--- a/src/libsystemd/sd-bus/test-bus-match.c
+++ b/src/libsystemd/sd-bus/test-bus-match.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,13 +17,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "log.h"
-#include "macro.h"
-
#include "bus-match.h"
#include "bus-message.h"
-#include "bus-util.h"
#include "bus-slot.h"
+#include "bus-util.h"
+#include "log.h"
+#include "macro.h"
static bool mask[32];
@@ -91,8 +88,8 @@ int main(int argc, char *argv[]) {
.type = BUS_MATCH_ROOT,
};
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
- _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
enum bus_match_node_type i;
sd_bus_slot slots[19];
int r;
@@ -115,10 +112,10 @@ int main(int argc, char *argv[]) {
assert_se(match_add(slots, &root, "arg1='two'", 12) >= 0);
assert_se(match_add(slots, &root, "member='waldo',arg2path='/prefix/'", 13) >= 0);
assert_se(match_add(slots, &root, "member=waldo,path='/foo/bar',arg3namespace='prefix'", 14) >= 0);
- assert_se(match_add(slots, &root, "arg4='pi'", 15) >= 0);
- assert_se(match_add(slots, &root, "arg4='pa'", 16) >= 0);
- assert_se(match_add(slots, &root, "arg4='po'", 17) >= 0);
- assert_se(match_add(slots, &root, "arg4='pu'", 18) >= 0);
+ assert_se(match_add(slots, &root, "arg4has='pi'", 15) >= 0);
+ assert_se(match_add(slots, &root, "arg4has='pa'", 16) >= 0);
+ assert_se(match_add(slots, &root, "arg4has='po'", 17) >= 0);
+ assert_se(match_add(slots, &root, "arg4='pi'", 18) >= 0);
bus_match_dump(&root, 0);
diff --git a/src/libsystemd/sd-bus/test-bus-objects.c b/src/libsystemd/sd-bus/test-bus-objects.c
index 1db67ecfac..f11cafd888 100644
--- a/src/libsystemd/sd-bus/test-bus-objects.c
+++ b/src/libsystemd/sd-bus/test-bus-objects.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,19 +17,20 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
#include <pthread.h>
-
-#include "log.h"
-#include "util.h"
-#include "macro.h"
-#include "strv.h"
+#include <stdlib.h>
#include "sd-bus.h"
+
+#include "alloc-util.h"
+#include "bus-dump.h"
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-util.h"
-#include "bus-dump.h"
+#include "log.h"
+#include "macro.h"
+#include "strv.h"
+#include "util.h"
struct context {
int fds[2];
@@ -115,13 +114,14 @@ static int set_handler(sd_bus *bus, const char *path, const char *interface, con
static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *s = NULL;
+ const char *x;
int r;
assert_se(asprintf(&s, "object %p, path %s", userdata, path) >= 0);
r = sd_bus_message_append(reply, "s", s);
assert_se(r >= 0);
- assert_se(startswith(path, "/value/") != NULL || strcmp(path, "/value") == 0);
+ assert_se(x = startswith(path, "/value/"));
assert_se(PTR_TO_UINT(userdata) == 30);
@@ -153,7 +153,7 @@ static int notify_test2(sd_bus_message *m, void *userdata, sd_bus_error *error)
static int emit_interfaces_added(sd_bus_message *m, void *userdata, sd_bus_error *error) {
int r;
- assert_se(sd_bus_emit_interfaces_added(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.test", NULL) >= 0);
+ assert_se(sd_bus_emit_interfaces_added(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0);
r = sd_bus_reply_method_return(m, NULL);
assert_se(r >= 0);
@@ -164,7 +164,7 @@ static int emit_interfaces_added(sd_bus_message *m, void *userdata, sd_bus_error
static int emit_interfaces_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
int r;
- assert_se(sd_bus_emit_interfaces_removed(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.test", NULL) >= 0);
+ assert_se(sd_bus_emit_interfaces_removed(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0);
r = sd_bus_reply_method_return(m, NULL);
assert_se(r >= 0);
@@ -175,7 +175,7 @@ static int emit_interfaces_removed(sd_bus_message *m, void *userdata, sd_bus_err
static int emit_object_added(sd_bus_message *m, void *userdata, sd_bus_error *error) {
int r;
- assert_se(sd_bus_emit_object_added(sd_bus_message_get_bus(m), m->path) >= 0);
+ assert_se(sd_bus_emit_object_added(sd_bus_message_get_bus(m), "/value/a/x") >= 0);
r = sd_bus_reply_method_return(m, NULL);
assert_se(r >= 0);
@@ -186,7 +186,7 @@ static int emit_object_added(sd_bus_message *m, void *userdata, sd_bus_error *er
static int emit_object_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
int r;
- assert_se(sd_bus_emit_object_removed(sd_bus_message_get_bus(m), m->path) >= 0);
+ assert_se(sd_bus_emit_object_removed(sd_bus_message_get_bus(m), "/value/a/x") >= 0);
r = sd_bus_reply_method_return(m, NULL);
assert_se(r >= 0);
@@ -217,6 +217,7 @@ static const sd_bus_vtable vtable2[] = {
SD_BUS_PROPERTY("Value2", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
SD_BUS_PROPERTY("Value3", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Value4", "s", value_handler, 10, 0),
+ SD_BUS_PROPERTY("AnExplicitProperty", "s", NULL, offsetof(struct context, something), SD_BUS_VTABLE_PROPERTY_EXPLICIT|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
SD_BUS_VTABLE_END
};
@@ -228,6 +229,14 @@ static int enumerator_callback(sd_bus *bus, const char *path, void *userdata, ch
return 1;
}
+static int enumerator2_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
+
+ if (object_path_startswith("/value/a", path))
+ assert_se(*nodes = strv_new("/value/a/x", "/value/a/y", "/value/a/z", NULL));
+
+ return 1;
+}
+
static void *server(void *p) {
struct context *c = p;
sd_bus *bus = NULL;
@@ -246,7 +255,9 @@ static void *server(void *p) {
assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0);
assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0);
assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0);
+ assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value/a", enumerator2_callback, NULL) >= 0);
assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0);
+ assert_se(sd_bus_add_object_manager(bus, NULL, "/value/a") >= 0);
assert_se(sd_bus_start(bus) >= 0);
@@ -284,9 +295,9 @@ fail:
}
static int client(struct context *c) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_unref_ sd_bus *bus = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *s;
int r;
diff --git a/src/libsystemd/sd-bus/test-bus-proxy.c b/src/libsystemd/sd-bus/test-bus-proxy.c
deleted file mode 100644
index 369c2f331c..0000000000
--- a/src/libsystemd/sd-bus/test-bus-proxy.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2015 David Herrmann <dh.herrmann@gmail.com>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-
-#include "util.h"
-#include "log.h"
-
-#include "sd-bus.h"
-#include "bus-kernel.h"
-#include "bus-util.h"
-#include "bus-dump.h"
-
-typedef struct {
- const char *sender;
- int matched_acquired;
-} TestProxyMatch;
-
-static int test_proxy_acquired(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- TestProxyMatch *match = userdata;
- const char *name;
- int r;
-
- r = sd_bus_message_read(m, "s", &name);
- assert_se(r >= 0);
-
- if (!streq_ptr(match->sender, name))
- return 0;
-
- ++match->matched_acquired;
- return 1;
-}
-
-static void test_proxy_matched(void) {
- _cleanup_bus_flush_close_unref_ sd_bus *a = NULL;
- TestProxyMatch match = {};
- int r;
-
- /* open bus 'a' */
-
- r = sd_bus_new(&a);
- assert_se(r >= 0);
-
- r = sd_bus_set_address(a, "unix:path=/var/run/dbus/system_bus_socket");
- assert_se(r >= 0);
-
- r = sd_bus_set_bus_client(a, true);
- assert_se(r >= 0);
-
- r = sd_bus_start(a);
- assert_se(r >= 0);
-
- r = sd_bus_add_match(a, NULL,
- "type='signal',"
- "member='NameAcquired'",
- test_proxy_acquired, &match);
- assert_se(r >= 0);
-
- r = sd_bus_get_unique_name(a, &match.sender);
- assert_se(r >= 0);
-
- /* barrier to guarantee proxy/dbus-daemon handled the previous data */
- r = sd_bus_call_method(a,
- "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "GetId",
- NULL, NULL, NULL);
- assert_se(r >= 0);
-
- /* now we can be sure the Name* signals were sent */
- do {
- r = sd_bus_process(a, NULL);
- } while (r > 0);
- assert_se(r == 0);
-
- assert_se(match.matched_acquired == 1);
-}
-
-int main(int argc, char **argv) {
- if (access("/var/run/dbus/system_bus_socket", F_OK) < 0)
- return EXIT_TEST_SKIP;
-
- log_parse_environment();
-
- test_proxy_matched();
-
- return EXIT_SUCCESS;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-server.c b/src/libsystemd/sd-bus/test-bus-server.c
index 080d8eddb7..b6272efc30 100644
--- a/src/libsystemd/sd-bus/test-bus-server.c
+++ b/src/libsystemd/sd-bus/test-bus-server.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,16 +17,16 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
#include <pthread.h>
-
-#include "log.h"
-#include "util.h"
-#include "macro.h"
+#include <stdlib.h>
#include "sd-bus.h"
+
#include "bus-internal.h"
#include "bus-util.h"
+#include "log.h"
+#include "macro.h"
+#include "util.h"
struct context {
int fds[2];
@@ -57,7 +55,7 @@ static void *server(void *p) {
assert_se(sd_bus_start(bus) >= 0);
while (!quit) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
r = sd_bus_process(bus, &m);
if (r < 0) {
@@ -124,8 +122,8 @@ fail:
}
static int client(struct context *c) {
- _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
- _cleanup_bus_unref_ sd_bus *bus = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
diff --git a/src/libsystemd/sd-bus/test-bus-signature.c b/src/libsystemd/sd-bus/test-bus-signature.c
index 17c6188ca0..4f4fd093bf 100644
--- a/src/libsystemd/sd-bus/test-bus-signature.c
+++ b/src/libsystemd/sd-bus/test-bus-signature.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,10 +17,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-
-#include "log.h"
-#include "bus-signature.h"
#include "bus-internal.h"
+#include "bus-signature.h"
+#include "log.h"
+#include "string-util.h"
int main(int argc, char *argv[]) {
char prefix[256];
diff --git a/src/libsystemd/sd-bus/test-bus-track.c b/src/libsystemd/sd-bus/test-bus-track.c
new file mode 100644
index 0000000000..4beb61f05a
--- /dev/null
+++ b/src/libsystemd/sd-bus/test-bus-track.c
@@ -0,0 +1,113 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sd-bus.h>
+
+#include "macro.h"
+
+static bool track_cb_called_x = false;
+static bool track_cb_called_y = false;
+
+static int track_cb_x(sd_bus_track *t, void *userdata) {
+
+ log_error("TRACK CB X");
+
+ assert_se(!track_cb_called_x);
+ track_cb_called_x = true;
+
+ /* This means b's name disappeared. Let's now disconnect, to make sure the track handling on disconnect works
+ * as it should. */
+
+ assert_se(shutdown(sd_bus_get_fd(sd_bus_track_get_bus(t)), SHUT_RDWR) >= 0);
+ return 1;
+}
+
+static int track_cb_y(sd_bus_track *t, void *userdata) {
+ int r;
+
+ log_error("TRACK CB Y");
+
+ assert_se(!track_cb_called_y);
+ track_cb_called_y = true;
+
+ /* We got disconnected, let's close everything */
+
+ r = sd_event_exit(sd_bus_get_event(sd_bus_track_get_bus(t)), EXIT_SUCCESS);
+ assert_se(r >= 0);
+
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
+ _cleanup_(sd_bus_track_unrefp) sd_bus_track *x = NULL, *y = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *a = NULL, *b = NULL;
+ const char *unique;
+ int r;
+
+ r = sd_event_default(&event);
+ assert_se(r >= 0);
+
+ r = sd_bus_open_system(&a);
+ if (IN_SET(r, -ECONNREFUSED, -ENOENT)) {
+ log_info("Failed to connect to bus, skipping tests.");
+ return EXIT_TEST_SKIP;
+ }
+ assert_se(r >= 0);
+
+ r = sd_bus_attach_event(a, event, SD_EVENT_PRIORITY_NORMAL);
+ assert_se(r >= 0);
+
+ r = sd_bus_open_system(&b);
+ assert_se(r >= 0);
+
+ r = sd_bus_attach_event(b, event, SD_EVENT_PRIORITY_NORMAL);
+ assert_se(r >= 0);
+
+ /* Watch b's name from a */
+ r = sd_bus_track_new(a, &x, track_cb_x, NULL);
+ assert_se(r >= 0);
+
+ r = sd_bus_get_unique_name(b, &unique);
+ assert_se(r >= 0);
+
+ r = sd_bus_track_add_name(x, unique);
+ assert_se(r >= 0);
+
+ /* Watch's a's own name from a */
+ r = sd_bus_track_new(a, &y, track_cb_y, NULL);
+ assert_se(r >= 0);
+
+ r = sd_bus_get_unique_name(a, &unique);
+ assert_se(r >= 0);
+
+ r = sd_bus_track_add_name(y, unique);
+ assert_se(r >= 0);
+
+ /* Now make b's name disappear */
+ sd_bus_close(b);
+
+ r = sd_event_loop(event);
+ assert_se(r >= 0);
+
+ assert_se(track_cb_called_x);
+ assert_se(track_cb_called_y);
+
+ return 0;
+}
diff --git a/src/libsystemd/sd-bus/test-bus-zero-copy.c b/src/libsystemd/sd-bus/test-bus-zero-copy.c
index 2d062fc9b5..3380e8500a 100644
--- a/src/libsystemd/sd-bus/test-bus-zero-copy.c
+++ b/src/libsystemd/sd-bus/test-bus-zero-copy.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,14 +19,17 @@
#include <sys/mman.h>
-#include "util.h"
-#include "log.h"
-#include "memfd-util.h"
-
#include "sd-bus.h"
-#include "bus-message.h"
-#include "bus-kernel.h"
+
+#include "alloc-util.h"
#include "bus-dump.h"
+#include "bus-kernel.h"
+#include "bus-message.h"
+#include "fd-util.h"
+#include "log.h"
+#include "memfd-util.h"
+#include "string-util.h"
+#include "util.h"
#define FIRST_ARRAY 17
#define SECOND_ARRAY 33