From: Mike Yuan Date: Fri, 13 Jan 2023 08:52:29 +0000 (+0800) Subject: systemctl: list-dependencies: support --type= and --state= X-Git-Tag: v253-rc1~102^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F26051%2Fhead;p=thirdparty%2Fsystemd.git systemctl: list-dependencies: support --type= and --state= Closes #25975 --- diff --git a/man/systemctl.xml b/man/systemctl.xml index bd64e430c38..04b2e9813d9 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, default.target is implied. + The units that are shown are additionally filtered by and + if those options are specified. Note that we won't be able to + use a tree structure in this case, so is implied. + By default, only target units are recursively expanded. When is passed, all other units are recursively expanded as well. @@ -1657,8 +1661,8 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err The argument is a comma-separated list of unit types such as and . When units are listed with list-units, - show, or status, only units of the specified types will be - shown. By default, units of all types are shown. + list-dependencies, show, or status, + only units of the specified types will be shown. By default, units of all types are shown. As a special case, if one of the arguments is , a list of allowed values will be printed and the program will exit. @@ -1670,9 +1674,9 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err The argument is a comma-separated list of unit LOAD, SUB, or ACTIVE states. When listing - units with list-units, show, or status, - show only those in the specified states. Use or - to show only failed units. + units with list-units, list-dependencies, show + or status, show only those in the specified states. Use + or to show only failed units. As a special case, if one of the arguments is , a list of allowed values will be printed and the program will exit. diff --git a/src/systemctl/systemctl-list-dependencies.c b/src/systemctl/systemctl-list-dependencies.c index 91b8ac6bff2..6878954268d 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 b333850bec8..bcad65f8dc2 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 6445bb48874..317bab75b73 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 a89d089e12f..dc2c7f5004a 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