Quazim0t0's picture
Import from Quazim0t0/neural-storage; repoint refs to NeuralVerified
bdfb884 verified
Raw
History Blame Contribute Delete
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