Download cdpreserve/scan.py from NeuralVerified/neural-cd-preserve: direct link, hf CLI and curl.
- Browser
- Download file 2.17 kB
-
https://huggingface.co/NeuralVerified/neural-cd-preserve/resolve/de15a9f1e628d5f702dc74ff6fffd227d256be68/cdpreserve/scan.py
- Command line
-
hf download hf://NeuralVerified/neural-cd-preserve@de15a9f1e628d5f702dc74ff6fffd227d256be68/cdpreserve/scan.py
-
curl -L -o scan.py https://huggingface.co/NeuralVerified/neural-cd-preserve/resolve/de15a9f1e628d5f702dc74ff6fffd227d256be68/cdpreserve/scan.py
2.17 kB
| """ | |
| Disc scanner. | |
| Reads a source sector by sector into bytes. The source can be a raw optical | |
| drive (Windows: r"\\\\.\\D:", may need admin) or an .iso / image file (for | |
| testing). Unreadable sectors (scratches / disc rot) are recorded as BAD and | |
| zero-filled -- ddrescue-style -- rather than aborting the scan. | |
| Important: bad sectors are data you never read. RS self-healing (archive.py) | |
| protects the STORED copy against future corruption; it cannot invent sectors the | |
| drive could not read. To recover those, re-scan the disc and merge good sectors | |
| across attempts (`merge_scans`). | |
| """ | |
| from __future__ import annotations | |
| SECTOR = 2048 # CD-ROM Mode-1 user data sector size | |
| def scan_image(path: str, sector: int = SECTOR): | |
| """-> (data: bytes, bad_sectors: list[int]). Robust to unreadable sectors.""" | |
| data = bytearray() | |
| bad = [] | |
| with open(path, "rb", buffering=0) as f: | |
| idx = 0 | |
| while True: | |
| try: | |
| blk = f.read(sector) | |
| except OSError: | |
| bad.append(idx) | |
| data += bytes(sector) | |
| try: | |
| f.seek((idx + 1) * sector) | |
| except OSError: | |
| break | |
| idx += 1 | |
| continue | |
| if not blk: | |
| break | |
| data += blk # keep true length (last | |
| idx += 1 # sector may be partial) | |
| return bytes(data), bad | |
| def merge_scans(scans, sector: int = SECTOR): | |
| """Combine multiple (data, bad) scans of the same failing disc: a sector is | |
| good if ANY scan read it. Returns (merged_data, still_bad_sectors).""" | |
| n = max(len(d) // sector for d, _ in scans) | |
| merged = bytearray(n * sector) | |
| known = [False] * n | |
| for data, bad in scans: | |
| badset = set(bad) | |
| for s in range(len(data) // sector): | |
| if s not in badset and not known[s]: | |
| merged[s * sector:(s + 1) * sector] = data[s * sector:(s + 1) * sector] | |
| known[s] = True | |
| still_bad = [s for s in range(n) if not known[s]] | |
| return bytes(merged), still_bad | |