| 1 | #!/usr/bin/env python3 |
| 2 | """Extract a native capture with links for identical files.""" |
| 3 | import hashlib |
| 4 | import os |
| 5 | from pathlib import Path, PurePosixPath |
| 6 | import sys |
| 7 | import zipfile |
| 8 | |
| 9 | archive, destination = map(Path, sys.argv[1:]) |
| 10 | destination.mkdir(parents=True, exist_ok=False) |
| 11 | seen = {} |
| 12 | with zipfile.ZipFile(archive) as captured: |
| 13 | for entry in captured.infolist(): |
| 14 | relative = PurePosixPath(entry.filename.replace('\\', '/')) |
| 15 | if relative.is_absolute() or '..' in relative.parts: |
| 16 | raise ValueError('Archive path escapes the corpus directory') |
| 17 | target = destination.joinpath(*relative.parts) |
| 18 | if entry.filename.endswith(('/', '\\')): |
| 19 | target.mkdir(parents=True, exist_ok=True) |
| 20 | continue |
| 21 | target.parent.mkdir(parents=True, exist_ok=True) |
| 22 | data = captured.read(entry) |
| 23 | digest = hashlib.sha256(data).digest() |
| 24 | if digest in seen: |
| 25 | target.symlink_to(os.path.relpath(seen[digest], target.parent)) |
| 26 | else: |
| 27 | target.write_bytes(data) |
| 28 | target.chmod(0o444) |
| 29 | seen[digest] = target |
| 30 | print(f'Imported {len(seen)} distinct files into {destination}') |