From: David Tardon Date: Fri, 15 Jul 2022 13:58:06 +0000 (+0200) Subject: systemctl: add list-automounts verb X-Git-Tag: v252-rc1~580^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ed462ea3fa3b85b15ca6f672eb0aa87236d3d67b;p=thirdparty%2Fsystemd.git systemctl: add list-automounts verb Fixes: #6056 --- diff --git a/src/systemctl/systemctl-list-units.c b/src/systemctl/systemctl-list-units.c index 80defede911..5a1311f5ea8 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; +} diff --git a/src/systemctl/systemctl-list-units.h b/src/systemctl/systemctl-list-units.h index 7f4cee0d102..117b7e378af 100644 --- a/src/systemctl/systemctl-list-units.h +++ b/src/systemctl/systemctl-list-units.h @@ -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); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index fa32c67a08e..fb40c478c29 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -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 },