diff --git a/src/shared/blockdev-list.c b/src/shared/blockdev-list.c new file mode 100644 index 0000000000..2e6ed362f2 --- /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 0000000000..7fbf824ab2 --- /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 b7ae5959e8..ea1e009286 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',