A lightweight .NET library for reading classic Macintosh HFS disks and volumes.
$ dotnet add package HfsReaderHfsReader is a .NET library for reading classic Macintosh HFS disk images and extracting their contents. It provides a simple API to enumerate volumes, list directory contents, and read file forks (data and resource forks) from HFS volumes embedded in disk images.
Add the project or reference the compiled library in your .NET application. If published on NuGet, you could install it like:
dotnet add package HfsReader
Or reference the project directly:
dotnet add reference ../HfsReader/HfsReader.csproj
using HfsReader;
using System.IO;
// Open a disk image (can be a .dsk file containing an HFS volume or an image with
// an Apple partition map).
using var stream = File.OpenRead("Samples/Microsoft Excel 1.03.dsk");
// Parse the disk and find HFS volumes.
var disk = new HFSDisk(stream);
var volume = disk.Volumes[0]; // Pick the first HFS volume
// List root contents
foreach (var node in volume.RootContents())
{
Console.WriteLine($"{(node is HFSDirectory ? "DIR" : "FILE")} {node.Name} (parent: {node.ParentIdentifier})");
if (node is HFSFile file)
{
// Read the data fork
byte[] data = volume.GetFileData(file, resourceFork: false);
Console.WriteLine($" Data fork size: {data.Length} bytes");
}
}
HFSDisk(Stream stream): Constructs an HFSDisk by scanning the provided seekable, readable stream for Apple partition map entries. If no partition map is found, the stream is treated as a single HFS volume.Volumes: List<HFSVolume> — the list of detected HFS volumes in the disk image.HFSVolume(Stream stream, int volumeStartOffset): Initialize an HFS volume reader given a stream and the byte offset where the volume begins.BootBlock: HFSBootBlockHeader — (internal structure; may be available depending on build).MasterDirectoryBlock: HFSMasterDirectoryBlock — contains allocation block size, catalog extents, and other volume metadata.CatalogTree: BTree — low-level access to the catalog B-Tree.IEnumerable<HFSNode> RootContents(): Enumerate top-level entries in the root directory.IEnumerable<HFSNode> ContentsOfDirectory(HFSDirectory directory): Enumerate entries in a given directory.byte[] GetFileData(HFSFile file, bool resourceFork): Read a file fork into a byte array.int GetFileData(HFSFile file, Stream outputStream, bool resourceFork): Write a file fork to a stream and return the number of bytes written.HFSNode: Base class with ParentIdentifier and Name properties and an abstract Identifier.HFSFile: Represents a file; exposes HFSFileRecord FileRecord for low-level metadata.HFSDirectory: Represents a folder; exposes HFSFolderRecord FolderRecord.using var outStream = File.Create("resource-fork.bin");
int written = volume.GetFileData(file, outStream, resourceFork: true);
Console.WriteLine($"Wrote {written} bytes");
Directly access HFSVolume.CatalogTree to traverse B-Tree nodes, examine BTNode descriptors, or dump catalog records for analysis.
HFSFile and HFSDirectory nodes with their names and metadata.MIT License.