跪拜 Guibai
← All articles
Open Source

HatchZip's Truncation Trick Extracts a 2.2GB Archive in 300MB of Free Space

By 高调的涵涵 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Developers extracting large packages on nearly full disks no longer need to free up double the archive's size; HatchZip requires only space for one file plus a configurable reserve. The trade-off is that the original archive is consumed by default, and the space benefit vanishes when the disk has plenty of headroom.

Summary

HatchZip 0.1.8, an MIT/Apache-2.0 dual-licensed decompressor written in Rust, extracts a 2.2GB ZIP in 6.97 seconds while capping disk usage at 2,412MB when available space is forced down to 300MB via `--keep-free`. It does this by starting from the end of the archive and truncating each committed batch, freeing the space for subsequent output. The mechanism requires the ZIP central directory tail to be saved as a separate file and kept in memory (up to 1GB), a strict commit order (flush, journal, then truncate), and batch sizes that adapt to available space minus the reserved `--keep-free` amount.

On a wide disk with roughly 34GB free, HatchZip's peak usage is nearly identical to normal `unzip` (4,429MB vs 4,404MB), so its space saving appears only under disk pressure. When the budget falls below the size of the largest file in the archive, it refuses cleanly with exit code 3, leaving the archive and output untouched. It supports resuming after budget exhaustion if the next run gets enough space, and it rejects path traversal before doing anything else.

The test archive was synthetic (21 × 100MiB random files), so real-world packages with many small files may hit the 512-file batch limit instead of the byte cap. HatchZip defaults to deleting the original archive on success, and the safe budget depends entirely on the size of the largest file; any change to the archive requires re-running `check`.

Takeaways
— HatchZip v0.1.8 extracts a 2.2GB ZIP (21×100MiB random files) in 6.97s with a 300MB budget, peak disk 2,412MB, and SHA-256 verified for all files.
— On a wide disk (~34GB free), HatchZip's peak (4,429MB) is 25MB (0.6%) higher than unzip's (4,404MB); no space saving appears.
— When available space drops below the size of one file, it refuses with exit code 3, prints 'Insufficient disk space', and leaves the archive and output unchanged.
— The `--keep-free` default is 2GB; each batch's budget is available space minus keep-free, capped at 2GiB and 512 files.
— It explicitly supports resuming after budget exhaustion, provided the next run has enough budget; the journal's committed length tracks progress.
— SIGKILL before the first batch commit leaves no resumable progress and forces a full redo; kill after commit wasn't tested.
— Path traversal (e.g., `../../evil.txt`) is refused at listing time with exit code 1 before any file operation.
— By default, the original archive is deleted on success; `--keep-archive` disables the space saving.
— Supported formats include ZIP, 7z, uncompressed tar, tar.gz, split, and RAR (solid only with `--keep-archive`); only ZIP was tested.
— The safe budget is not universal; it must cover the largest file in the archive plus `--keep-free`, so re-run `check` for each new archive.
Conclusions

The space saving is conditional on batch size, which is determined by available space minus `--keep-free`; on a large disk, HatchZip behaves like a normal unzip with a small overhead from tail copying and journaling.

HatchZip's failure mode is notably clean: it refuses before modifying anything, and even the journal is absent when the budget floor isn't met.

The test used equal-sized files that align perfectly with batch boundaries; real archives with many small files will hit the 512-file batch limit, changing truncation frequency and metadata overhead in ways not covered by this source.

A truly full disk was not simulated; the 300MB budget was created by `--keep-free`, so physical disk fragmentation and allocation behavior remain an open question.

The choice between `--keep-archive` and space saving is binary; there's no way to keep the archive and still benefit from in-place truncation.

Concepts & terms
In-place archive truncation
HatchZip extracts the archive from its end, truncating the already-processed bytes after each committed batch. This frees disk space immediately, allowing extraction to continue when the disk is nearly full, but it modifies the archive in place and deletes it by default.
Resume journal
A journal file records the committed length before each truncation. If extraction stops due to budget exhaustion or interruption, the journal allows HatchZip to resume from that point, provided the next run has enough free space to start a new batch.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗