summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Yuan <me@yhndnzj.com>2023-01-13 16:52:29 +0800
committerMike Yuan <me@yhndnzj.com>2023-01-16 19:46:52 +0800
commit372997694446f26ffdedc95a14278cd5b3d2b73d (patch)
tree769def8a2edd08531aa7c8aa78b94732b27dc4cf
parent8e481bd29258274b4d92737d4b11636eabfffcb5 (diff)
downloadsystemd-372997694446f26ffdedc95a14278cd5b3d2b73d.tar.gz
systemctl: list-dependencies: support --type= and --state=
Closes #25975
-rw-r--r--man/systemctl.xml14
-rw-r--r--src/systemctl/systemctl-list-dependencies.c29
-rw-r--r--src/systemctl/systemctl-util.c29
-rw-r--r--src/systemctl/systemctl-util.h3
-rwxr-xr-xtest/units/testsuite-26.sh3
5 files changed, 69 insertions, 9 deletions
diff --git a/man/systemctl.xml b/man/systemctl.xml
index bd64e430c3..04b2e9813d 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -354,6 +354,10 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
dependencies. If no units are specified,
<filename>default.target</filename> is implied.</para>
+ <para>The units that are shown are additionally filtered by <option>--type=</option> and
+ <option>--state=</option> if those options are specified. Note that we won't be able to
+ use a tree structure in this case, so <option>--plain</option> is implied.</para>
+
<para>By default, only target units are recursively
expanded. When <option>--all</option> is passed, all other
units are recursively expanded as well.</para>
@@ -1657,8 +1661,8 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<listitem>
<para>The argument is a comma-separated list of unit types such as <option>service</option> and
<option>socket</option>. When units are listed with <command>list-units</command>,
- <command>show</command>, or <command>status</command>, only units of the specified types will be
- shown. By default, units of all types are shown.</para>
+ <command>list-dependencies</command>, <command>show</command>, or <command>status</command>,
+ only units of the specified types will be shown. By default, units of all types are shown.</para>
<para>As a special case, if one of the arguments is <option>help</option>, a list of allowed values
will be printed and the program will exit.</para>
@@ -1670,9 +1674,9 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<listitem>
<para>The argument is a comma-separated list of unit LOAD, SUB, or ACTIVE states. When listing
- units with <command>list-units</command>, <command>show</command>, or <command>status</command>,
- show only those in the specified states. Use <option>--state=failed</option> or
- <option>--failed</option> to show only failed units.</para>
+ units with <command>list-units</command>, <command>list-dependencies</command>, <command>show</command>
+ or <command>status</command>, show only those in the specified states. Use <option>--state=failed</option>
+ or <option>--failed</option> to show only failed units.</para>
<para>As a special case, if one of the arguments is <option>help</option>, a list of allowed values
will be printed and the program will exit.</para>
diff --git a/src/systemctl/systemctl-list-dependencies.c b/src/systemctl/systemctl-list-dependencies.c
index 91b8ac6bff..6878954268 100644
--- a/src/systemctl/systemctl-list-dependencies.c
+++ b/src/systemctl/systemctl-list-dependencies.c
@@ -80,6 +80,9 @@ static int list_dependencies_one(
typesafe_qsort(deps, strv_length(deps), list_dependencies_compare);
STRV_FOREACH(c, deps) {
+ _cleanup_free_ char *load_state = NULL, *sub_state = NULL;
+ UnitActiveState active_state;
+
if (strv_contains(*units, *c)) {
if (!arg_plain) {
printf(" ");
@@ -90,14 +93,31 @@ static int list_dependencies_one(
continue;
}
+ if (arg_types && !strv_contains(arg_types, unit_type_suffix(*c)))
+ continue;
+
+ r = get_state_one_unit(bus, *c, &active_state);
+ if (r < 0)
+ return r;
+
+ if (arg_states) {
+ r = unit_load_state(bus, *c, &load_state);
+ if (r < 0)
+ return r;
+
+ r = get_sub_state_one_unit(bus, *c, &sub_state);
+ if (r < 0)
+ return r;
+
+ if (!strv_overlap(arg_states, STRV_MAKE(unit_active_state_to_string(active_state), load_state, sub_state)))
+ continue;
+ }
+
if (arg_plain)
printf(" ");
else {
- UnitActiveState active_state = _UNIT_ACTIVE_STATE_INVALID;
const char *on;
- (void) get_state_one_unit(bus, *c, &active_state);
-
switch (active_state) {
case UNIT_ACTIVE:
case UNIT_RELOADING:
@@ -141,6 +161,9 @@ int verb_list_dependencies(int argc, char *argv[], void *userdata) {
sd_bus *bus;
int r;
+ /* We won't be able to preserve the tree structure if --type= or --state= is used */
+ arg_plain = arg_plain || arg_types || arg_states;
+
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
diff --git a/src/systemctl/systemctl-util.c b/src/systemctl/systemctl-util.c
index b333850bec..bcad65f8dc 100644
--- a/src/systemctl/systemctl-util.c
+++ b/src/systemctl/systemctl-util.c
@@ -122,6 +122,7 @@ int get_state_one_unit(sd_bus *bus, const char *unit, UnitActiveState *ret_activ
UnitActiveState state;
int r;
+ assert(bus);
assert(unit);
assert(ret_active_state);
@@ -148,6 +149,34 @@ int get_state_one_unit(sd_bus *bus, const char *unit, UnitActiveState *ret_activ
return 0;
}
+int get_sub_state_one_unit(sd_bus *bus, const char *unit, char **ret_sub_state) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *sub_state = NULL, *dbus_path = NULL;
+ int r;
+
+ assert(bus);
+ assert(unit);
+ assert(ret_sub_state);
+
+ dbus_path = unit_dbus_path_from_name(unit);
+ if (!dbus_path)
+ return log_oom();
+
+ r = sd_bus_get_property_string(
+ bus,
+ "org.freedesktop.systemd1",
+ dbus_path,
+ "org.freedesktop.systemd1.Unit",
+ "SubState",
+ &error,
+ &sub_state);
+ if (r < 0)
+ return log_error_errno(r, "Failed to retrieve unit sub state: %s", bus_error_message(&error, r));
+
+ *ret_sub_state = TAKE_PTR(sub_state);
+ return 0;
+}
+
int get_unit_list(
sd_bus *bus,
const char *machine,
diff --git a/src/systemctl/systemctl-util.h b/src/systemctl/systemctl-util.h
index 6445bb4887..317bab75b7 100644
--- a/src/systemctl/systemctl-util.h
+++ b/src/systemctl/systemctl-util.h
@@ -21,7 +21,8 @@ void polkit_agent_open_maybe(void);
int translate_bus_error_to_exit_status(int r, const sd_bus_error *error);
-int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *ret_active_state);
+int get_state_one_unit(sd_bus *bus, const char *unit, UnitActiveState *ret_active_state);
+int get_sub_state_one_unit(sd_bus *bus, const char *unit, char **ret_sub_state);
int get_unit_list(sd_bus *bus, const char *machine, char **patterns, UnitInfo **unit_infos, int c, sd_bus_message **ret_reply);
int expand_unit_names(sd_bus *bus, char **names, const char* suffix, char ***ret, bool *ret_expanded);
diff --git a/test/units/testsuite-26.sh b/test/units/testsuite-26.sh
index a89d089e12..dc2c7f5004 100755
--- a/test/units/testsuite-26.sh
+++ b/test/units/testsuite-26.sh
@@ -99,6 +99,9 @@ systemctl list-jobs --after
systemctl list-jobs --before
systemctl list-jobs --after --before
systemctl list-jobs "*"
+systemctl list-dependencies sysinit.target --type=socket,mount
+systemctl list-dependencies multi-user.target --state=active
+systemctl list-dependencies sysinit.target --state=mounted --all
# is-* verbs
# Should return 4 for a missing unit file