diff options
author | David Tardon <dtardon@redhat.com> | 2022-07-15 15:58:06 +0200 |
---|---|---|
committer | David Tardon <dtardon@redhat.com> | 2022-07-25 13:37:19 +0200 |
commit | ed462ea3fa3b85b15ca6f672eb0aa87236d3d67b (patch) | |
tree | d3eba2e73a5b82fe2adf56c71848252eb4850a7f /src/systemctl/systemctl-list-units.c | |
parent | 0f787940b7d60429a1127d9898075d398c4f0384 (diff) | |
download | systemd-ed462ea3fa3b85b15ca6f672eb0aa87236d3d67b.tar.gz |
systemctl: add list-automounts verb
Fixes: #6056
Diffstat (limited to 'src/systemctl/systemctl-list-units.c')
-rw-r--r-- | src/systemctl/systemctl-list-units.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/src/systemctl/systemctl-list-units.c b/src/systemctl/systemctl-list-units.c index 80defede91..5a1311f5ea 100644 --- a/src/systemctl/systemctl-list-units.c +++ b/src/systemctl/systemctl-list-units.c @@ -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; +} |