Read and write MFS (Macintosh File System) floppy disk images — the flat
filesystem the original 1984 Macintosh used on its 400K single-sided floppies —
with no dependencies beyond std.
Images may be bare sector dumps or DiskCopy 4.2 containers; the container is autodetected on open and written back in the same shape. Anything the crate does not interpret is preserved verbatim — boot blocks, reserved MDB and directory fields, DiskCopy 4.2 tags — so opening an image and saving it again without changes reproduces the original bytes exactly. HFS volumes are detected and reported as unsupported.
use macfs::{Fork, ImageFormat, MfsVolume, Result};
use std::io::Cursor;
fn main() -> Result<()> {
// Format a blank 400K volume in memory and put a file on it.
let mut vol = MfsVolume::format(MfsVolume::FLOPPY_400K, "My Disk", ImageFormat::Raw)?;
vol.create_file("Read Me", *b"TEXT", *b"MACA")?;
vol.write_fork("Read Me", Fork::Data, b"hello from 1984")?;
let mut image = Cursor::new(Vec::new());
vol.save_to(&mut image)?;
// Read it back. Name lookup is case-insensitive, as on a real Mac.
let disk = MfsVolume::open(Cursor::new(image.into_inner()))?;
assert_eq!(disk.read_fork("read me", Fork::Data)?, b"hello from 1984");
Ok(())
}Volumes are handled whole: open pulls the entire image into memory, every
operation works on that copy, and one save_to call re-serializes it — a
failed operation can never leave a half-written volume behind. Files have the
two classic Mac forks (data and resource), and names are stored as MacRoman.
The crate ships an mfs binary:
mfs info <image>
mfs ls <image> [-l]
mfs cat <image> <name> [--rsrc]
mfs extract <image> <name> [--rsrc] [-o PATH]
mfs add <image> <hostfile> [--name N] [--type XXXX] [--creator XXXX] [--rsrc HOSTFILE]
mfs rm <image> <name> [--force]
mfs mv <image> <old> <new>
mfs mkfs <image> [--size 400k|800k|BYTES] [--name NAME] [--dc42] [--force]
mfs check <image>
mfs bootblocks <image> [--export FILE | --import FILE]
The unit and round-trip suites are self-contained. The golden tests
additionally verify byte-identical open/save against real Apple system disks,
which are copyrighted and not distributed with the crate; run
scripts/fetch-test-images.sh to download them into tests/images/, and set
MACFS_REQUIRE_GOLDEN=1 to make their absence a test failure instead of a
skip. See TESTING.md for details.
Format documentation:
- Inside Macintosh, Volume II, "The File Manager" (Apple, 1985) — the MFS
on-disk structures: master directory block, file directory, and the 12-bit
allocation block map. Field names in the source (
drSigWord,flFndrFlags, …) follow its nomenclature. - MFSLives — Apple's MFS sample code, a reference implementation of the format.
- The DiskCopy 4.2 container layout and its checksum algorithm — including the
undocumented but universal quirk that
tagChecksumskips the first sector's 12 tag bytes — were matched against real images produced by Apple's Disk Copy.
Golden test images (fetched by scripts/fetch-test-images.sh; provenance and
license notes in TESTING.md):
Sample.imgfrom the MFSLives repo — Apple's sample MFS volume.- Mini vMac blank disk images
(gryphel.com) — Apple-formatted blank 400K/800K volumes, used as the
mkfsoracle. - earlymacintosh.org — Finder 1.0, System 1.1, and System 2.0 boot disks.
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Developed with the help of Claude Code.