Documentation
¶
Overview ¶
Package pbo provides read, extract, pack, hash, and edit operations for PBO (Packed Bank of files) archives. It is designed for streaming workflows: packing accepts caller-provided streams (Input.Open), and reading/extracting works without loading full archive payload into memory.
Compression rules (summary):
- path decision must include entry via PackOptions.Compress rules;
- final entry size must be within [MinCompressSize, MaxCompressSize];
- known-size inputs use in-memory compression path (bounded by MaxCompressSize);
- unknown-size inputs are streamed raw (no temp-file fallback);
- compression is written only when result is smaller than source.
Reading ¶
Open a PBO and list or read entries:
r, err := pbo.Open("addon.pbo")
if err != nil {
return err
}
defer r.Close()
for _, e := range r.Entries() {
data, _ := r.ReadEntry(e.Path)
// use data
}
For metadata-only scans, use fast helpers without creating a full reader:
headers, err := pbo.ReadHeaders("addon.pbo")
if err != nil {
return err
}
entries, err := pbo.ListEntries("addon.pbo")
if err != nil {
return err
}
_, _ = headers, entries
For filesystem-safe listing names:
entries, err := pbo.ListEntriesWithOptions("addon.pbo", pbo.ReaderOptions{
SanitizeNames: true,
})
if err != nil {
return err
}
_ = entries
For noisy or obfuscated archives, combine entry filters:
r, err := pbo.OpenWithOptions("addon.pbo", pbo.ReaderOptions{
MinEntryOriginalSize: 12,
MinEntryDataSize: 0,
EntryPathPrefix: "scripts/4_world",
FilterASCIIOnly: false,
SanitizeControlChars: true,
SanitizeNames: true,
})
if err != nil {
return err
}
defer r.Close()
For archives with meaningful non-zero index offsets, use compatibility mode:
r, err := pbo.OpenWithOptions("addon.pbo", pbo.ReaderOptions{
OffsetMode: pbo.OffsetModeStoredCompat,
})
if err != nil {
return err
}
defer r.Close()
Extracting ¶
Extract all entries to a directory (parallel workers):
if err := r.Extract(ctx, "out/", pbo.ExtractOptions{MaxWorkers: 4}); err != nil {
return err
}
Path sanitization is enabled by default during extraction. Disable it explicitly when raw names are required:
if err := r.Extract(ctx, "out/", pbo.ExtractOptions{
MaxWorkers: 4,
RawNames: true,
}); err != nil {
return err
}
Packing ¶
Pack from stream-oriented inputs (order is deterministic by path): examples below use github.com/woozymasta/pathrules for compression filters:
inputs := []pbo.Input{
{Path: "config.cpp", Open: func() (io.ReadCloser, error) { return os.Open("src/config.cpp") }},
}
res, err := pbo.Pack(ctx, outFile, inputs, pbo.PackOptions{
Headers: []pbo.HeaderPair{{Key: "prefix", Value: "myaddon"}},
// Empty rule set means no compression.
Compress: []pathrules.Rule{
{Action: pathrules.ActionInclude, Pattern: "*.rvmat"},
{Action: pathrules.ActionInclude, Pattern: "textures/**"},
},
CompressMatcherOptions: pathrules.MatcherOptions{
CaseInsensitive: true,
DefaultAction: pathrules.ActionExclude,
},
OnEntryDone: func(entry pbo.PackEntryProgress) {
// progress callback per written entry
},
})
_ = res.CompressedEntries
_ = res.SkippedCompressionEntries
Use default mode for restricted environments where only output path is writable (unknown-size candidates remain raw):
res, err := pbo.Pack(ctx, outFile, inputs, pbo.PackOptions{
Compress: []pathrules.Rule{
{Action: pathrules.ActionInclude, Pattern: "*"},
},
})
To write to a path and append the SHA1 trailer:
res, err := pbo.PackFile(ctx, "addon.pbo", inputs, opts)
To pack and calculate signature hash set in one flow:
res, hs, err := pbo.PackAndHashFile(
ctx,
"addon.pbo",
inputs,
opts,
pbo.SignVersionV3,
pbo.GameTypeDayZ,
)
_, _ = res, hs
To edit existing archive in one transaction:
editor, err := pbo.OpenEditor("addon.pbo", pbo.EditOptions{
PackOptions: pbo.PackOptions{
Compress: []pathrules.Rule{
{Action: pathrules.ActionInclude, Pattern: "*.txt"},
},
CompressMatcherOptions: pathrules.MatcherOptions{
CaseInsensitive: true,
DefaultAction: pathrules.ActionExclude,
},
},
BackupKeep: 1,
})
if err != nil {
return err
}
if err := editor.Replace(pbo.Input{
Path: "scripts/main.c",
Open: func() (io.ReadCloser, error) { return os.Open("scripts/main.c") },
}); err != nil {
return err
}
if _, err := editor.Commit(ctx); err != nil {
return err
}
Index ¶
- Constants
- Variables
- func NormalizePath(raw string) string
- func NormalizePrefixHeader(raw string) string
- func PackAndHash(ctx context.Context, out io.WriteSeeker, inputs []Input, opts PackOptions, ...) (*PackResult, HashSet, error)
- func PackAndHashFile(ctx context.Context, outPath string, inputs []Input, opts PackOptions, ...) (*PackResult, HashSet, error)
- func SanitizePath(pathValue string) (string, error)
- func ToggleSealedInPlace(out io.ReadWriteSeeker, sealedKeyValue *SealedKey) error
- type EditOptions
- type Editor
- type EntryInfo
- func ListEntries(path string) ([]EntryInfo, error)
- func ListEntriesFromReaderAt(ra io.ReaderAt, size int64) ([]EntryInfo, error)
- func ListEntriesFromReaderAtWithOptions(ra io.ReaderAt, size int64, opts ReaderOptions) ([]EntryInfo, error)
- func ListEntriesWithOptions(path string, opts ReaderOptions) ([]EntryInfo, error)
- type ExtractFileMode
- type ExtractOptions
- type GameType
- type HashSet
- type HeaderPair
- func ReadHeaders(path string) ([]HeaderPair, error)
- func ReadHeadersFromReaderAt(ra io.ReaderAt, size int64) ([]HeaderPair, error)
- func ReadHeadersFromReaderAtWithOptions(ra io.ReaderAt, size int64, opts ReaderOptions) ([]HeaderPair, error)
- func ReadHeadersWithOptions(path string, opts ReaderOptions) ([]HeaderPair, error)
- type Input
- type MimeType
- type OffsetMode
- type PackEntryProgress
- type PackOptions
- type PackResult
- type Reader
- func (r *Reader) Close() error
- func (r *Reader) CopyEntryInfoTo(info EntryInfo, dst io.Writer, buf []byte) (int64, error)
- func (r *Reader) CopyEntryTo(name string, dst io.Writer, buf []byte) (int64, error)
- func (r *Reader) CopyPackedEntryInfoTo(info EntryInfo, dst io.Writer) (int64, error)
- func (r *Reader) Entries() []EntryInfo
- func (r *Reader) EntriesView() []EntryInfo
- func (r *Reader) Extract(ctx context.Context, dstDir string, opts ExtractOptions) error
- func (r *Reader) Headers() []HeaderPair
- func (r *Reader) OpenEntry(name string) (io.ReadCloser, error)
- func (r *Reader) OpenEntryInfo(info EntryInfo) (io.ReadCloser, error)
- func (r *Reader) OpenPackedEntryInfo(info EntryInfo) (io.ReadCloser, error)
- func (r *Reader) RangeEntries(fn func(EntryInfo) bool)
- func (r *Reader) ReadEntry(name string) ([]byte, error)
- func (r *Reader) SHA1Trailer() ([20]byte, bool)
- type ReaderOptions
- type SealedKey
- type SignVersion
Constants ¶
const ( DefaultWriteBuffer = 4 * 1024 * 1024 LargeWriteBuffer = 16 * 1024 * 1024 DefaultMinCompressSize = 512 DefaultMaxCompressSize = 16 * 1024 * 1024 )
Default packer tuning values.
const FileExtension = ".pbo"
FileExtension is the PBO file extension.
Variables ¶
var ( // ErrInvalidHeader means the PBO file is missing or has a bad header. ErrInvalidHeader = errors.New("invalid PBO file: missing or bad header") // ErrFileNameTooLong means the entry filename exceeds the maximum length. ErrFileNameTooLong = errors.New("entry filename exceeds maximum length") // ErrNilReader means the reader is nil. ErrNilReader = errors.New("reader is nil") // ErrReaderAtRequired means operation requires io.ReaderAt support. ErrReaderAtRequired = errors.New("readerAt is required") // ErrWriterAtRequired means operation requires io.WriterAt support. ErrWriterAtRequired = errors.New("writerAt is required") // ErrNilWriter means the writer is nil. ErrNilWriter = errors.New("writer is nil") // ErrEntryNotFound means the entry is not found. ErrEntryNotFound = errors.New("entry not found") // ErrClosed means the reader or resource is already closed. ErrClosed = errors.New("reader or resource already closed") // ErrSizeOverflow means the size exceeds the uint32 or 4 GiB PBO limit. ErrSizeOverflow = errors.New("size exceeds uint32 or 4 GiB PBO limit") // ErrEmptyInputs means no inputs provided for pack. ErrEmptyInputs = errors.New("no inputs provided for pack") // ErrInvalidCompressPattern means one or more compression rules are invalid. ErrInvalidCompressPattern = errors.New("invalid compress rules") // ErrUnsupportedSignVersion means the signature version is not supported. ErrUnsupportedSignVersion = errors.New("unsupported signature version") // ErrUnsupportedGameTypeV3 means the game type is not supported for v3. ErrUnsupportedGameTypeV3 = errors.New("unsupported game type for v3") // ErrTrailerTooShort means the file is too short for the trailer. ErrTrailerTooShort = errors.New("file too short for trailer") // ErrInvalidTrailerPrefix means the trailer does not start with 0x00. ErrInvalidTrailerPrefix = errors.New("trailer does not start with 0x00") // ErrTrailerHashMismatch means the trailer hash mismatch. ErrTrailerHashMismatch = errors.New("trailer hash mismatch") // ErrInvalidSHA1DigestLength means the SHA1 digest length is invalid. ErrInvalidSHA1DigestLength = errors.New("invalid SHA1 digest length") // ErrInvalidEntryPath means one of input entry paths is empty or invalid after normalization. ErrInvalidEntryPath = errors.New("invalid entry path") // ErrDuplicateEntryPath means two inputs resolve to the same path (case-insensitive). ErrDuplicateEntryPath = errors.New("duplicate entry path") // ErrInvalidExtractPath means archive entry path is invalid for extraction destination. ErrInvalidExtractPath = errors.New("invalid extract path") // ErrExtractPathOutsideRoot means resolved extraction path escapes destination root. ErrExtractPathOutsideRoot = errors.New("extract path escapes destination root") // ErrInvalidEntryOffset means one or more entry offsets are malformed for selected reader policy. ErrInvalidEntryOffset = errors.New("invalid entry offset") )
Sentinel errors for PBO operations. Use errors.Is in callers.
Functions ¶
func NormalizePath ¶
NormalizePath converts an archive/internal path to normalized slash-separated form. It trims spaces, accepts both "/" and "\", removes leading "./" and "/", and cleans "." segments.
func NormalizePrefixHeader ¶
NormalizePrefixHeader normalizes PBO "prefix" header value to "\" separators.
func PackAndHash ¶
func PackAndHash( ctx context.Context, out io.WriteSeeker, inputs []Input, opts PackOptions, signVersion SignVersion, gameType GameType, ) (*PackResult, HashSet, error)
PackAndHash writes a PBO to out and calculates hash set over written bytes. The output writer must also implement io.ReaderAt for hash calculation.
func PackAndHashFile ¶
func PackAndHashFile( ctx context.Context, outPath string, inputs []Input, opts PackOptions, signVersion SignVersion, gameType GameType, ) (*PackResult, HashSet, error)
PackAndHashFile writes a PBO to outPath, returns hash set, and appends SHA1 trailer.
func SanitizePath ¶ added in v0.1.1
SanitizePath rewrites one path to deterministic filesystem-safe slash-separated form.
func ToggleSealedInPlace ¶ added in v0.2.0
func ToggleSealedInPlace(out io.ReadWriteSeeker, sealedKeyValue *SealedKey) error
ToggleSealedInPlace toggles sealed transform for an existing archive stream.
This operation is symmetric: applying it twice with the same key restores the original bytes.
Types ¶
type EditOptions ¶
type EditOptions struct {
// PackOptions are applied for added/replaced entries during commit.
PackOptions PackOptions `json:"pack_options,omitzero" yaml:"pack_options,omitzero"`
// BackupKeep controls how many backup generations are kept after successful commit.
// 0 means remove backup, 1 keeps only `<archive>.bak`, N keeps `.bak` + `.bak.1..N-1`.
BackupKeep int `json:"backup_keep,omitempty" yaml:"backup_keep,omitempty"`
}
EditOptions configures file-based archive edit flow.
type Editor ¶
type Editor struct {
// contains filtered or unexported fields
}
Editor accumulates archive edit operations and applies them on Commit.
func OpenEditor ¶
func OpenEditor(path string, opts EditOptions) (*Editor, error)
OpenEditor creates staged editor for file-based archive rewrite workflow.
func (*Editor) Commit ¶
func (e *Editor) Commit(ctx context.Context) (*PackResult, error)
Commit applies all staged operations in one rewrite transaction.
type EntryInfo ¶
type EntryInfo struct {
// Path is the entry path as stored in archive index.
Path string `json:"path" yaml:"path"`
// Offset is byte offset of entry payload.
Offset uint32 `json:"offset" yaml:"offset"`
// DataSize is stored payload size in bytes.
DataSize uint32 `json:"data_size" yaml:"data_size"`
// OriginalSize is uncompressed size for compressed entries; zero otherwise.
OriginalSize uint32 `json:"original_size,omitempty" yaml:"original_size,omitempty"`
// TimeStamp is Unix timestamp from entry record.
TimeStamp uint32 `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`
// MimeType stores entry mime marker.
MimeType MimeType `json:"mime_type,omitempty" yaml:"mime_type,omitempty"`
}
EntryInfo describes a single parsed PBO entry.
func ListEntries ¶
ListEntries opens a PBO and returns entry metadata without payload reads.
func ListEntriesFromReaderAt ¶
ListEntriesFromReaderAt parses entry metadata from a random-access source.
func ListEntriesFromReaderAtWithOptions ¶
func ListEntriesFromReaderAtWithOptions(ra io.ReaderAt, size int64, opts ReaderOptions) ([]EntryInfo, error)
ListEntriesFromReaderAtWithOptions parses entry metadata from a random-access source using reader options.
func ListEntriesWithOptions ¶
func ListEntriesWithOptions(path string, opts ReaderOptions) ([]EntryInfo, error)
ListEntriesWithOptions opens a PBO and returns entry metadata without payload reads using reader options.
func (*EntryInfo) IsCompressed ¶
IsCompressed reports whether this entry is stored with LZSS compression.
type ExtractFileMode ¶
type ExtractFileMode string
ExtractFileMode controls output file open behavior during extraction.
const ( // ExtractFileModeAuto first tries create-only, then falls back to truncate for existing files. ExtractFileModeAuto ExtractFileMode = "auto" // ExtractFileModeOverwriteSmart rewrites files in place and truncates only when existing file is larger. ExtractFileModeOverwriteSmart ExtractFileMode = "overwrite_smart" // ExtractFileModeTruncate opens existing files with truncate and creates missing files. ExtractFileModeTruncate ExtractFileMode = "truncate" // ExtractFileModeCreateOnly creates files only when absent and fails on existing files. ExtractFileModeCreateOnly ExtractFileMode = "create_only" )
Output file creation policies for extraction.
type ExtractOptions ¶
type ExtractOptions struct {
// OnEntryDone is called after one entry is fully written to disk.
OnEntryDone func(entry EntryInfo, written int64, outputPath string) `json:"-" yaml:"-"`
// FileMode controls output file creation policy.
FileMode ExtractFileMode `json:"file_mode,omitempty" yaml:"file_mode,omitempty"`
// Entries limits extraction to selected metadata list; nil means all parsed entries.
Entries []EntryInfo `json:"-" yaml:"-"`
// MaxWorkers is number of extraction workers (zero means GOMAXPROCS).
MaxWorkers int `json:"max_workers,omitempty" yaml:"max_workers,omitempty"`
// ContinueOnError keeps extraction running when one or more entries fail.
// Default false is fail-fast mode.
ContinueOnError bool `json:"continue_on_error,omitempty" yaml:"continue_on_error,omitempty"`
// RawNames disables default path sanitization during extract.
// When false (default), extract rewrites names to filesystem-safe output paths.
RawNames bool `json:"raw_names,omitempty" yaml:"raw_names,omitempty"`
}
ExtractOptions configures Extract behavior.
type GameType ¶
type GameType string
GameType is game-specific hash policy discriminator for v3 signatures.
const ( // GameTypeAny is the default game type for v3 signature hash policy. GameTypeAny GameType = "" // GameTypeArma is the game type for Arma 3. GameTypeArma GameType = "arma" // GameTypeDayZ is the game type for DayZ. GameTypeDayZ GameType = "dayz" )
Supported game types for v3 signature hash policy.
type HashSet ¶
type HashSet struct {
// Hash1 is SHA1 of the full PBO data (without trailer).
Hash1 [20]byte `json:"hash1" yaml:"hash1"`
// Hash2 is composed from hash1, name hash, and prefix rules.
Hash2 [20]byte `json:"hash2" yaml:"hash2"`
// Hash3 is composed from file hash, name hash, and prefix rules.
Hash3 [20]byte `json:"hash3" yaml:"hash3"`
}
HashSet contains signature hashes for one PBO.
func ComputeHashSet ¶
func ComputeHashSet(path string, version SignVersion, gameType GameType) (HashSet, error)
ComputeHashSet calculates hash1/hash2/hash3 for a PBO.
type HeaderPair ¶
type HeaderPair struct {
Key string `json:"key" yaml:"key"`
Value string `json:"value" yaml:"value"`
}
HeaderPair is a PBO header key-value pair written in provided order.
func ReadHeaders ¶
func ReadHeaders(path string) ([]HeaderPair, error)
ReadHeaders opens a PBO and returns only header key-value pairs without parsing entry table.
func ReadHeadersFromReaderAt ¶
func ReadHeadersFromReaderAt(ra io.ReaderAt, size int64) ([]HeaderPair, error)
ReadHeadersFromReaderAt reads only PBO header key-value pairs from a random-access source.
func ReadHeadersFromReaderAtWithOptions ¶ added in v0.2.0
func ReadHeadersFromReaderAtWithOptions(ra io.ReaderAt, size int64, opts ReaderOptions) ([]HeaderPair, error)
ReadHeadersFromReaderAtWithOptions reads only PBO header key-value pairs from a random-access source.
func ReadHeadersWithOptions ¶ added in v0.2.0
func ReadHeadersWithOptions(path string, opts ReaderOptions) ([]HeaderPair, error)
ReadHeadersWithOptions opens a PBO and returns only header key-value pairs using reader options.
type Input ¶
type Input struct {
// ModTime is optional entry timestamp.
ModTime time.Time `json:"mod_time" yaml:"mod_time"`
// Open returns raw source stream for this entry.
Open func() (io.ReadCloser, error) `json:"-" yaml:"-"`
// Path is destination path inside PBO.
Path string `json:"path" yaml:"path"`
// SizeHint is expected size in bytes (zero when unknown).
SizeHint int64 `json:"size_hint,omitempty" yaml:"size_hint,omitempty"`
}
Input describes one source stream to be packed into a PBO entry.
type MimeType ¶
type MimeType uint32
MimeType is the 4-byte PBO entry type (stored little-endian).
const ( // MimeHeader marks the first header record ("Vers"). MimeHeader MimeType = 0x56657273 // MimeCompress marks LZSS-compressed data ("Cprs"). MimeCompress MimeType = 0x43707273 // MimeEncoded marks VBS-encrypted data ("Enco"). MimeEncoded MimeType = 0x456e6372 // MimeNil marks uncompressed or terminator entry. MimeNil MimeType = 0x00000000 )
PBO entry mime constants.
type OffsetMode ¶
type OffsetMode string
OffsetMode controls how reader resolves payload offsets from index table.
const ( // OffsetModeSequential ignores stored index offsets and derives payload offsets sequentially. OffsetModeSequential OffsetMode = "sequential" // OffsetModeStoredCompat tries to use non-zero stored offsets and falls back to sequential on malformed data. OffsetModeStoredCompat OffsetMode = "stored_compat" // OffsetModeStoredStrict requires stored non-zero offsets to be valid and fails otherwise. OffsetModeStoredStrict OffsetMode = "stored_strict" )
Reader offset resolution modes.
type PackEntryProgress ¶
type PackEntryProgress struct {
// Path is entry path written to archive.
Path string `json:"path" yaml:"path"`
// Offset is payload offset in resulting archive.
Offset uint32 `json:"offset" yaml:"offset"`
// DataSize is stored payload size in bytes.
DataSize uint32 `json:"data_size" yaml:"data_size"`
// OriginalSize is original size for compressed entries; zero for raw entries.
OriginalSize uint32 `json:"original_size,omitempty" yaml:"original_size,omitempty"`
// MimeType is stored entry mime marker.
MimeType MimeType `json:"mime_type,omitempty" yaml:"mime_type,omitempty"`
// CompressionCandidate reports whether compression path was selected for this input entry.
CompressionCandidate bool `json:"compression_candidate,omitempty" yaml:"compression_candidate,omitempty"`
// Compressed reports whether compressed payload was actually written.
Compressed bool `json:"compressed,omitempty" yaml:"compressed,omitempty"`
}
PackEntryProgress contains one completed entry write event from pack flow.
type PackOptions ¶
type PackOptions struct {
// OnEntryDone is called after one entry is fully written to archive payload.
OnEntryDone func(entry PackEntryProgress) `json:"-" yaml:"-"`
// SealedKey enables sealed archive transform when set.
// Nil keeps standard plain PBO read/write behavior.
SealedKey *SealedKey `json:"sealed_key,omitempty" yaml:"sealed_key,omitempty"`
// Headers are written in deterministic order.
Headers []HeaderPair `json:"headers,omitempty" yaml:"headers,omitempty"`
// Compress defines ordered path rules for compression candidate selection.
Compress []pathrules.Rule `json:"compress,omitempty" yaml:"compress,omitempty"`
// WriterBufferSize is buffered writer size in bytes.
WriterBufferSize int `json:"writer_buffer_size,omitempty" yaml:"writer_buffer_size,omitempty"`
// MinCompressSize disables compression for entries smaller than this size.
// Default is 512 bytes.
MinCompressSize uint32 `json:"min_compress_size,omitempty" yaml:"min_compress_size,omitempty"`
// MaxCompressSize disables compression for entries larger than this size.
// Default is 16 MiB and also bounds known-size in-memory compression path.
MaxCompressSize uint32 `json:"max_compress_size,omitempty" yaml:"max_compress_size,omitempty"`
// CompressMatcherOptions control compression path rule matching.
CompressMatcherOptions pathrules.MatcherOptions `json:"compress_matcher_options,omitzero" yaml:"compress_matcher_options,omitzero"`
// contains filtered or unexported fields
}
PackOptions configures pack behavior.
type PackResult ¶
type PackResult struct {
// WrittenEntries is number of entries written to archive.
WrittenEntries int `json:"written_entries" yaml:"written_entries"`
// DataSize is total payload bytes written.
DataSize int64 `json:"data_size" yaml:"data_size"`
// IndexSize is total index bytes written.
IndexSize int64 `json:"index_size" yaml:"index_size"`
// RawBytes is total bytes written for uncompressed payload entries.
RawBytes int64 `json:"raw_bytes,omitempty" yaml:"raw_bytes,omitempty"`
// CompressedBytes is total bytes written for compressed payload entries.
CompressedBytes int64 `json:"compressed_bytes,omitempty" yaml:"compressed_bytes,omitempty"`
// CompressedEntries is number of entries written with compressed payload.
CompressedEntries int `json:"compressed_entries,omitempty" yaml:"compressed_entries,omitempty"`
// SkippedCompressionEntries is number of compression candidates stored as raw payload.
SkippedCompressionEntries int `json:"skipped_compression_entries,omitempty" yaml:"skipped_compression_entries,omitempty"`
// Duration is end-to-end pack core duration.
Duration time.Duration `json:"duration,omitempty" yaml:"duration,omitempty"`
}
PackResult contains pack output statistics.
func Pack ¶
func Pack(ctx context.Context, out io.WriteSeeker, inputs []Input, opts PackOptions) (*PackResult, error)
Pack writes a PBO to out from the given inputs. Inputs are sorted by path for deterministic output.
func PackFile ¶
func PackFile(ctx context.Context, outPath string, inputs []Input, opts PackOptions) (*PackResult, error)
PackFile writes a PBO to outPath and appends a SHA1 trailer.
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
Reader provides read-only access to a parsed PBO file.
func NewReaderFromReaderAt ¶
NewReaderFromReaderAt parses PBO from existing ReaderAt and known size.
func NewReaderFromReaderAtWithOptions ¶
func NewReaderFromReaderAtWithOptions(ra io.ReaderAt, size int64, opts ReaderOptions) (*Reader, error)
NewReaderFromReaderAtWithOptions parses PBO from existing ReaderAt and known size using explicit reader options.
func OpenWithOptions ¶
func OpenWithOptions(path string, opts ReaderOptions) (*Reader, error)
OpenWithOptions opens PBO file by path and parses index/header structures using explicit reader options.
func (*Reader) CopyEntryInfoTo ¶ added in v0.3.0
CopyEntryInfoTo decompresses and copies entry described by info into dst using the provided buf. Unlike OpenEntryInfo, it does not spawn a goroutine or pipe. buf may be nil; a default buffer is used for the uncompressed path.
func (*Reader) CopyEntryTo ¶ added in v0.3.0
CopyEntryTo decompresses and copies the named entry into dst using the provided buf. Unlike OpenEntry, it does not spawn a goroutine or pipe, making it more efficient for callers that only need to push entry content into an io.Writer (os.File, http.ResponseWriter). buf may be nil; a default buffer is used for the uncompressed path.
func (*Reader) CopyPackedEntryInfoTo ¶ added in v0.3.0
CopyPackedEntryInfoTo copies the raw stored bytes of an entry into dst. Like OpenPackedEntryInfo, it yields compressed bytes for compressed entries.
func (*Reader) EntriesView ¶ added in v0.3.0
EntriesView returns the internal entry slice without copying. Callers must not modify the returned slice or its elements. Suitable for read-only listing and UI polling where avoiding the copy matters.
func (*Reader) Extract ¶
Extract writes selected entries from the PBO to dstDir. Extraction is parallelized by MaxWorkers. By default extraction is fail-fast; set ContinueOnError to keep processing and return the first encountered error at the end.
func (*Reader) Headers ¶
func (r *Reader) Headers() []HeaderPair
Headers returns parsed headers in original order.
func (*Reader) OpenEntry ¶
func (r *Reader) OpenEntry(name string) (io.ReadCloser, error)
OpenEntry opens named entry for reading. Returned stream yields decompressed content for LZSS-compressed entries.
func (*Reader) OpenEntryInfo ¶
func (r *Reader) OpenEntryInfo(info EntryInfo) (io.ReadCloser, error)
OpenEntryInfo opens entry stream by already resolved metadata. Returned stream yields decompressed content for LZSS-compressed entries.
func (*Reader) OpenPackedEntryInfo ¶ added in v0.3.0
func (r *Reader) OpenPackedEntryInfo(info EntryInfo) (io.ReadCloser, error)
OpenPackedEntryInfo opens a read stream over the raw stored bytes of an entry. The returned reader yields compressed bytes for LZSS-compressed entries no decompression is applied. Use this for selective replace in Editor, hash tooling, or any consumer that needs the packed payload verbatim.
func (*Reader) RangeEntries ¶ added in v0.3.0
RangeEntries calls fn for each entry in index order. Iteration stops early when fn returns false.
func (*Reader) SHA1Trailer ¶
SHA1Trailer returns parsed 20-byte trailer hash when present.
type ReaderOptions ¶
type ReaderOptions struct {
// SealedKey enables sealed archive decode when set.
// Nil keeps standard plain PBO read behavior.
SealedKey *SealedKey `json:"sealed_key,omitempty" yaml:"sealed_key,omitempty"`
// OffsetMode controls whether stored index offsets are used.
OffsetMode OffsetMode `json:"offset_mode,omitempty" yaml:"offset_mode,omitempty"`
// EntryPathPrefix keeps entries whose normalized path is equal to prefix or starts with "prefix/".
EntryPathPrefix string `json:"entry_path_prefix,omitempty" yaml:"entry_path_prefix,omitempty"`
// MinEntryOriginalSize keeps entries with original size >= this value.
// For uncompressed entries OriginalSize is treated as DataSize.
MinEntryOriginalSize uint32 `json:"min_entry_original_size,omitempty" yaml:"min_entry_original_size,omitempty"`
// MinEntryDataSize keeps entries with packed payload size >= this value.
MinEntryDataSize uint32 `json:"min_entry_data_size,omitempty" yaml:"min_entry_data_size,omitempty"`
// EnableJunkFilter drops malformed/mangled entries from visible entry list.
EnableJunkFilter bool `json:"enable_junk_filter,omitempty" yaml:"enable_junk_filter,omitempty"`
// FilterASCIIOnly keeps only entries with ASCII-only path bytes.
FilterASCIIOnly bool `json:"filter_ascii_only,omitempty" yaml:"filter_ascii_only,omitempty"`
// SanitizeControlChars rewrites control/format runes in entry paths for safe textual output.
SanitizeControlChars bool `json:"sanitize_control_chars,omitempty" yaml:"sanitize_control_chars,omitempty"`
// SanitizeNames rewrites entry paths to filesystem-safe names for listing workflows.
SanitizeNames bool `json:"sanitize_names,omitempty" yaml:"sanitize_names,omitempty"`
}
ReaderOptions configures reader parse compatibility behavior.
type SealedKey ¶ added in v0.2.0
type SealedKey [16]byte
SealedKey is a fixed 16-byte key used by optional sealed transform mode.
type SignVersion ¶
type SignVersion uint32
SignVersion is PBO signature hash policy version.
const ( // SignVersionV2 is the legacy version of PBO signature hash policy. SignVersionV2 SignVersion = 2 // SignVersionV3 is the current version of PBO signature hash policy. SignVersionV3 SignVersion = 3 )
Supported signature hash policy versions.