macfs 0.1.0

Read/write MFS (Macintosh File System) 400K/800K disk images, raw or DiskCopy 4.2
Documentation
  • Coverage
  • 86%
    43 out of 50 items documented1 out of 1 items with examples
  • Size
  • Source code size: 243.33 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 1.3 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 1s Average build duration of successful builds.
  • all releases: 1s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • John-K/macfs
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • John-K

macfs

crates.io docs.rs license

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.

Library

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.

Command-line tool

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]

Testing

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.

Resources

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 tagChecksum skips 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):

License

Licensed under either of

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.