Documentation
¶
Overview ¶
Package archive implements the mid-level MPQ archive engine: open, read, write, create, compact, and patch operations.
It composes github.com/ldmonster/go-stormlib/internal/mpq (table parsing and cryptography) with the codec packages under github.com/ldmonster/go-stormlib/internal/compress to produce a complete read/write pipeline for MPQ v1 and v2 archives.
This package is internal. External callers should use github.com/ldmonster/go-stormlib/pkg/storm instead.
Index ¶
- Variables
- func CreateEmpty(path string, opts CreateOptions) error
- type Archive
- func (a *Archive) Compact() error
- func (a *Archive) CreateFile(name string, fileSize, flags uint32) error
- func (a *Archive) CreateFileEx(name string, fileSize, flags uint32, compression byte) error
- func (a *Archive) FinishFile() error
- func (a *Archive) Flush() error
- func (a *Archive) GetAttributesFlags() uint32
- func (a *Archive) IsPatchedArchive() bool
- func (a *Archive) OpenIndexedFile(index int) (FileHandle, error)
- func (a *Archive) OpenIndexedFileByHash(hashA, hashB uint32, locale uint16, platform uint8) (FileHandle, error)
- func (a *Archive) OpenIndexedFileForDecrypt(hashA, hashB uint32, locale uint16, platform uint8, pathForDecryptKey string) (FileHandle, error)
- func (a *Archive) OpenPatchArchive(path, prefix string, flags uint32) error
- func (a *Archive) PersistHeaderAndTablesForTest(h mpq.Header, hashes []mpq.HashEntry, blocks []mpq.BlockEntry) error
- func (a *Archive) ReadFile(h FileHandle) ([]byte, error)
- func (a *Archive) ReadPatchedByName(name string, locale uint16, platform uint8) ([]byte, error)
- func (a *Archive) RemoveFile(name string, locale uint16, platform uint8) error
- func (a *Archive) RenameFile(oldName, newName string, locale uint16, platform uint8) error
- func (a *Archive) SetAddFileCallback(cb func(written, total uint32, done bool))
- func (a *Archive) SetAttributesFlags(flags uint32) uint32
- func (a *Archive) WriteFile(data []byte) error
- type CreateOptions
- type FileHandle
- type OpenOptions
Constants ¶
This section is empty.
Variables ¶
var ( ErrIndexOutOfRange = errors.New("file index out of range") ErrFileHashNotFound = errors.New("file hash entry not found") ErrDecodeFailed = errors.New("decode failed") // ErrUnsupportedCodec is returned when the sector compression mask uses a codec not implemented yet (pkware, huffman, ...). ErrUnsupportedCodec = errors.New("unsupported mpq sector compression codec") // ErrEncryptionNeedsPath is returned for MPQ_FILE_ENCRYPTED entries when no internal path was supplied for DecryptFileKey (open-by-hash/index cannot derive the key). ErrEncryptionNeedsPath = errors.New( "encrypted mpq entry requires opening by internal file path for decryption key", ) )
var ( ErrWriteInProgress = errors.New("mpq file write already in progress") ErrNoWriteInProgress = errors.New("mpq file write not started") ErrWriteSizeExceeded = errors.New("mpq file write exceeds declared size") ErrWriteSizeIncomplete = errors.New("mpq file write incomplete") ErrWriteFlagsUnsupported = errors.New("unsupported mpq file write flags") ErrArchiveWriteUnsupported = errors.New("archive write shape unsupported") ErrRenameCollision = errors.New("rename target already exists") ErrInvalidFileName = errors.New("invalid mpq file name") ErrInternalFileName = errors.New("internal mpq file name") ErrUnsupportedCodecWrite = errors.New("unsupported mpq codec for write") )
var ErrPatchDeltaUnsupported = errors.New("patch-chain delta unsupported")
ErrPatchDeltaUnsupported is returned when a patch-chain entry carries an unrecognised XFRM type that we do not know how to apply.
var ErrSectorChecksum = errors.New("sector checksum mismatch")
ErrSectorChecksum reports an adler32 mismatch on a stored sector.
Functions ¶
func CreateEmpty ¶
func CreateEmpty(path string, opts CreateOptions) error
CreateEmpty writes a new minimal MPQ without user data preamble, matching StormLib empty-archive layout (0x200 padding, header, encrypted empty hash table, block table size 0).
Types ¶
type Archive ¶
type Archive struct {
Path string
Header mpq.Header
HashTable []mpq.HashEntry
BlockTable []mpq.BlockEntry
FileIndex []mpq.IndexedFileEntry
// contains filtered or unexported fields
}
func OpenWithOptions ¶
func OpenWithOptions(path string, opts OpenOptions) (*Archive, error)
func (*Archive) Compact ¶
Compact rewrites the archive in place so that only live block entries remain, reclaiming gaps left behind by removed/replaced files. The on-disk archive layout after compaction is:
[lead padding] [header] [live block payloads concatenated] [hash table] [block table]
HET/BET/Hi-block extension tables are stripped by Compact — StormLib's BuildFileTable transparently falls back to the classic hash/block tables when the HET pointer is zero. v4 archives have their MD5HashTable and MD5BlockTable digests recomputed so VerifyHashTableMD5/VerifyBlockTableMD5 succeed after compaction.
func (*Archive) CreateFile ¶
CreateFile begins a minimal write lifecycle similar to SFileCreateFile. Current parity scope is intentionally narrow: uncompressed single-unit writes.
func (*Archive) CreateFileEx ¶
CreateFileEx is the explicit-codec variant of CreateFile. The compression argument is the MPQ codec mask byte (e.g. 0x02 zlib, 0x10 bzip2). Zero selects the implementation default when MPQ_FILE_COMPRESS is set.
func (*Archive) FinishFile ¶
FinishFile persists the pending file and updates MPQ tables/header, similar to SFileFinishFile.
func (*Archive) Flush ¶
Flush serialises the (listfile) for the current archive state. It is safe to call multiple times; existing internal entries are first marked deleted so the new payload occupies a fresh slot/block.
func (*Archive) GetAttributesFlags ¶
GetAttributesFlags returns the configured (attributes) flags, defaulting to CRC32|FILETIME|MD5 when SetAttributesFlags has not been called.
func (*Archive) IsPatchedArchive ¶
func (*Archive) OpenIndexedFile ¶
func (a *Archive) OpenIndexedFile(index int) (FileHandle, error)
func (*Archive) OpenIndexedFileByHash ¶
func (*Archive) OpenIndexedFileForDecrypt ¶
func (a *Archive) OpenIndexedFileForDecrypt( hashA, hashB uint32, locale uint16, platform uint8, pathForDecryptKey string, ) (FileHandle, error)
OpenIndexedFileForDecrypt opens by hash table entry but supplies the MPQ-internal path string required to derive Storm DecryptFileKey when MPQ_FILE_ENCRYPTED is set.
func (*Archive) OpenPatchArchive ¶
func (*Archive) PersistHeaderAndTablesForTest ¶
func (a *Archive) PersistHeaderAndTablesForTest( h mpq.Header, hashes []mpq.HashEntry, blocks []mpq.BlockEntry, ) error
PersistHeaderAndTablesForTest is an exported wrapper around persistHeaderAndTables for use by storm-package tests that need to inject/mutate tables.
func (*Archive) ReadPatchedByName ¶
ReadPatchedByName walks the patch chain newest-first to find the newest version, applying any BSDIFF40/COPY patch deltas over the most recent non-delta base. MPQ_FILE_DELETE_MARKER terminates lookup and returns ErrFileHashNotFound.
func (*Archive) RemoveFile ¶
RemoveFile marks a hash entry as deleted and clears its block table row.
func (*Archive) RenameFile ¶
RenameFile updates hash A/B for the selected locale/platform variant.
func (*Archive) SetAddFileCallback ¶
func (*Archive) SetAttributesFlags ¶
SetAttributesFlags overrides the bitmask used by Flush when emitting an (attributes) file. Returns the previous value. Pass 0 to suppress (attributes) emission entirely. Bits: 0x01=CRC32, 0x02=FILETIME, 0x04=MD5.
type CreateOptions ¶
type CreateOptions struct {
// ArchiveFormat is MPQ_FORMAT_VERSION_*: 0 = classic v1 header, 1 = Burning Crusade v2 header (44-byte).
ArchiveFormat uint16
// MaxFileCount is dwMaxFileCount; 0 uses StormLib default hash table sizing.
MaxFileCount uint32
// ReservedSlots counts extra hash slots for internal files when MaxFileCount > 0 (listfile/attributes/signature).
ReservedSlots uint32
// ReserveListfile mirrors StormLib create reserved-file accounting for (listfile).
ReserveListfile bool
// ReserveAttributes mirrors StormLib create reserved-file accounting for (attributes).
ReserveAttributes bool
// ReserveSignature mirrors StormLib create reserved-file accounting for (signature).
ReserveSignature bool
}
CreateOptions controls layout for a new empty archive (read StormLib SFileCreateArchive / SFileCreateArchive2).
type FileHandle ¶
type FileHandle struct {
Entry mpqIndexedEntry
DecryptKeySource string // Storm DecryptFileKey path string; empty when opened by hash/index only.
}