Recovery provenance / constructed software experiments
ddrescue image provenance: twelve controlled cases
Complete maps, stale output bytes, approximate map reconstruction and identical images with different acquisition histories.
Download CSV12 cases / 9 columnsMetadata and hashes / Original observations / Replay / Interpretation
Method
Eight rescue/resume cases, three approximate-map cases and one post-copy modification on a known 4096-byte fixture. Read errors are simulated with --test-mode. Source sectors are A, zero, C, D, E, F, G and H; letters denote 512 repetitions of that ASCII byte. Reused destinations start filled with Z. Copy buffers are one sector. GNU ddrescue 1.30 was built from the pinned official archive. These are selected counterexamples, not recovery-rate estimates.
| Case | Finished bytes | Matching bytes | Full-domain status | First-sector status |
|---|---|---|---|---|
fresh-bad-data | 3584 | 3584 | 1 | 0 |
reused-bad-data | 3584 | 3584 | 1 | 0 |
fresh-bad-zero | 3584 | 4096 | 1 | 0 |
fresh-healthy | 4096 | 4096 | 0 | 0 |
sparse-fresh-healthy | 4096 | 4096 | 0 | 0 |
sparse-reused-healthy | 4096 | 3584 | 0 | 0 |
sparse-reused-bad-data | 3584 | 3072 | 1 | 0 |
resume-sparse-reused | 4096 | 3584 | 0 | 0 |
generated-fresh-bad-data | 3072 | 3584 | 1 | 0 |
generated-reused-bad-data | 3584 | 3584 | 1 | 0 |
generated-sparse-reused-bad-data | 4096 | 3072 | 0 | 0 |
modified-after-completion | 4096 | 3584 | 0 | 0 |
What the columns establish
The mapfile provides interval states; the known source provides a separate byte oracle. Every mismatch fills an entire sector in these fixtures. Counting matching sectors therefore gives the matching-byte total here, but is not a generic byte-difference counter. Generate-mode rows inspect output and do not copy source bytes. The modification row records a fixture edit, not a ddrescue invocation.
Sparse writes into nonzero output intentionally violate the manual's precondition. The resume disables sparse writes and read-error simulation while keeping that image/map pair: 4,096 finished bytes, 3,584 matching bytes. Fresh-output controls distinguish the misuse from ordinary sparse-file behavior.
Reproduce
Build upstream 1.30 from the release archive with ./configure, make and make check. Its hash and inspected files are in the source ledger. No upstream executable or source is redistributed.
Place the harness, tests and results.json together. Python 3 is required. The harness uses disposable regular files only, bounds subprocess runtime and refuses to replace an existing receipt.
python3 observe.py --ddrescue /path/to/ddrescue \
--ddrescuelog /path/to/ddrescuelog --output fresh-results.json
DDRESCUE_BIN=/path/to/ddrescue DDRESCUELOG_BIN=/path/to/ddrescuelog \
python3 -B -m unittest -v test_observeFor a CSV/metadata rebuild, put all files named in metadata's sha256 object together, including the generator, publication tests, replay, claims and license. Run python3 -B build_publication.py --dev-root ./rebuilt. Outputs appear below rebuilt/sites/hesela-dev/public/. Run python3 -B -OO -m unittest test_publication to check mutation rejection, replay equivalence and file hashes.
Environments and replay
Original: Linux 6.18.55, x86_64, Python 3.12.14; generated 2026-10-18T05:23:15.836662+00:00. Replay: Linux 6.8.0-146-generic, x86_64, Python 3.12.3; generated 2026-10-18T09:23:46.198610+00:00. All twelve stable outcomes matched.
Comparison excludes timestamps and map comments, but retains image hashes, sector comparisons, ranges and exit statuses. Both raw receipts retain original timestamps and executable hashes. HTTPS and hash pinning were used without detached-signature verification. This is software repeatability evidence, not a hardware study.
Limits
- Regular files only; software-simulated read errors.
- One upstream version and build; no hardware recovery rates, power-loss or timing claims.
- Map '+' describes rescue bookkeeping, not a digest comparison with the source.
- Reused sparse output intentionally violates the documented empty-or-zeroed destination precondition.
- Matching-byte totals apply to fixtures with whole-sector differences, not a generic byte-difference calculation.
Column definitions
- case
- Stable scenario ID, not an independent fleet observation.
- mode
- Rescue, resume, approximate map generation or post-copy modification.
- source_bytes
- Known fixture extent in bytes.
- finished_bytes
- Bytes in map ranges marked +, not independently verified image bytes.
- matching_source_bytes
- Bytes equal to the fixture; differences in these cases occupy whole sectors.
- operation_status
- Operation exit status; modification is a fixture action, not ddrescue.
- done_status
- ddrescuelog --done-status over the full map domain.
- first_sector_done_status
- The same check restricted to the first 512 bytes.
- image_sha256
- Output digest, not source authentication or acquisition history.
Sources and reuse
Hesela-authored code, observations and derived CSV: MIT. GNU source and documentation retain their licenses and are not redistributed.
- GNU ddrescue 1.30 manual: sparse output, generate mode and ddrescuelog
- GNU ddrescue 1.30 source release: rescuebook.cc and genbook.cc
Related: sparse file, checksum, backup verification.
Published by Hesela team
Report a correction · Editorial standards · Reuse guidance
Cite this page
Hesela team. ddrescue image provenance: twelve controlled cases. Hesela. https://hesela.dev/datasets/ddrescue-image-provenance/