Library
You can use the exhume_apfs crate in your own Rust projects to programmatically parse APFS containers and volumes.
Installation​
Add exhume_apfs and exhume_body to your Cargo.toml:
[dependencies]
exhume_apfs = "0.1.0"
exhume_body = "0.5.0"
Basic Usage​
The following example shows how to open an APFS container from an image file, select a volume, and list the entries of the root directory (inode 2).
use exhume_apfs::APFS;
use exhume_body::{Body, BodySlice};
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
let image_path = "path/to/your/image.aff4";
// 1. Create a Body handle for the image (specifying format if needed)
let body = Body::new(image_path.to_string(), "aff4");
// 2. Wrap the body in a BodySlice (offset and size of the APFS container)
// Here we assume the container starts at offset 0.
let slice = BodySlice::new(&body, 0, 43_004_505_374)?;
// 3. Initialize the APFS container
let mut apfs = APFS::new(slice).map_err(|e| e)?;
// 4. Select a volume and open its filesystem tree
if let Some(vol) = apfs.volumes.first().cloned() {
println!("Opening volume: {}", vol.volume_name);
let fstree = apfs.open_fstree_for_volume(&vol).map_err(|e| e)?;
// 5. List directory entries for a specific inode (2 is usually root)
println!("Listing directory entries for inode 2:");
let children = fstree.dir_children(&mut apfs, 2).map_err(|e| e)?;
for entry in children {
let inode_str = entry.inode_id.map(|id| id.to_string()).unwrap_or_else(|| "-".to_string());
println!("{:>10} | {}", inode_str, entry.name);
}
}
Ok(())
}