Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
opticaldiscs
Format-agnostic optical disc image reading and filesystem browsing for Rust.
Provides a unified SectorReader abstraction that handles the cooked/raw sector
translation across container formats — ISO, BIN/CUE, CHD, CloneCD,
Nero (NRG), Alcohol 120% (MDS/MDF), DiscJuggler (CDI), DAEMON Tools
(MDX), PSP CSO, gzip, and Nintendo (GameCube/Wii) — with filesystem
browsers for ISO 9660, UDF, HFS/HFS+, SGI EFS, and
many more on top.
Status: Published on crates.io. Disc reading, detection, and filesystem browsing are complete and in production use; physical-disc ripping is the next milestone. See PLAN.md for the roadmap.
CHD support
opticaldiscs-rs reads CHD optical images via libchdman-rs,
which wraps MAME's official chd_file core. This provides byte-for-byte
parity with the chdman tool — including subcode handling, audio
byte-swapping, and per-track frame semantics — at the cost of needing
to link MAME's C++ code.
libchdman-rs 0.288.10 is a hard floor (since opticaldiscs 0.14.0). Earlier
versions abort the process when handed a CHD without CD track metadata — a
hard-disk, DVD, or A/V image — and since .chd detection keys on magic bytes
common to every CHD, that was reachable from DiscImageInfo::open.
CHD is a container, not a disc format
The same MComprHD magic fronts CD, GD-ROM, DVD, hard-disk and A/V images, so
identifying a file as a CHD says nothing about how to read it. chd::chd_media()
classifies it from the info record (cheap — no track parsing), and the media kind
picks the reader:
ChdMedia |
Reader | Notes |
|---|---|---|
Cd, GdRom |
ChdSectorReader |
open_chd() for track metadata first; GD-ROM HD area spans several tracks |
Dvd |
DvdChdSectorReader |
One flat run of 2048-byte sectors — no tracks, no cooking |
HardDisk, Av |
— | Not optical media; reported as UnsupportedFormat |
DiscImageInfo::open and browse::open_disc_filesystem do this dispatch
internally, so callers just pass a .chd path and get the right reader.
This lives behind the chd feature, on by default. Because linking MAME's
C++ core isn't possible everywhere, it can be dropped entirely with
default-features = false — libchdman-rs then leaves the dependency graph, and
every other container and filesystem keeps working. .chd files stay
recognised either way; see Feature Flags for the runtime
is_supported() queries.
By default, opticaldiscs-rs enables libchdman-rs's prebuilt feature,
which downloads a pre-built static archive matching the build target
from libchdman-rs's GitHub Releases instead of compiling MAME from
source. This keeps CI build times in seconds, not minutes.
When you might need to override prebuilt behavior
| Situation | Set env var |
|---|---|
| Target triple isn't covered by libchdman-rs's prebuilt matrix | LIBCHDMAN_PREBUILT_FALLBACK=1 |
| Local development without network access | LIBCHDMAN_FORCE_SOURCE=1 |
| Linux: pick a specific glibc floor for the prebuilt archive | LIBCHDMAN_GLIBC=2.31 (or 2.35, 2.39) |
See libchdman-rs's README for the full list of supported targets, glibc floors, and escape hatches.
Features
| Capability | Status |
|---|---|
| ISO sector reader | ✓ |
| BIN/CUE sector reader (raw 2352-byte) | ✓ |
| CHD sector reader — CD / GD-ROM (via libchdman-rs) | ✓ (chd feature, on by default — optional since 0.14.0) |
| CHD sector reader — DVD (flat 2048-byte sectors, no tracks) | ✓ (since 0.14.0) |
PSP .cso (CISOv1) + gzip-compressed (.gz) image readers |
✓ (since 0.9.0) |
CloneCD (.ccd / .img / .sub) container |
✓ (since 0.9.0) |
Nero (.nrg) container |
✓ (since 0.9.0) |
Alcohol 120% (.mds / .mdf) container |
✓ (since 0.9.0) |
DiscJuggler (.cdi) container — incl. Dreamcast GD-ROM absolute-LBA rebasing |
✓ (since 0.9.0) |
DAEMON Tools (.mdx) container — encrypted + zlib-compressed descriptor |
✓ (mdx feature, since 0.9.0) |
| Disc format + filesystem auto-detection | ✓ |
| ISO 9660 filesystem browser | ✓ |
| ISO 9660 PVD date/time metadata (creation/modification/expiration/effective) | ✓ (since 0.4.4) |
| Joliet (Unicode long names) | ✓ (since 0.6.0) |
| Rock Ridge / SUSP (POSIX metadata, long names, symlinks, timestamps) | ✓ (since 0.6.0) |
Per-file timestamps + POSIX ownership on FileEntry (all filesystems) |
✓ (since 0.6.0) |
High Sierra Format browser (pre-ISO 9660 CDROM discs) |
✓ (since 0.7.0) |
Raw 2352-byte-sector auto-detect in a bare .iso |
✓ (since 0.7.0) |
| HFS / HFS+ filesystem browser | ✓ |
| SGI Volume Header + EFS filesystem browser (IRIX CDs) | ✓ (since 0.3.0) |
| UFS1 / FFS browser — Digital UNIX/Tru64, SunOS; NeXT/OpenStep/Rhapsody | ✓ (since 0.7.0) |
| VMS ODS-2 / Files-11 browser (OpenVMS VAX/Alpha) | ✓ (since 0.7.0) |
| UDF browser — DVD / data discs (physical partition, UDF 1.02–2.01) | ✓ (since 0.7.0) |
| UDF 2.50+ metadata-partition browser (Blu-ray / BDMV discs) | ✓ (since 0.8.0) |
| Game-disc identification — console + serial/title/region (PS1/PS2, Saturn, Mega-CD, Dreamcast, PC-FX, PC Engine CD, CD32, Neo Geo CD, 3DO, CD-i, GameCube, Wii) | ✓ (since 0.8.0) |
GameCube & Wii filesystem browser (ISO/GCM, RVZ/WIA, WBFS, CISO, GCZ, TGC; Wii decryption — via nod) |
✓ (since 0.8.0) |
Dreamcast GD-ROM browser — high-density area (CHD + .gdi) |
✓ (since 0.8.0) |
| Philips CD-i (Green Book) filesystem browser | ✓ (since 0.8.0) |
| 3DO Opera filesystem browser | ✓ (since 0.8.0) |
| TOC + MusicBrainz/FreeDB DiscID | ✓ (toc feature) |
| Physical optical drive enumeration | ✓ (drives feature) |
Quick Example
use DiscImageInfo;
use browse;
let info = open?;
println!;
println!;
let mut fs = open_disc_filesystem?;
let root = fs.root?;
for entry in fs.list_directory?
Cargo.toml
= "0.14"
# with optional features
= { = "0.14", = ["toc", "drives", "mdx"] }
# without CHD — no libchdman-rs, no MAME C++ core, no build-time download.
# For targets its prebuilt matrix doesn't cover and that can't compile MAME
# (i486/i586, PowerPC, vintage macOS/Windows, offline builds).
= { = "0.14", = false, = ["toc"] }
To track unreleased changes, depend on the git repository instead:
= { = "https://github.com/danifunker/opticaldiscs-rs" }
Feature Flags
| Flag | Default | Enables | Extra deps |
|---|---|---|---|
chd |
on | CHD (.chd) reading |
libchdman-rs |
toc |
off | DiscTOC, MusicBrainz DiscID, FreeDB ID |
sha1, base64 |
drives |
off | list_drives() — enumerate physical optical drives |
— |
mdx |
off | DAEMON Tools .mdx browsing (its descriptor is always AES-256-encrypted + zlib-compressed) |
aes, pbkdf2, ripemd |
chd and mdx gate a container's read path, not its recognition. Without
either one, matching files are still identified — DiscFormat::Chd /
DiscFormat::Mdx from the extension and from magic bytes — and opening one
returns UnsupportedFormat with a message naming the missing feature. That lets
a caller say "this is a CHD, but CHD support wasn't built in" instead of
"unknown file".
Asking at runtime what this build supports
Rather than sprinkling cfg!(feature = "chd") through your own code, query the
crate:
use DiscFormat;
// Direct: is CHD reading compiled in?
if is_supported
// General: works for any conditionally-compiled format.
assert!;
if !Chd.is_supported
// File-open dialogs: `supported_extensions()` is everything the crate can
// identify; `enabled_extensions()` is what this build can actually open.
let filter = enabled_extensions;
// Enumerate every known format and filter it yourself.
let usable: = ALL
.iter
.copied
.filter
.collect;
The chd module itself always compiles: ChdTrack, ChdTrackType, ChdInfo
and their helpers are plain Rust and stay available in a lean build, so code that
names those types keeps compiling. Only open_chd and ChdSectorReader — the
parts that touch MAME's C++ core — are gated.
Used By
- rusty-backup — vintage disc backup/restore tool
- ODE-artwork-downloader — USBODE cover art downloader
License
GPL-3.0 — see LICENSE.