1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-06 13:17:44 +03:00

systemctl: add list-automounts verb

Fixes: #6056
This commit is contained in:
David Tardon 2022-07-15 15:58:06 +02:00
parent 0f787940b7
commit ed462ea3fa
3 changed files with 188 additions and 0 deletions

View 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;
}

View 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);

View 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 },