diff --git a/TODO b/TODO
index 7675d3d8ab..96d57861bd 100644
--- a/TODO
+++ b/TODO
@@ -4,9 +4,6 @@ Bugfixes:
manager or system manager can be always set. It would be better to reject
them when parsing config.
-* busctl prints errors to stdout:
- busctl tree org.freedesktop.systemd1 /org/freedesktop/systemd1
-
External:
* Fedora: add an rpmlint check that verifies that all unit files in the RPM are listed in %systemd_post macros.
diff --git a/man/rules/meson.build b/man/rules/meson.build
index 941e248d72..78440e6e91 100644
--- a/man/rules/meson.build
+++ b/man/rules/meson.build
@@ -267,6 +267,12 @@ manpages = [
['sd_bus_get_n_queued_read', '3', ['sd_bus_get_n_queued_write'], ''],
['sd_bus_get_name_creds', '3', ['sd_bus_get_owner_creds'], ''],
['sd_bus_get_name_machine_id', '3', [], ''],
+ ['sd_bus_interface_name_is_valid',
+ '3',
+ ['sd_bus_member_name_is_valid',
+ 'sd_bus_object_path_is_valid',
+ 'sd_bus_service_name_is_valid'],
+ ''],
['sd_bus_is_open', '3', ['sd_bus_is_ready'], ''],
['sd_bus_list_names', '3', [], ''],
['sd_bus_message_append', '3', ['sd_bus_message_appendv'], ''],
diff --git a/man/sd-bus.xml b/man/sd-bus.xml
index 24999337c8..0938255d5c 100644
--- a/man/sd-bus.xml
+++ b/man/sd-bus.xml
@@ -89,6 +89,7 @@
sd_bus_get_scope3,
sd_bus_get_tid3,
sd_bus_get_unique_name3,
+sd_bus_interface_name_is_valid3,
sd_bus_is_monitor3,
sd_bus_is_bus_client3,
sd_bus_is_server3,
diff --git a/man/sd_bus_interface_name_is_valid.xml b/man/sd_bus_interface_name_is_valid.xml
new file mode 100644
index 0000000000..73c0ba1bf1
--- /dev/null
+++ b/man/sd_bus_interface_name_is_valid.xml
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+ sd_bus_interface_name_is_valid
+ systemd
+
+
+
+ sd_bus_interface_name_is_valid
+ 3
+
+
+
+ sd_bus_interface_name_is_valid
+ sd_bus_service_name_is_valid
+ sd_bus_member_name_is_valid
+ sd_bus_object_path_is_valid
+
+ Check if a string is a valid bus name or object path
+
+
+
+
+ #include <systemd/sd-bus.h>
+
+
+ int sd_bus_interface_name_is_valid
+ const char* p
+
+
+
+ int sd_bus_service_name_is_valid
+ const char* p
+
+
+
+ int sd_bus_member_name_is_valid
+ const char* p
+
+
+
+ int sd_bus_object_path_is_valid
+ const char* p
+
+
+
+
+
+ Description
+
+ sd_bus_interface_name_is_valid() checks if a given string
+ p is a syntactically valid bus interface name. Similarly,
+ sd_bus_service_name_is_valid() checks if the argument is a valid bus service name,
+ sd_bus_member_name_is_valid() checks if the argument is a valid bus interface member
+ name, and sd_bus_object_path_is_valid() checks if the argument is a valid bus object
+ path. Those functions generally check that only allowed characters are used and that the length of the
+ string is within limits.
+
+
+
+ Return Value
+
+ Those functions return 1 if the argument is a valid interface / service / member name or object
+ path, and 0 if it is not. If the argument is NULL, an error is returned.
+
+
+ Errors
+
+ Returned errors may indicate the following problems:
+
+
+
+ -EINVAL
+
+ The p parameter is
+ NULL.
+
+
+
+
+
+
+
+
+ See Also
+
+
+ systemd1,
+ sd-bus3,
+ sd_bus_message_call_method3
+
+
+
+
diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c
index 7aceb1796f..8e000ee119 100644
--- a/src/busctl/busctl.c
+++ b/src/busctl/busctl.c
@@ -110,13 +110,10 @@ static int acquire_bus(bool set_monitor, sd_bus **ret) {
switch (arg_transport) {
case BUS_TRANSPORT_LOCAL:
- if (arg_user) {
- bus->is_user = true;
+ if (arg_user)
r = bus_set_address_user(bus);
- } else {
- bus->is_system = true;
+ else
r = bus_set_address_system(bus);
- }
break;
case BUS_TRANSPORT_REMOTE:
@@ -427,29 +424,15 @@ static void print_subtree(const char *prefix, const char *path, char **l) {
}
}
-static void print_tree(const char *prefix, char **l) {
-
- prefix = strempty(prefix);
-
- if (arg_list) {
- char **i;
-
- STRV_FOREACH(i, l)
- printf("%s%s\n", prefix, *i);
- return;
- }
-
- if (strv_isempty(l)) {
+static void print_tree(char **l) {
+ if (arg_list)
+ strv_print(l);
+ else if (strv_isempty(l))
printf("No objects discovered.\n");
- return;
- }
-
- if (streq(l[0], "/") && !l[1]) {
+ else if (streq(l[0], "/") && !l[1])
printf("Only root object discovered.\n");
- return;
- }
-
- print_subtree(prefix, "/", l);
+ else
+ print_subtree("", "/", l);
}
static int on_path(const char *path, void *userdata) {
@@ -465,7 +448,7 @@ static int on_path(const char *path, void *userdata) {
return 0;
}
-static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *paths, bool many) {
+static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *paths) {
static const XMLIntrospectOps ops = {
.on_path = on_path,
};
@@ -479,12 +462,10 @@ static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *p
"org.freedesktop.DBus.Introspectable", "Introspect",
&error, &reply, "");
if (r < 0) {
- if (many)
- printf("Failed to introspect object %s of service %s: %s\n",
- path, service, bus_error_message(&error, r));
- else
- log_error_errno(r, "Failed to introspect object %s of service %s: %s",
- path, service, bus_error_message(&error, r));
+ printf("%sFailed to introspect object %s of service %s: %s%s\n",
+ ansi_highlight_red(),
+ path, service, bus_error_message(&error, r),
+ ansi_normal());
return r;
}
@@ -495,34 +476,23 @@ static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *p
return parse_xml_introspect(path, xml, &ops, paths);
}
-static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool many) {
- _cleanup_set_free_free_ Set *paths = NULL, *done = NULL, *failed = NULL;
+static int tree_one(sd_bus *bus, const char *service) {
+ _cleanup_set_free_ Set *paths = NULL, *done = NULL, *failed = NULL;
_cleanup_free_ char **l = NULL;
- char *m;
int r;
- paths = set_new(&string_hash_ops);
- if (!paths)
+ r = set_put_strdup(&paths, "/");
+ if (r < 0)
return log_oom();
- done = set_new(&string_hash_ops);
+ done = set_new(&string_hash_ops_free);
if (!done)
return log_oom();
- failed = set_new(&string_hash_ops);
+ failed = set_new(&string_hash_ops_free);
if (!failed)
return log_oom();
- m = strdup("/");
- if (!m)
- return log_oom();
-
- r = set_put(paths, m);
- if (r < 0) {
- free(m);
- return log_oom();
- }
-
for (;;) {
_cleanup_free_ char *p = NULL;
int q;
@@ -535,20 +505,14 @@ static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool m
set_contains(failed, p))
continue;
- q = find_nodes(bus, service, p, paths, many);
- if (q < 0) {
- if (r >= 0)
- r = q;
-
- q = set_put(failed, p);
- } else
- q = set_put(done, p);
+ q = find_nodes(bus, service, p, paths);
+ if (q < 0 && r >= 0)
+ r = q;
+ q = set_consume(q < 0 ? failed : done, TAKE_PTR(p));
+ assert(q != 0);
if (q < 0)
return log_oom();
-
- assert(q != 0);
- p = NULL;
}
(void) pager_open(arg_pager_flags);
@@ -558,7 +522,7 @@ static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool m
return log_oom();
strv_sort(l);
- print_tree(prefix, l);
+ print_tree(l);
fflush(stdout);
@@ -570,6 +534,12 @@ static int tree(int argc, char **argv, void *userdata) {
char **i;
int r = 0;
+ /* Do superficial verification of arguments before even opening the bus */
+ STRV_FOREACH(i, strv_skip(argv, 1))
+ if (!sd_bus_service_name_is_valid(*i))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Invalid bus service name: %s", *i);
+
if (!arg_unique && !arg_acquired)
arg_acquired = true;
@@ -601,14 +571,14 @@ static int tree(int argc, char **argv, void *userdata) {
printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal());
- q = tree_one(bus, *i, NULL, true);
+ q = tree_one(bus, *i);
if (q < 0 && r >= 0)
r = q;
not_first = true;
}
- } else {
- STRV_FOREACH(i, argv+1) {
+ } else
+ STRV_FOREACH(i, strv_skip(argv, 1)) {
int q;
if (i > argv+1)
@@ -619,11 +589,10 @@ static int tree(int argc, char **argv, void *userdata) {
printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal());
}
- q = tree_one(bus, *i, NULL, !!argv[2]);
+ q = tree_one(bus, *i);
if (q < 0 && r >= 0)
r = q;
}
- }
return r;
}
@@ -1291,7 +1260,7 @@ static int monitor(int argc, char **argv, int (*dump)(sd_bus_message *m, FILE *f
STRV_FOREACH(i, argv+1) {
_cleanup_free_ char *m = NULL;
- if (!service_name_is_valid(*i))
+ if (!sd_bus_service_name_is_valid(*i))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid service name '%s'", *i);
m = strjoin("sender='", *i, "'");
@@ -2608,7 +2577,6 @@ static int parse_argv(int argc, char *argv[]) {
}
static int busctl_main(int argc, char *argv[]) {
-
static const Verb verbs[] = {
{ "list", VERB_ANY, 1, VERB_DEFAULT, list_bus_names },
{ "status", VERB_ANY, 2, 0, status },
diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c
index 84d91dcfa3..2d877a8c55 100644
--- a/src/core/dbus-scope.c
+++ b/src/core/dbus-scope.c
@@ -2,7 +2,6 @@
#include "alloc-util.h"
#include "bus-common-errors.h"
-#include "bus-internal.h"
#include "bus-util.h"
#include "dbus-cgroup.h"
#include "dbus-kill.h"
@@ -140,7 +139,7 @@ static int bus_scope_set_transient_property(
if (r < 0)
return r;
- if (!isempty(controller) && !service_name_is_valid(controller))
+ if (!isempty(controller) && !sd_bus_service_name_is_valid(controller))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
index 5cf9b21890..984ef2459e 100644
--- a/src/core/dbus-service.c
+++ b/src/core/dbus-service.c
@@ -4,7 +4,6 @@
#include "alloc-util.h"
#include "async.h"
-#include "bus-internal.h"
#include "bus-util.h"
#include "dbus-cgroup.h"
#include "dbus-execute.h"
@@ -258,7 +257,7 @@ static BUS_DEFINE_SET_TRANSIENT_PARSE(notify_access, NotifyAccess, notify_access
static BUS_DEFINE_SET_TRANSIENT_PARSE(service_type, ServiceType, service_type_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(service_restart, ServiceRestart, service_restart_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(oom_policy, OOMPolicy, oom_policy_from_string);
-static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name, service_name_is_valid);
+static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name, sd_bus_service_name_is_valid);
static int bus_service_set_transient_property(
Service *s,
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index e420239e15..352798fd6a 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -1948,7 +1948,7 @@ int config_parse_bus_name(
return 0;
}
- if (!service_name_is_valid(k)) {
+ if (!sd_bus_service_name_is_valid(k)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid bus name, ignoring: %s", k);
return 0;
}
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index 1cfe355089..cc396780ce 100644
--- a/src/libsystemd/libsystemd.sym
+++ b/src/libsystemd/libsystemd.sym
@@ -700,6 +700,11 @@ global:
LIBSYSTEMD_246 {
global:
+ sd_bus_interface_name_is_valid;
+ sd_bus_service_name_is_valid;
+ sd_bus_member_name_is_valid;
+ sd_bus_object_path_is_valid;
+
sd_bus_call_methodv;
sd_bus_call_method_asyncv;
sd_bus_emit_signalv;
@@ -707,6 +712,7 @@ global:
sd_bus_reply_method_errorfv;
sd_bus_reply_method_returnv;
sd_bus_set_propertyv;
+
sd_path_lookup;
sd_path_lookup_strv;
} LIBSYSTEMD_245;
diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
index 352a419e25..7e13f4f73b 100644
--- a/src/libsystemd/sd-bus/bus-internal.h
+++ b/src/libsystemd/sd-bus/bus-internal.h
@@ -354,6 +354,7 @@ bool interface_name_is_valid(const char *p) _pure_;
bool service_name_is_valid(const char *p) _pure_;
bool member_name_is_valid(const char *p) _pure_;
bool object_path_is_valid(const char *p) _pure_;
+
char *object_path_startswith(const char *a, const char *b) _pure_;
bool namespace_complex_pattern(const char *pattern, const char *value) _pure_;
diff --git a/src/libsystemd/sd-bus/bus-type.c b/src/libsystemd/sd-bus/bus-type.c
index 18564a5383..585f8424b3 100644
--- a/src/libsystemd/sd-bus/bus-type.c
+++ b/src/libsystemd/sd-bus/bus-type.c
@@ -4,6 +4,7 @@
#include "sd-bus.h"
+#include "bus-internal.h"
#include "bus-type.h"
bool bus_type_is_valid(char c) {
@@ -135,3 +136,27 @@ int bus_type_get_size(char c) {
return -EINVAL;
}
+
+_public_ int sd_bus_interface_name_is_valid(const char *p) {
+ assert_return(p, -EINVAL);
+
+ return interface_name_is_valid(p);
+}
+
+_public_ int sd_bus_service_name_is_valid(const char *p) {
+ assert_return(p, -EINVAL);
+
+ return service_name_is_valid(p);
+}
+
+_public_ int sd_bus_member_name_is_valid(const char *p) {
+ assert_return(p, -EINVAL);
+
+ return member_name_is_valid(p);
+}
+
+_public_ int sd_bus_object_path_is_valid(const char *p) {
+ assert_return(p, -EINVAL);
+
+ return object_path_is_valid(p);
+}
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index 366f36645a..cd1a79a256 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -1266,10 +1266,16 @@ _public_ int sd_bus_open(sd_bus **ret) {
int bus_set_address_system(sd_bus *b) {
const char *e;
+ int r;
+
assert(b);
e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
- return sd_bus_set_address(b, e ?: DEFAULT_SYSTEM_BUS_ADDRESS);
+
+ r = sd_bus_set_address(b, e ?: DEFAULT_SYSTEM_BUS_ADDRESS);
+ if (r >= 0)
+ b->is_system = true;
+ return r;
}
_public_ int sd_bus_open_system_with_description(sd_bus **ret, const char *description) {
@@ -1293,7 +1299,6 @@ _public_ int sd_bus_open_system_with_description(sd_bus **ret, const char *descr
return r;
b->bus_client = true;
- b->is_system = true;
/* Let's do per-method access control on the system bus. We
* need the caller's UID and capability set for that. */
@@ -1316,6 +1321,7 @@ _public_ int sd_bus_open_system(sd_bus **ret) {
int bus_set_address_user(sd_bus *b) {
const char *a;
_cleanup_free_ char *_a = NULL;
+ int r;
assert(b);
@@ -1337,7 +1343,10 @@ int bus_set_address_user(sd_bus *b) {
a = _a;
}
- return sd_bus_set_address(b, a);
+ r = sd_bus_set_address(b, a);
+ if (r >= 0)
+ b->is_user = true;
+ return r;
}
_public_ int sd_bus_open_user_with_description(sd_bus **ret, const char *description) {
@@ -1361,7 +1370,6 @@ _public_ int sd_bus_open_user_with_description(sd_bus **ret, const char *descrip
return r;
b->bus_client = true;
- b->is_user = true;
/* We don't do any per-method access control on the user bus. */
b->trusted = true;
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index 379aecf730..a61f8e70da 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -1156,7 +1156,7 @@ int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id,
int r;
assert_return(b || (sender_id && external_id), -EINVAL);
- assert_return(object_path_is_valid(prefix), -EINVAL);
+ assert_return(sd_bus_object_path_is_valid(prefix), -EINVAL);
assert_return(ret_path, -EINVAL);
if (!sender_id) {
@@ -1208,8 +1208,8 @@ int bus_path_decode_unique(const char *path, const char *prefix, char **ret_send
const char *p, *q;
char *sender, *external;
- assert(object_path_is_valid(path));
- assert(object_path_is_valid(prefix));
+ assert(sd_bus_object_path_is_valid(path));
+ assert(sd_bus_object_path_is_valid(prefix));
assert(ret_sender);
assert(ret_external);
@@ -1670,7 +1670,7 @@ int bus_introspect_implementations(
}
struct introspect intro = {};
- bool is_interface = interface_name_is_valid(pattern);
+ bool is_interface = sd_bus_interface_name_is_valid(pattern);
impl = find_implementation(pattern, bus_objects);
if (!impl)
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 61b5a493c7..d4b6befc8c 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -124,6 +124,13 @@ typedef _sd_destroy_t sd_bus_destroy_t;
#include "sd-bus-protocol.h"
#include "sd-bus-vtable.h"
+/* Naming */
+
+int sd_bus_interface_name_is_valid(const char *p);
+int sd_bus_service_name_is_valid(const char *p);
+int sd_bus_member_name_is_valid(const char *p);
+int sd_bus_object_path_is_valid(const char *p);
+
/* Connections */
int sd_bus_default(sd_bus **ret);