StuffIt (SIT, StuffIt 5)
A Go library and CLI for classic StuffIt archives:
- StuffIt 5.x (
StuffIt (c)1997-... signature)
- StuffIt 5.5 and earlier classic
SIT! archives
- MacBinary-wrapped
.sit files
- AppleSingle-wrapped
.sit files (.as / .AS)
- BinHex 4.0 (
.hqx) wrappers that contain a StuffIt archive
StuffIt X (.sitx) is not supported.
Quick start
Download a tagged release for macOS or Linux (.tar.gz) or Windows (.zip), or install from source:
go install github.com/ObsoleteMadness/StuffIt-Go/cmd/stuffit@latest
stuffit list archive.sit
stuffit info archive.sit
stuffit info -json archive.sit
stuffit extract -C out archive.sit
stuffit extract -C out archive.sit "Folder/File"
Resource forks are written as AppleDouble-style sidecars named ._<filename>. Extracted names are sanitized for the host OS: Windows reserved characters and device names are replaced, while POSIX systems (including macOS HFS+/APFS) keep characters that are legal there, such as CR (\r).
info -json writes one JSON object to stdout (archive metadata plus the full catalog) so other tools can consume it.
Each GitHub Release includes:
stuffit-darwin-arm64.tar.gz, stuffit-darwin-amd64.tar.gz
stuffit-linux-arm64.tar.gz, stuffit-linux-amd64.tar.gz
stuffit-windows-arm64.zip, stuffit-windows-amd64.zip
SHA256SUMS
Every archive contains the stuffit binary, README.md, and LICENSE. Push a version tag to publish:
git tag v0.1.1
git push origin v0.1.1
Library
Import the package from another Go module:
go get github.com/ObsoleteMadness/StuffIt-Go/stuffit@latest
import "github.com/ObsoleteMadness/StuffIt-Go/stuffit"
Fork output hooks
The package never writes files itself. You implement data-fork and resource-fork
handling independently.
Push (visitor): Extract() calls your ForkWriter:
WriteDataFork(entry, reader)
WriteResourceFork(entry, reader)
stuffit.Handler is a function-based adapter so you can set only the callbacks
you need. A nil callback skips that fork.
Pull: iterate f.Archive.Entries and call f.OpenFork(entry.DataFork, opts)
or f.OpenFork(entry.ResourceFork, opts) to stream each fork yourself.
The package does not enforce storage strategy. Consumers can map forks to:
- AppleDouble sidecar files (for example
._filename)
- Extended attributes
- Any custom metadata stream format
Compression support
- Fully supported:
None, RLE, Compress (LZW), Huffman, LZAH, Fixed Huffman, MW, LZ+Huffman (dynamic and preset table modes), Installer, Arsenic
Unsupported methods are returned as explicit errors during extraction.
Usage
f, err := stuffit.Open("archive.sit")
if err != nil {
return err
}
defer f.Close()
err = f.Extract(stuffit.Handler{
DataFork: func(entry stuffit.Entry, r io.Reader) error {
// persist the Macintosh data fork
return nil
},
ResourceFork: func(entry stuffit.Entry, r io.Reader) error {
// persist the Macintosh resource fork
return nil
},
Directory: func(entry stuffit.Entry) error {
return os.MkdirAll(entry.Path, 0o755)
},
}, stuffit.ExtractOptions{})
The package never writes files itself. Implement ForkWriter (or use stuffit.Handler) to store forks however you want. To stream a single fork without a visitor, call f.OpenFork(entry.DataFork, opts) or f.OpenFork(entry.ResourceFork, opts).
Credits
This library is inspired by XADMaster, MacPaw's Objective-C archive extraction library (the engine behind The Unarchiver). The classic StuffIt catalog layouts and compression methods implemented here follow that work.
The StuffIt 5 Arsenic (method 15) decoder follows Matthew T. Russotto's description of the format at http://www.russotto.net/arseniccomp.html.
Integration samples in testdata/stuffit-test-files come from Stephan Sokolow's stuffit-test-files collection of legally redistributable SIT archives. After clone, run git submodule update --init --recursive so the end-to-end tests can see them. Password-protected files in that set use password.