17

Near as I can tell the zip -T option only determines if files can be extracted -- it doesn't really test the archive for internal integrity. For example, I deliberately corrupted the local (not central directory) CRC for a file, and zip didn't care at all, reporting the archive as OK. Is there some other utility to do this?

There's a lot of internal redundancy in ZIP files, and it would be nice to have a way of checking it all. Of course, normally the central directory is all you need, but when repairing a corrupted archive often all you have is a fragment, with the central directory clobbered or missing. I'd like to know if archives I create are as recoverable as possible.

  • 2
    What about unzip -t? – FloHimself Apr 18 '15 at 20:09
  • Same behavior as zip. – Marc Rochkind Apr 18 '15 at 20:15
17

unzip -t

Test archive files.

This option extracts each specified file in memory and compares the CRC (cyclic redundancy check, an enhanced checksum) of the expanded file with the original's stored CRC value.

[ source: https://linux.die.net/man/1/unzip ]

  • There are 2 CRCs per file: local and central. unzip -t only tests the latter. – Marc Rochkind Apr 18 '15 at 20:33
  • 2
    i don't know what you mean by "local" versus "central" (central to what?) but when i run "unzip -t myzip_file.zip" i see a line output for commenting on the integrity of each and every zipped file, like (imagine better formatting): "testing: AARiseTransitSet.cpp OK testing: AARiseTransitSet.h OK testing: AASaturn.cpp OK testing: AASaturn.h OK ... – Theophrastus Apr 18 '15 at 20:39
  • Not the place to explain internal structure of ZIP files. Wikepedia article is pretty good on this. As I said, it is a misleading report that you are seeing. – Marc Rochkind Apr 18 '15 at 20:55
  • If i go into a zip file with a hex-editor and change one byte, then i see for one file: testing: AA_sphere.htm bad CRC 7952862e (should be 44c6f7f8) while the rest are listed as "OK". you'll continue to declare this as "misleading", but that's exactly what i expect for a file-by-file CRC check of a zip file. now... good luck to you Sir. – Theophrastus Apr 18 '15 at 21:02
  • I think you have changed the central directory CRC, at the end. Try changing the local one, before or after the file. – Marc Rochkind Apr 18 '15 at 21:21
9

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.)

  • Complicated. And no doubt very dependent on what versions (GNU, BSD, etc.) And CRC is only one of the numerous integrity checks that can be performed. – Marc Rochkind Apr 18 '15 at 22:55
  • There aren't many versions of zip and unzip available on Unix-like platforms; Info-ZIP is used pretty much everywhere... – Stephen Kitt Apr 18 '15 at 23:02
  • 1
    As far as it being complicated, it takes just two commands; if both unzip -t and zip -F run without error, you're OK and both CRCs have been checked. – Stephen Kitt Apr 18 '15 at 23:04
  • Thanks! Will check this out. Also, forgot to mention: ZIP files are ZIP64. – Marc Rochkind Apr 18 '15 at 23:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.