]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
blockdev-list: optionally return finds as list instead of writing it to stdout
authorLennart Poettering <lennart@poettering.net>
Thu, 28 Aug 2025 08:40:42 +0000 (10:40 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 23 Sep 2025 07:13:13 +0000 (09:13 +0200)
src/cryptenroll/cryptenroll.c
src/repart/repart.c
src/shared/blockdev-list.c
src/shared/blockdev-list.h
src/storagetm/storagetm.c

index 2f20af7e52035365024561a6db6c0d1c082525ee..5a0d9722421de1541a7383c392f4d219b94344e6 100644 (file)
@@ -630,7 +630,7 @@ static int parse_argv(int argc, char *argv[]) {
                 }
 
                 case ARG_LIST_DEVICES:
-                        r = blockdev_list(BLOCKDEV_LIST_SHOW_SYMLINKS|BLOCKDEV_LIST_REQUIRE_LUKS);
+                        r = blockdev_list(BLOCKDEV_LIST_SHOW_SYMLINKS|BLOCKDEV_LIST_REQUIRE_LUKS, /* ret_devices= */ NULL, /* ret_n_devices= */ NULL);
                         if (r < 0)
                                 return r;
 
index 5e312ce0861e296557f9d8d2396bd925239be388..74c348d030e7044057920a1aeb2d32f059fb2eaa 100644 (file)
@@ -9163,7 +9163,7 @@ static int parse_argv(
                         break;
 
                 case ARG_LIST_DEVICES:
-                        r = blockdev_list(BLOCKDEV_LIST_REQUIRE_PARTITION_SCANNING|BLOCKDEV_LIST_SHOW_SYMLINKS|BLOCKDEV_LIST_IGNORE_ZRAM);
+                        r = blockdev_list(BLOCKDEV_LIST_REQUIRE_PARTITION_SCANNING|BLOCKDEV_LIST_SHOW_SYMLINKS|BLOCKDEV_LIST_IGNORE_ZRAM, /* ret_devices= */ NULL, /* ret_n_devices= */ NULL);
                         if (r < 0)
                                 return r;
 
index 0e7cd99fad2e424d82ddade16ae404bae3f835b5..d61b86c0c0145ebba4ab426caeb06c538e815952 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "sd-device.h"
 
+#include "alloc-util.h"
 #include "ansi-color.h"
 #include "blockdev-list.h"
 #include "blockdev-util.h"
 #include "strv.h"
 #include "terminal-util.h"
 
-int blockdev_list(BlockDevListFlags flags) {
+void block_device_done(BlockDevice *d) {
+        assert(d);
+
+        d->node = mfree(d->node);
+        d->symlinks = strv_free(d->symlinks);
+ }
+
+void block_device_array_free(BlockDevice *d, size_t n_devices) {
+
+        FOREACH_ARRAY(i, d, n_devices)
+                block_device_done(d);
+
+        free(d);
+}
+
+int blockdev_list(BlockDevListFlags flags, BlockDevice **ret_devices, size_t *ret_n_devices) {
         _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
         int r;
 
+        assert(!!ret_devices == !!ret_n_devices);
+
+        /* If ret_devices/ret_n_devices are passed, returns a list of matching block devices, otherwise
+         * prints the list to stdout */
+
+        BlockDevice *l = NULL;
+        size_t n = 0;
+        CLEANUP_ARRAY(l, n, block_device_array_free);
+
         if (sd_device_enumerator_new(&e) < 0)
                 return log_oom();
 
@@ -57,21 +82,49 @@ int blockdev_list(BlockDevListFlags flags) {
                         }
                 }
 
-                printf("%s\n", node);
 
+                _cleanup_strv_free_ char **list = NULL;
                 if (FLAGS_SET(flags, BLOCKDEV_LIST_SHOW_SYMLINKS)) {
-                        _cleanup_strv_free_ char **list = NULL;
-
-                        FOREACH_DEVICE_DEVLINK(dev, l)
-                                if (strv_extend(&list, l) < 0)
+                        FOREACH_DEVICE_DEVLINK(dev, sl)
+                                if (strv_extend(&list, sl) < 0)
                                         return log_oom();
 
                         strv_sort(list);
+                }
+
+                if (ret_devices) {
+                        uint64_t diskseq = UINT64_MAX;
+
+                        r = sd_device_get_diskseq(dev, &diskseq);
+                        if (r < 0)
+                                log_debug_errno(r, "Failed to acquire diskseq of device '%s', ignoring: %m", node);
+
+                        if (!GREEDY_REALLOC(l, n+1))
+                                return log_oom();
 
-                        STRV_FOREACH(i, list)
-                                printf("%s%s%s%s\n", on_tty() ? "    " : "", ansi_grey(), *i, ansi_normal());
+                        _cleanup_free_ char *m = strdup(node);
+                        if (!m)
+                                return log_oom();
+
+                        l[n++] = (BlockDevice) {
+                                .node = TAKE_PTR(m),
+                                .symlinks = TAKE_PTR(list),
+                                .diskseq = diskseq,
+                        };
+
+                } else {
+                        printf("%s\n", node);
+
+                        if (FLAGS_SET(flags, BLOCKDEV_LIST_SHOW_SYMLINKS))
+                                STRV_FOREACH(i, list)
+                                        printf("%s%s%s%s\n", on_tty() ? "    " : "", ansi_grey(), *i, ansi_normal());
                 }
         }
 
+        if (ret_devices)
+                *ret_devices = TAKE_PTR(l);
+        if (ret_n_devices)
+                *ret_n_devices = n;
+
         return 0;
 }
index f569cf22e36de73961e28a12aaddd371af9a9f2c..c77952993e84e838a220be7f23a0d1b055bba6e7 100644 (file)
@@ -10,4 +10,18 @@ typedef enum BlockDevListFlags {
         BLOCKDEV_LIST_REQUIRE_LUKS               = 1 << 3,
 } BlockDevListFlags;
 
-int blockdev_list(BlockDevListFlags flags);
+typedef struct BlockDevice {
+        char *node;
+        char **symlinks;
+        uint64_t diskseq;
+} BlockDevice;
+
+#define BLOCK_DEVICE_NULL (BlockDevice) { \
+                .diskseq = UINT64_MAX,    \
+                .size = UINT64_MAX,       \
+        }
+
+void block_device_done(BlockDevice *d);
+void block_device_array_free(BlockDevice *d, size_t n_devices);
+
+int blockdev_list(BlockDevListFlags flags, BlockDevice **ret_devices, size_t *ret_n_devices);
index 0a4f8541e90f3a30360c3efd009e4390419d8e17..972b892ca1764b9f05e8c449041357f5e31083b1 100644 (file)
@@ -115,7 +115,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_LIST_DEVICES:
-                        r = blockdev_list(BLOCKDEV_LIST_SHOW_SYMLINKS|BLOCKDEV_LIST_IGNORE_ZRAM);
+                        r = blockdev_list(BLOCKDEV_LIST_SHOW_SYMLINKS|BLOCKDEV_LIST_IGNORE_ZRAM, /* ret_devices= */ NULL, /* ret_n_devices= */ NULL);
                         if (r < 0)
                                 return r;