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
.sitfiles - AppleSingle-wrapped
.sitfiles (.as/.AS) - BinHex 4.0 (
.hqx) wrappers that contain a StuffIt archive
StuffIt X (.sitx) is not supported.
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@lateststuffit 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.
Import the package from another Go module:
go get github.com/ObsoleteMadness/StuffIt-Go/stuffit@latestimport "github.com/ObsoleteMadness/StuffIt-Go/stuffit"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
- 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.
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).
Releases are generated via version tags.
git tag v0.1.1
git push origin v0.1.1Each GitHub Release includes:
stuffit-v0.1.1-darwin-arm64.tar.gz,stuffit-v0.1.1-darwin-amd64.tar.gzstuffit-v0.1.1-linux-arm64.tar.gz,stuffit-v0.1.1-linux-amd64.tar.gzstuffit-v0.1.1-windows-arm64.zip,stuffit-v0.1.1-windows-amd64.zipSHA256SUMS
Every archive contains the stuffit binary, README.md, and LICENSE. Push a version tag to publish:
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.