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.
This commit is contained in:
Lennart Poettering
2024-07-01 11:45:12 +02:00
parent bff5d2fd5a
commit 68ff31fa0a
3 changed files with 91 additions and 0 deletions

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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',