]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
systemctl: add list-automounts verb
authorDavid Tardon <dtardon@redhat.com>
Fri, 15 Jul 2022 13:58:06 +0000 (15:58 +0200)
committerDavid Tardon <dtardon@redhat.com>
Mon, 25 Jul 2022 11:37:19 +0000 (13:37 +0200)
Fixes: #6056
src/systemctl/systemctl-list-units.c
src/systemctl/systemctl-list-units.h
src/systemctl/systemctl.c

index 80defede91110697c8b9363c7e268cf92d4b5abe..5a1311f5ea800e45ff2aaae79338390f4b913bbf 100644 (file)
@@ -3,6 +3,7 @@
 #include "sd-login.h"
 
 #include "bus-error.h"
+#include "bus-locator.h"
 #include "format-table.h"
 #include "locale-util.h"
 #include "set.h"
@@ -748,3 +749,186 @@ int verb_list_timers(int argc, char *argv[], void *userdata) {
 
         return r;
 }
+
+struct automount_info {
+        const char *machine;
+        const char *id;
+        char *what;
+        char *where;
+        usec_t timeout_idle_usec;
+        bool mounted;
+};
+
+static int automount_info_compare(const struct automount_info *a, const struct automount_info *b) {
+        int r;
+
+        assert(a);
+        assert(b);
+
+        r = strcasecmp_ptr(a->machine, b->machine);
+        if (r != 0)
+                return r;
+
+        return strcmp(a->where, b->where);
+}
+
+static int collect_automount_info(sd_bus* bus, const UnitInfo* info, struct automount_info *ret_info) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_free_ char *mount = NULL, *mount_path = NULL, *where = NULL, *what = NULL, *state = NULL;
+        usec_t timeout_idle_usec;
+        BusLocator locator;
+        int r;
+
+        assert(bus);
+        assert(info);
+        assert(ret_info);
+
+        locator = (BusLocator) {
+                .destination = "org.freedesktop.systemd1",
+                .path = info->unit_path,
+                .interface = "org.freedesktop.systemd1.Automount",
+        };
+
+        r = bus_get_property_string(bus, &locator, "Where", &error, &where);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get automount target: %s", bus_error_message(&error, r));
+
+        r = bus_get_property_trivial(bus, &locator, "TimeoutIdleUSec", &error, 't', &timeout_idle_usec);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get idle timeout: %s", bus_error_message(&error, r));
+
+        r = unit_name_from_path(where, ".mount", &mount);
+        if (r < 0)
+                return log_error_errno(r, "Failed to generate unit name from path: %m");
+
+        mount_path = unit_dbus_path_from_name(mount);
+        if (!mount_path)
+                return log_oom();
+
+        locator.path = mount_path;
+        locator.interface = "org.freedesktop.systemd1.Mount";
+
+        r = bus_get_property_string(bus, &locator, "What", &error, &what);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get mount source: %s", bus_error_message(&error, r));
+
+        locator.interface = "org.freedesktop.systemd1.Unit";
+
+        r = bus_get_property_string(bus, &locator, "ActiveState", &error, &state);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get mount state: %s", bus_error_message(&error, r));
+
+        *ret_info = (struct automount_info) {
+                .machine = info->machine,
+                .id = info->id,
+                .what = TAKE_PTR(what),
+                .where = TAKE_PTR(where),
+                .timeout_idle_usec = timeout_idle_usec,
+                .mounted = streq_ptr(state, "active"),
+        };
+
+        return 0;
+}
+
+static int output_automounts_list(struct automount_info *infos, size_t n_infos) {
+        _cleanup_(table_unrefp) Table *table = NULL;
+        int r;
+
+        assert(infos || n_infos == 0);
+
+        table = table_new("what", "where", "mounted", "idle timeout", "unit");
+        if (!table)
+                return log_oom();
+
+        table_set_header(table, arg_legend != 0);
+        if (arg_full)
+                table_set_width(table, 0);
+
+        (void) table_set_empty_string(table, "-");
+
+        for (struct automount_info *info = infos; info < infos + n_infos; info++) {
+                _cleanup_free_ char *j = NULL;
+                const char *unit;
+
+                if (info->machine) {
+                        j = strjoin(info->machine, ":", info->id);
+                        if (!j)
+                                return log_oom();
+                        unit = j;
+                } else
+                        unit = info->id;
+
+                r = table_add_many(table,
+                                   TABLE_STRING, info->what,
+                                   TABLE_STRING, info->where,
+                                   TABLE_BOOLEAN, info->mounted,
+                                   TABLE_TIMESPAN_MSEC, info->timeout_idle_usec,
+                                   TABLE_STRING, unit);
+                if (r < 0)
+                        return table_log_add_error(r);
+        }
+
+        r = output_table(table);
+        if (r < 0)
+                return r;
+
+        if (arg_legend != 0)
+                output_legend("automount", n_infos);
+
+        return 0;
+}
+
+int verb_list_automounts(int argc, char *argv[], void *userdata) {
+        _cleanup_(message_set_freep) Set *replies = NULL;
+        _cleanup_strv_free_ char **machines = NULL, **automounts = NULL;
+        _cleanup_free_ UnitInfo *unit_infos = NULL;
+        _cleanup_free_ struct automount_info *automount_infos = NULL;
+        size_t c = 0;
+        int r, n;
+        sd_bus *bus;
+
+        r = acquire_bus(BUS_MANAGER, &bus);
+        if (r < 0)
+                return r;
+
+        pager_open(arg_pager_flags);
+
+        r = expand_unit_names(bus, strv_skip(argv, 1), ".automount", &automounts, NULL);
+        if (r < 0)
+                return r;
+
+        if (argc == 1 || automounts) {
+                n = get_unit_list_recursive(bus, automounts, &unit_infos, &replies, &machines);
+                if (n < 0)
+                        return n;
+
+                for (const UnitInfo *u = unit_infos; u < unit_infos + n; u++) {
+                        if (!endswith(u->id, ".automount"))
+                                continue;
+
+                        if (!GREEDY_REALLOC(automount_infos, c + 1)) {
+                                r = log_oom();
+                                goto cleanup;
+                        }
+
+                        r = collect_automount_info(bus, u, &automount_infos[c]);
+                        if (r < 0)
+                                goto cleanup;
+
+                        c++;
+                }
+
+                typesafe_qsort(automount_infos, c, automount_info_compare);
+        }
+
+        output_automounts_list(automount_infos, c);
+
+ cleanup:
+        assert(c == 0 || automount_infos);
+        for (struct automount_info *info = automount_infos; info < automount_infos + c; info++) {
+                free(info->what);
+                free(info->where);
+        }
+
+        return r;
+}
index 7f4cee0d10273be42b7720664a24095ef23bd688..117b7e378afbfd0af8c662d014a5c7bd9792d2f1 100644 (file)
@@ -4,5 +4,6 @@
 int verb_list_units(int argc, char *argv[], void *userdata);
 int verb_list_sockets(int argc, char *argv[], void *userdata);
 int verb_list_timers(int argc, char *argv[], void *userdata);
+int verb_list_automounts(int argc, char *argv[], void *userdata);
 
 usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next);
index fa32c67a08e2b8e9e823e05b24a5bb198bb0518b..fb40c478c2984ad01a8538f37a654e754df3f777 100644 (file)
@@ -138,6 +138,8 @@ static int systemctl_help(void) {
                "%5$sQuery or send control commands to the system manager.%6$s\n"
                "\n%3$sUnit Commands:%4$s\n"
                "  list-units [PATTERN...]             List units currently in memory\n"
+               "  list-automounts [PATTERN...]        List automount units currently in memory,\n"
+               "                                      ordered by path\n"
                "  list-sockets [PATTERN...]           List socket units currently in memory,\n"
                "                                      ordered by address\n"
                "  list-timers [PATTERN...]            List timer units currently in memory,\n"
@@ -1022,6 +1024,7 @@ static int systemctl_main(int argc, char *argv[]) {
         static const Verb verbs[] = {
                 { "list-units",            VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_ONLINE_ONLY, verb_list_units },
                 { "list-unit-files",       VERB_ANY, VERB_ANY, 0,                verb_list_unit_files         },
+                { "list-automounts",       VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_automounts         },
                 { "list-sockets",          VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_sockets            },
                 { "list-timers",           VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_timers             },
                 { "list-jobs",             VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_jobs               },