#!/usr/bin/env python3 """Restore byte-exact original files from the transparent text transport package. From the anc directory, run: python3 restore_files.py Then run: python3 code/check_all.py Full enumeration, if desired: python3 code/reproduce.py --output reproduction --workers 4 The transport README is replaced by the preserved original ancillary README. Part files, the manifest, and this script remain available after restoration. """ from __future__ import annotations import hashlib import json import os from pathlib import Path, PurePosixPath ROOT = Path(__file__).resolve().parent.parent MANIFEST = Path(__file__).resolve().parent / 'restoration-manifest.json' def checked_path(name: str) -> Path: rel = PurePosixPath(name) if rel.is_absolute() or not rel.parts or any(x in ('', '.', '..') for x in rel.parts): raise ValueError(f'Unsafe manifest path: {name!r}') result = ROOT.joinpath(*rel.parts) if not result.resolve().is_relative_to(ROOT): raise ValueError(f'Path leaves package: {name!r}') if result.is_symlink(): raise ValueError(f'Symlink is not an original package file: {name!r}') return result def digest(data: bytes) -> str: return hashlib.sha256(data).hexdigest() def main() -> None: manifest = json.loads(MANIFEST.read_text(encoding='utf-8')) if manifest['format_version'] != 1: raise ValueError('Unsupported restoration manifest version') originals = manifest['original_files'] if len({row['path'] for row in originals}) != len(originals): raise ValueError('Duplicate original paths') prepared: list[tuple[Path, bytes, dict]] = [] # Validate every source and every original digest before changing any file. for row in originals: destination = checked_path(row['path']) representation = row['representation'] kind = representation['kind'] if kind == 'empty': data = b'' elif kind in ('file', 'concatenate'): chunks = [] for part in representation['parts']: source = checked_path(part['path']) content = source.read_bytes() if len(content) != part['bytes'] or digest(content) != part['sha256']: raise ValueError(f'Transport file verification failed: {part["path"]}') chunks.append(content) data = b''.join(chunks) else: raise ValueError(f'Unsupported representation: {kind!r}') if len(data) != row['bytes'] or digest(data) != row['sha256']: raise ValueError(f'Original file verification failed: {row["path"]}') prepared.append((destination, data, row)) for destination, data, row in prepared: if destination.is_file() and digest(destination.read_bytes()) == row['sha256']: continue destination.parent.mkdir(parents=True, exist_ok=True) temporary = destination.with_name(destination.name + '.restore-tmp') if temporary.exists() or temporary.is_symlink(): raise ValueError(f'Temporary path already exists: {temporary}') temporary.write_bytes(data) os.replace(temporary, destination) for destination, _, row in prepared: data = destination.read_bytes() if len(data) != row['bytes'] or digest(data) != row['sha256']: raise ValueError(f'Post-restoration verification failed: {row["path"]}') print(f'Restored and SHA-256 verified all {len(originals)} original files.') print('From the anc directory, run the supplied checks: python3 code/check_all.py') if __name__ == '__main__': main()