Skip to main content

Exhume Filesystem as a library

Embed exhume_filesystem to detect, walk, and read supported filesystems through one normalized, read-only Rust interface.

Install​

cargo add exhume_filesystem
cargo add exhume_body

Detect and walk an image filesystem​

use exhume_body::Body;
use exhume_filesystem::detected_fs::detect_filesystem;
use exhume_filesystem::filesystem::WalkEvent;
use exhume_filesystem::Filesystem;

fn list_partition() -> Result<(), Box<dyn std::error::Error>> {
let body = Body::new("/evidence/disk.raw".to_string(), "raw");
let offset_bytes = 0x10_0000;
let size_sectors = 0x40_0000;
let size_bytes = size_sectors * body.get_sector_size() as u64;

let mut fs = detect_filesystem(&body, offset_bytes, size_bytes, None)?;
println!("detected {}", fs.filesystem_type());

fs.walk_fs(&mut |event| {
if let WalkEvent::File(file) = event {
println!("{}\t{}\t{}", file.identifier, file.size, file.absolute_path);
}
})?;

Ok(())
}

Unlike the CLI, detect_filesystem receives the partition length in bytes. The example therefore multiplies the sector count by the body's sector size.

Read a file without extracting it first​

FsFileReadSeek adapts a filesystem record to std::io::Read + Seek. It reads bounded slices through the backing filesystem and keeps a small read-ahead cache, making it suitable for parsers that expect a seekable stream.

use exhume_filesystem::detected_fs::detect_filesystem_from_path;
use exhume_filesystem::filesystem::FsFileReadSeek;
use exhume_filesystem::Filesystem;
use std::io::{Read, Seek, SeekFrom};

fn read_header() -> Result<(), Box<dyn std::error::Error>> {
let mut fs = detect_filesystem_from_path("/evidence/mobile-extraction")?;
let root_id = fs.get_root_file_id();
let file = fs.get_file_by_path("/private/var/mobile/example.db", root_id)?;
let mut reader = FsFileReadSeek::new(&mut fs, file);

let mut sqlite_header = [0_u8; 16];
reader.read_exact(&mut sqlite_header)?;
reader.seek(SeekFrom::Start(0))?;

assert_eq!(&sqlite_header, b"SQLite format 3\0");
Ok(())
}

The normalized record​

Walking a filesystem produces filesystem::File values with stable fields for downstream indexing:

  • native identifier, normalized absolute_path, name, type, and size;
  • created, modified, and accessed timestamps normalized to Unix seconds;
  • permissions, owner, and group where the filesystem records them;
  • optional signature fields populated later by exhume_indexer;
  • a metadata JSON value that retains filesystem-specific detail.

Use the normalized fields for cross-filesystem queries and preserve metadata when provenance or filesystem-specific interpretation matters.

License​

GPL-2.0-or-later.