Skip to content

unpack

zpack unpack <archive.zpak> <output-dir>

Extracts every entry into output-dir, which is created if it does not exist:

Terminal window
$ zpack unpack game.zpak extracted/
Extracted 56 files

Parent directories are created as needed. Because entries are sorted by path, files sharing a directory are contiguous, so the same parent is never created twice.

Contents are hashed as they stream. A mismatch aborts the command:

Terminal window
$ zpack unpack damaged.zpak out/
zpack: cannot unpack 'damaged.zpak': HashMismatch

Extraction is not transactional. Entries already written before the failure stay on disk. Since entries extract in sorted path order, a failure at entry n means the first n-1 are present and complete. Extract into a scratch directory and move it into place if you need all-or-nothing.

To check an archive without writing anything, use verify.

Every path is validated when the archive is opened, before a single byte is written. Absolute paths, .. segments, backslashes, NUL bytes, and colons are all rejected, so extraction cannot escape output-dir.

The colon rule catches more than a drive letter. On Windows, cfg:bak.txt names an alternate data stream on cfg, so those bytes would land somewhere unpack never reports. A colon anywhere in a path is rejected on every platform, which keeps an archive’s behaviour identical across hosts.

Paths are converted from / to the host separator on the way out, so an archive packed on Linux extracts correctly on Windows.

Not restored Why
File permissions Not recorded in the format
Modification times Not recorded in the format
Empty directories Directories are implied by entry paths, so one with nothing in it has nothing to imply it
Symlinks Never packed in the first place

Extracted files get whatever the platform’s default creation mode is.

Message Cause
cannot open archive '<f>': ... See validation
cannot open directory '<d>': ... output-dir could not be created or opened
cannot unpack '<f>': HashMismatch An entry’s contents do not match its recorded hash
cannot unpack '<f>': CorruptArchive An entry produced fewer or more bytes than the index promised