Documentation
¶
Overview ¶
Package stuffit parses and extracts classic StuffIt archives.
Supported formats:
- Classic SIT! archives (StuffIt 1.5 through 5.5)
- StuffIt 5.x archives (the "StuffIt (c)1997-..." signature)
- MacBinary-wrapped .sit files
- AppleSingle-wrapped .sit files
- BinHex 4.0 (.hqx) wrappers that contain a StuffIt archive
StuffIt X (.sitx) is not supported.
The package never writes files itself. Developers supply their own fork handling in one of two ways:
- Push: pass a ForkWriter (or the function-based Handler) to Extract or ExtractSelected. WriteDataFork and WriteResourceFork are independent hooks. Implement DirectoryWriter as well if you need folder entries.
- Pull: iterate Archive.Entries and call File.OpenFork with entry.DataFork or entry.ResourceFork to stream each fork yourself.
Typical 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 data fork
return nil
},
ResourceFork: func(entry stuffit.Entry, r io.Reader) error {
// persist the resource fork (AppleDouble, xattr, ...)
return nil
},
}, stuffit.ExtractOptions{})
Index ¶
- func SetDebug(enabled bool)
- type AppleSingleMetadata
- type Archive
- type ArchiveWrapper
- type BinHexMetadata
- type CompressionMethod
- type DataForkFunc
- type DirectoryFunc
- type DirectoryWriter
- type Entry
- type ExtractOptions
- type File
- type Fork
- type ForkKind
- type ForkReader
- type ForkWriter
- type FormatVersion
- type Handler
- type MacBinaryMetadata
- type Parser
- func (p *Parser) Extract(arc *Archive, sink ForkWriter, opts ExtractOptions) error
- func (p *Parser) ExtractSelected(arc *Archive, sink ForkWriter, opts ExtractOptions, onlyPaths []string) error
- func (p *Parser) OpenFork(arc *Archive, fork *Fork, opts ExtractOptions) (ForkReader, error)
- func (p *Parser) Parse() (*Archive, error)
- type ResourceForkFunc
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type AppleSingleMetadata ¶
type AppleSingleMetadata struct {
Name string
Comment string
FileType uint32
Creator uint32
FinderFlags uint16
DataForkSize uint32
ResourceForkSize uint32
// Double is true for AppleDouble (resource-fork sidecar layout).
Double bool
}
AppleSingleMetadata is recorded when the archive is wrapped in AppleSingle or AppleDouble (magic 0x00051600 / 0x00051607).
type Archive ¶
type Archive struct {
Format FormatVersion
Comment string
Encrypted bool
Wrappers []ArchiveWrapper
Entries []Entry
// contains filtered or unexported fields
}
Archive is the parsed catalog of a StuffIt file.
type ArchiveWrapper ¶
type ArchiveWrapper struct {
MacBinary *MacBinaryMetadata
BinHex *BinHexMetadata
AppleSingle *AppleSingleMetadata
}
ArchiveWrapper describes an outer encoding that contained the StuffIt payload.
type BinHexMetadata ¶
type BinHexMetadata struct {
Name string
FileType uint32
Creator uint32
Flags uint16
DataForkSize uint32
ResourceForkSize uint32
}
BinHexMetadata is recorded when the archive is wrapped in BinHex 4.0.
type CompressionMethod ¶
type CompressionMethod uint8
CompressionMethod is the per-fork StuffIt compression identifier stored in the archive catalog.
const ( // MethodNone stores the fork uncompressed (StuffIt method 0). MethodNone CompressionMethod = 0 // MethodRLE90 is PackIt/BinHex-style run-length encoding (method 1). // Byte 0x90 is an escape: 0x90 0x00 is a literal 0x90; 0x90 N repeats // the previous byte so it occurs N times in total. MethodRLE90 CompressionMethod = 1 // MethodCompressLZW is Unix-compress-style LZW (method 2, "Compress"). // Codes are LSB-first, 9–14 bits, with a clear code of 256. MethodCompressLZW CompressionMethod = 2 // MethodHuffman is classic StuffIt Huffman coding (method 3). The // bitstream starts with an explicit binary tree, then one symbol per // walk of that tree. MethodHuffman CompressionMethod = 3 // MethodLZAH is LZSS with an adaptive Huffman tree (method 5), similar // to LZHUF. Window is 4 KiB; 314 leaves cover literals and match lengths. MethodLZAH CompressionMethod = 5 // MethodFixedHuffman is StuffIt's "Faster" compressor (method 6): blocks // of a fixed Huffman codebook plus a byte translation table, followed by // Apple PackBits. Some blocks skip Huffman and are PackBits only. MethodFixedHuffman CompressionMethod = 6 // MethodMW is the Miller–Wegman compact dictionary coder (method 8). // Codes grow from 9 bits; values below 256 are literals and higher // values are pointers into a 16 KiB dictionary of earlier strings. MethodMW CompressionMethod = 8 // MethodLZHuffman is StuffIt's "Better" compressor (method 13): LZ77 // with Huffman-coded literals, match lengths, and offsets. Window is // 64 KiB. Tables may be sent in-stream or chosen from five presets. MethodLZHuffman CompressionMethod = 13 // MethodInstaller14 is the LZ77+Huffman codec used by StuffIt Installer // Maker (method 14). Window is 256 KiB; each block carries two Huffman // trees for literals/lengths and for match offsets. MethodInstaller14 CompressionMethod = 14 // MethodArsenic15 is the bzip2-like compressor used by StuffIt 5.5 // (method 15): Burrows–Wheeler transform, move-to-front, and an // adaptive arithmetic coder. MethodArsenic15 CompressionMethod = 15 )
func (CompressionMethod) Name ¶
func (m CompressionMethod) Name() string
Name returns a human-readable label for the compression method.
type DataForkFunc ¶
type DataForkFunc func(entry Entry, r ForkReader) error
DataForkFunc writes one data fork.
type DirectoryFunc ¶
DirectoryFunc is called for each folder entry when Handler.Directory is set.
type DirectoryWriter ¶
DirectoryWriter may be implemented alongside ForkWriter to receive folder entries. Parser.Extract and Parser.ExtractSelected skip directories when the sink does not implement this interface.
type Entry ¶
type Entry struct {
Name string
Path string
IsDirectory bool
ModTime time.Time
CreationTime time.Time
FileType uint32
FileCreator uint32
FinderFlags uint16
Comment string
DataFork *Fork
ResourceFork *Fork
}
Entry is one file or directory recorded in the archive catalog.
type ExtractOptions ¶
type ExtractOptions struct {
// Password is required for StuffIt 5 archives (or entries) that are
// encrypted. Classic SIT encryption is not supported.
Password []byte
}
ExtractOptions controls decryption during extraction.
type File ¶
type File struct {
// Archive is the parsed catalog. It is never nil after a successful Open.
Archive *Archive
// contains filtered or unexported fields
}
File is an opened StuffIt archive. Close it when extraction is finished.
func Open ¶
Open opens path, detects the format (classic SIT, StuffIt 5, MacBinary, AppleSingle, or BinHex), and parses the catalog. The underlying file stays open so forks can be extracted; call Close when done.
func (*File) Extract ¶
func (f *File) Extract(sink ForkWriter, opts ExtractOptions) error
Extract writes every file fork through sink. Folder entries are forwarded only when sink implements DirectoryWriter.
func (*File) ExtractSelected ¶
func (f *File) ExtractSelected(sink ForkWriter, opts ExtractOptions, onlyPaths []string) error
ExtractSelected is like Extract but only visits entries whose archive path is listed in onlyPaths. An empty onlyPaths list extracts everything.
func (*File) OpenFork ¶
func (f *File) OpenFork(fork *Fork, opts ExtractOptions) (ForkReader, error)
OpenFork returns a streaming reader for one Macintosh fork. Pass entry.DataFork or entry.ResourceFork from this archive. The caller must consume the reader fully; CRC16 is checked when the stream reaches EOF.
Example ¶
package main
import (
"io"
"github.com/ObsoleteMadness/StuffIt-Go/stuffit"
)
func main() {
f, err := stuffit.Open("archive.sit")
if err != nil {
return
}
defer f.Close()
for _, e := range f.Archive.Entries {
if e.DataFork != nil {
r, err := f.OpenFork(e.DataFork, stuffit.ExtractOptions{})
if err != nil {
return
}
_, _ = io.Copy(io.Discard, r)
}
if e.ResourceFork != nil {
r, err := f.OpenFork(e.ResourceFork, stuffit.ExtractOptions{})
if err != nil {
return
}
_, _ = io.Copy(io.Discard, r)
}
}
}
Output:
type Fork ¶
type Fork struct {
Kind ForkKind
Method CompressionMethod
CompressedSize uint32
UncompressedSize uint32
CRC16 uint16
// DataOffset is the absolute byte offset of the compressed fork in the
// archive source passed to [NewParser].
DataOffset int64
IsEncrypted bool
// EntryKey is the per-entry RC4 salt used by StuffIt 5 encryption.
// It is empty for unencrypted forks.
EntryKey []byte
}
Fork describes one Macintosh fork of an archive entry.
type ForkKind ¶
type ForkKind int
ForkKind identifies whether a Fork is a Macintosh data or resource fork.
type ForkReader ¶
ForkReader is the decompressed (and decrypted, if needed) byte stream for one Macintosh fork. Callers typically copy it with io.Copy.
type ForkWriter ¶
type ForkWriter interface {
WriteDataFork(entry Entry, r ForkReader) error
WriteResourceFork(entry Entry, r ForkReader) error
}
ForkWriter is the primary hook for custom Macintosh fork handling. The package never writes files itself; implement this interface to store forks however you want (AppleDouble sidecars, extended attributes, a custom database, etc.).
Each method is called at most once per entry that actually has that fork. r is a streaming reader of the decompressed bytes and should be consumed before the method returns. Any unread remainder is drained by Extract so CRC verification still runs.
See Handler for a function-based adapter, File.OpenFork to pull a single fork yourself, and DirectoryWriter if you also need folder entries.
type FormatVersion ¶
type FormatVersion int
FormatVersion identifies the on-disk StuffIt catalog format.
const ( // FormatSIT1 is a classic SIT! archive (StuffIt 1.5 through 5.5). FormatSIT1 FormatVersion = 1 // FormatSIT5 is a StuffIt 5.x archive ("StuffIt (c)1997-..." signature). FormatSIT5 FormatVersion = 5 )
func (FormatVersion) String ¶
func (v FormatVersion) String() string
String returns a short name for the archive format.
type Handler ¶
type Handler struct {
DataFork DataForkFunc
ResourceFork ResourceForkFunc
Directory DirectoryFunc
}
Handler is a function-based ForkWriter (and optional DirectoryWriter) for callers that do not want to define a named type. Set DataFork and ResourceFork independently; a nil callback skips that fork (the stream is still consumed). Set Directory if you want folder entries.
Example ¶
package main
import (
"io"
"os"
"github.com/ObsoleteMadness/StuffIt-Go/stuffit"
)
func main() {
f, err := stuffit.Open("archive.sit")
if err != nil {
return
}
defer f.Close()
err = f.Extract(stuffit.Handler{
DataFork: func(entry stuffit.Entry, r stuffit.ForkReader) error {
out, err := os.Create(entry.Path)
if err != nil {
return err
}
defer out.Close()
_, err = io.Copy(out, r)
return err
},
ResourceFork: func(entry stuffit.Entry, r stuffit.ForkReader) error {
// AppleDouble sidecar, xattr, or any other resource-fork store.
_, err := io.Copy(io.Discard, r)
return err
},
}, stuffit.ExtractOptions{})
_ = err
}
Output:
func (Handler) CreateDirectory ¶
CreateDirectory implements DirectoryWriter.
func (Handler) WriteDataFork ¶
func (h Handler) WriteDataFork(entry Entry, r ForkReader) error
WriteDataFork implements ForkWriter.
func (Handler) WriteResourceFork ¶
func (h Handler) WriteResourceFork(entry Entry, r ForkReader) error
WriteResourceFork implements ForkWriter.
type MacBinaryMetadata ¶
type MacBinaryMetadata struct {
Name string
}
MacBinaryMetadata is recorded when the archive is wrapped in a MacBinary header.
type Parser ¶
type Parser struct {
// contains filtered or unexported fields
}
func NewParser ¶
NewParser reads a StuffIt archive (or a MacBinary / AppleSingle / BinHex wrapper) from r. size is the number of readable bytes starting at offset 0.
func (*Parser) Extract ¶
func (p *Parser) Extract(arc *Archive, sink ForkWriter, opts ExtractOptions) error
Extract writes every file fork in arc through sink. Folder entries are forwarded only when sink implements DirectoryWriter.
func (*Parser) ExtractSelected ¶
func (p *Parser) ExtractSelected(arc *Archive, sink ForkWriter, opts ExtractOptions, onlyPaths []string) error
ExtractSelected writes forks for entries whose archive path is listed in onlyPaths. An empty or nil onlyPaths list extracts every file. Resource forks are delivered before data forks so callers can create AppleDouble sidecars (or equivalent metadata) first.
func (*Parser) OpenFork ¶
func (p *Parser) OpenFork(arc *Archive, fork *Fork, opts ExtractOptions) (ForkReader, error)
OpenFork returns a streaming reader for one Macintosh fork. fork should be an entry's DataFork or ResourceFork from arc. The caller must consume the reader fully; CRC16 is checked when the stream reaches EOF.
type ResourceForkFunc ¶
type ResourceForkFunc func(entry Entry, r ForkReader) error
ResourceForkFunc writes one resource fork.