Skip to content

HFSKit is a high-level framework written in pure Swift for programatically reading (and soon, writing!) Hierarchical File System (HFS) volumes

License

Notifications You must be signed in to change notification settings

kevinbrewster/HFSKit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HFSKit

HFSKit is a high-level framework written in pure Swift for programatically reading (and soon, writing!) Hierarchical File System (HFS) volumes.

Generally, these volumes will be in the form of ISO files, but HFSKit should support any raw HFS volume.

HFS was the standard file system on Macs from 1985 until 1998, when HFS+ was released. "With the introduction of Mac OS X 10.6, Apple dropped support for formatting or writing HFS disks and images, which remain supported as read-only volumes. Starting with macOS 10.15, HFS disks can no longer be read."

NOTE:

If you are interested in a GUI-based app to extract HFS volumes, check out HFS.app

If you are interested a cross platform python HFS library/CLI, check out machfs

Installation

Swift Package Manager

First, declare your dependency in your Package.swift file:

dependencies: [
    .package(url: "https://github.com/kevinbrewster/HFSKit.git", .branch("master")),
    // ...
]

and add "HFSKit" to your application/library target dependencies, e.g. like this:

.target(name: "ExampleApp", dependencies: [
    "HFSKit",
    // ...
])

Usage

Load a volume from an ISO

guard let isoURL = Bundle.module.url(forResource: "test", withExtension: "iso"),
    let disk = Disk(isoURL), 
    let volume = disk.volumes.first 
else {
    print("Invalid volume")
    return
}

Access file/directory at path

if let entry = volume["path:to:some:file.jpg"] {
    switch entry {
    case .file(let file):
        print("found the file at path!")
    case .directory(let directory):
        print("hmm..this was supposed to be a file..")
    }
}

if let file = volume.file(at: "path:to:some:file.jpg") {
    print("Copying \(file.name) to \(destURL)..")
    file.dataFork()?.write(to: destURL)
}

if let directory = volume.directory(at: "path:to:some:directory") {
    print("directory \(directory.name) has \(directory.contents.count) entries")
}

Access resource fork

if let file = volume.file(at: "path:to:some:icon"),
    let resourceForkData = file.resourceFork(),
    let resourceFork = ResourceFork(resourceForkData),
    let iconResourceData = resourceFork.resources["icl8"]?.first?.data,
    let icon = NSImage(clut8: iconResourceData, width: 32, height: 32) 
{    
    print("Recovered icon from resource data!")
}

Recursively read entire contents of a volume

func printContents(_ directory: Directory, _ indent: String = "") {
    for entry in directory.contents {
        switch entry {
        case .file(let file):
            print(indent + file.name)
        case .directory(let subdirectory):
            print(indent + subdirectory.name)
            printContents(subdirectory, indent + "   ")
        }
    }
}

if let rootDirectory = volume.rootDirectory {
    printContents(rootDirectory)
}

Write contents of volume to local directory

do {
    let destURL = URL(fileURLWithPath: "/path/to/desktop")
    try volume.write(to: destURL)
    
} catch let error {
    print("Error during volume write: \(error)")
}
    

About

HFSKit is a high-level framework written in pure Swift for programatically reading (and soon, writing!) Hierarchical File System (HFS) volumes

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages