]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
systemctl: list-dependencies: support --type= and --state= 26051/head
authorMike Yuan <me@yhndnzj.com>
Fri, 13 Jan 2023 08:52:29 +0000 (16:52 +0800)
committerMike Yuan <me@yhndnzj.com>
Mon, 16 Jan 2023 11:46:52 +0000 (19:46 +0800)
Closes #25975

man/systemctl.xml
src/systemctl/systemctl-list-dependencies.c
src/systemctl/systemctl-util.c
src/systemctl/systemctl-util.h
test/units/testsuite-26.sh

index bd64e430c383245c8728a3554ae5ad22bf7d9b27..04b2e9813d90c2e4ba3788efd1a6790ffb53ef9c 100644 (file)
@@ -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>
index 91b8ac6bff2382798be393830499d7417679fbfd..6878954268dd129f92f14ad492d331faa8771738 100644 (file)
@@ -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;
index b333850bec8e0e9171049d379829dfdc45dad877..bcad65f8dc2e55efd058bf56afe4fd606f05421e 100644 (file)
@@ -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,
index 6445bb488741b23039e4d5e90211cbf784baf8f6..317bab75b73fbd1cccbf7a64152d8f974999e465 100644 (file)
@@ -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);
 
index a89d089e12f121036df49b509ecd06bf08f90aff..dc2c7f5004a67808658e96505d903890cb08d9a2 100755 (executable)
@@ -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