Expand description
§Description
The rsblkid
library is a safe Rust wrapper around util-linux/libblkid
.
The libblkid
library helps identify disks (block devices), the file systems they use to
store content, as well as extracting additional information such as:
- File system labels,
- Volume names,
- Unique identifiers,
- Serial numbers,
- etc.
rsblkid
presents the data it gathers as key/value pairs (tags), where the keys can be for
example a device’s LABEL
, UUID
, file system TYPE
, etc. (see
FsProperty
for the list of keys supported by rsblkid
).
§API structure
rsblkid
’s API is roughly divided into two parts, a high-level API that keeps information
about block devices in a cache file, and a low-level API that offers more fine grained methods
to extract data about file systems, device partitions, and disk topology.
Provided it has permission to read raw block devices, the high-level part of the library
checks that device information is always up-to-date before returning it to the user. The cache
file allows unprivileged users, i.e. anyone other than root
or a member of the disk
user
group, to locate devices by label or id.
use std::path::PathBuf;
use rsblkid::device::Tag;
use rsblkid::cache::Cache;
fn main() -> rsblkid::Result<()> {
let mut cache = Cache::builder()
.discard_changes_on_drop()
.build()?;
cache.probe_all_devices()?;
// Find the absolute path to the device with the UUID.
let uuid: Tag = r#"UUID="ac4f36bf-191b-4fb0-b808-6d7fc9fc88be""#.parse()?;
let actual = cache.find_canonical_device_name_from_tag(&uuid);
let device_name = PathBuf::from("/dev/vda");
let expected = Some(device_name);
assert_eq!(actual, expected);
Ok(())
}
To determine the values of the LABEL
or UUID
tags of a block device, the high-level API supports two methods:
- extracting data directly by scanning a block device,
- or reading information from udev’s
/dev/disk/by-*
symlinks (method used by default).
The low-level API, on the other hand, always scans a block device directly. It offers more fine-grained control over the data collected.
use rsblkid::probe::{Probe, ScanResult};
fn main() -> rsblkid::Result<()> {
let mut probe = Probe::builder()
.scan_device("/dev/vda")
// Superblocks scanning is active by default, setting this option to `true` here
// is redundant.
.scan_device_superblocks(true)
// Activate partition search functions.
.scan_device_partitions(true)
// Search for partition entries ONLY in DOS or GPT partition tables
.scan_partitions_for_partition_tables(Filter::In,
vec![
PartitionTableType::DOS,
PartitionTableType::GPT,
])
// Activate topology search functions.
.scan_device_topology(true)
.build()?;
match probe.find_device_properties() {
ScanResult::FoundProperties => {
// Print collected file system properties
for property in probe.iter_device_properties() {
println!("{property}")
}
println!();
// Print metadata about partition table entries
// Header
println!("Partition table");
println!("{} {:>10} {:>10} {:>10}\n----", "number", "start", "size", "part_type");
for partition in probe.iter_partitions() {
let number = partition.number();
let start = partition.location_in_sectors();
let size = partition.size_in_sectors();
let part_type = partition.partition_type();
// Row
println!("#{}: {:>10} {:>10} 0x{:x}", number, start, size, part_type)
}
println!();
// Print metadata about device topology
let topology = probe.topology()?;
let alignment_offset = topology.alignment_offset_in_bytes();
let dax_support = if topology.supports_dax() { "yes" } else { "no" };
let minimum_io_size = topology.minimum_io_size();
let optimal_io_size = topology.optimal_io_size();
let logical_block_size = topology.logical_block_size();
let physical_block_size = topology.physical_block_size();
println!("Alignment offset (bytes): {}", alignment_offset);
println!("Direct Access support (DAX): {}", dax_support);
println!("Minimum I/O size (bytes): {}", minimum_io_size);
println!("Optimal I/O size (bytes): {}", optimal_io_size);
println!("Logical block size (bytes): {}", logical_block_size);
println!("Physical block size (bytes): {}", physical_block_size);
}
_ => eprintln!("could not find device properties"),
}
// Example output
//
// LABEL="nixos"
// UUID="ac4f36bf-191b-4fb0-b808-6d7fc9fc88be"
// BLOCK_SIZE="1024"
// TYPE="ext4"
//
// Partition table
// number start size part_type
// ----
// #1: 34 2014 0x0
// #2: 2048 2048 0x0
// #3: 4096 2048 0x0
// #4: 6144 2048 0x0
// #5: 8192 2048 0x0
//
// Alignment offset (bytes): 0
// Direct Access support (DAX): no
// Minimum I/O size (bytes): 512
// Optimal I/O size (bytes): 0
// Logical block size (bytes): 512
// Physical block size (bytes): 512
Ok(())
}
§From libblkid
to rsblkid
This section maps libblkid
functions to rsblkid
methods. It follows the same layout as
libblkid
’s documentation. You can use it as a reference to ease the transition from one API
to the other.
§High-Level functions
§Tag and spec evaluation
§Cache
basic routines
libblkid | rsblkid |
---|---|
blkid_gc_cache | Cache::garbage_collect |
blkid_get_cache | Cache::builder |
blkid_put_cache | Cache is automatically deallocated when it goes out of scope. |
blkid_probe_all | Cache::probe_all_devices |
blkid_probe_all_removable | Cache::probe_all_removable_devices |
blkid_probe_all_new | Cache::probe_all_new_devices |
blkid_verify | Cache::refresh_device_data |
§Search and iterate over devices in the cache
libblkid | rsblkid |
---|---|
blkid_dev_devname | Device::name |
blkid_dev_has_tag | Device::has_tag Device::has_tag_named |
blkid_dev_iterate_begin | Cache::iter Cache::try_iter |
blkid_dev_iterate_end | EntryIter is automatically deallocated when it goes out of scope. |
blkid_dev_next | EntryIter::next |
blkid_dev_set_search | Not implemented yet. |
blkid_find_dev_with_tag | Cache::find_device_with_tag |
blkid_get_dev | Cache::add_new_entry Cache::find_device_by_name Cache::lookup_device_by_name Cache::lookup_refreshed_device_by_name |
blkid_get_devname | Not implemented. Use Cache::find_device_with_tag instead. |
blkid_get_tag_value | Cache::tag_value_from_device |
blkid_tag_iterate_begin | Device::iter |
blkid_tag_iterate_end | TagIter is automatically deallocated when it goes out of scope. |
blkid_tag_next | TagIter::next |
§Low-Level functions
§Library initialization
libblkid | rsblkid |
---|---|
blkid_init_debug | init_default_debug init_full_debug |
§Low-level probing
§Low-level tags
§Superblocks probing
§Partitions probing
§Topology information
§Common Utils
§Encoding utils
libblkid | rsblkid |
---|---|
blkid_encode_string | core::utils::encode::encode_string |
blkid_safe_string | core::utils::encode::to_safe_string |
§Miscellaneous utils
Modules§
- cache
- High-level API to handle device identification and tag extraction.
- debug
- Activate debug message output.
- device
- Device objects and helper functions.
- errors
- Runtime errors.
- num
- Arithmetic objects and helper functions.
- partition
- Module for handling disk partitions.
- probe
- Low-level API to probe block devices.
- utils
- Utility objects and helper functions.
Enums§
- RsBlkid
Error - Library-level runtime errors.