From 68ff31fa0aa23060c60a51cebbe593e1e4c769ff Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 1 Jul 2024 11:45:12 +0200 Subject: [PATCH] util: add generic block device listener helper Various of our tools operate on block devices, and it's not always obvious to know which block devices are actually appropriate for use. Hence, let's add a helper that allows to list block devices, and supports some limited filtering. --- src/shared/blockdev-list.c | 79 ++++++++++++++++++++++++++++++++++++++ src/shared/blockdev-list.h | 11 ++++++ src/shared/meson.build | 1 + 3 files changed, 91 insertions(+) create mode 100644 src/shared/blockdev-list.c create mode 100644 src/shared/blockdev-list.h diff --git a/src/shared/blockdev-list.c b/src/shared/blockdev-list.c new file mode 100644 index 00000000000..2e6ed362f28 --- /dev/null +++ b/src/shared/blockdev-list.c @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "sd-device.h" + +#include "blockdev-list.h" +#include "blockdev-util.h" +#include "device-util.h" +#include "macro.h" +#include "terminal-util.h" + +int blockdev_list(BlockDevListFlags flags) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + int r; + + if (sd_device_enumerator_new(&e) < 0) + return log_oom(); + + r = sd_device_enumerator_add_match_subsystem(e, "block", /* match = */ true); + if (r < 0) + return log_error_errno(r, "Failed to add subsystem match: %m"); + + if (FLAGS_SET(flags, BLOCKDEV_LIST_REQUIRE_LUKS)) { + r = sd_device_enumerator_add_match_property(e, "ID_FS_TYPE", "crypto_LUKS"); + if (r < 0) + return log_error_errno(r, "Failed to add match for LUKS block devices: %m"); + } + + FOREACH_DEVICE(e, dev) { + const char *node; + + r = sd_device_get_devname(dev, &node); + if (r < 0) { + log_warning_errno(r, "Failed to get device node of discovered block device, ignoring: %m"); + continue; + } + + if (FLAGS_SET(flags, BLOCKDEV_LIST_IGNORE_ZRAM)) { + const char *dn; + + r = sd_device_get_sysname(dev, &dn); + if (r < 0) { + log_warning_errno(r, "Failed to get device name of discovered block device '%s', ignoring: %m", node); + continue; + } + + if (startswith(dn, "zram")) + continue; + } + + if (FLAGS_SET(flags, BLOCKDEV_LIST_REQUIRE_PARTITION_SCANNING)) { + r = blockdev_partscan_enabled(dev); + if (r < 0) { + log_warning_errno(r, "Unable to determine whether '%s' supports partition scanning, skipping device: %m", node); + continue; + } + if (r == 0) { + log_debug("Device '%s' does not support partition scanning, skipping.", node); + continue; + } + } + + printf("%s\n", node); + + 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) + return log_oom(); + + strv_sort(list); + + STRV_FOREACH(i, list) + printf("%s%s%s%s\n", on_tty() ? " " : "", ansi_grey(), *i, ansi_normal()); + } + } + + return 0; +} diff --git a/src/shared/blockdev-list.h b/src/shared/blockdev-list.h new file mode 100644 index 00000000000..7fbf824ab2c --- /dev/null +++ b/src/shared/blockdev-list.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +typedef enum BlockDevListFlags { + BLOCKDEV_LIST_SHOW_SYMLINKS = 1 << 0, + BLOCKDEV_LIST_REQUIRE_PARTITION_SCANNING = 1 << 1, + BLOCKDEV_LIST_IGNORE_ZRAM = 1 << 2, + BLOCKDEV_LIST_REQUIRE_LUKS = 1 << 3, +} BlockDevListFlags; + +int blockdev_list(BlockDevListFlags flags); diff --git a/src/shared/meson.build b/src/shared/meson.build index b7ae5959e83..ea1e0092869 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -12,6 +12,7 @@ shared_sources = files( 'battery-util.c', 'binfmt-util.c', 'bitmap.c', + 'blockdev-list.c', 'blockdev-util.c', 'bond-util.c', 'boot-entry.c', -- 2.47.3