zipatch-rs
A Rust library for parsing and applying FFXIV ZiPatch files (.patch).
ZiPatch is the binary patch format Square Enix ships Final Fantasy XIV game updates in. A patch is a chunked binary log of file additions, deletions, SqPack .dat/.index mutations, and binary diffs that an applier walks against an existing game installation to bring it to a new version.
Quick start
[]
= "1.5"
Apply a patch to an existing install:
use ;
let reader = from_path?;
let mut ctx = new;
reader.apply_to?;
See docs.rs for the indexed-apply path (Plan / Verifier / IndexApplier), post-apply hash verification (HashVerifier), dry-run mode, observer hooks, and resume entry points.
Features
- Streaming chunk parser — bounded memory, one chunk in flight at a time.
- Sequential apply — chunk-by-chunk, in-place writes to the install tree.
- Dry-run mode —
ApplyMode::DryRunwalks every chunk, resolves every path, decompresses every DEFLATE block, and validates every chunk CRC32 without opening files for write. Sanity-checks a downloaded patch before touching the install. - Indexed verify-and-repair — build a
Plandescribing every byte of every target, verify an install against it, and re-apply only the regions that drift viaRepairManifest. - Post-apply hash verification —
HashVerifierreads the resulting.index/.datfiles back from disk and compares against caller-supplied SHA1s (whole-file or 50 MiB block-mode). Catches silent on-disk corruption the per-chunk CRC32s can't see. - Parallel verify — both
HashVerifier::executeandindex::Verifier::executefan out across rayon's global pool. SHA1 hashing scales near-linearly with cores. - Multi-patch chains — a single
Planspans the patch chain end-to-end; mid-chainRemoveAll/DeleteFile/AddFile @ 0retroactively drop superseded regions. - Resumable apply — checkpoint emission at every chunk and every DEFLATE block inside
SqpkFile::AddFile; resume entry points fast-forward to the recorded position. - Progress + cancellation —
ApplyObserverfires per chunk;should_cancelis polled mid-block on long DEFLATE streams. - Optional CRC32 verification —
Plan::compute_crc32populates expected CRCs so the verifier catches single-byte damage the size-only policy would miss. - Alternate DEFLATE backends — opt into
zlib-rsorzlib-ngfor faster DEFLATE; the default is pure-Rustminiz_oxidewith no system dependencies. - Fuzz harness — eight cargo-fuzz targets cover the full parse + apply surface; weekly cron in CI.
Cargo features
| Feature | Default | Purpose |
|---|---|---|
serde |
off | Serialize / Deserialize on Plan, RepairManifest, the Checkpoint types, and the index data model. The crate does not pick an on-disk format; you bring your own (bincode, rmp-serde, JSON, etc.). |
zlib-rs |
off | Switches the SqpkFile::AddFile decompress path to the pure-Rust zlib-rs port. Mutually exclusive with zlib-ng. |
zlib-ng |
off | Switches the decompress path to the C zlib-ng fork. Requires cmake and a C compiler at build time. |
test-utils |
off | Exposes a zipatch_rs::test_utils module of chunk-framing fixtures used by the test suite and benchmarks. Not part of the stable public API. |
Where it fits
zipatch-rs is a library, not a launcher. It does no network I/O — patch fetch, authentication, version negotiation, and progress UI all live somewhere else. The companion gaveloc workspace is the full launcher product that consumes this crate as a path dependency.
If all you want to do is apply a .patch file you already have on disk to an install you already have on disk, this crate alone is enough.
Reference implementation
The primary reference for the ZiPatch binary format is XIVLauncher's C# implementation in FFXIVQuickLauncher. This crate is not a port — the parser and applier are independently implemented — but the C# tree is authoritative for chunk semantics when the spec is ambiguous.
Stability
- MSRV: Rust 1.85 (the minimum that supports edition 2024). Bumps land as a major version bump.
- SemVer: public API changes follow semantic versioning. The
test_utilsmodule is explicitly excluded. - License: MIT — see LICENSE.
Contributing
See CONTRIBUTING.md. Security issues go through the private advisory form; see SECURITY.md.
Supported chunks
Chunk types
| Tag | Name | Notes |
|---|---|---|
FHDR |
File Header | V2 and V3 |
APLY |
Apply Option | ignore-missing, ignore-old-mismatch flags |
APFS |
Apply Free Space | |
ADIR |
Add Directory | |
DELD |
Delete Directory | |
SQPK |
SQPK command block | See sub-commands below |
EOF_ |
End of File |
SQPK sub-commands
| Command | Name | Notes |
|---|---|---|
A |
AddData | Writes data into a .dat file at a block offset |
D |
DeleteData | Zeros a block range in a .dat file |
E |
ExpandData | Expands a .dat file with an empty block |
H |
Header | Writes version or index headers into .dat/.index files |
F |
File | AddFile, DeleteFile, RemoveAll, MakeDirTree; supports DEFLATE-compressed blocks |
T |
TargetInfo | Platform (Win32, PS3, PS4), region, debug flag |
I |
Index | Parsed; no-op at apply time |
X |
PatchInfo | Parsed; no-op at apply time |