Skip to main content
Version: 3.0.0-rc.2

Detect and open unknown images

Use the hadris umbrella crate when the input format is not known in advance. Detection is non-destructive: it only reads identifying metadata and never writes. Opening performs the format's full validation.

[dependencies.hadris]
version = "3.0.0-rc.2"
default-features = false
features = ["std", "sync", "detect"]

The default features include detect, which adds fat, iso, udf and cpio, so what detection recognizes never depends on the features enabled.

Detect​

use hadris::ImageFormat;
use hadris::host::FileDevice;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut image = FileDevice::open("disk.img")?;
let found = hadris::sync::detect(&mut image)?;
for candidate in found.iter() {
match candidate.damage() {
Some(err) => println!("{:?}, damaged: {err}", candidate.format()),
None => println!("{:?}", candidate.format()),
}
}
if matches!(found.first().map(|c| c.format()), Some(ImageFormat::Mbr | ImageFormat::Gpt)) {
println!("partitioned disk: open one partition with hadris::part::sync::open");
}
Ok(())
}

detect takes any hadris-storage block device and returns a Detection listing every format found, most specific first, without allocating. A bridge image lists IsoUdfBridge, then Iso, then Udf; a hybrid ISO lists Iso, then Gpt or Mbr. Each Candidate has its ImageFormat and, when its signature is present but the structures a mount reads first are damaged, the Corrupt error that mount would give, so a damaged volume never reads as another format. An empty Detection means nothing was recognized. The device's block size is the logical block size used to find a GPT header.

Open​

use hadris::fs::sync::Volume;
use hadris::sync::AnyFs;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let fs = hadris::host::open("disc.img")?;
if let AnyFs::Udf(udf) = &fs {
println!("UDF revision {:?}", udf.info().revision());
}
let vol = Volume::new(fs);
for entry in vol.read_dir("/")? {
println!("{:?}", entry?.name());
}
Ok(())
}

hadris::host::open(path) detects the image and mounts it read-only with the host's clock and time zone; hadris::host::open_with(path, options) takes the MountOptions and opens the file for writing unless they are read-only. On any other device, hadris::sync::open(dev, options) (or hadris::r#async::open) mounts the first filesystem detect finds with the caller's MountOptions, and returns an AnyFs: Fat, ExFat, Iso or Udf. AnyFs implements the FileSystem trait, so Volume and its handles work on it, and a match reaches each driver's extras. A bridge image opens as UDF; if its UDF side does not mount, it opens as ISO 9660. Open hadris::iso::sync::IsoFs directly to choose an ISO namespace.

A failed open returns the device in a MountError. NTFS volumes, partition tables and archives fail with ErrorKind::NotRecognized (the messages are "ntfs", "partition table" and "archive"), and so does a device with no known format. For a partitioned disk, select a partition with hadris::part::sync::open and open the Partition it returns.

The volume-list example is a complete program: it detects the format, opens it, and prints the tree with one function generic over the FileSystem trait.

Detection is not validation​

Detection answers "what does this look like?" using signatures and the first structures of each format. Always open the image before trusting offsets, sizes, or directory data. Treat an empty Detection as an unknown format rather than as proof that the input is unformatted.