From: Lennart Poettering Date: Thu, 28 Aug 2025 08:40:42 +0000 (+0200) Subject: blockdev-list: optionally return finds as list instead of writing it to stdout X-Git-Tag: v259-rc1~467^2~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9f6b2745eaa15be80568fde2a44d0a10ed6eb2a1;p=thirdparty%2Fsystemd.git blockdev-list: optionally return finds as list instead of writing it to stdout --- diff --git a/src/cryptenroll/cryptenroll.c b/src/cryptenroll/cryptenroll.c index 2f20af7e520..5a0d9722421 100644 --- a/src/cryptenroll/cryptenroll.c +++ b/src/cryptenroll/cryptenroll.c @@ -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; diff --git a/src/repart/repart.c b/src/repart/repart.c index 5e312ce0861..74c348d030e 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -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; diff --git a/src/shared/blockdev-list.c b/src/shared/blockdev-list.c index 0e7cd99fad2..d61b86c0c01 100644 --- a/src/shared/blockdev-list.c +++ b/src/shared/blockdev-list.c @@ -2,6 +2,7 @@ #include "sd-device.h" +#include "alloc-util.h" #include "ansi-color.h" #include "blockdev-list.h" #include "blockdev-util.h" @@ -9,10 +10,34 @@ #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; } diff --git a/src/shared/blockdev-list.h b/src/shared/blockdev-list.h index f569cf22e36..c77952993e8 100644 --- a/src/shared/blockdev-list.h +++ b/src/shared/blockdev-list.h @@ -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); diff --git a/src/storagetm/storagetm.c b/src/storagetm/storagetm.c index 0a4f8541e90..972b892ca17 100644 --- a/src/storagetm/storagetm.c +++ b/src/storagetm/storagetm.c @@ -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;