Exhume exFAT as a library
This document provides guidance on how to use the exhume_exfat
crate as a library in your Rust projects. You will learn how to integrate the library, its basic usage, and a sample minimalist main code example. Exhume exFAT is also part of Exhume FileSystem.
Install
Create a project:
cargo new exfat_test
cd exfat_test/src
📦 Adding Exhume ExtFS as a Dependency
To use the exhume_exfat
library in your Rust project, you need to add it as a dependency in your Cargo.toml
file. Below is the sections you need to include:
[dependencies]
exhume_body = "=0.3.1"
exhume_exfat= ">=0.1.1"
# Required crates to log events
log = "0.4.25"
env_logger = "0.11.6"
🛠️ Basic Usage
Below is a sample code illustrating how to use exhume_exfat
as a library in the newly created Rust project.
use exhume_body::{Body, BodySlice};
use exhume_exfat::ExFatFS;
fn main() {
// Connect our log env
env_logger::Builder::new()
.filter_level(log::LevelFilter::Info)
.init();
// We create an exhume body object to fetch our image.
let mut body = Body::new("/path/to/evidence.E01".to_string(), "auto");
// These values (offset & size in sectors) are typically discovered with "exhume partitions"
let offset: u64 = 0x100000; // exFAT partition start (bytes)
let part_sectors: u64 = 0x9c00000; // exFAT partition size (in sectors)
let partition_size = part_sectors * body.get_sector_size() as u64;
// Create a slice over the exFAT partition
let mut slice = match BodySlice::new(&mut body, offset, partition_size) {
Ok(sl) => sl,
Err(e) => {
eprintln!("Could not create BodySlice: {}", e);
return;
}
};
// Open the filesystem
let mut fs = match ExFatFS::new(&mut slice) {
Ok(v) => v,
Err(e) => {
eprintln!("Couldn't open exFAT: {}", e);
return;
}
};
// ---- Examples of basic usage ----
// 1) Print BPB / super info (human friendly table)
println!("{}", fs.bpb.to_string());
// 2) List root directory entries with their fake inode numbers
match fs.list_root_with_inodes() {
Ok(list) => {
println!("\n# Root directory:");
for (inode, f) in list {
println!(
"inode=0x{:016x} {:>10} cluster {:>8} {}{}",
inode,
f.size,
f.first_cluster,
f.name,
if f.is_dir() { " /" } else { "" }
);
}
}
Err(e) => eprintln!("Root listing failed: {}", e),
}
// 3) Resolve a path to an inode and print its metadata
// (change the path below to something that exists on your image)
let sample_path = "Documents/Report.txt";
match fs.resolve_path_to_inode_num(sample_path) {
Ok((ino, inode)) => {
println!("\n# Resolved '{}':", sample_path);
println!("Fake inode: 0x{:016x}", ino);
println!("{}", inode.to_string());
// 4) If it's a regular file, read its content
if inode.is_regular_file() {
match fs.read_inode(&inode) {
Ok(bytes) => {
println!("Read {} bytes from '{}'", bytes.len(), sample_path);
// Do something with `bytes` (hash, carve, save, …)
}
Err(e) => eprintln!("read_inode failed: {}", e),
}
}
}
Err(e) => eprintln!("resolve_path_to_inode_num('{}') failed: {}", sample_path, e),
}
}