Using Info-ZIP, attempting to fix an archive will compare the local and central CRCs, and combining that with archive tests will allow all the CRCs to be checked. If you run
unzip -t archive.zip
and
zip -F archive.zip --out archivefix.zip
and neither complain, that means the archive’s contents match both the central and local CRCs. (You can delete archivefix.zip afterwards.)
To verify this, starting with the Info-ZIP source code for zip 3.0, I created a file as follows:
zip -9 test.zip zip.txt zipup.c
I then corrupted the central directory CRC for zip.txt by changing the byte at offset 0xB137. I got the opposite behaviour to what you observed; unzip -v reported the altered CRC from the central directory, but unzip -t and zip -T reported that the file was OK (checking against the local CRC).
But running
zip -F test --out testfix
reported
Fix archive (-F) - assume mostly intact archive
Zip entry offsets do not need adjusting
copying: zip.txt
zip warning: Local Entry CRC does not match CD: zip.txt
copying: zipup.c
The "corrected" file still listed the altered CRC for zip.txt.
Altering the local CRC for zip.txt at offset 0x10 caused both unzip -t and zip -T to report a CRC error, but zip -F didn't spot anything wrong.
Thus from my experiments, mismatches between an archive entry's contents and its CRCs can be detected as follows:
- local only:
zip -T and unzip -t; zip -F will also complain about the local-central mismatch
- local and central:
zip -T and unzip -t
- central only:
zip -T and unzip -t will not complain, but zip -F will indicate a local-central mismatch
(Note that by default zip -T simply uses unzip -tqq, so zip -T and unzip -t really are equivalent. You can read the unzip source code to check that testing an archive really compares the local CRC, not the central one; look for extract_or_test_files(), extract_or_test_entrylist() and extract_or_test_member(), all in extract.c.)
unzip -t?unzip -tcould be an option, but what if we need to use the Alpine Linux unzip where -t option is not available?