Hadris ISO
A pure Rust ISO 9660 filesystem and ISO image library with allocation-free
reading plus full-featured read/write support for Joliet, Rock Ridge (RRIP),
SUSP, El Torito, and ISO 9660:1999. Hadris ISO is designed for desktop
applications and no_std bootloaders, operating-system kernels, firmware, and
embedded systems working with CD-ROM, DVD, and bootable optical-disc images.
Features
- Read & Write Support - Full-featured ISO creation and extraction; file contents can be streamed from a reader while the image is written, so large inputs never have to be held in memory
- Zero-allocation Reader - Navigate ISO 9660 and Joliet trees and stream multi-extent files entirely through caller-owned buffers
- No-std Compatible - Use the sync or async reader in bootloaders, firmware, and custom kernels without a global allocator
- El-Torito Boot - Create bootable CD/DVD images for BIOS systems
- Joliet Extension - UTF-16 Unicode filenames (up to 64 characters)
- Rock Ridge (RRIP) Extension - POSIX filesystem semantics (long names, permissions, symlinks)
- SUSP (System Use Sharing Protocol) - Standardized extension framework
- ISO 9660:1999 - Long filenames up to 207 characters with proper Level 2/3 compliance
Quick Start
Reading an ISO
use File;
use BufReader;
use IsoImage;
let file = open?;
let reader = new;
let image = open?;
// Iterate through root directory
let root = image.root_dir;
for entry in root.iter.entries
Creating a Bootable ISO
use Cursor;
use Arc;
use ;
use EmulationType;
use PathSeparator;
use ;
use ;
// Prepare files
let files = InputFiles ;
// Configure boot options
let boot_options = BootOptions ;
// Create ISO
let format_options = IsoFormatOptions ;
let mut buffer = new;
create?;
With the unstable-streaming feature, a file can be added without loading it
into memory: give the input tree an InputEntryKind::Source instead of a
File. A FileSource carries the length and a way to open a reader; the writer
opens it once, when the file's extents are written, and streams the contents in
fixed-size chunks. The feature is outside the V2 stability promise, and enabling
it adds the Source variant to InputEntryKind, so exhaustive matches on that
enum must account for it.
use Arc;
use ;
let entry = InputEntry ;
Feature Flags
| Feature | Description | Dependencies |
|---|---|---|
read |
Allocation-free ISO 9660/Joliet navigation and streamed file reads | No heap allocator |
alloc |
Owned collections, names, RRIP enrichment, and convenience reads | read, alloc crate |
std |
Full standard library support | std, alloc |
sync |
Synchronous API under hadris_iso::sync |
— |
async |
Asynchronous read API under hadris_iso::r#async |
— |
write |
Synchronous ISO creation/formatting | std, alloc |
joliet |
Allocating Joliet encode/write helpers; allocation-free Joliet reading is part of read |
alloc |
unstable-streaming |
Unstable: stream file contents from a reader while writing (InputEntryKind::Source) |
write |
std selects platform integration but does not select an I/O mode. The default
configuration enables sync; custom configurations should select sync,
async, or both explicitly. Write and modification APIs are currently available
only under sync.
For Bootloaders (minimal footprint)
[]
= { = "2.5.0", = false, = ["read", "sync"] }
The read feature exposes IsoReader, which opens and navigates ISO 9660 and
Joliet trees without heap allocation. It performs nested path lookup, groups
multi-extent files, and streams file contents into caller-owned buffers in
both synchronous and asynchronous configurations:
use IsoReader;
let mut image = open?;
if let Some = image.find_path?
# Ok::
The reader prefers the highest recognized Joliet namespace. Use
primary_root() with find_path_in() when raw ISO 9660 naming is required.
Rock Ridge enrichment remains part of the allocation-backed IsoImage API;
the allocation-free reader exposes raw system-use bytes for custom handling.
For Kernels with Heap (no-std + alloc)
[]
= { = "2.5.0", = false, = ["read", "alloc", "sync"] }
For Desktop Applications (full features)
[]
= "2.5.0" # Uses default features
Extension Support
| Extension | Read | Write | Notes |
|---|---|---|---|
| ISO 9660 Level 1-3 | Yes | Yes | Allocation-free navigation and multi-extent streaming available |
| ISO 9660:1999 | Yes | Yes | Long filenames up to 207 chars (Level 2/3 compliance) |
| SUSP | Yes | Yes | System Use Sharing Protocol for extension framework |
| Joliet | Yes | Yes | Allocation-free UTF-16BE lookup/decoding; owned helpers with alloc |
| Rock Ridge (RRIP) | Yes | Yes | Allocation-backed metadata enrichment; raw system-use bytes remain available without alloc |
| El-Torito | Yes | Yes | BIOS bootable images |
| Hybrid Boot (MBR/GPT) | - | Yes | USB bootable images (MBR, GPT, or dual) |
Comparison with Other Tools
| Feature | hadris-iso | cdfs | iso9660-rs | xorriso |
|---|---|---|---|---|
| Read | Yes | Yes | Yes | Yes |
| Write | Yes | No | No | Yes |
| No-std | Yes | No | No | No |
| El-Torito | Yes | No | No | Yes |
| Rock Ridge | Yes | Yes | Partial | Yes |
| Joliet | Yes | Yes | Yes | Yes |
| Language | Rust | Rust | Rust | C |
Examples
Run the examples with:
# Read an ISO and display its contents
# Extract files from an ISO
# Create a bootable ISO
Compatibility
The conformance harness checks Hadris images with an independent ECMA-119 oracle and measures widely available ISO readers. Current bounded results are:
| Consumer of Hadris images | Result |
|---|---|
| ECMA-119 raw-image oracle | 2/2 |
| xorriso/libisofs 1.5.8 | 2/2 |
| Linux kernel ISO driver | 2/2 |
| macOS 26.6.2 built-in ISO reader | 2/2 |
Windows Mount-DiskImage |
Available manual target; not yet measured |
The compliance profile contains the producer matrix, methodology, and known peer deviations.
Specification References
- ECMA-119 (ISO 9660)
- IEEE P1281 (System Use Sharing Protocol / SUSP)
- IEEE P1282 (Rock Ridge Interchange Protocol / RRIP)
- Joliet Specification (Microsoft)
- El-Torito Bootable CD-ROM Format Specification
Documentation
License
This project is licensed under the MIT license.
Rock Ridge relocation
Deep or overlong directory paths use a Rock Ridge relocation container compatible
with libarchive/bsdtar. The writer prefers an unoccupied rr_moved or .rr_moved
root name, but only when that name would be the first recognized directory in ISO
File Identifier order. If a user directory already occupies the name libarchive
will select, that directory is reused as the container: relocated entries are
marked RE and the original user tree stays in place. Creation fails only when
relocation is needed and both recognized names are occupied by non-directory
entries. Shallow trees that do not need relocation may use either name freely.