]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/systemctl/systemctl-list-units.c
Merge pull request #26535 from yuwata/systemctl-list-cleanups
[thirdparty/systemd.git] / src / systemctl / systemctl-list-units.c
index 77088fb3ebff82241322033cadebb27fbf904457..c52eaec5547d1798d3b50ac93ebe18c4335940fa 100644 (file)
@@ -632,7 +632,7 @@ static int output_timers_list(const TimerInfo *timers, size_t n_timers) {
 
                 r = table_add_many(table,
                                    TABLE_TIMESTAMP, t->next_elapse,
-                                   TABLE_TIMESTAMP_RELATIVE, t->next_elapse,
+                                   TABLE_TIMESTAMP_LEFT, t->next_elapse,
                                    TABLE_TIMESTAMP, t->last_trigger,
                                    TABLE_TIMESTAMP_RELATIVE, t->last_trigger,
                                    TABLE_STRING, unit);
@@ -772,16 +772,27 @@ int verb_list_timers(int argc, char *argv[], void *userdata) {
         return 0;
 }
 
-struct automount_info {
+typedef struct AutomountInfo {
         const char *machine;
         const char *id;
         char *what;
         char *where;
         usec_t timeout_idle_usec;
         bool mounted;
-};
+} AutomountInfo;
 
-static int automount_info_compare(const struct automount_info *a, const struct automount_info *b) {
+static void automount_info_array_free(AutomountInfo *automounts, size_t n_automounts) {
+        assert(automounts || n_automounts == 0);
+
+        for (AutomountInfo *i = automounts; i < automounts + n_automounts; i++) {
+                free(i->what);
+                free(i->where);
+        }
+
+        free(automounts);
+}
+
+static int automount_info_compare(const AutomountInfo *a, const AutomountInfo *b) {
         int r;
 
         assert(a);
@@ -791,10 +802,15 @@ static int automount_info_compare(const struct automount_info *a, const struct a
         if (r != 0)
                 return r;
 
-        return strcmp(a->where, b->where);
+        return path_compare(a->where, b->where);
 }
 
-static int collect_automount_info(sd_bus* bus, const UnitInfo* info, struct automount_info *ret_info) {
+static int automount_info_add(
+                sd_bus* bus,
+                const UnitInfo *info,
+                AutomountInfo **automounts,
+                size_t *n_automounts) {
+
         _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;
         uint64_t timeout_idle_usec;
@@ -803,7 +819,11 @@ static int collect_automount_info(sd_bus* bus, const UnitInfo* info, struct auto
 
         assert(bus);
         assert(info);
-        assert(ret_info);
+        assert(automounts);
+        assert(n_automounts);
+
+        if (!endswith(info->id, ".automount"))
+                return 0;
 
         locator = (BusLocator) {
                 .destination = "org.freedesktop.systemd1",
@@ -840,7 +860,10 @@ static int collect_automount_info(sd_bus* bus, const UnitInfo* info, struct auto
         if (r < 0)
                 return log_error_errno(r, "Failed to get mount state: %s", bus_error_message(&error, r));
 
-        *ret_info = (struct automount_info) {
+        if (!GREEDY_REALLOC(*automounts, *n_automounts + 1))
+                return log_oom();
+
+        (*automounts)[(*n_automounts)++] = (AutomountInfo) {
                 .machine = info->machine,
                 .id = info->id,
                 .what = TAKE_PTR(what),
@@ -852,7 +875,7 @@ static int collect_automount_info(sd_bus* bus, const UnitInfo* info, struct auto
         return 0;
 }
 
-static int output_automounts_list(struct automount_info *infos, size_t n_infos) {
+static int output_automounts_list(const AutomountInfo *infos, size_t n_infos) {
         _cleanup_(table_unrefp) Table *table = NULL;
         int r;
 
@@ -868,7 +891,7 @@ static int output_automounts_list(struct automount_info *infos, size_t n_infos)
 
         table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
 
-        for (struct automount_info *info = infos; info < infos + n_infos; info++) {
+        for (const AutomountInfo *info = infos; info < infos + n_infos; info++) {
                 _cleanup_free_ char *unit = NULL;
 
                 unit = format_unit_id(info->id, info->machine);
@@ -906,12 +929,14 @@ static int output_automounts_list(struct automount_info *infos, size_t n_infos)
 
 int verb_list_automounts(int argc, char *argv[], void *userdata) {
         _cleanup_(message_set_freep) Set *replies = NULL;
-        _cleanup_strv_free_ char **automounts = NULL;
+        _cleanup_strv_free_ char **names = NULL;
         _cleanup_free_ UnitInfo *unit_infos = NULL;
-        _cleanup_free_ struct automount_info *automount_infos = NULL;
-        size_t c = 0;
-        int r, n;
+        AutomountInfo *automounts = NULL;
+        size_t n_automounts = 0;
         sd_bus *bus;
+        int r;
+
+        CLEANUP_ARRAY(automounts, n_automounts, automount_info_array_free);
 
         r = acquire_bus(BUS_MANAGER, &bus);
         if (r < 0)
@@ -919,47 +944,32 @@ int verb_list_automounts(int argc, char *argv[], void *userdata) {
 
         pager_open(arg_pager_flags);
 
-        r = expand_unit_names(bus, strv_skip(argv, 1), ".automount", &automounts, NULL);
+        r = expand_unit_names(bus, strv_skip(argv, 1), ".automount", &names, NULL);
         if (r < 0)
                 return r;
 
         if (argc == 1 || automounts) {
-                n = get_unit_list_recursive(bus, automounts, &unit_infos, &replies);
+                int n;
+
+                n = get_unit_list_recursive(bus, names, &unit_infos, &replies);
                 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]);
+                        r = automount_info_add(bus, u, &automounts, &n_automounts);
                         if (r < 0)
-                                goto cleanup;
-
-                        c++;
+                                return r;
                 }
 
-                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);
-        }
+        typesafe_qsort(automounts, n_automounts, automount_info_compare);
+        output_automounts_list(automounts, n_automounts);
 
-        return r;
+        return 0;
 }
 
-struct path_info {
+typedef struct PathInfo {
         const char *machine;
         const char *id;
 
@@ -969,14 +979,9 @@ struct path_info {
         /* Note: triggered is a list here, although it almost certainly will always be one
          * unit. Nevertheless, dbus API allows for multiple values, so let's follow that. */
         char** triggered;
-};
-
-struct path_infos {
-        size_t count;
-        struct path_info *items;
-};
+} PathInfo;
 
-static int path_info_compare(const struct path_info *a, const struct path_info *b) {
+static int path_info_compare(const PathInfo *a, const PathInfo *b) {
         int r;
 
         assert(a);
@@ -997,34 +1002,45 @@ static int path_info_compare(const struct path_info *a, const struct path_info *
         return strcasecmp_ptr(a->id, b->id);
 }
 
-static void path_infos_done(struct path_infos *ps) {
-        assert(ps);
-        assert(ps->items || ps->count == 0);
+static void path_info_array_free(PathInfo *paths, size_t n_paths) {
+        assert(paths || n_paths == 0);
 
-        for (struct path_info *p = ps->items; p < ps->items + ps->count; p++) {
+        for (PathInfo *p = paths; p < paths + n_paths; p++) {
                 free(p->condition);
                 free(p->path);
                 strv_free(p->triggered);
         }
 
-        free(ps->items);
+        free(paths);
 }
 
-static int get_paths(sd_bus *bus, const char *unit_path, char ***ret_conditions, char ***ret_paths) {
+static int path_info_add(
+                sd_bus *bus,
+                const struct UnitInfo *u,
+                PathInfo **paths,
+                size_t *n_paths) {
+
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_strv_free_ char **conditions = NULL, **paths = NULL;
+        _cleanup_strv_free_ char **triggered = NULL;
         const char *condition, *path;
-        int r, n = 0;
+        int r;
 
         assert(bus);
-        assert(unit_path);
-        assert(ret_conditions);
-        assert(ret_paths);
+        assert(u);
+        assert(paths);
+        assert(n_paths);
+
+        if (!endswith(u->id, ".path"))
+                return 0;
+
+        r = get_triggered_units(bus, u->unit_path, &triggered);
+        if (r < 0)
+                return r;
 
         r = sd_bus_get_property(bus,
                                 "org.freedesktop.systemd1",
-                                unit_path,
+                                u->unit_path,
                                 "org.freedesktop.systemd1.Path",
                                 "Paths",
                                 &error,
@@ -1038,13 +1054,31 @@ static int get_paths(sd_bus *bus, const char *unit_path, char ***ret_conditions,
                 return bus_log_parse_error(r);
 
         while ((r = sd_bus_message_read(reply, "(ss)", &condition, &path)) > 0) {
-                if (strv_extend(&conditions, condition) < 0)
+                _cleanup_free_ char *condition_dup = NULL, *path_dup = NULL;
+                _cleanup_strv_free_ char **triggered_dup = NULL;
+
+                condition_dup = strdup(condition);
+                if (!condition_dup)
                         return log_oom();
 
-                if (strv_extend(&paths, path) < 0)
+                path_dup = strdup(path);
+                if (!path_dup)
+                        return log_oom();
+
+                triggered_dup = strv_copy(triggered);
+                if (!triggered_dup)
                         return log_oom();
 
-                n++;
+                if (!GREEDY_REALLOC(*paths, *n_paths + 1))
+                        return log_oom();
+
+                (*paths)[(*n_paths)++] = (PathInfo) {
+                        .machine = u->machine,
+                        .id = u->id,
+                        .condition = TAKE_PTR(condition_dup),
+                        .path = TAKE_PTR(path_dup),
+                        .triggered = TAKE_PTR(triggered_dup),
+                };
         }
         if (r < 0)
                 return bus_log_parse_error(r);
@@ -1053,18 +1087,14 @@ static int get_paths(sd_bus *bus, const char *unit_path, char ***ret_conditions,
         if (r < 0)
                 return bus_log_parse_error(r);
 
-        *ret_conditions = TAKE_PTR(conditions);
-        *ret_paths = TAKE_PTR(paths);
-
-        return n;
+        return 0;
 }
 
-static int output_paths_list(struct path_infos *ps) {
+static int output_paths_list(const PathInfo *paths, size_t n_paths) {
         _cleanup_(table_unrefp) Table *table = NULL;
         int r;
 
-        assert(ps);
-        assert(ps->items || ps->count == 0);
+        assert(paths || n_paths == 0);
 
         table = table_new("path", "condition", "unit", "activates");
         if (!table)
@@ -1076,7 +1106,7 @@ static int output_paths_list(struct path_infos *ps) {
 
         table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
 
-        for (struct path_info *p = ps->items; p < ps->items + ps->count; p++) {
+        for (const PathInfo *p = paths; p < paths + n_paths; p++) {
                 _cleanup_free_ char *unit = NULL;
 
                 unit = format_unit_id(p->id, p->machine);
@@ -1100,7 +1130,7 @@ static int output_paths_list(struct path_infos *ps) {
                 return r;
 
         if (arg_legend != 0)
-                output_legend("path", ps->count);
+                output_legend("path", n_paths);
 
         return 0;
 }
@@ -1109,9 +1139,12 @@ int verb_list_paths(int argc, char *argv[], void *userdata) {
         _cleanup_(message_set_freep) Set *replies = NULL;
         _cleanup_strv_free_ char **units = NULL;
         _cleanup_free_ UnitInfo *unit_infos = NULL;
-        _cleanup_(path_infos_done) struct path_infos path_infos = {};
-        int r, n;
+        PathInfo *paths = NULL;
+        size_t n_paths = 0;
         sd_bus *bus;
+        int r;
+
+        CLEANUP_ARRAY(paths, n_paths, path_info_array_free);
 
         r = acquire_bus(BUS_MANAGER, &bus);
         if (r < 0)
@@ -1124,49 +1157,21 @@ int verb_list_paths(int argc, char *argv[], void *userdata) {
                 return r;
 
         if (argc == 1 || units) {
+                int n;
+
                 n = get_unit_list_recursive(bus, units, &unit_infos, &replies);
                 if (n < 0)
                         return n;
 
                 for (const UnitInfo *u = unit_infos; u < unit_infos + n; u++) {
-                        _cleanup_strv_free_ char **conditions = NULL, **paths = NULL, **triggered = NULL;
-                        int c;
-
-                        if (!endswith(u->id, ".path"))
-                                continue;
-
-                        r = get_triggered_units(bus, u->unit_path, &triggered);
+                        r = path_info_add(bus, u, &paths, &n_paths);
                         if (r < 0)
                                 return r;
-
-                        c = get_paths(bus, u->unit_path, &conditions, &paths);
-                        if (c < 0)
-                                return c;
-
-                        if (!GREEDY_REALLOC(path_infos.items, path_infos.count + c))
-                                return log_oom();
-
-                        for (int i = c - 1; i >= 0; i--) {
-                                char **t;
-
-                                t = strv_copy(triggered);
-                                if (!t)
-                                        return log_oom();
-
-                                path_infos.items[path_infos.count++] = (struct path_info) {
-                                        .machine = u->machine,
-                                        .id = u->id,
-                                        .condition = TAKE_PTR(conditions[i]),
-                                        .path = TAKE_PTR(paths[i]),
-                                        .triggered = t,
-                                };
-                        }
                 }
-
-                typesafe_qsort(path_infos.items, path_infos.count, path_info_compare);
         }
 
-        output_paths_list(&path_infos);
+        typesafe_qsort(paths, n_paths, path_info_compare);
+        output_paths_list(paths, n_paths);
 
         return 0;
 }