Skip to main content
Version: 3.0.0-rc.2

Read files from a FAT image

Use the FAT driver through hadris::fat when the image is known to contain a standalone FAT filesystem. Only the FAT format is enabled in this recipe.

[dependencies]
anyhow = "1"
[dependencies.hadris]
version = "3.0.0-rc.2"
default-features = false
features = ["std", "sync", "fat"]
use std::io::Read;

use anyhow::{Context, Result};
use hadris::fat::sync::FatFs;
use hadris::fs::sync::Volume;
use hadris::fs::{ErrorKind, MountOptions, OpenOptions};
use hadris::storage::host::FileDevice;

fn main() -> Result<()> {
let image = FileDevice::open("disk.img").context("open disk.img")?;
let fs = FatFs::mount(image, MountOptions::new().read_only())
.context("open FAT filesystem")?;
let vol = Volume::new(fs);

for entry in vol.read_dir("/").context("open root directory")? {
let entry = entry.context("read directory entry")?;
let name = entry.name().to_str().context("name is not UTF-8")?;
let meta = entry.metadata();
let kind = if meta.file_type().is_dir() { "dir " } else { "file" };
println!("{kind} {:>10} {name}", meta.len());
}

match vol.open("/README.TXT", OpenOptions::new().read()) {
Ok(mut file) => {
let mut contents = Vec::new();
file.read_to_end(&mut contents)?;
println!("{}", String::from_utf8_lossy(&contents));
}
Err(err) if err.kind() == ErrorKind::NotFound => {}
Err(err) => return Err(err.into()),
}

Ok(())
}

host::FileDevice defaults image files to 512-byte blocks and queries the logical block size of physical devices. Use open_with_block_size to specify an image's geometry. FatFs also opens any other hadris-storage device, such as a MemDevice over bytes already in memory. Lookups ignore case, and long names are always read. Files opened with vol.open(path, OpenOptions::new().read()) implement std::io::Read and Seek, and hadris::fs::sync::read_tree(&vol, "/") followed by hadris::fs::host::write_tree("out", &tree) copies the whole tree to the host. Short names are read in CP437 unless MountOptions::with_code_page names another code page.

Directory iteration surfaces malformed entries and I/O failures as errors; do not discard them with while let Some(Ok(...)) in production code.

Mount without read_only when the same image must be modified. For a partitioned disk, follow Open FAT inside a partition instead of opening the whole disk as a filesystem.