Crate rsblkid

Source
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
§Search and iterate over devices in the cache

§Low-Level functions

§Library initialization
§Low-level probing
libblkidrsblkid
blkid_free_probeProbe is automatically deallocated when it goes out of scope.
blkid_new_probeProbe::builder
blkid_new_probe_from_filenameProbeBuilder::scan_device
blkid_probe_get_devnoProbe::device_number
blkid_probe_get_fdProbe::device_file
blkid_probe_get_offsetProbe::scanned_device_segment_location
blkid_probe_get_sectorsProbe::device_size_in_sectors
blkid_probe_get_sectorsizeProbe::device_logical_sector_size
blkid_probe_get_sizeProbe::scanned_device_segment_size
blkid_probe_get_wholedisk_devnoProbe::device_whole_disk_number
blkid_probe_hide_rangeProbe::device_skip_bytes
blkid_probe_is_wholediskProbe::is_device_whole_disk
Probe::is_device_partition
blkid_probe_reset_buffersProbe::empty_buffers
blkid_probe_reset_hintsProbe::discard_hints
blkid_probe_set_deviceNot implemented.
blkid_probe_set_hintProbe::set_hint
blkid_probe_set_sectorsizeProbeBuilder::bytes_per_sector
blkid_probe_step_backProbe::backtrack
blkid_reset_probeProbe::reset
§Low-level tags
§Superblocks probing
libblkidrsblkid
blkid_probe_enable_superblocksProbeBuilder::scan_device_superblocks
blkid_known_fstypeNot implemented. FileSystem lists all supported file systems.
blkid_superblocks_get_nameProbe::iter_supported_file_systems
blkid_probe_filter_superblocks_typeProbeBuilder::scan_superblocks_for_file_systems
Probe::scan_superblocks_for_file_systems
blkid_probe_filter_superblocks_usageProbeBuilder::scan_superblocks_with_usage_flags
Probe::scan_superblocks_with_usage_flags
blkid_probe_invert_superblocks_filterProbe::invert_superblocks_scanning_filter
blkid_probe_reset_superblocks_filterProbe::reset_superblocks_scanning_filter
blkid_probe_set_superblocks_flagsProbe::collect_fs_properties
blkid_probe_reset_filterDeprecated.
blkid_probe_filter_typesDeprecated.
blkid_probe_filter_usageDeprecated.
blkid_probe_invert_filterDeprecated.
blkid_probe_set_requestDeprecated.
§Partitions probing
libblkidrsblkid
blkid_probe_enable_partitionsProbeBuilder::scan_device_partitions
blkid_probe_set_partitions_flagsProbeBuilder::partitions_scanning_options
Probe::set_partitions_scanning_options
blkid_probe_filter_partitions_typeProbeBuilder::scan_partitions_for_partition_tables
Probe::scan_partitions_for_partition_tables
blkid_probe_invert_partitions_filterProbe::invert_partitions_scanning_filter
blkid_probe_reset_partitions_filterProbe::reset_partitions_scanning_filter
blkid_known_pttypeNot implemented. PartitionTableType lists all supported partition table types.
blkid_partitions_get_nameProbe::iter_supported_partition_tables
blkid_partition_get_namePartition::name
blkid_partition_get_flagsPartition::flags
blkid_partition_get_partnoPartition::number
blkid_partition_get_sizePartition::size_in_sectors
blkid_partition_get_startPartition::location_in_sectors
blkid_partition_get_tablePartition::partition_table
blkid_partition_get_typePartition::partition_type
blkid_partition_get_type_stringPartition::partition_type_string
blkid_partition_get_uuidPartition::uuid
blkid_partition_is_extendedPartition::is_extended
blkid_partition_is_logicalPartition::is_logical
blkid_partition_is_primaryPartition::is_primary
blkid_partlist_get_partitionPartitionIter::nth
blkid_partlist_get_partition_by_partnoPartitionIter::nth_by_partition_number
blkid_partlist_numof_partitionsPartitionIter::count
blkid_partlist_devno_to_partitionPartitionIter::partition_from_device_number
blkid_partlist_get_tablePartitionIter::partition_table
blkid_parttable_get_idPartitionTable::id
blkid_parttable_get_offsetPartitionTable::location_in_bytes
blkid_parttable_get_parentPartitionTable::parent
blkid_parttable_get_typePartitionTable::partition_table_type
blkid_probe_get_partitionsProbe::iter_partitions
§Topology information

§Common Utils

§Encoding utils
§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§

RsBlkidError
Library-level runtime errors.

Type Aliases§

Result
A specialized Result type for rsblkid.